4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
26 #include <sys/t_lock.h>
27 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/sysmacros.h>
31 #include <sys/resource.h>
32 #include <sys/signal.h>
38 #include <sys/vnode.h>
43 #include <sys/fcntl.h>
44 #include <sys/flock.h>
49 #include <sys/errno.h>
52 #include <sys/pathname.h>
53 #include <sys/debug.h>
54 #include <sys/vmsystm.h>
55 #include <sys/cmn_err.h>
56 #include <sys/dirent.h>
57 #include <sys/errno.h>
58 #include <sys/modctl.h>
59 #include <sys/statvfs.h>
60 #include <sys/mount.h>
61 #include <sys/sunddi.h>
62 #include <sys/bootconf.h>
63 #include <sys/policy.h>
70 #include <vm/seg_map.h>
71 #include <vm/seg_kmem.h>
72 #include <vm/seg_vn.h>
78 #include <sys/fs_subr.h>
81 #include <sys/fs/udf_volume.h>
82 #include <sys/fs/udf_inode.h>
86 enum {NONE
, COMPACT
, FOUND
, EXIST
} status
;
87 off_t offset
; /* offset of area with free space */
88 int size
; /* size of area at slotoffset */
89 struct fbuf
*fbp
; /* dir buf where slot is */
90 struct file_id
*ep
; /* pointer to slot */
91 off_t endoff
; /* last useful location found in search */
95 int32_t ud_dircheckforname(struct ud_inode
*, char *, int,
96 struct slot
*, struct ud_inode
**, uint8_t *, struct cred
*);
97 int32_t ud_dirempty(struct ud_inode
*, uint64_t, struct cred
*);
98 int32_t str2cmp(char *, int32_t, char *, int32_t, char *, int32_t);
99 int32_t ud_dircheckpath(int32_t, struct ud_inode
*, struct cred
*);
100 int32_t ud_dirmakeinode(struct ud_inode
*, struct ud_inode
**,
101 struct vattr
*, enum de_op
, struct cred
*);
102 int32_t ud_diraddentry(struct ud_inode
*, char *,
103 enum de_op
, int, struct slot
*, struct ud_inode
*,
104 struct ud_inode
*, struct cred
*);
105 int32_t ud_dirmakedirect(struct ud_inode
*, struct ud_inode
*, struct cred
*);
106 int32_t ud_dirrename(struct ud_inode
*, struct ud_inode
*,
107 struct ud_inode
*, struct ud_inode
*, char *, uint8_t *,
108 struct slot
*, struct cred
*);
109 int32_t ud_dirprepareentry(struct ud_inode
*,
110 struct slot
*, uint8_t *, struct cred
*);
111 int32_t ud_dirfixdotdot(struct ud_inode
*, struct ud_inode
*,
113 int32_t ud_write_fid(struct ud_inode
*, struct slot
*, uint8_t *);
116 ud_dirlook(struct ud_inode
*dip
,
117 char *namep
, struct ud_inode
**ipp
, struct cred
*cr
, int32_t skipdnlc
)
119 struct udf_vfs
*udf_vfsp
;
120 int32_t error
= 0, namelen
, adhoc_search
;
121 uoff_t offset
, adhoc_offset
, dirsize
, end
;
122 struct vnode
*dvp
, *vp
;
125 uint8_t *fname
, dummy
[3];
126 int32_t id_len
, doingchk
;
133 ud_printf("ud_dirlook\n");
135 udf_vfsp
= dip
->i_udf
;
143 * Check accessibility of directory.
145 if (dip
->i_type
!= VDIR
) {
148 if (error
= ud_iaccess(dip
, IEXEC
, cr
, 1)) {
153 * Null component name is synonym for directory being searched.
155 if (*namep
== '\0') {
160 namelen
= strlen(namep
);
161 if ((namelen
== 1) &&
162 (namep
[0] == '.') && (namep
[1] == '\0')) {
163 /* Current directory */
166 dnlc_enter(dvp
, namep
, ITOV(*ipp
));
170 if ((!skipdnlc
) && (vp
= dnlc_lookup(dvp
, namep
))) {
171 /* vp is already held from dnlc_lookup */
177 dname
= kmem_zalloc(1024, KM_SLEEP
);
178 buf
= kmem_zalloc(udf_vfsp
->udf_lbsize
, KM_SLEEP
);
181 * Read lock the inode we are searching. You will notice that we
182 * didn't hold the read lock while searching the dnlc. This means
183 * that the entry could now be in the dnlc. This doesn't cause any
184 * problems because dnlc_enter won't add an entry if it is already
187 rw_enter(&dip
->i_rwlock
, RW_READER
);
190 * Take care to look at dip->i_diroff only once, as it
191 * may be changing due to other threads/cpus.
195 offset
= dip
->i_diroff
;
196 end
= dirsize
= dip
->i_size
;
198 if (offset
> dirsize
) {
201 adhoc_offset
= offset
;
202 adhoc_search
= (offset
== 0) ? 1 : 2;
206 while (adhoc_search
--) {
207 while (offset
< end
) {
208 error
= ud_get_next_fid(dip
, &fbp
,
209 offset
, &fid
, &fname
, buf
);
213 if ((fid
->fid_flags
& FID_DELETED
) == 0) {
214 if (fid
->fid_flags
& FID_PARENT
) {
221 if ((error
= ud_uncompress(
222 fid
->fid_idlen
, &id_len
,
223 fname
, dname
)) != 0) {
226 fname
= (uint8_t *)dname
;
227 fname
[id_len
] = '\0';
229 if ((namelen
== id_len
) &&
230 (strncmp(namep
, (caddr_t
)fname
,
236 loc
= SWAP_32(fid
->fid_icb
.lad_ext_loc
);
237 prn
= SWAP_16(fid
->fid_icb
.lad_ext_prn
);
238 dip
->i_diroff
= offset
+ FID_LEN(fid
);
241 if ((loc
== old_loc
) &&
251 rw_exit(&dip
->i_rwlock
);
261 struct timespec32 omtime
;
263 omtime
= dip
->i_mtime
;
264 rw_exit(&dip
->i_rwlock
);
266 error
= ud_iget(dip
->i_vfs
, prn
,
269 rw_enter(&dip
->i_rwlock
,
276 if ((omtime
.tv_sec
!=
277 dip
->i_mtime
.tv_sec
) ||
279 dip
->i_mtime
.tv_nsec
)) {
294 error
= ud_iget(dip
->i_vfs
, prn
,
299 dnlc_enter(dvp
, namep
,
305 offset
+= FID_LEN(fid
);
308 fbrelse(fbp
, S_READ
);
316 kmem_free(buf
, udf_vfsp
->udf_lbsize
);
317 kmem_free(dname
, 1024);
319 fbrelse(fbp
, S_READ
);
321 rw_exit(&dip
->i_rwlock
);
327 struct ud_inode
*tdp
,
330 struct ud_inode
*sdp
,
331 struct ud_inode
*sip
,
333 struct ud_inode
**ipp
,
335 caller_context_t
*ctp
)
337 struct udf_vfs
*udf_vfsp
;
338 struct ud_inode
*tip
;
345 ud_printf("ud_direnter\n");
347 udf_vfsp
= tdp
->i_udf
;
348 /* don't allow '/' characters in pathname component */
349 for (s
= namep
, namlen
= 0; *s
; s
++, namlen
++) {
356 cmn_err(CE_WARN
, "name length == 0 in ud_direnter");
360 ASSERT(RW_WRITE_HELD(&tdp
->i_rwlock
));
362 * If name is "." or ".." then if this is a create look it up
363 * and return EEXIST. Rename or link TO "." or ".." is forbidden.
365 if (namep
[0] == '.' &&
366 (namlen
== 1 || (namlen
== 2 && namep
[1] == '.'))) {
367 if (op
== DE_RENAME
) {
368 return (EINVAL
); /* *SIGH* should be ENOTEMPTY */
372 * ud_dirlook will acquire the i_rwlock
374 rw_exit(&tdp
->i_rwlock
);
375 if (err
= ud_dirlook(tdp
, namep
, ipp
, cr
, 0)) {
376 rw_enter(&tdp
->i_rwlock
, RW_WRITER
);
379 rw_enter(&tdp
->i_rwlock
, RW_WRITER
);
393 * For link and rename lock the source entry and check the link count
394 * to see if it has been removed while it was unlocked. If not, we
395 * increment the link count and force the inode to disk to make sure
396 * that it is there before any directory entry that points to it.
398 if (op
== DE_LINK
|| op
== DE_RENAME
) {
399 rw_enter(&sip
->i_contents
, RW_WRITER
);
400 if (sip
->i_nlink
== 0) {
401 rw_exit(&sip
->i_contents
);
404 if (sip
->i_nlink
== MAXLINK
) {
405 rw_exit(&sip
->i_contents
);
410 mutex_enter(&sip
->i_tlock
);
412 mutex_exit(&sip
->i_tlock
);
414 rw_exit(&sip
->i_contents
);
417 * If target directory has not been removed, then we can consider
418 * allowing file to be created.
420 if (tdp
->i_nlink
== 0) {
425 * Check accessibility of directory.
427 if (tdp
->i_type
!= VDIR
) {
432 * Execute access is required to search the directory.
434 if (err
= ud_iaccess(tdp
, IEXEC
, cr
, 1)) {
438 * If this is a rename of a directory and the parent is
439 * different (".." must be changed), then the source
440 * directory must not be in the directory hierarchy
441 * above the target, as this would orphan everything
442 * below the source directory. Also the user must have
443 * write permission in the source so as to be able to
446 if (op
== DE_RENAME
) {
451 rw_enter(&sip
->i_contents
, RW_READER
);
452 if ((sip
->i_type
== VDIR
) && (sdp
!= tdp
)) {
455 if ((err
= ud_iaccess(sip
, IWRITE
, cr
, 0))) {
456 rw_exit(&sip
->i_contents
);
459 blkno
= sip
->i_icb_lbano
;
460 rw_exit(&sip
->i_contents
);
461 if ((err
= ud_dircheckpath(blkno
, tdp
, cr
))) {
465 rw_exit(&sip
->i_contents
);
470 * Search for the entry. Return VN_HELD tip if found.
472 buf
= kmem_zalloc(udf_vfsp
->udf_lbsize
, KM_SLEEP
);
473 rw_enter(&tdp
->i_contents
, RW_WRITER
);
474 if (err
= ud_dircheckforname(tdp
,
475 namep
, namlen
, &slot
, &tip
, buf
, cr
)) {
490 err
= ud_dirrename(sdp
, sip
, tdp
, tip
,
491 namep
, buf
, &slot
, cr
);
493 * We used to VN_RELE() here, but this
494 * was moved down so that we could send
495 * a vnevent after the locks were dropped.
500 * Can't link to an existing file.
508 * The entry does not exist. Check write permission in
509 * directory to see if entry can be created.
511 if (err
= ud_iaccess(tdp
, IWRITE
, cr
, 0)) {
514 if ((op
== DE_CREATE
) || (op
== DE_MKDIR
)) {
516 * Make new inode and directory entry as required.
518 if (err
= ud_dirmakeinode(tdp
, &sip
, vap
, op
, cr
))
521 if (err
= ud_diraddentry(tdp
, namep
, op
,
522 namlen
, &slot
, sip
, sdp
, cr
)) {
523 if ((op
== DE_CREATE
) || (op
== DE_MKDIR
)) {
525 * Unmake the inode we just made.
527 rw_enter(&sip
->i_contents
, RW_WRITER
);
528 if (sip
->i_type
== VDIR
) {
532 mutex_enter(&sip
->i_tlock
);
534 mutex_exit(&sip
->i_tlock
);
535 rw_exit(&sip
->i_contents
);
541 } else if ((op
== DE_CREATE
) || (op
== DE_MKDIR
)) {
547 kmem_free(buf
, udf_vfsp
->udf_lbsize
);
550 fbrelse(slot
.fbp
, S_OTHER
);
552 rw_exit(&tdp
->i_contents
);
554 if (op
== DE_RENAME
) {
556 * If it's all good, send events after locks are dropped
557 * but before vnodes are released.
561 vnevent_rename_dest(ITOV(tip
), ITOV(tdp
),
566 vnevent_rename_dest_dir(ITOV(tdp
), ctp
);
571 * The following VN_RELE() was moved from the
572 * DE_RENAME case above
580 if (err
&& ((op
== DE_LINK
) || (op
== DE_RENAME
))) {
582 * Undo bumped link count.
584 rw_enter(&sip
->i_contents
, RW_WRITER
);
586 rw_exit(&sip
->i_contents
);
588 mutex_enter(&sip
->i_tlock
);
590 mutex_exit(&sip
->i_tlock
);
596 * Locking i_contents in this
597 * function seems to be really weird
603 struct ud_inode
*oip
,
607 caller_context_t
*ctp
)
609 struct udf_vfs
*udf_vfsp
;
610 int32_t namelen
, err
= 0;
618 ud_printf("ud_dirremove\n");
620 ASSERT(RW_WRITE_HELD(&dp
->i_rwlock
));
622 udf_vfsp
= dp
->i_udf
;
623 namelen
= (int)strlen(namep
);
625 cmn_err(CE_WARN
, "name length == 0 in ud_dirremove");
630 * return err when removing . and ..
632 if (namep
[0] == '.') {
635 } else if (namelen
== 2 && namep
[1] == '.') {
636 return (EEXIST
); /* SIGH should be ENOTEMPTY */
640 ASSERT(RW_WRITE_HELD(&dp
->i_rwlock
));
643 * Check accessibility of directory.
645 if (dp
->i_type
!= VDIR
) {
650 slot
.status
= FOUND
; /* don't need to look for empty slot */
657 * Execute access is required to search the directory.
658 * Access for write is interpreted as allowing
659 * deletion of files in the directory.
661 if (err
= ud_iaccess(dp
, IEXEC
|IWRITE
, cr
, 1)) {
665 buf
= kmem_zalloc(udf_vfsp
->udf_lbsize
, KM_SLEEP
);
667 rw_enter(&dp
->i_contents
, RW_WRITER
);
669 if (err
= ud_dircheckforname(dp
, namep
, namelen
, &slot
, &ip
,
677 if (oip
&& oip
!= ip
) {
682 if ((mode
= ip
->i_type
) == VDIR
) {
684 * vn_vfswlock() prevents races between mount and rmdir.
686 if (vn_vfswlock(ITOV(ip
))) {
690 if (vn_mountedvfs(ITOV(ip
)) != NULL
&& op
!= DR_RENAME
) {
695 * If we are removing a directory, get a lock on it.
696 * If the directory is empty, it will stay empty until
699 rw_enter(&ip
->i_rwlock
, RW_READER
);
701 /* We must be holding i_contents */
702 rw_enter(&ip
->i_contents
, RW_READER
);
704 if (err
= ud_sticky_remove_access(dp
, ip
, cr
)) {
705 rw_exit(&ip
->i_contents
);
707 rw_exit(&ip
->i_rwlock
);
711 if (op
== DR_RMDIR
) {
713 * For rmdir(2), some special checks are required.
714 * (a) Don't remove any alias of the parent (e.g. ".").
715 * (b) Don't remove the current directory.
716 * (c) Make sure the entry is (still) a directory.
717 * (d) Make sure the directory is empty.
720 if (dp
== ip
|| ITOV(ip
) == cdir
) {
722 } else if (ip
->i_type
!= VDIR
) {
724 } else if ((ip
->i_nlink
!= 1) ||
725 (!ud_dirempty(ip
, dp
->i_uniqid
, cr
))) {
727 * Directories do not have an
728 * entry for "." so only one link
731 err
= EEXIST
; /* SIGH should be ENOTEMPTY */
734 rw_exit(&ip
->i_contents
);
736 rw_exit(&ip
->i_rwlock
);
740 } else if (op
== DR_REMOVE
) {
742 * unlink(2) requires a different check: allow only
743 * privileged processes to unlink a directory.
745 struct vnode
*vp
= ITOV(ip
);
747 if (vp
->v_type
== VDIR
&&
748 secpolicy_fs_linkdir(cr
, vp
->v_vfsp
)) {
750 rw_exit(&ip
->i_contents
);
751 rw_exit(&ip
->i_rwlock
);
755 rw_exit(&ip
->i_contents
);
758 * Remove the cache'd entry, if any.
760 dnlc_remove(ITOV(dp
), namep
);
763 * We can collapse all the directory
764 * entries that are deleted into one big entry
765 * but the better way is to
766 * defer it till next directory entry
767 * creation. where we can do this
768 * in a more efficient way
773 * If this is the last entry
774 * just truncate the file instead
775 * of marking it deleted
777 if ((slot
.offset
+ FID_LEN(fid
)) == dp
->i_size
) {
778 fbrelse(slot
.fbp
, S_OTHER
);
779 if ((err
= ud_itrunc(dp
, slot
.offset
, 0, cr
)) != 0) {
783 fid
->fid_flags
|= FID_DELETED
;
785 if ((err
= ud_ip_off2bno(dp
, slot
.offset
, &tbno
)) != 0) {
789 ud_make_tag(dp
->i_udf
, &fid
->fid_tag
,
790 UD_FILE_ID_DESC
, tbno
, FID_LEN(fid
));
792 err
= ud_write_fid(dp
, &slot
, buf
);
798 * If we were removing a directory, it is 'gone' now so we can
802 rw_exit(&ip
->i_rwlock
);
805 mutex_enter(&dp
->i_tlock
);
806 dp
->i_flag
|= IUPD
|ICHG
;
807 mutex_exit(&dp
->i_tlock
);
808 mutex_enter(&ip
->i_tlock
);
810 mutex_exit(&ip
->i_tlock
);
816 rw_enter(&ip
->i_contents
, RW_WRITER
);
819 * Now dispose of the inode.
821 if (ip
->i_nlink
> 0) {
822 if ((op
== DR_RMDIR
) && (ip
->i_type
== VDIR
)) {
824 * Decrement by 1 because there is no "."
825 * Clear the inode, but there may be other hard
826 * links so don't free the inode.
827 * Decrement the dp linkcount because we're
828 * trashing the ".." entry.
832 dnlc_remove(ITOV(ip
), ".");
833 dnlc_remove(ITOV(ip
), "..");
835 * (void) ud_itrunc(ip, 0, 0, cr);
843 rw_exit(&ip
->i_contents
);
846 vn_vfsunlock(ITOV(ip
));
849 ASSERT(RW_WRITE_HELD(&dp
->i_contents
));
851 if (slot
.fbp
!= NULL
) {
852 fbrelse(slot
.fbp
, S_OTHER
);
854 rw_exit(&dp
->i_contents
);
858 * If no errors, send any events after locks are dropped,
859 * but before the VN_RELE().
862 if (op
== DR_REMOVE
) {
863 vnevent_remove(ITOV(ip
), ITOV(dp
), namep
, ctp
);
864 } else if (op
== DR_RMDIR
) {
865 vnevent_rmdir(ITOV(ip
), ITOV(dp
), namep
, ctp
);
871 kmem_free(buf
, udf_vfsp
->udf_lbsize
);
876 ud_dircheckforname(struct ud_inode
*tdp
,
877 char *namep
, int32_t namelen
, struct slot
*slotp
,
878 struct ud_inode
**ipp
, uint8_t *buf
, struct cred
*cr
)
880 struct udf_vfs
*udf_vfsp
;
881 uint32_t dirsize
, offset
;
884 int32_t sz
, error
= 0, sz_req
, matched
= 0;
890 ud_printf("ud_dircheckforname\n");
892 ASSERT(RW_WRITE_HELD(&tdp
->i_rwlock
));
895 dname
= kmem_zalloc(1024, KM_SLEEP
);
897 udf_vfsp
= tdp
->i_udf
;
900 dirsize
= tdp
->i_size
;
902 if (slotp
->status
!= FOUND
) {
905 temp
= 1024; /* set to size of dname allocated above */
906 if ((error
= ud_compress(namelen
, &temp
,
907 (uint8_t *)namep
, dname
)) != 0) {
910 sz_req
= F_LEN
+ temp
;
911 sz_req
= (sz_req
+ 3) & ~3;
914 while (offset
< dirsize
) {
915 if ((error
= ud_get_next_fid(tdp
, &fbp
,
916 offset
, &fid
, &nm
, buf
)) != 0) {
919 if ((error
= ud_uncompress(fid
->fid_idlen
,
920 &id_len
, nm
, dname
)) != 0) {
923 if ((fid
->fid_flags
& FID_DELETED
) == 0) {
924 /* Check for name match */
925 if (((namelen
== id_len
) &&
926 (strncmp(namep
, (caddr_t
)dname
, namelen
) == 0)) ||
927 ((fid
->fid_flags
& FID_PARENT
) &&
930 (namelen
== 2 && namep
[1] == '.'))))) {
932 tdp
->i_diroff
= offset
;
933 if ((fid
->fid_flags
& FID_PARENT
) &&
934 (namelen
== 1) && (namep
[0] == '.')) {
935 struct vnode
*vp
= ITOV(tdp
);
943 prn
= SWAP_16(fid
->fid_icb
.lad_ext_prn
);
944 loc
= SWAP_32(fid
->fid_icb
.lad_ext_loc
);
945 if ((error
= ud_iget(tdp
->i_vfs
, prn
,
946 loc
, ipp
, NULL
, cr
)) != 0) {
948 fbrelse(fbp
, S_OTHER
);
952 slotp
->status
= EXIST
;
953 slotp
->offset
= offset
;
954 slotp
->size
= FID_LEN(fid
);
962 * see if we need to find an
963 * empty slot and the current slot
966 if ((slotp
->status
!= FOUND
) || (matched
== 0)) {
969 slotp
->status
= FOUND
;
970 slotp
->offset
= offset
;
974 if ((namelen
== id_len
) &&
975 (strncmp(namep
, (caddr_t
)dname
,
978 slotp
->status
= FOUND
;
979 slotp
->offset
= offset
;
985 offset
+= FID_LEN(fid
);
988 fbrelse(fbp
, S_OTHER
);
990 if (slotp
->status
== NONE
) {
992 * We didn't find a slot; the new directory entry should be put
993 * at the end of the directory. Return an indication of where
994 * this is, and set "endoff" to zero; since we're going to have
995 * to extend the directory, we're certainly not going to
998 slotp
->offset
= dirsize
;
999 if (tdp
->i_desc_type
== ICB_FLAG_ONE_AD
) {
1000 slotp
->size
= tdp
->i_max_emb
- tdp
->i_size
;
1002 slotp
->size
= udf_vfsp
->udf_lbsize
-
1003 slotp
->offset
& udf_vfsp
->udf_lbmask
;
1010 kmem_free((caddr_t
)dname
, 1024);
1015 * Return 1 if the dir has all files
1016 * deleted except the parent
1021 ud_dirempty(struct ud_inode
*ip
, uint64_t ino
, struct cred
*cr
)
1024 int32_t empty
= 1, error
, count
, entry_len
, rcount
;
1025 struct file_id
*fid
;
1030 ud_printf("ud_dirempty\n");
1032 ASSERT(RW_LOCK_HELD(&ip
->i_contents
));
1034 if (ip
->i_size
== 0) {
1039 addr
= kmem_zalloc(desc_len
, KM_SLEEP
);
1040 fid
= (struct file_id
*)addr
;
1042 for (off
= 0; off
< ip
->i_size
; off
+= entry_len
) {
1046 * and verify checksum
1049 rcount
= sizeof (struct file_id
);
1050 error
= ud_rdwri(UIO_READ
, FREAD
, ip
, addr
, rcount
, off
,
1051 UIO_SYSSPACE
, &count
, cr
);
1052 if ((error
!= 0) || (count
!= 0)) {
1057 if ((error
= ud_ip_off2bno(ip
, off
, &tbno
)) != 0) {
1063 * We verify the tag id and also the FID_LEN.
1064 * FID_LEN should be <= desc_len.
1066 if (ud_verify_tag_and_desc(&fid
->fid_tag
,
1068 tbno
, 0, desc_len
) != 0) {
1069 /* Corrupted directory */
1075 * Read the fid + iulen + len
1076 * Now verify both checksum andCRC
1079 rcount
= FID_LEN(fid
);
1080 error
= ud_rdwri(UIO_READ
, FREAD
, ip
, addr
, rcount
, off
,
1081 UIO_SYSSPACE
, &count
, cr
);
1082 if ((error
!= 0) || (count
!= 0)) {
1087 * Now that the entire decsriptor is read we verify the
1090 if (ud_verify_tag_and_desc(&fid
->fid_tag
,
1094 /* Corrupted directory */
1100 * Is the file deleted
1103 if ((fid
->fid_flags
& FID_DELETED
) == 0) {
1104 if ((fid
->fid_flags
& FID_PARENT
) == 0) {
1109 entry_len
= FID_LEN(fid
);
1112 kmem_free(addr
, 1024);
1119 ud_dircheckpath(int32_t blkno
,
1120 struct ud_inode
*target
, struct cred
*cr
)
1124 struct udf_vfs
*udf_vfsp
;
1126 struct file_id
*fid
;
1127 struct ud_inode
*ip
, *tip
;
1129 uint32_t lbno
, dummy
, tbno
;
1130 daddr_t parent_icb_loc
;
1132 ud_printf("ud_dircheckpath\n");
1134 udf_vfsp
= target
->i_udf
;
1137 ASSERT(udf_vfsp
!= NULL
);
1138 ASSERT(MUTEX_HELD(&target
->i_udf
->udf_rename_lck
));
1139 ASSERT(RW_WRITE_HELD(&ip
->i_rwlock
));
1141 if (ip
->i_icb_lbano
== blkno
) {
1145 if (ip
->i_icb_lbano
== udf_vfsp
->udf_root_blkno
) {
1150 * Search back through the directory tree, using the PARENT entries
1151 * Fail any attempt to move a directory into an ancestor directory.
1154 if ((err
= fbread(ITOV(ip
), 0,
1155 udf_vfsp
->udf_lbsize
, S_READ
, &fbp
)) != 0) {
1159 if ((err
= ud_ip_off2bno(ip
, 0, &tbno
)) != 0) {
1162 fid
= (struct file_id
*)fbp
->fb_addr
;
1163 /* IS this a valid file_identifier */
1164 if (ud_verify_tag_and_desc(&fid
->fid_tag
,
1167 1, udf_vfsp
->udf_lbsize
) != 0) {
1170 if ((fid
->fid_flags
& FID_DELETED
) != 0) {
1173 if ((fid
->fid_flags
& FID_PARENT
) == 0) {
1175 * This cannot happen unless
1176 * something is grossly wrong
1177 * First entry has to be parent
1181 prn
= SWAP_16(fid
->fid_icb
.lad_ext_prn
);
1182 lbno
= SWAP_32(fid
->fid_icb
.lad_ext_loc
);
1184 ud_xlate_to_daddr(udf_vfsp
, prn
, lbno
, 1, &dummy
);
1186 if (parent_icb_loc
== blkno
) {
1191 udf_vfsp
= ip
->i_udf
;
1192 if (parent_icb_loc
== udf_vfsp
->udf_root_blkno
) {
1196 fbrelse(fbp
, S_OTHER
);
1200 rw_exit(&ip
->i_rwlock
);
1205 * Race to get the inode.
1207 if (err
= ud_iget(vfsp
, prn
, lbno
, &tip
, NULL
, cr
)) {
1212 rw_enter(&ip
->i_rwlock
, RW_READER
);
1215 fbrelse(fbp
, S_OTHER
);
1220 rw_exit(&ip
->i_rwlock
);
1228 ud_dirmakeinode(struct ud_inode
*tdp
, struct ud_inode
**ipp
,
1229 struct vattr
*vap
, enum de_op op
, struct cred
*cr
)
1231 struct ud_inode
*ip
;
1234 ASSERT(vap
!= NULL
);
1235 ASSERT(op
== DE_CREATE
|| op
== DE_MKDIR
);
1236 ASSERT((vap
->va_mask
& (AT_TYPE
|AT_MODE
)) == (AT_TYPE
|AT_MODE
));
1237 ASSERT(RW_WRITE_HELD(&tdp
->i_rwlock
));
1240 * Allocate a new inode.
1242 if ((error
= ud_ialloc(tdp
, &ip
, vap
, cr
)) != 0) {
1248 rw_enter(&ip
->i_contents
, RW_WRITER
);
1250 if (op
== DE_MKDIR
) {
1251 error
= ud_dirmakedirect(ip
, tdp
, cr
);
1254 ip
->i_flag
|= IACC
|IUPD
|ICHG
;
1256 * Clear IACC and/or IUPD if the caller specified the atime and/or
1257 * mtime fields. They were set from the passed in attributes in
1260 if (vap
->va_mask
& AT_ATIME
)
1261 ip
->i_flag
&= ~IACC
;
1262 if (vap
->va_mask
& AT_MTIME
)
1263 ip
->i_flag
&= ~IUPD
;
1265 * push inode before it's name appears in a directory
1269 rw_exit(&ip
->i_contents
);
1274 * Enter the file sip in the directory tdp with name namep.
1277 ud_diraddentry(struct ud_inode
*tdp
, char *namep
,
1278 enum de_op op
, int32_t namelen
, struct slot
*slotp
,
1279 struct ud_inode
*sip
, struct ud_inode
*sdp
, struct cred
*cr
)
1281 struct udf_vfs
*udf_vfsp
;
1282 int32_t error
, temp
;
1283 struct file_id
*fid
;
1284 uint8_t *buf
= NULL
;
1286 ASSERT(RW_WRITE_HELD(&tdp
->i_rwlock
));
1288 ud_printf("ud_diraddentry\n");
1290 udf_vfsp
= sip
->i_udf
;
1293 * Check inode to be linked to see if it is in the
1296 if (ITOV(tdp
)->v_vfsp
!= ITOV(sip
)->v_vfsp
) {
1301 if ((op
== DE_RENAME
) && (sip
->i_type
== VDIR
)) {
1302 if ((error
= ud_dirfixdotdot(sip
, sdp
, tdp
)) != 0) {
1307 buf
= kmem_zalloc(udf_vfsp
->udf_lbsize
, KM_SLEEP
);
1310 * Fill in entry data.
1312 fid
= (struct file_id
*)buf
;
1313 fid
->fid_ver
= SWAP_16(1);
1314 if (sip
->i_type
== VDIR
) {
1315 fid
->fid_flags
= FID_DIR
;
1321 fid
->fid_icb
.lad_ext_len
= SWAP_32(sip
->i_udf
->udf_lbsize
);
1322 fid
->fid_icb
.lad_ext_loc
= SWAP_32(sip
->i_icb_block
);
1323 fid
->fid_icb
.lad_ext_prn
= SWAP_16(sip
->i_icb_prn
);
1326 temp
= MIN(udf_vfsp
->udf_lbsize
- F_LEN
, MAXNAMELEN
);
1327 if ((error
= ud_compress(namelen
, &temp
,
1328 (uint8_t *)namep
, fid
->fid_spec
)) == 0) {
1329 fid
->fid_idlen
= (uint8_t)temp
;
1330 error
= ud_dirprepareentry(tdp
, slotp
, buf
, cr
);
1333 kmem_free(buf
, udf_vfsp
->udf_lbsize
);
1340 * Write a prototype directory into the empty inode ip, whose parent is dp.
1344 ud_dirmakedirect(struct ud_inode
*ip
,
1345 struct ud_inode
*dp
, struct cred
*cr
)
1348 uint32_t blkno
, size
, parent_len
, tbno
;
1350 struct file_id
*fid
;
1351 struct icb_ext
*iext
;
1353 ud_printf("ud_dirmakedirect\n");
1355 ASSERT(RW_WRITE_HELD(&ip
->i_contents
));
1356 ASSERT(RW_WRITE_HELD(&dp
->i_rwlock
));
1358 parent_len
= sizeof (struct file_id
);
1360 if ((ip
->i_desc_type
!= ICB_FLAG_ONE_AD
) ||
1361 (parent_len
> ip
->i_max_emb
)) {
1364 * Allocate space for the directory we're creating.
1366 if ((err
= ud_alloc_space(ip
->i_vfs
, ip
->i_icb_prn
,
1367 0, 1, &blkno
, &size
, 0, 0)) != 0) {
1371 * init with the size of
1372 * directory with just the
1375 ip
->i_size
= sizeof (struct file_id
);
1376 ip
->i_flag
|= IUPD
|ICHG
|IATTCHG
;
1378 iext
->ib_prn
= ip
->i_icb_prn
;
1379 iext
->ib_block
= blkno
;
1380 iext
->ib_count
= ip
->i_size
;
1381 iext
->ib_offset
= 0;
1384 ip
->i_size
= sizeof (struct file_id
);
1385 ip
->i_flag
|= IUPD
|ICHG
|IATTCHG
;
1391 * Update the dp link count and write out the change.
1392 * This reflects the ".." entry we'll soon write.
1394 if (dp
->i_nlink
== MAXLINK
) {
1402 * Initialize directory with ".."
1403 * Since the parent directory is locked, we don't have to
1404 * worry about anything changing when we drop the write
1407 rw_exit(&ip
->i_contents
);
1408 if ((err
= fbread(ITOV(ip
), (offset_t
)0,
1409 ip
->i_udf
->udf_lbsize
, S_WRITE
, &fbp
)) != 0) {
1410 rw_enter(&ip
->i_contents
, RW_WRITER
);
1414 bzero(fbp
->fb_addr
, ip
->i_udf
->udf_lbsize
);
1416 fid
= (struct file_id
*)fbp
->fb_addr
;
1417 fid
->fid_ver
= SWAP_16(1);
1418 fid
->fid_flags
= FID_DIR
| FID_PARENT
;
1419 fid
->fid_icb
.lad_ext_len
= SWAP_32(dp
->i_udf
->udf_lbsize
);
1420 fid
->fid_icb
.lad_ext_loc
= SWAP_32(dp
->i_icb_block
);
1421 fid
->fid_icb
.lad_ext_prn
= SWAP_16(dp
->i_icb_prn
);
1424 * fid_idlen, fid_iulen and fid_spec are zero
1425 * due to bzero above
1428 if ((err
= ud_ip_off2bno(ip
, 0, &tbno
)) == 0) {
1429 ud_make_tag(ip
->i_udf
, &fid
->fid_tag
,
1430 UD_FILE_ID_DESC
, tbno
, FID_LEN(fid
));
1433 err
= ud_fbwrite(fbp
, ip
);
1434 rw_enter(&ip
->i_contents
, RW_WRITER
);
1440 ud_dirrename(struct ud_inode
*sdp
, struct ud_inode
*sip
,
1441 struct ud_inode
*tdp
, struct ud_inode
*tip
, char *namep
,
1442 uint8_t *buf
, struct slot
*slotp
, struct cred
*cr
)
1444 int32_t error
= 0, doingdirectory
;
1445 struct file_id
*fid
;
1447 ud_printf("ud_dirrename\n");
1448 ASSERT(sdp
->i_udf
!= NULL
);
1449 ASSERT(MUTEX_HELD(&sdp
->i_udf
->udf_rename_lck
));
1450 ASSERT(RW_WRITE_HELD(&tdp
->i_rwlock
));
1451 ASSERT(RW_WRITE_HELD(&tdp
->i_contents
));
1458 * Short circuit rename of something to itself.
1460 if (sip
->i_icb_lbano
== tip
->i_icb_lbano
) {
1461 return (ESAME
); /* special KLUDGE error code */
1464 * Everything is protected under the vfs_rename_lock so the ordering
1465 * of i_contents locks doesn't matter here.
1467 rw_enter(&sip
->i_contents
, RW_READER
);
1468 rw_enter(&tip
->i_contents
, RW_READER
);
1471 * Check that everything is on the same filesystem.
1473 if ((ITOV(tip
)->v_vfsp
!= ITOV(tdp
)->v_vfsp
) ||
1474 (ITOV(tip
)->v_vfsp
!= ITOV(sip
)->v_vfsp
)) {
1475 error
= EXDEV
; /* XXX archaic */
1480 * Must have write permission to rewrite target entry.
1482 if ((error
= ud_iaccess(tdp
, IWRITE
, cr
, 0)) != 0 ||
1483 (error
= ud_sticky_remove_access(tdp
, tip
, cr
)) != 0)
1487 * Ensure source and target are compatible (both directories
1488 * or both not directories). If target is a directory it must
1489 * be empty and have no links to it; in addition it must not
1490 * be a mount point, and both the source and target must be
1493 doingdirectory
= (sip
->i_type
== VDIR
);
1494 if (tip
->i_type
== VDIR
) {
1495 if (!doingdirectory
) {
1500 * vn_vfswlock will prevent mounts from using the directory
1501 * until we are done.
1503 if (vn_vfswlock(ITOV(tip
))) {
1507 if (vn_mountedvfs(ITOV(tip
)) != NULL
) {
1508 vn_vfsunlock(ITOV(tip
));
1512 if (!ud_dirempty(tip
, tdp
->i_uniqid
, cr
) || tip
->i_nlink
> 2) {
1513 vn_vfsunlock(ITOV(tip
));
1514 error
= EEXIST
; /* SIGH should be ENOTEMPTY */
1517 } else if (doingdirectory
) {
1523 * Rewrite the inode pointer for target name entry
1524 * from the target inode (ip) to the source inode (sip).
1525 * This prevents the target entry from disappearing
1526 * during a crash. Mark the directory inode to reflect the changes.
1528 dnlc_remove(ITOV(tdp
), namep
);
1529 fid
->fid_icb
.lad_ext_prn
= SWAP_16(sip
->i_icb_prn
);
1530 fid
->fid_icb
.lad_ext_loc
= SWAP_32(sip
->i_icb_block
);
1531 dnlc_enter(ITOV(tdp
), namep
, ITOV(sip
));
1533 ud_make_tag(tdp
->i_udf
, &fid
->fid_tag
, UD_FILE_ID_DESC
,
1534 SWAP_32(fid
->fid_tag
.tag_loc
), FID_LEN(fid
));
1536 error
= ud_write_fid(tdp
, slotp
, buf
);
1539 if (doingdirectory
) {
1540 vn_vfsunlock(ITOV(tip
));
1546 * Upgrade to write lock on tip
1548 rw_exit(&tip
->i_contents
);
1549 rw_enter(&tip
->i_contents
, RW_WRITER
);
1551 mutex_enter(&tdp
->i_tlock
);
1552 tdp
->i_flag
|= IUPD
|ICHG
;
1553 mutex_exit(&tdp
->i_tlock
);
1555 * Decrement the link count of the target inode.
1556 * Fix the ".." entry in sip to point to dp.
1557 * This is done after the new entry is on the disk.
1560 mutex_enter(&tip
->i_tlock
);
1561 tip
->i_flag
|= ICHG
;
1562 mutex_exit(&tip
->i_tlock
);
1564 if (doingdirectory
) {
1566 * The entry for tip no longer exists so I can unlock the
1569 vn_vfsunlock(ITOV(tip
));
1571 * Decrement target link count once more if it was a directory.
1573 if (tip
->i_nlink
!= 0) {
1575 "ud_direnter: target directory link count != 0");
1576 rw_exit(&tip
->i_contents
);
1577 rw_exit(&sip
->i_contents
);
1581 * Renaming a directory with the parent different
1582 * requires that ".." be rewritten. The window is
1583 * still there for ".." to be inconsistent, but this
1584 * is unavoidable, and a lot shorter than when it was
1585 * done in a user process. We decrement the link
1586 * count in the new parent as appropriate to reflect
1587 * the just-removed target. If the parent is the
1588 * same, this is appropriate since the original
1589 * directory is going away. If the new parent is
1590 * different, dirfixdotdot() will bump the link count
1594 mutex_enter(&tdp
->i_tlock
);
1595 tdp
->i_flag
|= ICHG
;
1596 mutex_exit(&tdp
->i_tlock
);
1599 rw_exit(&tip
->i_contents
);
1600 rw_exit(&sip
->i_contents
);
1601 error
= ud_dirfixdotdot(sip
, sdp
, tdp
);
1607 rw_exit(&tip
->i_contents
);
1608 rw_exit(&sip
->i_contents
);
1614 * 1. When we find a slot that belonged to a file which was deleted
1615 * and is in the middle of the directory
1616 * 2. There is not empty slot available. The new entry
1617 * will be at the end of the directory and fits in the same block.
1618 * 3. There is no empty slot available. The new
1619 * entry will not fit the left over directory
1620 * so we need to allocate a new block. If
1621 * we cannot allocate a proximity block we need
1622 * to allocate a new icb, and data block.
1625 ud_dirprepareentry(struct ud_inode
*dp
,
1626 struct slot
*slotp
, uint8_t *buf
, struct cred
*cr
)
1631 uint32_t entrysize
, count
, offset
, tbno
, old_size
, off
;
1632 struct file_id
*fid
;
1633 int32_t lbsize
, lbmask
, mask
;
1635 ASSERT(RW_WRITE_HELD(&dp
->i_rwlock
));
1637 ASSERT((slotp
->status
== NONE
) || (slotp
->status
== FOUND
));
1639 ud_printf("ud_dirprepareentry\n");
1640 lbsize
= dp
->i_udf
->udf_lbsize
;
1641 lbmask
= dp
->i_udf
->udf_lbmask
;
1644 fid
= (struct file_id
*)buf
;
1645 entrysize
= FID_LEN(fid
);
1648 * If we didn't find a slot, then indicate that the
1649 * new slot belongs at the end of the directory.
1650 * If we found a slot, then the new entry can be
1651 * put at slotp->offset.
1653 if (slotp
->status
== NONE
) {
1655 * We did not find a slot, the next
1656 * entry will be in the end of the directory
1657 * see if we can fit the new entry inside
1658 * the old block. If not allocate a new block.
1660 if (entrysize
> slotp
->size
) {
1662 * extend the directory
1663 * size by one new block
1665 old_dtype
= dp
->i_desc_type
;
1666 old_size
= (uint32_t)dp
->i_size
;
1667 error
= ud_bmap_write(dp
, slotp
->offset
,
1668 blkoff(dp
->i_udf
, slotp
->offset
) + entrysize
,
1673 if (old_dtype
!= dp
->i_desc_type
) {
1675 * oops we changed the astrat
1676 * of the file, we have to
1678 * fortunately we donot have more
1679 * than one lbsize to handle here
1681 if ((error
= ud_ip_off2bno(dp
,
1685 if ((error
= fbread(ITOV(dp
), 0,
1686 dp
->i_udf
->udf_lbsize
,
1687 S_WRITE
, &fbp
)) != 0) {
1691 while (off
< old_size
) {
1692 struct file_id
*tfid
;
1694 tfid
= (struct file_id
*)
1695 (fbp
->fb_addr
+ off
);
1697 ud_make_tag(dp
->i_udf
, &tfid
->fid_tag
,
1698 UD_FILE_ID_DESC
, tbno
,
1701 off
+= FID_LEN(tfid
);
1703 if (error
= ud_fbwrite(fbp
, dp
)) {
1708 /* Extend the directory size */
1709 if (dp
->i_desc_type
!= ICB_FLAG_ONE_AD
) {
1711 dp
->i_ext
[dp
->i_ext_used
- 1].ib_count
+=
1715 dp
->i_size
+= entrysize
;
1716 dp
->i_flag
|= IUPD
|ICHG
|IATTCHG
;
1718 } else if (slotp
->status
!= FOUND
) {
1719 cmn_err(CE_WARN
, "status is not NONE/FOUND");
1723 if ((error
= ud_ip_off2bno(dp
, slotp
->offset
, &tbno
)) != 0) {
1726 ud_make_tag(dp
->i_udf
, &fid
->fid_tag
, UD_FILE_ID_DESC
,
1727 tbno
, FID_LEN(fid
));
1730 * fbread cannot cross a
1731 * MAXBSIZE boundary so handle it here
1733 offset
= slotp
->offset
;
1734 if ((error
= fbread(ITOV(dp
), offset
& mask
, lbsize
,
1735 S_WRITE
, &fbp
)) != 0) {
1738 if ((offset
& mask
) != ((offset
+ entrysize
) & mask
)) {
1739 count
= entrysize
- ((offset
+ entrysize
) & lbmask
);
1743 bcopy((caddr_t
)buf
, fbp
->fb_addr
+ (offset
& lbmask
), count
);
1745 if (error
= ud_fbwrite(fbp
, dp
)) {
1749 if (entrysize
> count
) {
1750 if ((error
= fbread(ITOV(dp
), (offset
+ entrysize
) & mask
,
1751 lbsize
, S_WRITE
, &fbp
)) != 0) {
1754 bcopy((caddr_t
)(buf
+ count
), fbp
->fb_addr
, entrysize
- count
);
1755 if (error
= ud_fbwrite(fbp
, dp
)) {
1760 dp
->i_flag
|= IUPD
|ICHG
|IATTCHG
;
1767 * Fix the FID_PARENT entry of the child directory so that it points
1768 * to the new parent directory instead of the old one. Routine
1769 * assumes that dp is a directory and that all the inodes are on
1770 * the same file system.
1773 ud_dirfixdotdot(struct ud_inode
*dp
,
1774 struct ud_inode
*opdp
, struct ud_inode
*npdp
)
1778 struct file_id
*fid
;
1779 uint32_t loc
, dummy
, tbno
;
1781 ud_printf("ud_dirfixdotdot\n");
1783 ASSERT(opdp
->i_type
== VDIR
);
1784 ASSERT(npdp
->i_type
== VDIR
);
1786 ASSERT(RW_WRITE_HELD(&npdp
->i_rwlock
));
1788 err
= fbread(ITOV(dp
), (offset_t
)0,
1789 dp
->i_udf
->udf_lbsize
, S_WRITE
, &fbp
);
1791 if (err
|| dp
->i_nlink
== 0 ||
1792 dp
->i_size
< sizeof (struct file_id
)) {
1796 if ((err
= ud_ip_off2bno(dp
, 0, &tbno
)) != 0) {
1800 fid
= (struct file_id
*)fbp
->fb_addr
;
1801 if ((ud_verify_tag_and_desc(&fid
->fid_tag
, UD_FILE_ID_DESC
,
1803 1, dp
->i_udf
->udf_lbsize
) != 0) ||
1804 ((fid
->fid_flags
& (FID_DIR
| FID_PARENT
)) !=
1805 (FID_DIR
| FID_PARENT
))) {
1810 loc
= ud_xlate_to_daddr(dp
->i_udf
,
1811 SWAP_16(fid
->fid_icb
.lad_ext_prn
),
1812 SWAP_32(fid
->fid_icb
.lad_ext_loc
), 1, &dummy
);
1814 if (loc
== npdp
->i_icb_lbano
) {
1819 * Increment the link count in the new parent inode and force it out.
1821 if (npdp
->i_nlink
== MAXLINK
) {
1827 mutex_enter(&npdp
->i_tlock
);
1828 npdp
->i_flag
|= ICHG
;
1829 mutex_exit(&npdp
->i_tlock
);
1833 * Rewrite the child FID_PARENT entry and force it out.
1835 dnlc_remove(ITOV(dp
), "..");
1836 fid
->fid_icb
.lad_ext_loc
= SWAP_32(npdp
->i_icb_block
);
1837 fid
->fid_icb
.lad_ext_prn
= SWAP_16(npdp
->i_icb_prn
);
1838 ud_make_tag(npdp
->i_udf
, &fid
->fid_tag
,
1839 UD_FILE_ID_DESC
, tbno
, FID_LEN(fid
));
1840 dnlc_enter(ITOV(dp
), "..", ITOV(npdp
));
1842 err
= ud_fbwrite(fbp
, dp
);
1849 * Decrement the link count of the old parent inode and force
1850 * it out. If opdp is NULL, then this is a new directory link;
1851 * it has no parent, so we need not do anything.
1854 rw_enter(&opdp
->i_contents
, RW_WRITER
);
1855 if (opdp
->i_nlink
!= 0) {
1857 mutex_enter(&opdp
->i_tlock
);
1858 opdp
->i_flag
|= ICHG
;
1859 mutex_exit(&opdp
->i_tlock
);
1862 rw_exit(&opdp
->i_contents
);
1868 fbrelse(fbp
, S_OTHER
);
1874 ud_write_fid(struct ud_inode
*dp
, struct slot
*slot
, uint8_t *buf
)
1876 struct udf_vfs
*udf_vfsp
;
1878 struct file_id
*fid
;
1880 uint32_t lbsize
, lbmask
, count
, old_count
;
1886 udf_vfsp
= dp
->i_udf
;
1888 lbsize
= dp
->i_udf
->udf_lbsize
;
1889 lbmask
= dp
->i_udf
->udf_lbmask
;
1891 if (((uint8_t *)fid
>= buf
) &&
1892 ((uint8_t *)fid
< &buf
[udf_vfsp
->udf_lbsize
])) {
1894 if ((error
= fbread(ITOV(dp
),
1895 (offset_t
)(slot
->offset
& ~lbmask
),
1896 lbsize
, S_WRITE
, &lfbp
)) != 0) {
1902 * We do not need to write the
1903 * file name. So check if the entry
1904 * does not cross a block boundary
1905 * and write only required portions
1907 if (((slot
->offset
& lbmask
) +
1908 sizeof (struct file_id
)) > lbsize
) {
1910 if ((slot
->offset
& lbmask
) != 0) {
1911 old_count
= lbsize
-
1912 (slot
->offset
& lbmask
);
1913 count
= (slot
->offset
+
1914 sizeof (struct file_id
)) &
1918 count
= sizeof (struct file_id
);
1921 bcopy(buf
, lfbp
->fb_addr
+
1922 (slot
->offset
& lbmask
), old_count
);
1923 bcopy(buf
+ old_count
,
1924 slot
->fbp
->fb_addr
, count
);
1926 error
= ud_fbwrite(lfbp
, dp
);
1928 error
= ud_fbwrite(slot
->fbp
, dp
);
1930 bcopy(buf
, lfbp
->fb_addr
+
1931 (slot
->offset
& lbmask
),
1932 sizeof (struct file_id
));
1934 error
= ud_fbwrite(lfbp
, dp
);
1936 fbrelse(slot
->fbp
, S_OTHER
);
1939 if ((error
= ud_fbwrite(slot
->fbp
, dp
)) != 0) {
1940 fid
->fid_flags
&= ~FID_DELETED
;
1941 ud_make_tag(dp
->i_udf
, &fid
->fid_tag
, UD_FILE_ID_DESC
,
1942 SWAP_32(fid
->fid_tag
.tag_loc
), FID_LEN(fid
));