17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5df2381bfSpraks * Common Development and Distribution License (the "License").
6df2381bfSpraks * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22b39a0235SMilan Cermak * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include <sys/types.h>
267c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
277c478bd9Sstevel@tonic-gate #include <sys/param.h>
287c478bd9Sstevel@tonic-gate #include <sys/time.h>
297c478bd9Sstevel@tonic-gate #include <sys/systm.h>
307c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
317c478bd9Sstevel@tonic-gate #include <sys/resource.h>
327c478bd9Sstevel@tonic-gate #include <sys/signal.h>
337c478bd9Sstevel@tonic-gate #include <sys/cred.h>
347c478bd9Sstevel@tonic-gate #include <sys/user.h>
357c478bd9Sstevel@tonic-gate #include <sys/buf.h>
367c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
377c478bd9Sstevel@tonic-gate #include <sys/stat.h>
387c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
397c478bd9Sstevel@tonic-gate #include <sys/mode.h>
407c478bd9Sstevel@tonic-gate #include <sys/proc.h>
417c478bd9Sstevel@tonic-gate #include <sys/disp.h>
427c478bd9Sstevel@tonic-gate #include <sys/file.h>
437c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
447c478bd9Sstevel@tonic-gate #include <sys/flock.h>
457c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
467c478bd9Sstevel@tonic-gate #include <sys/uio.h>
477c478bd9Sstevel@tonic-gate #include <sys/dnlc.h>
487c478bd9Sstevel@tonic-gate #include <sys/conf.h>
497c478bd9Sstevel@tonic-gate #include <sys/errno.h>
507c478bd9Sstevel@tonic-gate #include <sys/mman.h>
517c478bd9Sstevel@tonic-gate #include <sys/fbuf.h>
527c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
537c478bd9Sstevel@tonic-gate #include <sys/debug.h>
547c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h>
557c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
567c478bd9Sstevel@tonic-gate #include <sys/dirent.h>
577c478bd9Sstevel@tonic-gate #include <sys/errno.h>
587c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
597c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
607c478bd9Sstevel@tonic-gate #include <sys/mount.h>
617c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
627c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
637c478bd9Sstevel@tonic-gate #include <sys/policy.h>
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate #include <vm/hat.h>
667c478bd9Sstevel@tonic-gate #include <vm/page.h>
677c478bd9Sstevel@tonic-gate #include <vm/pvn.h>
687c478bd9Sstevel@tonic-gate #include <vm/as.h>
697c478bd9Sstevel@tonic-gate #include <vm/seg.h>
707c478bd9Sstevel@tonic-gate #include <vm/seg_map.h>
717c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
727c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h>
737c478bd9Sstevel@tonic-gate #include <vm/rm.h>
747c478bd9Sstevel@tonic-gate #include <vm/page.h>
757c478bd9Sstevel@tonic-gate #include <sys/swap.h>
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
827c478bd9Sstevel@tonic-gate #include <sys/fs/udf_inode.h>
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate struct slot {
867c478bd9Sstevel@tonic-gate enum {NONE, COMPACT, FOUND, EXIST} status;
877c478bd9Sstevel@tonic-gate off_t offset; /* offset of area with free space */
887c478bd9Sstevel@tonic-gate int size; /* size of area at slotoffset */
897c478bd9Sstevel@tonic-gate struct fbuf *fbp; /* dir buf where slot is */
907c478bd9Sstevel@tonic-gate struct file_id *ep; /* pointer to slot */
917c478bd9Sstevel@tonic-gate off_t endoff; /* last useful location found in search */
927c478bd9Sstevel@tonic-gate };
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate int32_t ud_dircheckforname(struct ud_inode *, char *, int,
967c478bd9Sstevel@tonic-gate struct slot *, struct ud_inode **, uint8_t *, struct cred *);
977c478bd9Sstevel@tonic-gate int32_t ud_dirempty(struct ud_inode *, uint64_t, struct cred *);
987c478bd9Sstevel@tonic-gate int32_t str2cmp(char *, int32_t, char *, int32_t, char *, int32_t);
997c478bd9Sstevel@tonic-gate int32_t ud_dircheckpath(int32_t, struct ud_inode *, struct cred *);
1007c478bd9Sstevel@tonic-gate int32_t ud_dirmakeinode(struct ud_inode *, struct ud_inode **,
1017c478bd9Sstevel@tonic-gate struct vattr *, enum de_op, struct cred *);
1027c478bd9Sstevel@tonic-gate int32_t ud_diraddentry(struct ud_inode *, char *,
1037c478bd9Sstevel@tonic-gate enum de_op, int, struct slot *, struct ud_inode *,
1047c478bd9Sstevel@tonic-gate struct ud_inode *, struct cred *);
1057c478bd9Sstevel@tonic-gate int32_t ud_dirmakedirect(struct ud_inode *, struct ud_inode *, struct cred *);
1067c478bd9Sstevel@tonic-gate int32_t ud_dirrename(struct ud_inode *, struct ud_inode *,
1077c478bd9Sstevel@tonic-gate struct ud_inode *, struct ud_inode *, char *, uint8_t *,
1087c478bd9Sstevel@tonic-gate struct slot *, struct cred *);
1097c478bd9Sstevel@tonic-gate int32_t ud_dirprepareentry(struct ud_inode *,
1107c478bd9Sstevel@tonic-gate struct slot *, uint8_t *, struct cred *);
1117c478bd9Sstevel@tonic-gate int32_t ud_dirfixdotdot(struct ud_inode *, struct ud_inode *,
1127c478bd9Sstevel@tonic-gate struct ud_inode *);
1137c478bd9Sstevel@tonic-gate int32_t ud_write_fid(struct ud_inode *, struct slot *, uint8_t *);
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate int
ud_dirlook(struct ud_inode * dip,char * namep,struct ud_inode ** ipp,struct cred * cr,int32_t skipdnlc)1167c478bd9Sstevel@tonic-gate ud_dirlook(struct ud_inode *dip,
1177c478bd9Sstevel@tonic-gate char *namep, struct ud_inode **ipp, struct cred *cr, int32_t skipdnlc)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
1207c478bd9Sstevel@tonic-gate int32_t error = 0, namelen, adhoc_search;
1217c478bd9Sstevel@tonic-gate u_offset_t offset, adhoc_offset, dirsize, end;
1227c478bd9Sstevel@tonic-gate struct vnode *dvp, *vp;
1237c478bd9Sstevel@tonic-gate struct fbuf *fbp;
1247c478bd9Sstevel@tonic-gate struct file_id *fid;
1257c478bd9Sstevel@tonic-gate uint8_t *fname, dummy[3];
1267c478bd9Sstevel@tonic-gate int32_t id_len, doingchk;
1277c478bd9Sstevel@tonic-gate uint32_t old_loc;
1287c478bd9Sstevel@tonic-gate uint16_t old_prn;
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate uint8_t *dname;
1317c478bd9Sstevel@tonic-gate uint8_t *buf = NULL;
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate ud_printf("ud_dirlook\n");
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate udf_vfsp = dip->i_udf;
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate restart:
1387c478bd9Sstevel@tonic-gate doingchk = 0;
1397c478bd9Sstevel@tonic-gate old_prn = 0xFFFF;
1407c478bd9Sstevel@tonic-gate old_loc = 0;
1417c478bd9Sstevel@tonic-gate dvp = ITOV(dip);
1427c478bd9Sstevel@tonic-gate /*
1437c478bd9Sstevel@tonic-gate * Check accessibility of directory.
1447c478bd9Sstevel@tonic-gate */
1457c478bd9Sstevel@tonic-gate if (dip->i_type != VDIR) {
1467c478bd9Sstevel@tonic-gate return (ENOTDIR);
1477c478bd9Sstevel@tonic-gate }
148b39a0235SMilan Cermak if (error = ud_iaccess(dip, IEXEC, cr, 1)) {
1497c478bd9Sstevel@tonic-gate return (error);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate * Null component name is synonym for directory being searched.
1547c478bd9Sstevel@tonic-gate */
1557c478bd9Sstevel@tonic-gate if (*namep == '\0') {
1567c478bd9Sstevel@tonic-gate VN_HOLD(dvp);
1577c478bd9Sstevel@tonic-gate *ipp = dip;
1587c478bd9Sstevel@tonic-gate return (0);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate namelen = strlen(namep);
1617c478bd9Sstevel@tonic-gate if ((namelen == 1) &&
1627c478bd9Sstevel@tonic-gate (namep[0] == '.') && (namep[1] == '\0')) {
1637c478bd9Sstevel@tonic-gate /* Current directory */
1647c478bd9Sstevel@tonic-gate VN_HOLD(dvp);
1657c478bd9Sstevel@tonic-gate *ipp = dip;
1667c478bd9Sstevel@tonic-gate dnlc_enter(dvp, namep, ITOV(*ipp));
1677c478bd9Sstevel@tonic-gate return (0);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate if ((!skipdnlc) && (vp = dnlc_lookup(dvp, namep))) {
1717c478bd9Sstevel@tonic-gate /* vp is already held from dnlc_lookup */
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate *ipp = VTOI(vp);
1747c478bd9Sstevel@tonic-gate return (0);
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate dname = kmem_zalloc(1024, KM_SLEEP);
1787c478bd9Sstevel@tonic-gate buf = kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP);
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate * Read lock the inode we are searching. You will notice that we
1827c478bd9Sstevel@tonic-gate * didn't hold the read lock while searching the dnlc. This means
1837c478bd9Sstevel@tonic-gate * that the entry could now be in the dnlc. This doesn't cause any
1847c478bd9Sstevel@tonic-gate * problems because dnlc_enter won't add an entry if it is already
1857c478bd9Sstevel@tonic-gate * there.
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate rw_enter(&dip->i_rwlock, RW_READER);
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate * Take care to look at dip->i_diroff only once, as it
1917c478bd9Sstevel@tonic-gate * may be changing due to other threads/cpus.
1927c478bd9Sstevel@tonic-gate */
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate recheck:
1957c478bd9Sstevel@tonic-gate offset = dip->i_diroff;
1967c478bd9Sstevel@tonic-gate end = dirsize = dip->i_size;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate if (offset > dirsize) {
1997c478bd9Sstevel@tonic-gate offset = 0;
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate adhoc_offset = offset;
2027c478bd9Sstevel@tonic-gate adhoc_search = (offset == 0) ? 1 : 2;
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate fbp = NULL;
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate while (adhoc_search--) {
2077c478bd9Sstevel@tonic-gate while (offset < end) {
2087c478bd9Sstevel@tonic-gate error = ud_get_next_fid(dip, &fbp,
2097c478bd9Sstevel@tonic-gate offset, &fid, &fname, buf);
2107c478bd9Sstevel@tonic-gate if (error != 0) {
2117c478bd9Sstevel@tonic-gate break;
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate if ((fid->fid_flags & FID_DELETED) == 0) {
2147c478bd9Sstevel@tonic-gate if (fid->fid_flags & FID_PARENT) {
2157c478bd9Sstevel@tonic-gate id_len = 2;
2167c478bd9Sstevel@tonic-gate fname = dummy;
2177c478bd9Sstevel@tonic-gate dummy[0] = '.';
2187c478bd9Sstevel@tonic-gate dummy[1] = '.';
2197c478bd9Sstevel@tonic-gate dummy[2] = '\0';
2207c478bd9Sstevel@tonic-gate } else {
2217c478bd9Sstevel@tonic-gate if ((error = ud_uncompress(
2227c478bd9Sstevel@tonic-gate fid->fid_idlen, &id_len,
2237c478bd9Sstevel@tonic-gate fname, dname)) != 0) {
2247c478bd9Sstevel@tonic-gate break;
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate fname = (uint8_t *)dname;
2277c478bd9Sstevel@tonic-gate fname[id_len] = '\0';
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate if ((namelen == id_len) &&
2307c478bd9Sstevel@tonic-gate (strncmp(namep, (caddr_t)fname,
2317c478bd9Sstevel@tonic-gate namelen) == 0)) {
2327c478bd9Sstevel@tonic-gate uint32_t loc;
2337c478bd9Sstevel@tonic-gate uint16_t prn;
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate loc = SWAP_32(fid->fid_icb.lad_ext_loc);
2377c478bd9Sstevel@tonic-gate prn = SWAP_16(fid->fid_icb.lad_ext_prn);
238b39a0235SMilan Cermak dip->i_diroff = offset + FID_LEN(fid);
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate if (doingchk) {
2417c478bd9Sstevel@tonic-gate if ((loc == old_loc) &&
2427c478bd9Sstevel@tonic-gate (prn == old_prn)) {
2437c478bd9Sstevel@tonic-gate goto checkok;
2447c478bd9Sstevel@tonic-gate } else {
2457c478bd9Sstevel@tonic-gate if (fbp != NULL) {
2467c478bd9Sstevel@tonic-gate fbrelse(fbp,
2477c478bd9Sstevel@tonic-gate S_READ);
2487c478bd9Sstevel@tonic-gate fbp = NULL;
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate VN_RELE(ITOV(*ipp));
2517c478bd9Sstevel@tonic-gate rw_exit(&dip->i_rwlock);
2527c478bd9Sstevel@tonic-gate goto restart;
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate /* NOTREACHED */
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate if (namelen == 2 &&
2587c478bd9Sstevel@tonic-gate fname[0] == '.' &&
2597c478bd9Sstevel@tonic-gate fname[1] == '.') {
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate struct timespec32 omtime;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate omtime = dip->i_mtime;
2647c478bd9Sstevel@tonic-gate rw_exit(&dip->i_rwlock);
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate error = ud_iget(dip->i_vfs, prn,
2677c478bd9Sstevel@tonic-gate loc, ipp, NULL, cr);
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate rw_enter(&dip->i_rwlock,
2707c478bd9Sstevel@tonic-gate RW_READER);
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate if (error) {
2737c478bd9Sstevel@tonic-gate goto done;
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate if ((omtime.tv_sec !=
2777c478bd9Sstevel@tonic-gate dip->i_mtime.tv_sec) ||
2787c478bd9Sstevel@tonic-gate (omtime.tv_nsec !=
2797c478bd9Sstevel@tonic-gate dip->i_mtime.tv_nsec)) {
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate doingchk = 1;
2827c478bd9Sstevel@tonic-gate old_prn = prn;
2837c478bd9Sstevel@tonic-gate old_loc = loc;
2847c478bd9Sstevel@tonic-gate dip->i_diroff = 0;
2857c478bd9Sstevel@tonic-gate if (fbp != NULL) {
2867c478bd9Sstevel@tonic-gate fbrelse(fbp,
2877c478bd9Sstevel@tonic-gate S_READ);
2887c478bd9Sstevel@tonic-gate fbp = NULL;
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate goto recheck;
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate } else {
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate error = ud_iget(dip->i_vfs, prn,
2957c478bd9Sstevel@tonic-gate loc, ipp, NULL, cr);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate checkok:
2987c478bd9Sstevel@tonic-gate if (error == 0) {
2997c478bd9Sstevel@tonic-gate dnlc_enter(dvp, namep,
3007c478bd9Sstevel@tonic-gate ITOV(*ipp));
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate goto done;
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate offset += FID_LEN(fid);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate if (fbp != NULL) {
3087c478bd9Sstevel@tonic-gate fbrelse(fbp, S_READ);
3097c478bd9Sstevel@tonic-gate fbp = NULL;
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate end = adhoc_offset;
3127c478bd9Sstevel@tonic-gate offset = 0;
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate error = ENOENT;
3157c478bd9Sstevel@tonic-gate done:
3167c478bd9Sstevel@tonic-gate kmem_free(buf, udf_vfsp->udf_lbsize);
3177c478bd9Sstevel@tonic-gate kmem_free(dname, 1024);
3187c478bd9Sstevel@tonic-gate if (fbp != NULL) {
3197c478bd9Sstevel@tonic-gate fbrelse(fbp, S_READ);
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate rw_exit(&dip->i_rwlock);
3227c478bd9Sstevel@tonic-gate return (error);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate int
ud_direnter(struct ud_inode * tdp,char * namep,enum de_op op,struct ud_inode * sdp,struct ud_inode * sip,struct vattr * vap,struct ud_inode ** ipp,struct cred * cr,caller_context_t * ctp)326da6c28aaSamw ud_direnter(
327da6c28aaSamw struct ud_inode *tdp,
328da6c28aaSamw char *namep,
329da6c28aaSamw enum de_op op,
330da6c28aaSamw struct ud_inode *sdp,
331da6c28aaSamw struct ud_inode *sip,
332da6c28aaSamw struct vattr *vap,
333da6c28aaSamw struct ud_inode **ipp,
334da6c28aaSamw struct cred *cr,
335da6c28aaSamw caller_context_t *ctp)
3367c478bd9Sstevel@tonic-gate {
3377c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
3387c478bd9Sstevel@tonic-gate struct ud_inode *tip;
3397c478bd9Sstevel@tonic-gate struct slot slot;
3407c478bd9Sstevel@tonic-gate int32_t namlen, err;
3417c478bd9Sstevel@tonic-gate char *s;
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate uint8_t *buf = NULL;
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate ud_printf("ud_direnter\n");
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate udf_vfsp = tdp->i_udf;
3487c478bd9Sstevel@tonic-gate /* don't allow '/' characters in pathname component */
3497c478bd9Sstevel@tonic-gate for (s = namep, namlen = 0; *s; s++, namlen++) {
3507c478bd9Sstevel@tonic-gate if (*s == '/') {
3517c478bd9Sstevel@tonic-gate return (EACCES);
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate if (namlen == 0) {
3567c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "name length == 0 in ud_direnter");
3577c478bd9Sstevel@tonic-gate return (EINVAL);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&tdp->i_rwlock));
3617c478bd9Sstevel@tonic-gate /*
3627c478bd9Sstevel@tonic-gate * If name is "." or ".." then if this is a create look it up
3637c478bd9Sstevel@tonic-gate * and return EEXIST. Rename or link TO "." or ".." is forbidden.
3647c478bd9Sstevel@tonic-gate */
3657c478bd9Sstevel@tonic-gate if (namep[0] == '.' &&
3667c478bd9Sstevel@tonic-gate (namlen == 1 || (namlen == 2 && namep[1] == '.'))) {
3677c478bd9Sstevel@tonic-gate if (op == DE_RENAME) {
3687c478bd9Sstevel@tonic-gate return (EINVAL); /* *SIGH* should be ENOTEMPTY */
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate if (ipp) {
3717c478bd9Sstevel@tonic-gate /*
3727c478bd9Sstevel@tonic-gate * ud_dirlook will acquire the i_rwlock
3737c478bd9Sstevel@tonic-gate */
3747c478bd9Sstevel@tonic-gate rw_exit(&tdp->i_rwlock);
3757c478bd9Sstevel@tonic-gate if (err = ud_dirlook(tdp, namep, ipp, cr, 0)) {
3767c478bd9Sstevel@tonic-gate rw_enter(&tdp->i_rwlock, RW_WRITER);
3777c478bd9Sstevel@tonic-gate return (err);
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate rw_enter(&tdp->i_rwlock, RW_WRITER);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate return (EEXIST);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate tip = NULL;
3857c478bd9Sstevel@tonic-gate slot.status = NONE;
3867c478bd9Sstevel@tonic-gate slot.offset = 0;
3877c478bd9Sstevel@tonic-gate slot.size = 0;
3887c478bd9Sstevel@tonic-gate slot.fbp = NULL;
3897c478bd9Sstevel@tonic-gate slot.ep = NULL;
3907c478bd9Sstevel@tonic-gate slot.endoff = 0;
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate /*
3937c478bd9Sstevel@tonic-gate * For link and rename lock the source entry and check the link count
3947c478bd9Sstevel@tonic-gate * to see if it has been removed while it was unlocked. If not, we
3957c478bd9Sstevel@tonic-gate * increment the link count and force the inode to disk to make sure
3967c478bd9Sstevel@tonic-gate * that it is there before any directory entry that points to it.
3977c478bd9Sstevel@tonic-gate */
3987c478bd9Sstevel@tonic-gate if (op == DE_LINK || op == DE_RENAME) {
3997c478bd9Sstevel@tonic-gate rw_enter(&sip->i_contents, RW_WRITER);
4007c478bd9Sstevel@tonic-gate if (sip->i_nlink == 0) {
4017c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
4027c478bd9Sstevel@tonic-gate return (ENOENT);
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate if (sip->i_nlink == MAXLINK) {
4057c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
4067c478bd9Sstevel@tonic-gate return (EMLINK);
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate sip->i_nlink++;
4107c478bd9Sstevel@tonic-gate mutex_enter(&sip->i_tlock);
4117c478bd9Sstevel@tonic-gate sip->i_flag |= ICHG;
4127c478bd9Sstevel@tonic-gate mutex_exit(&sip->i_tlock);
4137c478bd9Sstevel@tonic-gate ud_iupdat(sip, 1);
4147c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate /*
4177c478bd9Sstevel@tonic-gate * If target directory has not been removed, then we can consider
4187c478bd9Sstevel@tonic-gate * allowing file to be created.
4197c478bd9Sstevel@tonic-gate */
4207c478bd9Sstevel@tonic-gate if (tdp->i_nlink == 0) {
4217c478bd9Sstevel@tonic-gate err = ENOENT;
4227c478bd9Sstevel@tonic-gate goto out2;
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate * Check accessibility of directory.
4267c478bd9Sstevel@tonic-gate */
4277c478bd9Sstevel@tonic-gate if (tdp->i_type != VDIR) {
4287c478bd9Sstevel@tonic-gate err = ENOTDIR;
4297c478bd9Sstevel@tonic-gate goto out2;
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate /*
4327c478bd9Sstevel@tonic-gate * Execute access is required to search the directory.
4337c478bd9Sstevel@tonic-gate */
434b39a0235SMilan Cermak if (err = ud_iaccess(tdp, IEXEC, cr, 1)) {
4357c478bd9Sstevel@tonic-gate goto out2;
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate /*
4387c478bd9Sstevel@tonic-gate * If this is a rename of a directory and the parent is
4397c478bd9Sstevel@tonic-gate * different (".." must be changed), then the source
4407c478bd9Sstevel@tonic-gate * directory must not be in the directory hierarchy
4417c478bd9Sstevel@tonic-gate * above the target, as this would orphan everything
4427c478bd9Sstevel@tonic-gate * below the source directory. Also the user must have
4437c478bd9Sstevel@tonic-gate * write permission in the source so as to be able to
4447c478bd9Sstevel@tonic-gate * change "..".
4457c478bd9Sstevel@tonic-gate */
4467c478bd9Sstevel@tonic-gate if (op == DE_RENAME) {
4477c478bd9Sstevel@tonic-gate if (sip == tdp) {
4487c478bd9Sstevel@tonic-gate err = EINVAL;
4497c478bd9Sstevel@tonic-gate goto out2;
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate rw_enter(&sip->i_contents, RW_READER);
4527c478bd9Sstevel@tonic-gate if ((sip->i_type == VDIR) && (sdp != tdp)) {
4537c478bd9Sstevel@tonic-gate uint32_t blkno;
4547c478bd9Sstevel@tonic-gate
455b39a0235SMilan Cermak if ((err = ud_iaccess(sip, IWRITE, cr, 0))) {
4567c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
4577c478bd9Sstevel@tonic-gate goto out2;
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate blkno = sip->i_icb_lbano;
4607c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
4617c478bd9Sstevel@tonic-gate if ((err = ud_dircheckpath(blkno, tdp, cr))) {
4627c478bd9Sstevel@tonic-gate goto out2;
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate } else {
4657c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate * Search for the entry. Return VN_HELD tip if found.
4717c478bd9Sstevel@tonic-gate */
4727c478bd9Sstevel@tonic-gate buf = kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP);
4737c478bd9Sstevel@tonic-gate rw_enter(&tdp->i_contents, RW_WRITER);
4747c478bd9Sstevel@tonic-gate if (err = ud_dircheckforname(tdp,
4757c478bd9Sstevel@tonic-gate namep, namlen, &slot, &tip, buf, cr)) {
4767c478bd9Sstevel@tonic-gate goto out;
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate if (tip) {
4797c478bd9Sstevel@tonic-gate switch (op) {
4807c478bd9Sstevel@tonic-gate case DE_CREATE :
4817c478bd9Sstevel@tonic-gate case DE_MKDIR :
4827c478bd9Sstevel@tonic-gate if (ipp) {
4837c478bd9Sstevel@tonic-gate *ipp = tip;
4847c478bd9Sstevel@tonic-gate err = EEXIST;
4857c478bd9Sstevel@tonic-gate } else {
4867c478bd9Sstevel@tonic-gate VN_RELE(ITOV(tip));
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate break;
4897c478bd9Sstevel@tonic-gate case DE_RENAME :
4907c478bd9Sstevel@tonic-gate err = ud_dirrename(sdp, sip, tdp, tip,
4917c478bd9Sstevel@tonic-gate namep, buf, &slot, cr);
4927c478bd9Sstevel@tonic-gate /*
4937c478bd9Sstevel@tonic-gate * We used to VN_RELE() here, but this
4947c478bd9Sstevel@tonic-gate * was moved down so that we could send
4957c478bd9Sstevel@tonic-gate * a vnevent after the locks were dropped.
4967c478bd9Sstevel@tonic-gate */
4977c478bd9Sstevel@tonic-gate break;
4987c478bd9Sstevel@tonic-gate case DE_LINK :
4997c478bd9Sstevel@tonic-gate /*
5007c478bd9Sstevel@tonic-gate * Can't link to an existing file.
5017c478bd9Sstevel@tonic-gate */
5027c478bd9Sstevel@tonic-gate VN_RELE(ITOV(tip));
5037c478bd9Sstevel@tonic-gate err = EEXIST;
5047c478bd9Sstevel@tonic-gate break;
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate } else {
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate * The entry does not exist. Check write permission in
5097c478bd9Sstevel@tonic-gate * directory to see if entry can be created.
5107c478bd9Sstevel@tonic-gate */
511b39a0235SMilan Cermak if (err = ud_iaccess(tdp, IWRITE, cr, 0)) {
5127c478bd9Sstevel@tonic-gate goto out;
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate if ((op == DE_CREATE) || (op == DE_MKDIR)) {
5157c478bd9Sstevel@tonic-gate /*
5167c478bd9Sstevel@tonic-gate * Make new inode and directory entry as required.
5177c478bd9Sstevel@tonic-gate */
5187c478bd9Sstevel@tonic-gate if (err = ud_dirmakeinode(tdp, &sip, vap, op, cr))
5197c478bd9Sstevel@tonic-gate goto out;
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate if (err = ud_diraddentry(tdp, namep, op,
5227c478bd9Sstevel@tonic-gate namlen, &slot, sip, sdp, cr)) {
5237c478bd9Sstevel@tonic-gate if ((op == DE_CREATE) || (op == DE_MKDIR)) {
5247c478bd9Sstevel@tonic-gate /*
5257c478bd9Sstevel@tonic-gate * Unmake the inode we just made.
5267c478bd9Sstevel@tonic-gate */
5277c478bd9Sstevel@tonic-gate rw_enter(&sip->i_contents, RW_WRITER);
5287c478bd9Sstevel@tonic-gate if (sip->i_type == VDIR) {
5297c478bd9Sstevel@tonic-gate tdp->i_nlink--;
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate sip->i_nlink = 0;
5327c478bd9Sstevel@tonic-gate mutex_enter(&sip->i_tlock);
5337c478bd9Sstevel@tonic-gate sip->i_flag |= ICHG;
5347c478bd9Sstevel@tonic-gate mutex_exit(&sip->i_tlock);
5357c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
5367c478bd9Sstevel@tonic-gate VN_RELE(ITOV(sip));
5377c478bd9Sstevel@tonic-gate sip = NULL;
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate } else if (ipp) {
5407c478bd9Sstevel@tonic-gate *ipp = sip;
5417c478bd9Sstevel@tonic-gate } else if ((op == DE_CREATE) || (op == DE_MKDIR)) {
5427c478bd9Sstevel@tonic-gate VN_RELE(ITOV(sip));
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate out:
5467c478bd9Sstevel@tonic-gate if (buf != NULL) {
5477c478bd9Sstevel@tonic-gate kmem_free(buf, udf_vfsp->udf_lbsize);
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate if (slot.fbp) {
5507c478bd9Sstevel@tonic-gate fbrelse(slot.fbp, S_OTHER);
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate rw_exit(&tdp->i_contents);
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate if (op == DE_RENAME) {
5557c478bd9Sstevel@tonic-gate /*
5567c478bd9Sstevel@tonic-gate * If it's all good, send events after locks are dropped
5577c478bd9Sstevel@tonic-gate * but before vnodes are released.
5587c478bd9Sstevel@tonic-gate */
5597c478bd9Sstevel@tonic-gate if (err == 0) {
5607c478bd9Sstevel@tonic-gate if (tip) {
561df2381bfSpraks vnevent_rename_dest(ITOV(tip), ITOV(tdp),
562da6c28aaSamw namep, ctp);
5637c478bd9Sstevel@tonic-gate }
564df2381bfSpraks
565df2381bfSpraks if (sdp != tdp) {
566da6c28aaSamw vnevent_rename_dest_dir(ITOV(tdp), ctp);
567df2381bfSpraks }
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate /*
5717c478bd9Sstevel@tonic-gate * The following VN_RELE() was moved from the
5727c478bd9Sstevel@tonic-gate * DE_RENAME case above
5737c478bd9Sstevel@tonic-gate */
5747c478bd9Sstevel@tonic-gate if (tip) {
5757c478bd9Sstevel@tonic-gate VN_RELE(ITOV(tip));
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate
5797c478bd9Sstevel@tonic-gate out2:
5807c478bd9Sstevel@tonic-gate if (err && ((op == DE_LINK) || (op == DE_RENAME))) {
5817c478bd9Sstevel@tonic-gate /*
5827c478bd9Sstevel@tonic-gate * Undo bumped link count.
5837c478bd9Sstevel@tonic-gate */
5847c478bd9Sstevel@tonic-gate rw_enter(&sip->i_contents, RW_WRITER);
5857c478bd9Sstevel@tonic-gate sip->i_nlink--;
5867c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate mutex_enter(&sip->i_tlock);
5897c478bd9Sstevel@tonic-gate sip->i_flag |= ICHG;
5907c478bd9Sstevel@tonic-gate mutex_exit(&sip->i_tlock);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate return (err);
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate /*
5967c478bd9Sstevel@tonic-gate * Locking i_contents in this
5977c478bd9Sstevel@tonic-gate * function seems to be really weird
5987c478bd9Sstevel@tonic-gate */
5997c478bd9Sstevel@tonic-gate int
ud_dirremove(struct ud_inode * dp,char * namep,struct ud_inode * oip,struct vnode * cdir,enum dr_op op,struct cred * cr,caller_context_t * ctp)600da6c28aaSamw ud_dirremove(
601da6c28aaSamw struct ud_inode *dp,
602da6c28aaSamw char *namep,
603da6c28aaSamw struct ud_inode *oip,
604da6c28aaSamw struct vnode *cdir,
605da6c28aaSamw enum dr_op op,
606da6c28aaSamw struct cred *cr,
607da6c28aaSamw caller_context_t *ctp)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
6107c478bd9Sstevel@tonic-gate int32_t namelen, err = 0;
6117c478bd9Sstevel@tonic-gate struct slot slot;
6127c478bd9Sstevel@tonic-gate struct ud_inode *ip;
6137c478bd9Sstevel@tonic-gate mode_t mode;
6147c478bd9Sstevel@tonic-gate struct file_id *fid;
6157c478bd9Sstevel@tonic-gate uint8_t *buf = NULL;
6167c478bd9Sstevel@tonic-gate uint32_t tbno;
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate ud_printf("ud_dirremove\n");
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&dp->i_rwlock));
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate udf_vfsp = dp->i_udf;
6237c478bd9Sstevel@tonic-gate namelen = (int)strlen(namep);
6247c478bd9Sstevel@tonic-gate if (namelen == 0) {
6257c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "name length == 0 in ud_dirremove");
6267c478bd9Sstevel@tonic-gate return (EINVAL);
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate /*
6307c478bd9Sstevel@tonic-gate * return err when removing . and ..
6317c478bd9Sstevel@tonic-gate */
6327c478bd9Sstevel@tonic-gate if (namep[0] == '.') {
6337c478bd9Sstevel@tonic-gate if (namelen == 1) {
6347c478bd9Sstevel@tonic-gate return (EINVAL);
6357c478bd9Sstevel@tonic-gate } else if (namelen == 2 && namep[1] == '.') {
6367c478bd9Sstevel@tonic-gate return (EEXIST); /* SIGH should be ENOTEMPTY */
6377c478bd9Sstevel@tonic-gate }
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&dp->i_rwlock));
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate /*
6437c478bd9Sstevel@tonic-gate * Check accessibility of directory.
6447c478bd9Sstevel@tonic-gate */
6457c478bd9Sstevel@tonic-gate if (dp->i_type != VDIR) {
6467c478bd9Sstevel@tonic-gate return (ENOTDIR);
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate ip = NULL;
6507c478bd9Sstevel@tonic-gate slot.status = FOUND; /* don't need to look for empty slot */
6517c478bd9Sstevel@tonic-gate slot.offset = 0;
6527c478bd9Sstevel@tonic-gate slot.size = 0;
6537c478bd9Sstevel@tonic-gate slot.fbp = NULL;
6547c478bd9Sstevel@tonic-gate slot.ep = NULL;
6557c478bd9Sstevel@tonic-gate slot.endoff = 0;
6567c478bd9Sstevel@tonic-gate /*
6577c478bd9Sstevel@tonic-gate * Execute access is required to search the directory.
6587c478bd9Sstevel@tonic-gate * Access for write is interpreted as allowing
6597c478bd9Sstevel@tonic-gate * deletion of files in the directory.
6607c478bd9Sstevel@tonic-gate */
661b39a0235SMilan Cermak if (err = ud_iaccess(dp, IEXEC|IWRITE, cr, 1)) {
6627c478bd9Sstevel@tonic-gate return (err);
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate buf = (uint8_t *)kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP);
6667c478bd9Sstevel@tonic-gate
6677c478bd9Sstevel@tonic-gate rw_enter(&dp->i_contents, RW_WRITER);
6687c478bd9Sstevel@tonic-gate
669b39a0235SMilan Cermak if (err = ud_dircheckforname(dp, namep, namelen, &slot, &ip,
670b39a0235SMilan Cermak buf, cr)) {
6717c478bd9Sstevel@tonic-gate goto out_novfs;
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate if (ip == NULL) {
6747c478bd9Sstevel@tonic-gate err = ENOENT;
6757c478bd9Sstevel@tonic-gate goto out_novfs;
6767c478bd9Sstevel@tonic-gate }
6777c478bd9Sstevel@tonic-gate if (oip && oip != ip) {
6787c478bd9Sstevel@tonic-gate err = ENOENT;
6797c478bd9Sstevel@tonic-gate goto out_novfs;
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate
6827c478bd9Sstevel@tonic-gate if ((mode = ip->i_type) == VDIR) {
6837c478bd9Sstevel@tonic-gate /*
684d5dbd18dSbatschul * vn_vfswlock() prevents races between mount and rmdir.
6857c478bd9Sstevel@tonic-gate */
686d5dbd18dSbatschul if (vn_vfswlock(ITOV(ip))) {
6877c478bd9Sstevel@tonic-gate err = EBUSY;
6887c478bd9Sstevel@tonic-gate goto out_novfs;
6897c478bd9Sstevel@tonic-gate }
6907c478bd9Sstevel@tonic-gate if (vn_mountedvfs(ITOV(ip)) != NULL && op != DR_RENAME) {
6917c478bd9Sstevel@tonic-gate err = EBUSY;
6927c478bd9Sstevel@tonic-gate goto out;
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate /*
6957c478bd9Sstevel@tonic-gate * If we are removing a directory, get a lock on it.
6967c478bd9Sstevel@tonic-gate * If the directory is empty, it will stay empty until
6977c478bd9Sstevel@tonic-gate * we can remove it.
6987c478bd9Sstevel@tonic-gate */
6997c478bd9Sstevel@tonic-gate rw_enter(&ip->i_rwlock, RW_READER);
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate /* We must be holding i_contents */
7027c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_READER);
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate if (err = ud_sticky_remove_access(dp, ip, cr)) {
7057c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents);
7067c478bd9Sstevel@tonic-gate if (mode == VDIR) {
7077c478bd9Sstevel@tonic-gate rw_exit(&ip->i_rwlock);
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate goto out;
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate if (op == DR_RMDIR) {
7127c478bd9Sstevel@tonic-gate /*
7137c478bd9Sstevel@tonic-gate * For rmdir(2), some special checks are required.
7147c478bd9Sstevel@tonic-gate * (a) Don't remove any alias of the parent (e.g. ".").
7157c478bd9Sstevel@tonic-gate * (b) Don't remove the current directory.
7167c478bd9Sstevel@tonic-gate * (c) Make sure the entry is (still) a directory.
7177c478bd9Sstevel@tonic-gate * (d) Make sure the directory is empty.
7187c478bd9Sstevel@tonic-gate */
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate if (dp == ip || ITOV(ip) == cdir) {
7217c478bd9Sstevel@tonic-gate err = EINVAL;
7227c478bd9Sstevel@tonic-gate } else if (ip->i_type != VDIR) {
7237c478bd9Sstevel@tonic-gate err = ENOTDIR;
7247c478bd9Sstevel@tonic-gate } else if ((ip->i_nlink != 1) ||
7257c478bd9Sstevel@tonic-gate (!ud_dirempty(ip, dp->i_uniqid, cr))) {
7267c478bd9Sstevel@tonic-gate /*
7277c478bd9Sstevel@tonic-gate * Directories do not have an
7287c478bd9Sstevel@tonic-gate * entry for "." so only one link
7297c478bd9Sstevel@tonic-gate * will be there
7307c478bd9Sstevel@tonic-gate */
7317c478bd9Sstevel@tonic-gate err = EEXIST; /* SIGH should be ENOTEMPTY */
7327c478bd9Sstevel@tonic-gate }
7337c478bd9Sstevel@tonic-gate if (err) {
7347c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents);
7357c478bd9Sstevel@tonic-gate if (mode == VDIR) {
7367c478bd9Sstevel@tonic-gate rw_exit(&ip->i_rwlock);
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate goto out;
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate } else if (op == DR_REMOVE) {
7417c478bd9Sstevel@tonic-gate /*
7427c478bd9Sstevel@tonic-gate * unlink(2) requires a different check: allow only
7437c478bd9Sstevel@tonic-gate * privileged processes to unlink a directory.
7447c478bd9Sstevel@tonic-gate */
7457c478bd9Sstevel@tonic-gate struct vnode *vp = ITOV(ip);
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate if (vp->v_type == VDIR &&
7487c478bd9Sstevel@tonic-gate secpolicy_fs_linkdir(cr, vp->v_vfsp)) {
7497c478bd9Sstevel@tonic-gate err = EPERM;
7507c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents);
7517c478bd9Sstevel@tonic-gate rw_exit(&ip->i_rwlock);
7527c478bd9Sstevel@tonic-gate goto out;
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents);
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate /*
7587c478bd9Sstevel@tonic-gate * Remove the cache'd entry, if any.
7597c478bd9Sstevel@tonic-gate */
7607c478bd9Sstevel@tonic-gate dnlc_remove(ITOV(dp), namep);
7617c478bd9Sstevel@tonic-gate
7627c478bd9Sstevel@tonic-gate /*
7637c478bd9Sstevel@tonic-gate * We can collapse all the directory
7647c478bd9Sstevel@tonic-gate * entries that are deleted into one big entry
7657c478bd9Sstevel@tonic-gate * but the better way is to
7667c478bd9Sstevel@tonic-gate * defer it till next directory entry
7677c478bd9Sstevel@tonic-gate * creation. where we can do this
7687c478bd9Sstevel@tonic-gate * in a more efficient way
7697c478bd9Sstevel@tonic-gate */
7707c478bd9Sstevel@tonic-gate fid = slot.ep;
7717c478bd9Sstevel@tonic-gate
7727c478bd9Sstevel@tonic-gate /*
7737c478bd9Sstevel@tonic-gate * If this is the last entry
7747c478bd9Sstevel@tonic-gate * just truncate the file instead
7757c478bd9Sstevel@tonic-gate * of marking it deleted
7767c478bd9Sstevel@tonic-gate */
7777c478bd9Sstevel@tonic-gate if ((slot.offset + FID_LEN(fid)) == dp->i_size) {
7787c478bd9Sstevel@tonic-gate fbrelse(slot.fbp, S_OTHER);
7797c478bd9Sstevel@tonic-gate if ((err = ud_itrunc(dp, slot.offset, 0, cr)) != 0) {
7807c478bd9Sstevel@tonic-gate goto out;
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate } else {
7837c478bd9Sstevel@tonic-gate fid->fid_flags |= FID_DELETED;
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate if ((err = ud_ip_off2bno(dp, slot.offset, &tbno)) != 0) {
7867c478bd9Sstevel@tonic-gate goto out;
7877c478bd9Sstevel@tonic-gate }
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate ud_make_tag(dp->i_udf, &fid->fid_tag,
7907c478bd9Sstevel@tonic-gate UD_FILE_ID_DESC, tbno, FID_LEN(fid));
7917c478bd9Sstevel@tonic-gate
7927c478bd9Sstevel@tonic-gate err = ud_write_fid(dp, &slot, buf);
7937c478bd9Sstevel@tonic-gate }
7947c478bd9Sstevel@tonic-gate
7957c478bd9Sstevel@tonic-gate slot.fbp = NULL;
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate /*
7987c478bd9Sstevel@tonic-gate * If we were removing a directory, it is 'gone' now so we can
7997c478bd9Sstevel@tonic-gate * unlock it.
8007c478bd9Sstevel@tonic-gate */
8017c478bd9Sstevel@tonic-gate if (mode == VDIR) {
8027c478bd9Sstevel@tonic-gate rw_exit(&ip->i_rwlock);
8037c478bd9Sstevel@tonic-gate }
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate mutex_enter(&dp->i_tlock);
8067c478bd9Sstevel@tonic-gate dp->i_flag |= IUPD|ICHG;
8077c478bd9Sstevel@tonic-gate mutex_exit(&dp->i_tlock);
8087c478bd9Sstevel@tonic-gate mutex_enter(&ip->i_tlock);
8097c478bd9Sstevel@tonic-gate ip->i_flag |= ICHG;
8107c478bd9Sstevel@tonic-gate mutex_exit(&ip->i_tlock);
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate if (err != 0) {
8137c478bd9Sstevel@tonic-gate goto out;
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER);
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate * Now dispose of the inode.
8207c478bd9Sstevel@tonic-gate */
8217c478bd9Sstevel@tonic-gate if (ip->i_nlink > 0) {
8227c478bd9Sstevel@tonic-gate if ((op == DR_RMDIR) && (ip->i_type == VDIR)) {
8237c478bd9Sstevel@tonic-gate /*
8247c478bd9Sstevel@tonic-gate * Decrement by 1 because there is no "."
8257c478bd9Sstevel@tonic-gate * Clear the inode, but there may be other hard
8267c478bd9Sstevel@tonic-gate * links so don't free the inode.
8277c478bd9Sstevel@tonic-gate * Decrement the dp linkcount because we're
8287c478bd9Sstevel@tonic-gate * trashing the ".." entry.
8297c478bd9Sstevel@tonic-gate */
8307c478bd9Sstevel@tonic-gate ip->i_nlink --;
8317c478bd9Sstevel@tonic-gate dp->i_nlink--;
8327c478bd9Sstevel@tonic-gate dnlc_remove(ITOV(ip), ".");
8337c478bd9Sstevel@tonic-gate dnlc_remove(ITOV(ip), "..");
8347c478bd9Sstevel@tonic-gate /*
8357c478bd9Sstevel@tonic-gate * (void) ud_itrunc(ip, 0, 0, cr);
8367c478bd9Sstevel@tonic-gate */
8377c478bd9Sstevel@tonic-gate } else {
8387c478bd9Sstevel@tonic-gate ip->i_nlink--;
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate }
8417c478bd9Sstevel@tonic-gate ITIMES_NOLOCK(dp);
8427c478bd9Sstevel@tonic-gate ITIMES_NOLOCK(ip);
8437c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents);
8447c478bd9Sstevel@tonic-gate out:
8457c478bd9Sstevel@tonic-gate if (mode == VDIR) {
8467c478bd9Sstevel@tonic-gate vn_vfsunlock(ITOV(ip));
8477c478bd9Sstevel@tonic-gate }
8487c478bd9Sstevel@tonic-gate out_novfs:
8497c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&dp->i_contents));
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate if (slot.fbp != NULL) {
8527c478bd9Sstevel@tonic-gate fbrelse(slot.fbp, S_OTHER);
8537c478bd9Sstevel@tonic-gate }
8547c478bd9Sstevel@tonic-gate rw_exit(&dp->i_contents);
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate if (ip) {
8577c478bd9Sstevel@tonic-gate /*
8587c478bd9Sstevel@tonic-gate * If no errors, send any events after locks are dropped,
8597c478bd9Sstevel@tonic-gate * but before the VN_RELE().
8607c478bd9Sstevel@tonic-gate */
8617c478bd9Sstevel@tonic-gate if (err == 0) {
8627c478bd9Sstevel@tonic-gate if (op == DR_REMOVE) {
863da6c28aaSamw vnevent_remove(ITOV(ip), ITOV(dp), namep, ctp);
8647c478bd9Sstevel@tonic-gate } else if (op == DR_RMDIR) {
865da6c28aaSamw vnevent_rmdir(ITOV(ip), ITOV(dp), namep, ctp);
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate VN_RELE(ITOV(ip));
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate kmem_free(buf, udf_vfsp->udf_lbsize);
8727c478bd9Sstevel@tonic-gate return (err);
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate int
ud_dircheckforname(struct ud_inode * tdp,char * namep,int32_t namelen,struct slot * slotp,struct ud_inode ** ipp,uint8_t * buf,struct cred * cr)8767c478bd9Sstevel@tonic-gate ud_dircheckforname(struct ud_inode *tdp,
8777c478bd9Sstevel@tonic-gate char *namep, int32_t namelen, struct slot *slotp,
8787c478bd9Sstevel@tonic-gate struct ud_inode **ipp, uint8_t *buf, struct cred *cr)
8797c478bd9Sstevel@tonic-gate {
8807c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
8817c478bd9Sstevel@tonic-gate uint32_t dirsize, offset;
8827c478bd9Sstevel@tonic-gate struct fbuf *fbp;
8837c478bd9Sstevel@tonic-gate struct file_id *fid;
8847c478bd9Sstevel@tonic-gate int32_t sz, error = 0, sz_req, matched = 0;
8857c478bd9Sstevel@tonic-gate uint8_t *nm;
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate uint8_t *dname;
8887c478bd9Sstevel@tonic-gate int32_t id_len;
8897c478bd9Sstevel@tonic-gate
8907c478bd9Sstevel@tonic-gate ud_printf("ud_dircheckforname\n");
8917c478bd9Sstevel@tonic-gate
8927c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&tdp->i_rwlock));
8937c478bd9Sstevel@tonic-gate fbp = NULL;
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate dname = (uint8_t *)kmem_zalloc(1024, KM_SLEEP);
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate udf_vfsp = tdp->i_udf;
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate offset = 0;
9007c478bd9Sstevel@tonic-gate dirsize = tdp->i_size;
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate if (slotp->status != FOUND) {
9037c478bd9Sstevel@tonic-gate int32_t temp;
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate temp = 1024; /* set to size of dname allocated above */
9067c478bd9Sstevel@tonic-gate if ((error = ud_compress(namelen, &temp,
9077c478bd9Sstevel@tonic-gate (uint8_t *)namep, dname)) != 0) {
9087c478bd9Sstevel@tonic-gate goto end;
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate sz_req = F_LEN + temp;
9117c478bd9Sstevel@tonic-gate sz_req = (sz_req + 3) & ~3;
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate while (offset < dirsize) {
9157c478bd9Sstevel@tonic-gate if ((error = ud_get_next_fid(tdp, &fbp,
9167c478bd9Sstevel@tonic-gate offset, &fid, &nm, buf)) != 0) {
9177c478bd9Sstevel@tonic-gate break;
9187c478bd9Sstevel@tonic-gate }
9197c478bd9Sstevel@tonic-gate if ((error = ud_uncompress(fid->fid_idlen,
9207c478bd9Sstevel@tonic-gate &id_len, nm, dname)) != 0) {
9217c478bd9Sstevel@tonic-gate break;
9227c478bd9Sstevel@tonic-gate }
9237c478bd9Sstevel@tonic-gate if ((fid->fid_flags & FID_DELETED) == 0) {
9247c478bd9Sstevel@tonic-gate /* Check for name match */
9257c478bd9Sstevel@tonic-gate if (((namelen == id_len) &&
926b39a0235SMilan Cermak (strncmp(namep, (caddr_t)dname, namelen) == 0)) ||
9277c478bd9Sstevel@tonic-gate ((fid->fid_flags & FID_PARENT) &&
9287c478bd9Sstevel@tonic-gate (namep[0] == '.' &&
9297c478bd9Sstevel@tonic-gate (namelen == 1 ||
9307c478bd9Sstevel@tonic-gate (namelen == 2 && namep[1] == '.'))))) {
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate tdp->i_diroff = offset;
9337c478bd9Sstevel@tonic-gate if ((fid->fid_flags & FID_PARENT) &&
9347c478bd9Sstevel@tonic-gate (namelen == 1) && (namep[0] == '.')) {
9357c478bd9Sstevel@tonic-gate struct vnode *vp = ITOV(tdp);
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate *ipp = tdp;
9387c478bd9Sstevel@tonic-gate VN_HOLD(vp);
9397c478bd9Sstevel@tonic-gate } else {
9407c478bd9Sstevel@tonic-gate uint16_t prn;
9417c478bd9Sstevel@tonic-gate uint32_t loc;
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate prn = SWAP_16(fid->fid_icb.lad_ext_prn);
9447c478bd9Sstevel@tonic-gate loc = SWAP_32(fid->fid_icb.lad_ext_loc);
9457c478bd9Sstevel@tonic-gate if ((error = ud_iget(tdp->i_vfs, prn,
9467c478bd9Sstevel@tonic-gate loc, ipp, NULL, cr)) != 0) {
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate fbrelse(fbp, S_OTHER);
9497c478bd9Sstevel@tonic-gate goto end;
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate }
9527c478bd9Sstevel@tonic-gate slotp->status = EXIST;
9537c478bd9Sstevel@tonic-gate slotp->offset = offset;
9547c478bd9Sstevel@tonic-gate slotp->size = FID_LEN(fid);
9557c478bd9Sstevel@tonic-gate slotp->fbp = fbp;
9567c478bd9Sstevel@tonic-gate slotp->ep = fid;
9577c478bd9Sstevel@tonic-gate slotp->endoff = 0;
9587c478bd9Sstevel@tonic-gate goto end;
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate } else {
9617c478bd9Sstevel@tonic-gate /*
9627c478bd9Sstevel@tonic-gate * see if we need to find an
9637c478bd9Sstevel@tonic-gate * empty slot and the current slot
9647c478bd9Sstevel@tonic-gate * matches
9657c478bd9Sstevel@tonic-gate */
966b39a0235SMilan Cermak if ((slotp->status != FOUND) || (matched == 0)) {
9677c478bd9Sstevel@tonic-gate sz = FID_LEN(fid);
9687c478bd9Sstevel@tonic-gate if (sz == sz_req) {
9697c478bd9Sstevel@tonic-gate slotp->status = FOUND;
9707c478bd9Sstevel@tonic-gate slotp->offset = offset;
9717c478bd9Sstevel@tonic-gate slotp->size = sz;
9727c478bd9Sstevel@tonic-gate }
9737c478bd9Sstevel@tonic-gate if (matched == 0) {
9747c478bd9Sstevel@tonic-gate if ((namelen == id_len) &&
9757c478bd9Sstevel@tonic-gate (strncmp(namep, (caddr_t)dname,
9767c478bd9Sstevel@tonic-gate namelen) == 0)) {
9777c478bd9Sstevel@tonic-gate matched = 1;
9787c478bd9Sstevel@tonic-gate slotp->status = FOUND;
9797c478bd9Sstevel@tonic-gate slotp->offset = offset;
9807c478bd9Sstevel@tonic-gate slotp->size = sz;
9817c478bd9Sstevel@tonic-gate }
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate }
9857c478bd9Sstevel@tonic-gate offset += FID_LEN(fid);
9867c478bd9Sstevel@tonic-gate }
9877c478bd9Sstevel@tonic-gate if (fbp) {
9887c478bd9Sstevel@tonic-gate fbrelse(fbp, S_OTHER);
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate if (slotp->status == NONE) {
9917c478bd9Sstevel@tonic-gate /*
9927c478bd9Sstevel@tonic-gate * We didn't find a slot; the new directory entry should be put
9937c478bd9Sstevel@tonic-gate * at the end of the directory. Return an indication of where
9947c478bd9Sstevel@tonic-gate * this is, and set "endoff" to zero; since we're going to have
9957c478bd9Sstevel@tonic-gate * to extend the directory, we're certainly not going to
9967c478bd9Sstevel@tonic-gate * trucate it.
9977c478bd9Sstevel@tonic-gate */
9987c478bd9Sstevel@tonic-gate slotp->offset = dirsize;
9997c478bd9Sstevel@tonic-gate if (tdp->i_desc_type == ICB_FLAG_ONE_AD) {
10007c478bd9Sstevel@tonic-gate slotp->size = tdp->i_max_emb - tdp->i_size;
10017c478bd9Sstevel@tonic-gate } else {
10027c478bd9Sstevel@tonic-gate slotp->size = udf_vfsp->udf_lbsize -
10037c478bd9Sstevel@tonic-gate slotp->offset & udf_vfsp->udf_lbmask;
10047c478bd9Sstevel@tonic-gate }
10057c478bd9Sstevel@tonic-gate slotp->endoff = 0;
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate
10087c478bd9Sstevel@tonic-gate *ipp = NULL;
10097c478bd9Sstevel@tonic-gate end:
10107c478bd9Sstevel@tonic-gate kmem_free((caddr_t)dname, 1024);
10117c478bd9Sstevel@tonic-gate return (error);
10127c478bd9Sstevel@tonic-gate }
10137c478bd9Sstevel@tonic-gate
10147c478bd9Sstevel@tonic-gate /*
10157c478bd9Sstevel@tonic-gate * Return 1 if the dir has all files
10167c478bd9Sstevel@tonic-gate * deleted except the parent
10177c478bd9Sstevel@tonic-gate * else return 0
10187c478bd9Sstevel@tonic-gate */
10197c478bd9Sstevel@tonic-gate /* ARGSUSED */
10207c478bd9Sstevel@tonic-gate int
ud_dirempty(struct ud_inode * ip,uint64_t ino,struct cred * cr)10217c478bd9Sstevel@tonic-gate ud_dirempty(struct ud_inode *ip, uint64_t ino, struct cred *cr)
10227c478bd9Sstevel@tonic-gate {
10237c478bd9Sstevel@tonic-gate offset_t off;
10247c478bd9Sstevel@tonic-gate int32_t empty = 1, error, count, entry_len, rcount;
10257c478bd9Sstevel@tonic-gate struct file_id *fid;
10267c478bd9Sstevel@tonic-gate caddr_t addr;
10277c478bd9Sstevel@tonic-gate uint32_t tbno;
10287c478bd9Sstevel@tonic-gate int32_t desc_len;
10297c478bd9Sstevel@tonic-gate
10307c478bd9Sstevel@tonic-gate ud_printf("ud_dirempty\n");
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate ASSERT(RW_LOCK_HELD(&ip->i_contents));
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate if (ip->i_size == 0) {
10357c478bd9Sstevel@tonic-gate return (empty);
10367c478bd9Sstevel@tonic-gate }
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate desc_len = 1024;
10397c478bd9Sstevel@tonic-gate addr = kmem_zalloc(desc_len, KM_SLEEP);
10407c478bd9Sstevel@tonic-gate fid = (struct file_id *)addr;
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate for (off = 0; off < ip->i_size; off += entry_len) {
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate /*
10457c478bd9Sstevel@tonic-gate * First read fid
10467c478bd9Sstevel@tonic-gate * and verify checksum
10477c478bd9Sstevel@tonic-gate */
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate rcount = sizeof (struct file_id);
1050b39a0235SMilan Cermak error = ud_rdwri(UIO_READ, FREAD, ip, addr, rcount, off,
10517c478bd9Sstevel@tonic-gate UIO_SYSSPACE, &count, cr);
10527c478bd9Sstevel@tonic-gate if ((error != 0) || (count != 0)) {
10537c478bd9Sstevel@tonic-gate empty = 0;
10547c478bd9Sstevel@tonic-gate break;
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate if ((error = ud_ip_off2bno(ip, off, &tbno)) != 0) {
10587c478bd9Sstevel@tonic-gate empty = 0;
10597c478bd9Sstevel@tonic-gate break;
10607c478bd9Sstevel@tonic-gate }
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate /*
10637c478bd9Sstevel@tonic-gate * We verify the tag id and also the FID_LEN.
10647c478bd9Sstevel@tonic-gate * FID_LEN should be <= desc_len.
10657c478bd9Sstevel@tonic-gate */
10667c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&fid->fid_tag,
10677c478bd9Sstevel@tonic-gate UD_FILE_ID_DESC,
10687c478bd9Sstevel@tonic-gate tbno, 0, desc_len) != 0) {
10697c478bd9Sstevel@tonic-gate /* Corrupted directory */
10707c478bd9Sstevel@tonic-gate empty = 0;
10717c478bd9Sstevel@tonic-gate break;
10727c478bd9Sstevel@tonic-gate }
10737c478bd9Sstevel@tonic-gate
10747c478bd9Sstevel@tonic-gate /*
10757c478bd9Sstevel@tonic-gate * Read the fid + iulen + len
10767c478bd9Sstevel@tonic-gate * Now verify both checksum andCRC
10777c478bd9Sstevel@tonic-gate */
10787c478bd9Sstevel@tonic-gate
10797c478bd9Sstevel@tonic-gate rcount = FID_LEN(fid);
1080b39a0235SMilan Cermak error = ud_rdwri(UIO_READ, FREAD, ip, addr, rcount, off,
10817c478bd9Sstevel@tonic-gate UIO_SYSSPACE, &count, cr);
10827c478bd9Sstevel@tonic-gate if ((error != 0) || (count != 0)) {
10837c478bd9Sstevel@tonic-gate empty = 0;
10847c478bd9Sstevel@tonic-gate break;
10857c478bd9Sstevel@tonic-gate }
10867c478bd9Sstevel@tonic-gate /*
10877c478bd9Sstevel@tonic-gate * Now that the entire decsriptor is read we verify the
10887c478bd9Sstevel@tonic-gate * crc.
10897c478bd9Sstevel@tonic-gate */
10907c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&fid->fid_tag,
10917c478bd9Sstevel@tonic-gate UD_FILE_ID_DESC,
10927c478bd9Sstevel@tonic-gate tbno,
10937c478bd9Sstevel@tonic-gate 1, rcount) != 0) {
10947c478bd9Sstevel@tonic-gate /* Corrupted directory */
10957c478bd9Sstevel@tonic-gate empty = 0;
10967c478bd9Sstevel@tonic-gate break;
10977c478bd9Sstevel@tonic-gate }
10987c478bd9Sstevel@tonic-gate
10997c478bd9Sstevel@tonic-gate /*
11007c478bd9Sstevel@tonic-gate * Is the file deleted
11017c478bd9Sstevel@tonic-gate */
11027c478bd9Sstevel@tonic-gate
11037c478bd9Sstevel@tonic-gate if ((fid->fid_flags & FID_DELETED) == 0) {
11047c478bd9Sstevel@tonic-gate if ((fid->fid_flags & FID_PARENT) == 0) {
11057c478bd9Sstevel@tonic-gate empty = 0;
11067c478bd9Sstevel@tonic-gate break;
11077c478bd9Sstevel@tonic-gate }
11087c478bd9Sstevel@tonic-gate }
11097c478bd9Sstevel@tonic-gate entry_len = FID_LEN(fid);
11107c478bd9Sstevel@tonic-gate }
11117c478bd9Sstevel@tonic-gate
11127c478bd9Sstevel@tonic-gate kmem_free(addr, 1024);
11137c478bd9Sstevel@tonic-gate
11147c478bd9Sstevel@tonic-gate return (empty);
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate
11187c478bd9Sstevel@tonic-gate int
ud_dircheckpath(int32_t blkno,struct ud_inode * target,struct cred * cr)11197c478bd9Sstevel@tonic-gate ud_dircheckpath(int32_t blkno,
11207c478bd9Sstevel@tonic-gate struct ud_inode *target, struct cred *cr)
11217c478bd9Sstevel@tonic-gate {
11227c478bd9Sstevel@tonic-gate int32_t err = 0;
11237c478bd9Sstevel@tonic-gate struct vfs *vfsp;
11247c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
11257c478bd9Sstevel@tonic-gate struct fbuf *fbp;
11267c478bd9Sstevel@tonic-gate struct file_id *fid;
11277c478bd9Sstevel@tonic-gate struct ud_inode *ip, *tip;
11287c478bd9Sstevel@tonic-gate uint16_t prn;
11297c478bd9Sstevel@tonic-gate uint32_t lbno, dummy, tbno;
11307c478bd9Sstevel@tonic-gate daddr_t parent_icb_loc;
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate ud_printf("ud_dircheckpath\n");
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate udf_vfsp = target->i_udf;
11357c478bd9Sstevel@tonic-gate ip = target;
11367c478bd9Sstevel@tonic-gate
11377c478bd9Sstevel@tonic-gate ASSERT(udf_vfsp != NULL);
11387c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&target->i_udf->udf_rename_lck));
11397c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&ip->i_rwlock));
11407c478bd9Sstevel@tonic-gate
11417c478bd9Sstevel@tonic-gate if (ip->i_icb_lbano == blkno) {
11427c478bd9Sstevel@tonic-gate err = EINVAL;
11437c478bd9Sstevel@tonic-gate goto out;
11447c478bd9Sstevel@tonic-gate }
11457c478bd9Sstevel@tonic-gate if (ip->i_icb_lbano == udf_vfsp->udf_root_blkno) {
11467c478bd9Sstevel@tonic-gate goto out;
11477c478bd9Sstevel@tonic-gate }
11487c478bd9Sstevel@tonic-gate
11497c478bd9Sstevel@tonic-gate /*
11507c478bd9Sstevel@tonic-gate * Search back through the directory tree, using the PARENT entries
11517c478bd9Sstevel@tonic-gate * Fail any attempt to move a directory into an ancestor directory.
11527c478bd9Sstevel@tonic-gate */
11537c478bd9Sstevel@tonic-gate for (;;) {
11547c478bd9Sstevel@tonic-gate if ((err = fbread(ITOV(ip), 0,
11557c478bd9Sstevel@tonic-gate udf_vfsp->udf_lbsize, S_READ, &fbp)) != 0) {
11567c478bd9Sstevel@tonic-gate break;
11577c478bd9Sstevel@tonic-gate }
11587c478bd9Sstevel@tonic-gate
11597c478bd9Sstevel@tonic-gate if ((err = ud_ip_off2bno(ip, 0, &tbno)) != 0) {
11607c478bd9Sstevel@tonic-gate break;
11617c478bd9Sstevel@tonic-gate }
11627c478bd9Sstevel@tonic-gate fid = (struct file_id *)fbp->fb_addr;
11637c478bd9Sstevel@tonic-gate /* IS this a valid file_identifier */
11647c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&fid->fid_tag,
11657c478bd9Sstevel@tonic-gate UD_FILE_ID_DESC,
11667c478bd9Sstevel@tonic-gate tbno,
11677c478bd9Sstevel@tonic-gate 1, udf_vfsp->udf_lbsize) != 0) {
11687c478bd9Sstevel@tonic-gate break;
11697c478bd9Sstevel@tonic-gate }
11707c478bd9Sstevel@tonic-gate if ((fid->fid_flags & FID_DELETED) != 0) {
11717c478bd9Sstevel@tonic-gate break;
11727c478bd9Sstevel@tonic-gate }
11737c478bd9Sstevel@tonic-gate if ((fid->fid_flags & FID_PARENT) == 0) {
11747c478bd9Sstevel@tonic-gate /*
11757c478bd9Sstevel@tonic-gate * This cannot happen unless
11767c478bd9Sstevel@tonic-gate * something is grossly wrong
11777c478bd9Sstevel@tonic-gate * First entry has to be parent
11787c478bd9Sstevel@tonic-gate */
11797c478bd9Sstevel@tonic-gate break;
11807c478bd9Sstevel@tonic-gate }
11817c478bd9Sstevel@tonic-gate prn = SWAP_16(fid->fid_icb.lad_ext_prn);
11827c478bd9Sstevel@tonic-gate lbno = SWAP_32(fid->fid_icb.lad_ext_loc);
1183b39a0235SMilan Cermak parent_icb_loc =
1184b39a0235SMilan Cermak ud_xlate_to_daddr(udf_vfsp, prn, lbno, 1, &dummy);
11857c478bd9Sstevel@tonic-gate ASSERT(dummy == 1);
11867c478bd9Sstevel@tonic-gate if (parent_icb_loc == blkno) {
11877c478bd9Sstevel@tonic-gate err = EINVAL;
11887c478bd9Sstevel@tonic-gate break;
11897c478bd9Sstevel@tonic-gate }
11907c478bd9Sstevel@tonic-gate vfsp = ip->i_vfs;
11917c478bd9Sstevel@tonic-gate udf_vfsp = ip->i_udf;
11927c478bd9Sstevel@tonic-gate if (parent_icb_loc == udf_vfsp->udf_root_blkno) {
11937c478bd9Sstevel@tonic-gate break;
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate if (fbp != NULL) {
11967c478bd9Sstevel@tonic-gate fbrelse(fbp, S_OTHER);
11977c478bd9Sstevel@tonic-gate fbp = NULL;
11987c478bd9Sstevel@tonic-gate }
11997c478bd9Sstevel@tonic-gate if (ip != target) {
12007c478bd9Sstevel@tonic-gate rw_exit(&ip->i_rwlock);
12017c478bd9Sstevel@tonic-gate VN_RELE(ITOV(ip));
12027c478bd9Sstevel@tonic-gate }
12037c478bd9Sstevel@tonic-gate
12047c478bd9Sstevel@tonic-gate /*
12057c478bd9Sstevel@tonic-gate * Race to get the inode.
12067c478bd9Sstevel@tonic-gate */
12077c478bd9Sstevel@tonic-gate if (err = ud_iget(vfsp, prn, lbno, &tip, NULL, cr)) {
12087c478bd9Sstevel@tonic-gate ip = NULL;
12097c478bd9Sstevel@tonic-gate break;
12107c478bd9Sstevel@tonic-gate }
12117c478bd9Sstevel@tonic-gate ip = tip;
12127c478bd9Sstevel@tonic-gate rw_enter(&ip->i_rwlock, RW_READER);
12137c478bd9Sstevel@tonic-gate }
12147c478bd9Sstevel@tonic-gate if (fbp) {
12157c478bd9Sstevel@tonic-gate fbrelse(fbp, S_OTHER);
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate out:
12187c478bd9Sstevel@tonic-gate if (ip) {
12197c478bd9Sstevel@tonic-gate if (ip != target) {
12207c478bd9Sstevel@tonic-gate rw_exit(&ip->i_rwlock);
12217c478bd9Sstevel@tonic-gate VN_RELE(ITOV(ip));
12227c478bd9Sstevel@tonic-gate }
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate return (err);
12257c478bd9Sstevel@tonic-gate }
12267c478bd9Sstevel@tonic-gate
12277c478bd9Sstevel@tonic-gate int
ud_dirmakeinode(struct ud_inode * tdp,struct ud_inode ** ipp,struct vattr * vap,enum de_op op,struct cred * cr)12287c478bd9Sstevel@tonic-gate ud_dirmakeinode(struct ud_inode *tdp, struct ud_inode **ipp,
12297c478bd9Sstevel@tonic-gate struct vattr *vap, enum de_op op, struct cred *cr)
12307c478bd9Sstevel@tonic-gate {
12317c478bd9Sstevel@tonic-gate struct ud_inode *ip;
12327c478bd9Sstevel@tonic-gate int32_t error;
12337c478bd9Sstevel@tonic-gate
12347c478bd9Sstevel@tonic-gate ASSERT(vap != NULL);
12357c478bd9Sstevel@tonic-gate ASSERT(op == DE_CREATE || op == DE_MKDIR);
12367c478bd9Sstevel@tonic-gate ASSERT((vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE));
12377c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&tdp->i_rwlock));
12387c478bd9Sstevel@tonic-gate
12397c478bd9Sstevel@tonic-gate /*
12407c478bd9Sstevel@tonic-gate * Allocate a new inode.
12417c478bd9Sstevel@tonic-gate */
12427c478bd9Sstevel@tonic-gate if ((error = ud_ialloc(tdp, &ip, vap, cr)) != 0) {
12437c478bd9Sstevel@tonic-gate return (error);
12447c478bd9Sstevel@tonic-gate }
12457c478bd9Sstevel@tonic-gate
12467c478bd9Sstevel@tonic-gate ASSERT(ip != NULL);
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER);
12497c478bd9Sstevel@tonic-gate
12507c478bd9Sstevel@tonic-gate if (op == DE_MKDIR) {
12517c478bd9Sstevel@tonic-gate error = ud_dirmakedirect(ip, tdp, cr);
12527c478bd9Sstevel@tonic-gate }
12537c478bd9Sstevel@tonic-gate
12547c478bd9Sstevel@tonic-gate ip->i_flag |= IACC|IUPD|ICHG;
12557c478bd9Sstevel@tonic-gate /*
12567c478bd9Sstevel@tonic-gate * Clear IACC and/or IUPD if the caller specified the atime and/or
12577c478bd9Sstevel@tonic-gate * mtime fields. They were set from the passed in attributes in
12587c478bd9Sstevel@tonic-gate * ud_ialloc().
12597c478bd9Sstevel@tonic-gate */
12607c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_ATIME)
12617c478bd9Sstevel@tonic-gate ip->i_flag &= ~IACC;
12627c478bd9Sstevel@tonic-gate if (vap->va_mask & AT_MTIME)
12637c478bd9Sstevel@tonic-gate ip->i_flag &= ~IUPD;
12647c478bd9Sstevel@tonic-gate /*
12657c478bd9Sstevel@tonic-gate * push inode before it's name appears in a directory
12667c478bd9Sstevel@tonic-gate */
12677c478bd9Sstevel@tonic-gate ud_iupdat(ip, 1);
12687c478bd9Sstevel@tonic-gate *ipp = ip;
12697c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents);
12707c478bd9Sstevel@tonic-gate return (error);
12717c478bd9Sstevel@tonic-gate }
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate /*
12747c478bd9Sstevel@tonic-gate * Enter the file sip in the directory tdp with name namep.
12757c478bd9Sstevel@tonic-gate */
12767c478bd9Sstevel@tonic-gate int
ud_diraddentry(struct ud_inode * tdp,char * namep,enum de_op op,int32_t namelen,struct slot * slotp,struct ud_inode * sip,struct ud_inode * sdp,struct cred * cr)12777c478bd9Sstevel@tonic-gate ud_diraddentry(struct ud_inode *tdp, char *namep,
12787c478bd9Sstevel@tonic-gate enum de_op op, int32_t namelen, struct slot *slotp,
12797c478bd9Sstevel@tonic-gate struct ud_inode *sip, struct ud_inode *sdp, struct cred *cr)
12807c478bd9Sstevel@tonic-gate {
12817c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
12827c478bd9Sstevel@tonic-gate int32_t error, temp;
12837c478bd9Sstevel@tonic-gate struct file_id *fid;
12847c478bd9Sstevel@tonic-gate uint8_t *buf = NULL;
12857c478bd9Sstevel@tonic-gate
12867c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&tdp->i_rwlock));
12877c478bd9Sstevel@tonic-gate
12887c478bd9Sstevel@tonic-gate ud_printf("ud_diraddentry\n");
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate udf_vfsp = sip->i_udf;
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate /*
12937c478bd9Sstevel@tonic-gate * Check inode to be linked to see if it is in the
12947c478bd9Sstevel@tonic-gate * same filesystem.
12957c478bd9Sstevel@tonic-gate */
12967c478bd9Sstevel@tonic-gate if (ITOV(tdp)->v_vfsp != ITOV(sip)->v_vfsp) {
12977c478bd9Sstevel@tonic-gate error = EXDEV;
12987c478bd9Sstevel@tonic-gate goto bad;
12997c478bd9Sstevel@tonic-gate }
13007c478bd9Sstevel@tonic-gate
13017c478bd9Sstevel@tonic-gate if ((op == DE_RENAME) && (sip->i_type == VDIR)) {
13027c478bd9Sstevel@tonic-gate if ((error = ud_dirfixdotdot(sip, sdp, tdp)) != 0) {
13037c478bd9Sstevel@tonic-gate goto bad;
13047c478bd9Sstevel@tonic-gate }
13057c478bd9Sstevel@tonic-gate }
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate buf = (uint8_t *)kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP);
13087c478bd9Sstevel@tonic-gate
13097c478bd9Sstevel@tonic-gate /*
13107c478bd9Sstevel@tonic-gate * Fill in entry data.
13117c478bd9Sstevel@tonic-gate */
13127c478bd9Sstevel@tonic-gate fid = (struct file_id *)buf;
13137c478bd9Sstevel@tonic-gate fid->fid_ver = SWAP_16(1);
13147c478bd9Sstevel@tonic-gate if (sip->i_type == VDIR) {
13157c478bd9Sstevel@tonic-gate fid->fid_flags = FID_DIR;
13167c478bd9Sstevel@tonic-gate } else {
13177c478bd9Sstevel@tonic-gate fid->fid_flags = 0;
13187c478bd9Sstevel@tonic-gate }
13197c478bd9Sstevel@tonic-gate fid->fid_iulen = 0;
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_len = SWAP_32(sip->i_udf->udf_lbsize);
13227c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_loc = SWAP_32(sip->i_icb_block);
13237c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_prn = SWAP_16(sip->i_icb_prn);
13247c478bd9Sstevel@tonic-gate fid->fid_iulen = 0;
13257c478bd9Sstevel@tonic-gate
1326*a777837dSMilan Cermak temp = MIN(udf_vfsp->udf_lbsize - F_LEN, MAXNAMELEN);
13277c478bd9Sstevel@tonic-gate if ((error = ud_compress(namelen, &temp,
13287c478bd9Sstevel@tonic-gate (uint8_t *)namep, fid->fid_spec)) == 0) {
13297c478bd9Sstevel@tonic-gate fid->fid_idlen = (uint8_t)temp;
13307c478bd9Sstevel@tonic-gate error = ud_dirprepareentry(tdp, slotp, buf, cr);
13317c478bd9Sstevel@tonic-gate }
13327c478bd9Sstevel@tonic-gate
13337c478bd9Sstevel@tonic-gate kmem_free(buf, udf_vfsp->udf_lbsize);
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate bad:
13367c478bd9Sstevel@tonic-gate return (error);
13377c478bd9Sstevel@tonic-gate }
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate /*
13407c478bd9Sstevel@tonic-gate * Write a prototype directory into the empty inode ip, whose parent is dp.
13417c478bd9Sstevel@tonic-gate */
13427c478bd9Sstevel@tonic-gate /* ARGSUSED2 */
13437c478bd9Sstevel@tonic-gate int
ud_dirmakedirect(struct ud_inode * ip,struct ud_inode * dp,struct cred * cr)13447c478bd9Sstevel@tonic-gate ud_dirmakedirect(struct ud_inode *ip,
13457c478bd9Sstevel@tonic-gate struct ud_inode *dp, struct cred *cr)
13467c478bd9Sstevel@tonic-gate {
13477c478bd9Sstevel@tonic-gate int32_t err;
13487c478bd9Sstevel@tonic-gate uint32_t blkno, size, parent_len, tbno;
13497c478bd9Sstevel@tonic-gate struct fbuf *fbp;
13507c478bd9Sstevel@tonic-gate struct file_id *fid;
13517c478bd9Sstevel@tonic-gate struct icb_ext *iext;
13527c478bd9Sstevel@tonic-gate
13537c478bd9Sstevel@tonic-gate ud_printf("ud_dirmakedirect\n");
13547c478bd9Sstevel@tonic-gate
13557c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&ip->i_contents));
13567c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&dp->i_rwlock));
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate parent_len = sizeof (struct file_id);
13597c478bd9Sstevel@tonic-gate
13607c478bd9Sstevel@tonic-gate if ((ip->i_desc_type != ICB_FLAG_ONE_AD) ||
13617c478bd9Sstevel@tonic-gate (parent_len > ip->i_max_emb)) {
13627c478bd9Sstevel@tonic-gate ASSERT(ip->i_ext);
13637c478bd9Sstevel@tonic-gate /*
13647c478bd9Sstevel@tonic-gate * Allocate space for the directory we're creating.
13657c478bd9Sstevel@tonic-gate */
13667c478bd9Sstevel@tonic-gate if ((err = ud_alloc_space(ip->i_vfs, ip->i_icb_prn,
13677c478bd9Sstevel@tonic-gate 0, 1, &blkno, &size, 0, 0)) != 0) {
13687c478bd9Sstevel@tonic-gate return (err);
13697c478bd9Sstevel@tonic-gate }
13707c478bd9Sstevel@tonic-gate /*
13717c478bd9Sstevel@tonic-gate * init with the size of
13727c478bd9Sstevel@tonic-gate * directory with just the
13737c478bd9Sstevel@tonic-gate * parent
13747c478bd9Sstevel@tonic-gate */
13757c478bd9Sstevel@tonic-gate ip->i_size = sizeof (struct file_id);
13767c478bd9Sstevel@tonic-gate ip->i_flag |= IUPD|ICHG|IATTCHG;
13777c478bd9Sstevel@tonic-gate iext = ip->i_ext;
13787c478bd9Sstevel@tonic-gate iext->ib_prn = ip->i_icb_prn;
13797c478bd9Sstevel@tonic-gate iext->ib_block = blkno;
13807c478bd9Sstevel@tonic-gate iext->ib_count = ip->i_size;
13817c478bd9Sstevel@tonic-gate iext->ib_offset = 0;
13827c478bd9Sstevel@tonic-gate ip->i_ext_used = 1;
13837c478bd9Sstevel@tonic-gate } else {
13847c478bd9Sstevel@tonic-gate ip->i_size = sizeof (struct file_id);
13857c478bd9Sstevel@tonic-gate ip->i_flag |= IUPD|ICHG|IATTCHG;
13867c478bd9Sstevel@tonic-gate }
13877c478bd9Sstevel@tonic-gate
13887c478bd9Sstevel@tonic-gate ITIMES_NOLOCK(ip);
13897c478bd9Sstevel@tonic-gate
13907c478bd9Sstevel@tonic-gate /*
13917c478bd9Sstevel@tonic-gate * Update the dp link count and write out the change.
13927c478bd9Sstevel@tonic-gate * This reflects the ".." entry we'll soon write.
13937c478bd9Sstevel@tonic-gate */
13947c478bd9Sstevel@tonic-gate if (dp->i_nlink == MAXLINK) {
13957c478bd9Sstevel@tonic-gate return (EMLINK);
13967c478bd9Sstevel@tonic-gate }
13977c478bd9Sstevel@tonic-gate dp->i_nlink++;
13987c478bd9Sstevel@tonic-gate dp->i_flag |= ICHG;
13997c478bd9Sstevel@tonic-gate ud_iupdat(dp, 1);
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate /*
14027c478bd9Sstevel@tonic-gate * Initialize directory with ".."
14037c478bd9Sstevel@tonic-gate * Since the parent directory is locked, we don't have to
14047c478bd9Sstevel@tonic-gate * worry about anything changing when we drop the write
14057c478bd9Sstevel@tonic-gate * lock on (ip).
14067c478bd9Sstevel@tonic-gate */
14077c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents);
14087c478bd9Sstevel@tonic-gate if ((err = fbread(ITOV(ip), (offset_t)0,
14097c478bd9Sstevel@tonic-gate ip->i_udf->udf_lbsize, S_WRITE, &fbp)) != 0) {
14107c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER);
14117c478bd9Sstevel@tonic-gate return (err);
14127c478bd9Sstevel@tonic-gate }
14137c478bd9Sstevel@tonic-gate
14147c478bd9Sstevel@tonic-gate bzero(fbp->fb_addr, ip->i_udf->udf_lbsize);
14157c478bd9Sstevel@tonic-gate
14167c478bd9Sstevel@tonic-gate fid = (struct file_id *)fbp->fb_addr;
14177c478bd9Sstevel@tonic-gate fid->fid_ver = SWAP_16(1);
14187c478bd9Sstevel@tonic-gate fid->fid_flags = FID_DIR | FID_PARENT;
14197c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_len = SWAP_32(dp->i_udf->udf_lbsize);
14207c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_loc = SWAP_32(dp->i_icb_block);
14217c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_prn = SWAP_16(dp->i_icb_prn);
14227c478bd9Sstevel@tonic-gate
14237c478bd9Sstevel@tonic-gate /*
14247c478bd9Sstevel@tonic-gate * fid_idlen, fid_iulen and fid_spec are zero
14257c478bd9Sstevel@tonic-gate * due to bzero above
14267c478bd9Sstevel@tonic-gate */
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate if ((err = ud_ip_off2bno(ip, 0, &tbno)) == 0) {
14297c478bd9Sstevel@tonic-gate ud_make_tag(ip->i_udf, &fid->fid_tag,
14307c478bd9Sstevel@tonic-gate UD_FILE_ID_DESC, tbno, FID_LEN(fid));
14317c478bd9Sstevel@tonic-gate }
14327c478bd9Sstevel@tonic-gate
14337c478bd9Sstevel@tonic-gate err = ud_fbwrite(fbp, ip);
14347c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER);
14357c478bd9Sstevel@tonic-gate
14367c478bd9Sstevel@tonic-gate return (err);
14377c478bd9Sstevel@tonic-gate }
14387c478bd9Sstevel@tonic-gate
14397c478bd9Sstevel@tonic-gate int
ud_dirrename(struct ud_inode * sdp,struct ud_inode * sip,struct ud_inode * tdp,struct ud_inode * tip,char * namep,uint8_t * buf,struct slot * slotp,struct cred * cr)14407c478bd9Sstevel@tonic-gate ud_dirrename(struct ud_inode *sdp, struct ud_inode *sip,
14417c478bd9Sstevel@tonic-gate struct ud_inode *tdp, struct ud_inode *tip, char *namep,
14427c478bd9Sstevel@tonic-gate uint8_t *buf, struct slot *slotp, struct cred *cr)
14437c478bd9Sstevel@tonic-gate {
14447c478bd9Sstevel@tonic-gate int32_t error = 0, doingdirectory;
14457c478bd9Sstevel@tonic-gate struct file_id *fid;
14467c478bd9Sstevel@tonic-gate
14477c478bd9Sstevel@tonic-gate ud_printf("ud_dirrename\n");
14487c478bd9Sstevel@tonic-gate ASSERT(sdp->i_udf != NULL);
14497c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&sdp->i_udf->udf_rename_lck));
14507c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&tdp->i_rwlock));
1451b39a0235SMilan Cermak ASSERT(RW_WRITE_HELD(&tdp->i_contents));
14527c478bd9Sstevel@tonic-gate ASSERT(buf);
14537c478bd9Sstevel@tonic-gate ASSERT(slotp->ep);
14547c478bd9Sstevel@tonic-gate
14557c478bd9Sstevel@tonic-gate fid = slotp->ep;
14567c478bd9Sstevel@tonic-gate
14577c478bd9Sstevel@tonic-gate /*
14587c478bd9Sstevel@tonic-gate * Short circuit rename of something to itself.
14597c478bd9Sstevel@tonic-gate */
14607c478bd9Sstevel@tonic-gate if (sip->i_icb_lbano == tip->i_icb_lbano) {
14617c478bd9Sstevel@tonic-gate return (ESAME); /* special KLUDGE error code */
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate /*
14647c478bd9Sstevel@tonic-gate * Everything is protected under the vfs_rename_lock so the ordering
14657c478bd9Sstevel@tonic-gate * of i_contents locks doesn't matter here.
14667c478bd9Sstevel@tonic-gate */
14677c478bd9Sstevel@tonic-gate rw_enter(&sip->i_contents, RW_READER);
14687c478bd9Sstevel@tonic-gate rw_enter(&tip->i_contents, RW_READER);
14697c478bd9Sstevel@tonic-gate
14707c478bd9Sstevel@tonic-gate /*
14717c478bd9Sstevel@tonic-gate * Check that everything is on the same filesystem.
14727c478bd9Sstevel@tonic-gate */
14737c478bd9Sstevel@tonic-gate if ((ITOV(tip)->v_vfsp != ITOV(tdp)->v_vfsp) ||
14747c478bd9Sstevel@tonic-gate (ITOV(tip)->v_vfsp != ITOV(sip)->v_vfsp)) {
14757c478bd9Sstevel@tonic-gate error = EXDEV; /* XXX archaic */
14767c478bd9Sstevel@tonic-gate goto out;
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate
14797c478bd9Sstevel@tonic-gate /*
14807c478bd9Sstevel@tonic-gate * Must have write permission to rewrite target entry.
14817c478bd9Sstevel@tonic-gate */
1482b39a0235SMilan Cermak if ((error = ud_iaccess(tdp, IWRITE, cr, 0)) != 0 ||
14837c478bd9Sstevel@tonic-gate (error = ud_sticky_remove_access(tdp, tip, cr)) != 0)
14847c478bd9Sstevel@tonic-gate goto out;
14857c478bd9Sstevel@tonic-gate
14867c478bd9Sstevel@tonic-gate /*
14877c478bd9Sstevel@tonic-gate * Ensure source and target are compatible (both directories
14887c478bd9Sstevel@tonic-gate * or both not directories). If target is a directory it must
14897c478bd9Sstevel@tonic-gate * be empty and have no links to it; in addition it must not
14907c478bd9Sstevel@tonic-gate * be a mount point, and both the source and target must be
14917c478bd9Sstevel@tonic-gate * writable.
14927c478bd9Sstevel@tonic-gate */
14937c478bd9Sstevel@tonic-gate doingdirectory = (sip->i_type == VDIR);
14947c478bd9Sstevel@tonic-gate if (tip->i_type == VDIR) {
14957c478bd9Sstevel@tonic-gate if (!doingdirectory) {
14967c478bd9Sstevel@tonic-gate error = EISDIR;
14977c478bd9Sstevel@tonic-gate goto out;
14987c478bd9Sstevel@tonic-gate }
14997c478bd9Sstevel@tonic-gate /*
1500d5dbd18dSbatschul * vn_vfswlock will prevent mounts from using the directory
1501d5dbd18dSbatschul * until we are done.
15027c478bd9Sstevel@tonic-gate */
1503d5dbd18dSbatschul if (vn_vfswlock(ITOV(tip))) {
15047c478bd9Sstevel@tonic-gate error = EBUSY;
15057c478bd9Sstevel@tonic-gate goto out;
15067c478bd9Sstevel@tonic-gate }
15077c478bd9Sstevel@tonic-gate if (vn_mountedvfs(ITOV(tip)) != NULL) {
15087c478bd9Sstevel@tonic-gate vn_vfsunlock(ITOV(tip));
15097c478bd9Sstevel@tonic-gate error = EBUSY;
15107c478bd9Sstevel@tonic-gate goto out;
15117c478bd9Sstevel@tonic-gate }
15127c478bd9Sstevel@tonic-gate if (!ud_dirempty(tip, tdp->i_uniqid, cr) || tip->i_nlink > 2) {
15137c478bd9Sstevel@tonic-gate vn_vfsunlock(ITOV(tip));
15147c478bd9Sstevel@tonic-gate error = EEXIST; /* SIGH should be ENOTEMPTY */
15157c478bd9Sstevel@tonic-gate goto out;
15167c478bd9Sstevel@tonic-gate }
15177c478bd9Sstevel@tonic-gate } else if (doingdirectory) {
15187c478bd9Sstevel@tonic-gate error = ENOTDIR;
15197c478bd9Sstevel@tonic-gate goto out;
15207c478bd9Sstevel@tonic-gate }
15217c478bd9Sstevel@tonic-gate
15227c478bd9Sstevel@tonic-gate /*
15237c478bd9Sstevel@tonic-gate * Rewrite the inode pointer for target name entry
15247c478bd9Sstevel@tonic-gate * from the target inode (ip) to the source inode (sip).
15257c478bd9Sstevel@tonic-gate * This prevents the target entry from disappearing
15267c478bd9Sstevel@tonic-gate * during a crash. Mark the directory inode to reflect the changes.
15277c478bd9Sstevel@tonic-gate */
15287c478bd9Sstevel@tonic-gate dnlc_remove(ITOV(tdp), namep);
15297c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_prn = SWAP_16(sip->i_icb_prn);
15307c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_loc = SWAP_32(sip->i_icb_block);
15317c478bd9Sstevel@tonic-gate dnlc_enter(ITOV(tdp), namep, ITOV(sip));
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate ud_make_tag(tdp->i_udf, &fid->fid_tag, UD_FILE_ID_DESC,
15347c478bd9Sstevel@tonic-gate SWAP_32(fid->fid_tag.tag_loc), FID_LEN(fid));
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate error = ud_write_fid(tdp, slotp, buf);
15377c478bd9Sstevel@tonic-gate
15387c478bd9Sstevel@tonic-gate if (error) {
15397c478bd9Sstevel@tonic-gate if (doingdirectory) {
15407c478bd9Sstevel@tonic-gate vn_vfsunlock(ITOV(tip));
15417c478bd9Sstevel@tonic-gate }
15427c478bd9Sstevel@tonic-gate goto out;
15437c478bd9Sstevel@tonic-gate }
15447c478bd9Sstevel@tonic-gate
15457c478bd9Sstevel@tonic-gate /*
15467c478bd9Sstevel@tonic-gate * Upgrade to write lock on tip
15477c478bd9Sstevel@tonic-gate */
15487c478bd9Sstevel@tonic-gate rw_exit(&tip->i_contents);
15497c478bd9Sstevel@tonic-gate rw_enter(&tip->i_contents, RW_WRITER);
15507c478bd9Sstevel@tonic-gate
15517c478bd9Sstevel@tonic-gate mutex_enter(&tdp->i_tlock);
15527c478bd9Sstevel@tonic-gate tdp->i_flag |= IUPD|ICHG;
15537c478bd9Sstevel@tonic-gate mutex_exit(&tdp->i_tlock);
15547c478bd9Sstevel@tonic-gate /*
15557c478bd9Sstevel@tonic-gate * Decrement the link count of the target inode.
15567c478bd9Sstevel@tonic-gate * Fix the ".." entry in sip to point to dp.
15577c478bd9Sstevel@tonic-gate * This is done after the new entry is on the disk.
15587c478bd9Sstevel@tonic-gate */
15597c478bd9Sstevel@tonic-gate tip->i_nlink--;
15607c478bd9Sstevel@tonic-gate mutex_enter(&tip->i_tlock);
15617c478bd9Sstevel@tonic-gate tip->i_flag |= ICHG;
15627c478bd9Sstevel@tonic-gate mutex_exit(&tip->i_tlock);
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate if (doingdirectory) {
15657c478bd9Sstevel@tonic-gate /*
15667c478bd9Sstevel@tonic-gate * The entry for tip no longer exists so I can unlock the
15677c478bd9Sstevel@tonic-gate * vfslock.
15687c478bd9Sstevel@tonic-gate */
15697c478bd9Sstevel@tonic-gate vn_vfsunlock(ITOV(tip));
15707c478bd9Sstevel@tonic-gate /*
15717c478bd9Sstevel@tonic-gate * Decrement target link count once more if it was a directory.
15727c478bd9Sstevel@tonic-gate */
15737c478bd9Sstevel@tonic-gate if (tip->i_nlink != 0) {
15747c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
15757c478bd9Sstevel@tonic-gate "ud_direnter: target directory link count != 0");
15767c478bd9Sstevel@tonic-gate rw_exit(&tip->i_contents);
15777c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
15787c478bd9Sstevel@tonic-gate return (EINVAL);
15797c478bd9Sstevel@tonic-gate }
15807c478bd9Sstevel@tonic-gate /*
15817c478bd9Sstevel@tonic-gate * Renaming a directory with the parent different
15827c478bd9Sstevel@tonic-gate * requires that ".." be rewritten. The window is
15837c478bd9Sstevel@tonic-gate * still there for ".." to be inconsistent, but this
15847c478bd9Sstevel@tonic-gate * is unavoidable, and a lot shorter than when it was
15857c478bd9Sstevel@tonic-gate * done in a user process. We decrement the link
15867c478bd9Sstevel@tonic-gate * count in the new parent as appropriate to reflect
15877c478bd9Sstevel@tonic-gate * the just-removed target. If the parent is the
15887c478bd9Sstevel@tonic-gate * same, this is appropriate since the original
15897c478bd9Sstevel@tonic-gate * directory is going away. If the new parent is
15907c478bd9Sstevel@tonic-gate * different, dirfixdotdot() will bump the link count
15917c478bd9Sstevel@tonic-gate * back.
15927c478bd9Sstevel@tonic-gate */
15937c478bd9Sstevel@tonic-gate tdp->i_nlink--;
15947c478bd9Sstevel@tonic-gate mutex_enter(&tdp->i_tlock);
15957c478bd9Sstevel@tonic-gate tdp->i_flag |= ICHG;
15967c478bd9Sstevel@tonic-gate mutex_exit(&tdp->i_tlock);
15977c478bd9Sstevel@tonic-gate ITIMES_NOLOCK(tdp);
15987c478bd9Sstevel@tonic-gate if (sdp != tdp) {
15997c478bd9Sstevel@tonic-gate rw_exit(&tip->i_contents);
16007c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
16017c478bd9Sstevel@tonic-gate error = ud_dirfixdotdot(sip, sdp, tdp);
16027c478bd9Sstevel@tonic-gate return (error);
16037c478bd9Sstevel@tonic-gate }
16047c478bd9Sstevel@tonic-gate }
16057c478bd9Sstevel@tonic-gate
16067c478bd9Sstevel@tonic-gate out:
16077c478bd9Sstevel@tonic-gate rw_exit(&tip->i_contents);
16087c478bd9Sstevel@tonic-gate rw_exit(&sip->i_contents);
16097c478bd9Sstevel@tonic-gate return (error);
16107c478bd9Sstevel@tonic-gate }
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate /*
16147c478bd9Sstevel@tonic-gate * 1. When we find a slot that belonged to a file which was deleted
16157c478bd9Sstevel@tonic-gate * and is in the middle of the directory
16167c478bd9Sstevel@tonic-gate * 2. There is not empty slot available. The new entry
16177c478bd9Sstevel@tonic-gate * will be at the end of the directory and fits in the same block.
16187c478bd9Sstevel@tonic-gate * 3. There is no empty slot available. The new
16197c478bd9Sstevel@tonic-gate * entry will not fit the left over directory
16207c478bd9Sstevel@tonic-gate * so we need to allocate a new block. If
16217c478bd9Sstevel@tonic-gate * we cannot allocate a proximity block we need
16227c478bd9Sstevel@tonic-gate * to allocate a new icb, and data block.
16237c478bd9Sstevel@tonic-gate */
16247c478bd9Sstevel@tonic-gate int
ud_dirprepareentry(struct ud_inode * dp,struct slot * slotp,uint8_t * buf,struct cred * cr)16257c478bd9Sstevel@tonic-gate ud_dirprepareentry(struct ud_inode *dp,
16267c478bd9Sstevel@tonic-gate struct slot *slotp, uint8_t *buf, struct cred *cr)
16277c478bd9Sstevel@tonic-gate {
16287c478bd9Sstevel@tonic-gate struct fbuf *fbp;
16297c478bd9Sstevel@tonic-gate uint16_t old_dtype;
16307c478bd9Sstevel@tonic-gate int32_t error = 0;
16317c478bd9Sstevel@tonic-gate uint32_t entrysize, count, offset, tbno, old_size, off;
16327c478bd9Sstevel@tonic-gate struct file_id *fid;
16337c478bd9Sstevel@tonic-gate int32_t lbsize, lbmask, mask;
16347c478bd9Sstevel@tonic-gate
16357c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&dp->i_rwlock));
16367c478bd9Sstevel@tonic-gate
1637b39a0235SMilan Cermak ASSERT((slotp->status == NONE) || (slotp->status == FOUND));
16387c478bd9Sstevel@tonic-gate
16397c478bd9Sstevel@tonic-gate ud_printf("ud_dirprepareentry\n");
16407c478bd9Sstevel@tonic-gate lbsize = dp->i_udf->udf_lbsize;
16417c478bd9Sstevel@tonic-gate lbmask = dp->i_udf->udf_lbmask;
16427c478bd9Sstevel@tonic-gate mask = ~lbmask;
16437c478bd9Sstevel@tonic-gate
16447c478bd9Sstevel@tonic-gate fid = (struct file_id *)buf;
16457c478bd9Sstevel@tonic-gate entrysize = FID_LEN(fid);
16467c478bd9Sstevel@tonic-gate
16477c478bd9Sstevel@tonic-gate /*
16487c478bd9Sstevel@tonic-gate * If we didn't find a slot, then indicate that the
16497c478bd9Sstevel@tonic-gate * new slot belongs at the end of the directory.
16507c478bd9Sstevel@tonic-gate * If we found a slot, then the new entry can be
16517c478bd9Sstevel@tonic-gate * put at slotp->offset.
16527c478bd9Sstevel@tonic-gate */
16537c478bd9Sstevel@tonic-gate if (slotp->status == NONE) {
16547c478bd9Sstevel@tonic-gate /*
16557c478bd9Sstevel@tonic-gate * We did not find a slot, the next
16567c478bd9Sstevel@tonic-gate * entry will be in the end of the directory
16577c478bd9Sstevel@tonic-gate * see if we can fit the new entry inside
16587c478bd9Sstevel@tonic-gate * the old block. If not allocate a new block.
16597c478bd9Sstevel@tonic-gate */
16607c478bd9Sstevel@tonic-gate if (entrysize > slotp->size) {
16617c478bd9Sstevel@tonic-gate /*
16627c478bd9Sstevel@tonic-gate * extend the directory
16637c478bd9Sstevel@tonic-gate * size by one new block
16647c478bd9Sstevel@tonic-gate */
16657c478bd9Sstevel@tonic-gate old_dtype = dp->i_desc_type;
16667c478bd9Sstevel@tonic-gate old_size = (uint32_t)dp->i_size;
16677c478bd9Sstevel@tonic-gate error = ud_bmap_write(dp, slotp->offset,
16687c478bd9Sstevel@tonic-gate blkoff(dp->i_udf, slotp->offset) + entrysize,
16697c478bd9Sstevel@tonic-gate 0, cr);
16707c478bd9Sstevel@tonic-gate if (error != 0) {
16717c478bd9Sstevel@tonic-gate return (error);
16727c478bd9Sstevel@tonic-gate }
16737c478bd9Sstevel@tonic-gate if (old_dtype != dp->i_desc_type) {
16747c478bd9Sstevel@tonic-gate /*
16757c478bd9Sstevel@tonic-gate * oops we changed the astrat
16767c478bd9Sstevel@tonic-gate * of the file, we have to
16777c478bd9Sstevel@tonic-gate * recaliculate tags
16787c478bd9Sstevel@tonic-gate * fortunately we donot have more
16797c478bd9Sstevel@tonic-gate * than one lbsize to handle here
16807c478bd9Sstevel@tonic-gate */
16817c478bd9Sstevel@tonic-gate if ((error = ud_ip_off2bno(dp,
16827c478bd9Sstevel@tonic-gate 0, &tbno)) != 0) {
16837c478bd9Sstevel@tonic-gate return (error);
16847c478bd9Sstevel@tonic-gate }
16857c478bd9Sstevel@tonic-gate if ((error = fbread(ITOV(dp), 0,
16867c478bd9Sstevel@tonic-gate dp->i_udf->udf_lbsize,
16877c478bd9Sstevel@tonic-gate S_WRITE, &fbp)) != 0) {
16887c478bd9Sstevel@tonic-gate return (error);
16897c478bd9Sstevel@tonic-gate }
16907c478bd9Sstevel@tonic-gate off = 0;
16917c478bd9Sstevel@tonic-gate while (off < old_size) {
16927c478bd9Sstevel@tonic-gate struct file_id *tfid;
16937c478bd9Sstevel@tonic-gate
16947c478bd9Sstevel@tonic-gate tfid = (struct file_id *)
16957c478bd9Sstevel@tonic-gate (fbp->fb_addr + off);
16967c478bd9Sstevel@tonic-gate
16977c478bd9Sstevel@tonic-gate ud_make_tag(dp->i_udf, &tfid->fid_tag,
1698b39a0235SMilan Cermak UD_FILE_ID_DESC, tbno,
1699b39a0235SMilan Cermak FID_LEN(tfid));
17007c478bd9Sstevel@tonic-gate
17017c478bd9Sstevel@tonic-gate off += FID_LEN(tfid);
17027c478bd9Sstevel@tonic-gate }
17037c478bd9Sstevel@tonic-gate if (error = ud_fbwrite(fbp, dp)) {
17047c478bd9Sstevel@tonic-gate return (error);
17057c478bd9Sstevel@tonic-gate }
17067c478bd9Sstevel@tonic-gate }
17077c478bd9Sstevel@tonic-gate } else {
17087c478bd9Sstevel@tonic-gate /* Extend the directory size */
17097c478bd9Sstevel@tonic-gate if (dp->i_desc_type != ICB_FLAG_ONE_AD) {
17107c478bd9Sstevel@tonic-gate ASSERT(dp->i_ext);
17117c478bd9Sstevel@tonic-gate dp->i_ext[dp->i_ext_used - 1].ib_count +=
17127c478bd9Sstevel@tonic-gate entrysize;
17137c478bd9Sstevel@tonic-gate }
17147c478bd9Sstevel@tonic-gate }
17157c478bd9Sstevel@tonic-gate dp->i_size += entrysize;
17167c478bd9Sstevel@tonic-gate dp->i_flag |= IUPD|ICHG|IATTCHG;
17177c478bd9Sstevel@tonic-gate ITIMES_NOLOCK(dp);
17187c478bd9Sstevel@tonic-gate } else if (slotp->status != FOUND) {
17197c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "status is not NONE/FOUND");
17207c478bd9Sstevel@tonic-gate return (EINVAL);
17217c478bd9Sstevel@tonic-gate }
17227c478bd9Sstevel@tonic-gate
17237c478bd9Sstevel@tonic-gate if ((error = ud_ip_off2bno(dp, slotp->offset, &tbno)) != 0) {
17247c478bd9Sstevel@tonic-gate return (error);
17257c478bd9Sstevel@tonic-gate }
1726b39a0235SMilan Cermak ud_make_tag(dp->i_udf, &fid->fid_tag, UD_FILE_ID_DESC,
1727b39a0235SMilan Cermak tbno, FID_LEN(fid));
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate /*
17307c478bd9Sstevel@tonic-gate * fbread cannot cross a
17317c478bd9Sstevel@tonic-gate * MAXBSIZE boundary so handle it here
17327c478bd9Sstevel@tonic-gate */
17337c478bd9Sstevel@tonic-gate offset = slotp->offset;
17347c478bd9Sstevel@tonic-gate if ((error = fbread(ITOV(dp), offset & mask, lbsize,
17357c478bd9Sstevel@tonic-gate S_WRITE, &fbp)) != 0) {
17367c478bd9Sstevel@tonic-gate return (error);
17377c478bd9Sstevel@tonic-gate }
17387c478bd9Sstevel@tonic-gate if ((offset & mask) != ((offset + entrysize) & mask)) {
17397c478bd9Sstevel@tonic-gate count = entrysize - ((offset + entrysize) & lbmask);
17407c478bd9Sstevel@tonic-gate } else {
17417c478bd9Sstevel@tonic-gate count = entrysize;
17427c478bd9Sstevel@tonic-gate }
17437c478bd9Sstevel@tonic-gate bcopy((caddr_t)buf, fbp->fb_addr + (offset & lbmask), count);
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate if (error = ud_fbwrite(fbp, dp)) {
17467c478bd9Sstevel@tonic-gate return (error);
17477c478bd9Sstevel@tonic-gate }
17487c478bd9Sstevel@tonic-gate
17497c478bd9Sstevel@tonic-gate if (entrysize > count) {
17507c478bd9Sstevel@tonic-gate if ((error = fbread(ITOV(dp), (offset + entrysize) & mask,
17517c478bd9Sstevel@tonic-gate lbsize, S_WRITE, &fbp)) != 0) {
17527c478bd9Sstevel@tonic-gate return (error);
17537c478bd9Sstevel@tonic-gate }
17547c478bd9Sstevel@tonic-gate bcopy((caddr_t)(buf + count), fbp->fb_addr, entrysize - count);
17557c478bd9Sstevel@tonic-gate if (error = ud_fbwrite(fbp, dp)) {
17567c478bd9Sstevel@tonic-gate return (error);
17577c478bd9Sstevel@tonic-gate }
17587c478bd9Sstevel@tonic-gate }
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate dp->i_flag |= IUPD|ICHG|IATTCHG;
17617c478bd9Sstevel@tonic-gate ITIMES_NOLOCK(dp);
17627c478bd9Sstevel@tonic-gate return (error);
17637c478bd9Sstevel@tonic-gate }
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate
17667c478bd9Sstevel@tonic-gate /*
17677c478bd9Sstevel@tonic-gate * Fix the FID_PARENT entry of the child directory so that it points
17687c478bd9Sstevel@tonic-gate * to the new parent directory instead of the old one. Routine
17697c478bd9Sstevel@tonic-gate * assumes that dp is a directory and that all the inodes are on
17707c478bd9Sstevel@tonic-gate * the same file system.
17717c478bd9Sstevel@tonic-gate */
17727c478bd9Sstevel@tonic-gate int
ud_dirfixdotdot(struct ud_inode * dp,struct ud_inode * opdp,struct ud_inode * npdp)17737c478bd9Sstevel@tonic-gate ud_dirfixdotdot(struct ud_inode *dp,
17747c478bd9Sstevel@tonic-gate struct ud_inode *opdp, struct ud_inode *npdp)
17757c478bd9Sstevel@tonic-gate {
17767c478bd9Sstevel@tonic-gate int32_t err = 0;
17777c478bd9Sstevel@tonic-gate struct fbuf *fbp;
17787c478bd9Sstevel@tonic-gate struct file_id *fid;
17797c478bd9Sstevel@tonic-gate uint32_t loc, dummy, tbno;
17807c478bd9Sstevel@tonic-gate
17817c478bd9Sstevel@tonic-gate ud_printf("ud_dirfixdotdot\n");
17827c478bd9Sstevel@tonic-gate
17837c478bd9Sstevel@tonic-gate ASSERT(opdp->i_type == VDIR);
17847c478bd9Sstevel@tonic-gate ASSERT(npdp->i_type == VDIR);
17857c478bd9Sstevel@tonic-gate
17867c478bd9Sstevel@tonic-gate ASSERT(RW_WRITE_HELD(&npdp->i_rwlock));
17877c478bd9Sstevel@tonic-gate
17887c478bd9Sstevel@tonic-gate err = fbread(ITOV(dp), (offset_t)0,
17897c478bd9Sstevel@tonic-gate dp->i_udf->udf_lbsize, S_WRITE, &fbp);
17907c478bd9Sstevel@tonic-gate
17917c478bd9Sstevel@tonic-gate if (err || dp->i_nlink == 0 ||
17927c478bd9Sstevel@tonic-gate dp->i_size < sizeof (struct file_id)) {
17937c478bd9Sstevel@tonic-gate goto bad;
17947c478bd9Sstevel@tonic-gate }
17957c478bd9Sstevel@tonic-gate
17967c478bd9Sstevel@tonic-gate if ((err = ud_ip_off2bno(dp, 0, &tbno)) != 0) {
17977c478bd9Sstevel@tonic-gate goto bad;
17987c478bd9Sstevel@tonic-gate }
17997c478bd9Sstevel@tonic-gate
18007c478bd9Sstevel@tonic-gate fid = (struct file_id *)fbp->fb_addr;
18017c478bd9Sstevel@tonic-gate if ((ud_verify_tag_and_desc(&fid->fid_tag, UD_FILE_ID_DESC,
18027c478bd9Sstevel@tonic-gate tbno,
18037c478bd9Sstevel@tonic-gate 1, dp->i_udf->udf_lbsize) != 0) ||
18047c478bd9Sstevel@tonic-gate ((fid->fid_flags & (FID_DIR | FID_PARENT)) !=
18057c478bd9Sstevel@tonic-gate (FID_DIR | FID_PARENT))) {
18067c478bd9Sstevel@tonic-gate err = ENOTDIR;
18077c478bd9Sstevel@tonic-gate goto bad;
18087c478bd9Sstevel@tonic-gate }
18097c478bd9Sstevel@tonic-gate
18107c478bd9Sstevel@tonic-gate loc = ud_xlate_to_daddr(dp->i_udf,
18117c478bd9Sstevel@tonic-gate SWAP_16(fid->fid_icb.lad_ext_prn),
18127c478bd9Sstevel@tonic-gate SWAP_32(fid->fid_icb.lad_ext_loc), 1, &dummy);
18137c478bd9Sstevel@tonic-gate ASSERT(dummy == 1);
18147c478bd9Sstevel@tonic-gate if (loc == npdp->i_icb_lbano) {
18157c478bd9Sstevel@tonic-gate goto bad;
18167c478bd9Sstevel@tonic-gate }
18177c478bd9Sstevel@tonic-gate
18187c478bd9Sstevel@tonic-gate /*
18197c478bd9Sstevel@tonic-gate * Increment the link count in the new parent inode and force it out.
18207c478bd9Sstevel@tonic-gate */
18217c478bd9Sstevel@tonic-gate if (npdp->i_nlink == MAXLINK) {
18227c478bd9Sstevel@tonic-gate err = EMLINK;
18237c478bd9Sstevel@tonic-gate goto bad;
18247c478bd9Sstevel@tonic-gate }
18257c478bd9Sstevel@tonic-gate
18267c478bd9Sstevel@tonic-gate npdp->i_nlink++;
18277c478bd9Sstevel@tonic-gate mutex_enter(&npdp->i_tlock);
18287c478bd9Sstevel@tonic-gate npdp->i_flag |= ICHG;
18297c478bd9Sstevel@tonic-gate mutex_exit(&npdp->i_tlock);
18307c478bd9Sstevel@tonic-gate ud_iupdat(npdp, 1);
18317c478bd9Sstevel@tonic-gate
18327c478bd9Sstevel@tonic-gate /*
18337c478bd9Sstevel@tonic-gate * Rewrite the child FID_PARENT entry and force it out.
18347c478bd9Sstevel@tonic-gate */
18357c478bd9Sstevel@tonic-gate dnlc_remove(ITOV(dp), "..");
18367c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_loc = SWAP_32(npdp->i_icb_block);
18377c478bd9Sstevel@tonic-gate fid->fid_icb.lad_ext_prn = SWAP_16(npdp->i_icb_prn);
18387c478bd9Sstevel@tonic-gate ud_make_tag(npdp->i_udf, &fid->fid_tag,
18397c478bd9Sstevel@tonic-gate UD_FILE_ID_DESC, tbno, FID_LEN(fid));
18407c478bd9Sstevel@tonic-gate dnlc_enter(ITOV(dp), "..", ITOV(npdp));
18417c478bd9Sstevel@tonic-gate
18427c478bd9Sstevel@tonic-gate err = ud_fbwrite(fbp, dp);
18437c478bd9Sstevel@tonic-gate fbp = NULL;
18447c478bd9Sstevel@tonic-gate if (err != 0) {
18457c478bd9Sstevel@tonic-gate goto bad;
18467c478bd9Sstevel@tonic-gate }
18477c478bd9Sstevel@tonic-gate
18487c478bd9Sstevel@tonic-gate /*
18497c478bd9Sstevel@tonic-gate * Decrement the link count of the old parent inode and force
18507c478bd9Sstevel@tonic-gate * it out. If opdp is NULL, then this is a new directory link;
18517c478bd9Sstevel@tonic-gate * it has no parent, so we need not do anything.
18527c478bd9Sstevel@tonic-gate */
18537c478bd9Sstevel@tonic-gate if (opdp != NULL) {
18547c478bd9Sstevel@tonic-gate rw_enter(&opdp->i_contents, RW_WRITER);
18557c478bd9Sstevel@tonic-gate if (opdp->i_nlink != 0) {
18567c478bd9Sstevel@tonic-gate opdp->i_nlink--;
18577c478bd9Sstevel@tonic-gate mutex_enter(&opdp->i_tlock);
18587c478bd9Sstevel@tonic-gate opdp->i_flag |= ICHG;
18597c478bd9Sstevel@tonic-gate mutex_exit(&opdp->i_tlock);
18607c478bd9Sstevel@tonic-gate ud_iupdat(opdp, 1);
18617c478bd9Sstevel@tonic-gate }
18627c478bd9Sstevel@tonic-gate rw_exit(&opdp->i_contents);
18637c478bd9Sstevel@tonic-gate }
18647c478bd9Sstevel@tonic-gate return (0);
18657c478bd9Sstevel@tonic-gate
18667c478bd9Sstevel@tonic-gate bad:
18677c478bd9Sstevel@tonic-gate if (fbp) {
18687c478bd9Sstevel@tonic-gate fbrelse(fbp, S_OTHER);
18697c478bd9Sstevel@tonic-gate }
18707c478bd9Sstevel@tonic-gate return (err);
18717c478bd9Sstevel@tonic-gate }
18727c478bd9Sstevel@tonic-gate
18737c478bd9Sstevel@tonic-gate int32_t
ud_write_fid(struct ud_inode * dp,struct slot * slot,uint8_t * buf)18747c478bd9Sstevel@tonic-gate ud_write_fid(struct ud_inode *dp, struct slot *slot, uint8_t *buf)
18757c478bd9Sstevel@tonic-gate {
18767c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
18777c478bd9Sstevel@tonic-gate struct fbuf *lfbp;
18787c478bd9Sstevel@tonic-gate struct file_id *fid;
18797c478bd9Sstevel@tonic-gate int32_t error = 0;
18807c478bd9Sstevel@tonic-gate uint32_t lbsize, lbmask, count, old_count;
18817c478bd9Sstevel@tonic-gate
18827c478bd9Sstevel@tonic-gate
18837c478bd9Sstevel@tonic-gate ASSERT(slot->fbp);
18847c478bd9Sstevel@tonic-gate ASSERT(slot->ep);
18857c478bd9Sstevel@tonic-gate
18867c478bd9Sstevel@tonic-gate udf_vfsp = dp->i_udf;
18877c478bd9Sstevel@tonic-gate fid = slot->ep;
18887c478bd9Sstevel@tonic-gate lbsize = dp->i_udf->udf_lbsize;
18897c478bd9Sstevel@tonic-gate lbmask = dp->i_udf->udf_lbmask;
18907c478bd9Sstevel@tonic-gate
18917c478bd9Sstevel@tonic-gate if (((uint8_t *)fid >= buf) &&
18927c478bd9Sstevel@tonic-gate ((uint8_t *)fid < &buf[udf_vfsp->udf_lbsize])) {
18937c478bd9Sstevel@tonic-gate
18947c478bd9Sstevel@tonic-gate if ((error = fbread(ITOV(dp),
18957c478bd9Sstevel@tonic-gate (offset_t)(slot->offset & ~lbmask),
18967c478bd9Sstevel@tonic-gate lbsize, S_WRITE, &lfbp)) != 0) {
18977c478bd9Sstevel@tonic-gate goto out;
18987c478bd9Sstevel@tonic-gate }
18997c478bd9Sstevel@tonic-gate
19007c478bd9Sstevel@tonic-gate
19017c478bd9Sstevel@tonic-gate /*
19027c478bd9Sstevel@tonic-gate * We do not need to write the
19037c478bd9Sstevel@tonic-gate * file name. So check if the entry
19047c478bd9Sstevel@tonic-gate * does not cross a block boundary
19057c478bd9Sstevel@tonic-gate * and write only required portions
19067c478bd9Sstevel@tonic-gate */
19077c478bd9Sstevel@tonic-gate if (((slot->offset & lbmask) +
19087c478bd9Sstevel@tonic-gate sizeof (struct file_id)) > lbsize) {
19097c478bd9Sstevel@tonic-gate
19107c478bd9Sstevel@tonic-gate if ((slot->offset & lbmask) != 0) {
19117c478bd9Sstevel@tonic-gate old_count = lbsize -
19127c478bd9Sstevel@tonic-gate (slot->offset & lbmask);
19137c478bd9Sstevel@tonic-gate count = (slot->offset +
19147c478bd9Sstevel@tonic-gate sizeof (struct file_id)) &
19157c478bd9Sstevel@tonic-gate lbmask;
19167c478bd9Sstevel@tonic-gate } else {
19177c478bd9Sstevel@tonic-gate old_count = 0;
19187c478bd9Sstevel@tonic-gate count = sizeof (struct file_id);
19197c478bd9Sstevel@tonic-gate }
19207c478bd9Sstevel@tonic-gate
19217c478bd9Sstevel@tonic-gate bcopy(buf, lfbp->fb_addr +
19227c478bd9Sstevel@tonic-gate (slot->offset & lbmask), old_count);
19237c478bd9Sstevel@tonic-gate bcopy(buf + old_count,
19247c478bd9Sstevel@tonic-gate slot->fbp->fb_addr, count);
19257c478bd9Sstevel@tonic-gate
19267c478bd9Sstevel@tonic-gate error = ud_fbwrite(lfbp, dp);
19277c478bd9Sstevel@tonic-gate
19287c478bd9Sstevel@tonic-gate error = ud_fbwrite(slot->fbp, dp);
19297c478bd9Sstevel@tonic-gate } else {
19307c478bd9Sstevel@tonic-gate bcopy(buf, lfbp->fb_addr +
19317c478bd9Sstevel@tonic-gate (slot->offset & lbmask),
19327c478bd9Sstevel@tonic-gate sizeof (struct file_id));
19337c478bd9Sstevel@tonic-gate
19347c478bd9Sstevel@tonic-gate error = ud_fbwrite(lfbp, dp);
19357c478bd9Sstevel@tonic-gate
19367c478bd9Sstevel@tonic-gate fbrelse(slot->fbp, S_OTHER);
19377c478bd9Sstevel@tonic-gate }
19387c478bd9Sstevel@tonic-gate } else {
19397c478bd9Sstevel@tonic-gate if ((error = ud_fbwrite(slot->fbp, dp)) != 0) {
19407c478bd9Sstevel@tonic-gate fid->fid_flags &= ~FID_DELETED;
19417c478bd9Sstevel@tonic-gate ud_make_tag(dp->i_udf, &fid->fid_tag, UD_FILE_ID_DESC,
19427c478bd9Sstevel@tonic-gate SWAP_32(fid->fid_tag.tag_loc), FID_LEN(fid));
19437c478bd9Sstevel@tonic-gate }
19447c478bd9Sstevel@tonic-gate }
19457c478bd9Sstevel@tonic-gate slot->fbp = NULL;
19467c478bd9Sstevel@tonic-gate
19477c478bd9Sstevel@tonic-gate out:
19487c478bd9Sstevel@tonic-gate return (error);
19497c478bd9Sstevel@tonic-gate }
1950