2 * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/fs/udf/udf_vnops.c,v 1.33 2003/12/07 05:04:49 scottl Exp $
27 * $DragonFly: src/sys/vfs/udf/udf_vnops.c,v 1.32 2007/11/20 21:03:51 dillon Exp $
31 /* Take care of the vnode side of things */
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/namei.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
39 #include <sys/module.h>
41 #include <sys/iconv.h>
42 #include <sys/mount.h>
43 #include <sys/vnode.h>
44 #include <sys/dirent.h>
45 #include <sys/queue.h>
46 #include <sys/unistd.h>
48 #include <machine/inttypes.h>
50 #include <vfs/udf/ecma167-udf.h>
51 #include <vfs/udf/osta.h>
52 #include <vfs/udf/udf.h>
53 #include <vfs/udf/udf_mount.h>
55 static int udf_access(struct vop_access_args
*);
56 static int udf_getattr(struct vop_getattr_args
*);
57 static int udf_ioctl(struct vop_ioctl_args
*);
58 static int udf_pathconf(struct vop_pathconf_args
*);
59 static int udf_read(struct vop_read_args
*);
60 static int udf_readdir(struct vop_readdir_args
*);
61 static int udf_readlink(struct vop_readlink_args
*ap
);
62 static int udf_strategy(struct vop_strategy_args
*);
63 static int udf_bmap(struct vop_bmap_args
*);
64 static int udf_lookup(struct vop_old_lookup_args
*);
65 static int udf_reclaim(struct vop_reclaim_args
*);
66 static int udf_readatoffset(struct udf_node
*, int *, int, struct buf
**, uint8_t **);
67 static int udf_bmap_internal(struct udf_node
*, uint32_t, daddr_t
*, uint32_t *);
69 struct vop_ops udf_vnode_vops
= {
70 .vop_default
= vop_defaultop
,
71 .vop_access
= udf_access
,
73 .vop_old_lookup
= udf_lookup
,
74 .vop_getattr
= udf_getattr
,
75 .vop_ioctl
= udf_ioctl
,
76 .vop_pathconf
= udf_pathconf
,
78 .vop_readdir
= udf_readdir
,
79 .vop_readlink
= udf_readlink
,
80 .vop_reclaim
= udf_reclaim
,
81 .vop_strategy
= udf_strategy
84 MALLOC_DEFINE(M_UDFFID
, "UDF FID", "UDF FileId structure");
85 MALLOC_DEFINE(M_UDFDS
, "UDF DS", "UDF Dirstream structure");
87 #define UDF_INVALID_BMAP -1
89 /* Look up a udf_node based on the ino_t passed in and return it's vnode */
91 udf_hashlookup(struct udf_mnt
*udfmp
, ino_t id
, struct vnode
**vpp
)
93 struct udf_node
*node
;
94 struct udf_hash_lh
*lh
;
100 lwkt_gettoken(&hashlock
, &udfmp
->hash_token
);
102 lh
= &udfmp
->hashtbl
[id
% udfmp
->hashsz
];
104 lwkt_reltoken(&hashlock
);
107 LIST_FOREACH(node
, lh
, le
) {
108 if (node
->hash_id
!= id
)
111 if (vget(vp
, LK_EXCLUSIVE
))
114 * We must check to see if the inode has been ripped
115 * out from under us after blocking.
117 lh
= &udfmp
->hashtbl
[id
% udfmp
->hashsz
];
118 LIST_FOREACH(node
, lh
, le
) {
119 if (node
->hash_id
== id
)
122 if (node
== NULL
|| vp
!= node
->i_vnode
) {
126 lwkt_reltoken(&hashlock
);
131 lwkt_reltoken(&hashlock
);
136 udf_hashins(struct udf_node
*node
)
138 struct udf_mnt
*udfmp
;
139 struct udf_hash_lh
*lh
;
140 lwkt_tokref hashlock
;
144 lwkt_gettoken(&hashlock
, &udfmp
->hash_token
);
145 lh
= &udfmp
->hashtbl
[node
->hash_id
% udfmp
->hashsz
];
148 LIST_INSERT_HEAD(lh
, node
, le
);
149 lwkt_reltoken(&hashlock
);
155 udf_hashrem(struct udf_node
*node
)
157 struct udf_mnt
*udfmp
;
158 struct udf_hash_lh
*lh
;
159 lwkt_tokref hashlock
;
163 lwkt_gettoken(&hashlock
, &udfmp
->hash_token
);
164 lh
= &udfmp
->hashtbl
[node
->hash_id
% udfmp
->hashsz
];
166 panic("hash entry is NULL, node->hash_id= %"PRId64
"\n", node
->hash_id
);
167 LIST_REMOVE(node
, le
);
168 lwkt_reltoken(&hashlock
);
174 udf_allocv(struct mount
*mp
, struct vnode
**vpp
)
179 error
= getnewvnode(VT_UDF
, mp
, &vp
, 0, 0);
181 kprintf("udf_allocv: failed to allocate new vnode\n");
189 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */
191 udf_permtomode(struct udf_node
*node
)
197 perm
= node
->fentry
->perm
;
198 flags
= node
->fentry
->icbtag
.flags
;
200 mode
= perm
& UDF_FENTRY_PERM_USER_MASK
;
201 mode
|= ((perm
& UDF_FENTRY_PERM_GRP_MASK
) >> 2);
202 mode
|= ((perm
& UDF_FENTRY_PERM_OWNER_MASK
) >> 4);
203 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_STICKY
) << 4);
204 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_SETGID
) << 6);
205 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_SETUID
) << 8);
211 udf_access(struct vop_access_args
*a
)
214 struct udf_node
*node
;
215 mode_t a_mode
, mode
, mask
;
216 struct ucred
*cred
= a
->a_cred
;
224 if (a_mode
& VWRITE
) {
225 switch (vp
->v_type
) {
236 mode
= udf_permtomode(node
);
238 if (cred
->cr_uid
== 0)
243 /* Otherwise, check the owner. */
244 if (cred
->cr_uid
== node
->fentry
->uid
) {
251 return((mode
& mask
) == mask
? 0 : EACCES
);
254 /* Otherwise, check the groups. */
255 for (i
= 0, gp
= cred
->cr_groups
; i
< cred
->cr_ngroups
; i
++, gp
++)
256 if (node
->fentry
->gid
== *gp
) {
263 return((mode
& mask
) == mask
? 0 : EACCES
);
266 /* Otherwise, check everyone else. */
273 return((mode
& mask
) == mask
? 0 : EACCES
);
276 static int mon_lens
[2][12] = {
277 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
278 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
282 udf_isaleapyear(int year
)
286 i
= (year
% 4) ? 0 : 1;
287 i
&= (year
% 100) ? 1 : 0;
288 i
|= (year
% 400) ? 0 : 1;
294 * XXX This is just a rough hack. Daylight savings isn't calculated and tv_nsec
296 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>.
299 udf_timetotimespec(struct timestamp
*time
, struct timespec
*t
)
301 int i
, lpyear
, daysinyear
;
303 uint16_t u_tz_offset
;
309 /* DirectCD seems to like using bogus year values */
310 if (time
->year
< 1970) {
315 /* Calculate the time and day */
316 t
->tv_sec
= time
->second
;
317 t
->tv_sec
+= time
->minute
* 60;
318 t
->tv_sec
+= time
->hour
* 3600;
319 t
->tv_sec
+= time
->day
* 3600 * 24;
321 /* Calclulate the month */
322 lpyear
= udf_isaleapyear(time
->year
);
323 for (i
= 1; i
< time
->month
; i
++)
324 t
->tv_sec
+= mon_lens
[lpyear
][i
] * 3600 * 24;
326 /* Speed up the calculation */
327 if (time
->year
> 1979)
328 t
->tv_sec
+= 315532800;
329 if (time
->year
> 1989)
330 t
->tv_sec
+= 315619200;
331 if (time
->year
> 1999)
332 t
->tv_sec
+= 315532800;
333 for (i
= 2000; i
< time
->year
; i
++) {
334 daysinyear
= udf_isaleapyear(i
) + 365 ;
335 t
->tv_sec
+= daysinyear
* 3600 * 24;
339 * Calculate the time zone. The timezone is 12 bit signed 2's
340 * compliment, so we gotta do some extra magic to handle it right.
342 tz
.u_tz_offset
= time
->type_tz
;
343 tz
.u_tz_offset
&= 0x0fff;
344 if (tz
.u_tz_offset
& 0x0800)
345 tz
.u_tz_offset
|= 0xf000; /* extend the sign to 16 bits */
346 if ((time
->type_tz
& 0x1000) && (tz
.s_tz_offset
!= -2047))
347 t
->tv_sec
-= tz
.s_tz_offset
* 60;
353 udf_getattr(struct vop_getattr_args
*a
)
356 struct udf_node
*node
;
358 struct file_entry
*fentry
;
366 fentry
= node
->fentry
;
368 vap
->va_fsid
= dev2udev(node
->i_dev
);
369 vap
->va_fileid
= node
->hash_id
;
370 vap
->va_mode
= udf_permtomode(node
);
371 vap
->va_nlink
= fentry
->link_cnt
;
373 * XXX The spec says that -1 is valid for uid/gid and indicates an
374 * invalid uid/gid. How should this be represented?
376 vap
->va_uid
= (fentry
->uid
== 0xffffffff) ? 0 : fentry
->uid
;
377 vap
->va_gid
= (fentry
->gid
== 0xffffffff) ? 0 : fentry
->gid
;
378 udf_timetotimespec(&fentry
->atime
, &vap
->va_atime
);
379 udf_timetotimespec(&fentry
->mtime
, &vap
->va_mtime
);
380 vap
->va_ctime
= vap
->va_mtime
; /* XXX Stored as an Extended Attribute */
381 vap
->va_rmajor
= VNOVAL
;
382 vap
->va_rminor
= VNOVAL
;
383 if (vp
->v_type
& VDIR
) {
385 * Directories that are recorded within their ICB will show
386 * as having 0 blocks recorded. Since tradition dictates
387 * that directories consume at least one logical block,
390 if (fentry
->logblks_rec
!= 0)
391 vap
->va_size
= fentry
->logblks_rec
* node
->udfmp
->bsize
;
393 vap
->va_size
= node
->udfmp
->bsize
;
395 vap
->va_size
= fentry
->inf_len
;
398 vap
->va_blocksize
= node
->udfmp
->bsize
;
399 vap
->va_bytes
= fentry
->inf_len
;
400 vap
->va_type
= vp
->v_type
;
401 vap
->va_filerev
= 0; /* XXX */
406 * File specific ioctls. DeCSS candidate?
409 udf_ioctl(struct vop_ioctl_args
*a
)
411 kprintf("%s called\n", __func__
);
416 * I'm not sure that this has much value in a read-only filesystem, but
420 udf_pathconf(struct vop_pathconf_args
*a
)
425 *a
->a_retval
= 65535;
428 *a
->a_retval
= NAME_MAX
;
431 *a
->a_retval
= PATH_MAX
;
442 udf_read(struct vop_read_args
*a
)
444 struct vnode
*vp
= a
->a_vp
;
445 struct uio
*uio
= a
->a_uio
;
446 struct udf_node
*node
= VTON(vp
);
450 int size
, fsize
, offset
;
452 if (uio
->uio_offset
< 0)
455 fsize
= node
->fentry
->inf_len
;
457 while (uio
->uio_offset
< fsize
&& uio
->uio_resid
> 0) {
458 offset
= uio
->uio_offset
;
459 size
= uio
->uio_resid
;
460 error
= udf_readatoffset(node
, &size
, offset
, &bp
, &data
);
462 error
= uiomove(data
, size
, uio
);
473 * Call the OSTA routines to translate the name from a CS0 dstring to a
474 * 16-bit Unicode String. Hooks need to be placed in here to translate from
475 * Unicode to the encoding that the kernel/user expects. Return the length
476 * of the translated string.
479 udf_transname(char *cs0string
, char *destname
, int len
, struct udf_mnt
*udfmp
)
481 unicode_t
*transname
;
482 int i
, unilen
= 0, destlen
;
484 /* Convert 16-bit Unicode to destname */
485 /* allocate a buffer big enough to hold an 8->16 bit expansion */
486 transname
= kmalloc(NAME_MAX
* sizeof(unicode_t
), M_TEMP
, M_WAITOK
| M_ZERO
);
488 if ((unilen
= udf_UncompressUnicode(len
, cs0string
, transname
)) == -1) {
489 kprintf("udf: Unicode translation failed\n");
490 kfree(transname
, M_TEMP
);
494 for (i
= 0; i
< unilen
; i
++)
495 if (transname
[i
] & 0xff00)
496 destname
[i
] = '.'; /* Fudge the 16bit chars */
498 destname
[i
] = transname
[i
] & 0xff;
499 kfree(transname
, M_TEMP
);
500 destname
[unilen
] = 0;
507 * Compare a CS0 dstring with a name passed in from the VFS layer. Return
508 * 0 on a successful match, nonzero therwise. Unicode work may need to be done
512 udf_cmpname(char *cs0string
, char *cmpname
, int cs0len
, int cmplen
, struct udf_mnt
*udfmp
)
517 /* This is overkill, but not worth creating a new zone */
519 transname
= kmalloc(NAME_MAX
* sizeof(unicode_t
), M_TEMP
,
522 cs0len
= udf_transname(cs0string
, transname
, cs0len
, udfmp
);
524 /* Easy check. If they aren't the same length, they aren't equal */
525 if ((cs0len
== 0) || (cs0len
!= cmplen
))
528 error
= bcmp(transname
, cmpname
, cmplen
);
530 kfree(transname
, M_TEMP
);
535 struct dirent
*dirent
;
542 static struct udf_dirstream
*
543 udf_opendir(struct udf_node
*node
, int offset
, int fsize
, struct udf_mnt
*udfmp
)
545 struct udf_dirstream
*ds
;
547 ds
= kmalloc(sizeof(*ds
), M_UDFDS
, M_WAITOK
| M_ZERO
);
557 static struct fileid_desc
*
558 udf_getfid(struct udf_dirstream
*ds
)
560 struct fileid_desc
*fid
;
561 int error
, frag_size
= 0, total_fid_size
;
563 /* End of directory? */
564 if (ds
->offset
+ ds
->off
>= ds
->fsize
) {
569 /* Grab the first extent of the directory */
574 error
= udf_readatoffset(ds
->node
, &ds
->size
, ds
->offset
,
583 * Clean up from a previous fragmented FID.
584 * XXX Is this the right place for this?
586 if (ds
->fid_fragment
&& ds
->buf
!= NULL
) {
587 ds
->fid_fragment
= 0;
588 kfree(ds
->buf
, M_UDFFID
);
591 fid
= (struct fileid_desc
*)&ds
->data
[ds
->off
];
594 * Check to see if the fid is fragmented. The first test
595 * ensures that we don't wander off the end of the buffer
596 * looking for the l_iu and l_fi fields.
598 if (ds
->off
+ UDF_FID_SIZE
> ds
->size
||
599 ds
->off
+ fid
->l_iu
+ fid
->l_fi
+ UDF_FID_SIZE
> ds
->size
) {
601 /* Copy what we have of the fid into a buffer */
602 frag_size
= ds
->size
- ds
->off
;
603 if (frag_size
>= ds
->udfmp
->bsize
) {
604 kprintf("udf: invalid FID fragment\n");
610 * File ID descriptors can only be at most one
611 * logical sector in size.
613 ds
->buf
= kmalloc(ds
->udfmp
->bsize
, M_UDFFID
, M_WAITOK
| M_ZERO
);
614 bcopy(fid
, ds
->buf
, frag_size
);
616 /* Reduce all of the casting magic */
617 fid
= (struct fileid_desc
*)ds
->buf
;
622 /* Fetch the next allocation */
623 ds
->offset
+= ds
->size
;
625 error
= udf_readatoffset(ds
->node
, &ds
->size
, ds
->offset
,
633 * If the fragment was so small that we didn't get
634 * the l_iu and l_fi fields, copy those in.
636 if (frag_size
< UDF_FID_SIZE
)
637 bcopy(ds
->data
, &ds
->buf
[frag_size
],
638 UDF_FID_SIZE
- frag_size
);
641 * Now that we have enough of the fid to work with,
642 * copy in the rest of the fid from the new
645 total_fid_size
= UDF_FID_SIZE
+ fid
->l_iu
+ fid
->l_fi
;
646 if (total_fid_size
> ds
->udfmp
->bsize
) {
647 kprintf("udf: invalid FID\n");
651 bcopy(ds
->data
, &ds
->buf
[frag_size
],
652 total_fid_size
- frag_size
);
654 ds
->fid_fragment
= 1;
656 total_fid_size
= fid
->l_iu
+ fid
->l_fi
+ UDF_FID_SIZE
;
659 * Update the offset. Align on a 4 byte boundary because the
662 ds
->this_off
= ds
->off
;
663 if (!ds
->fid_fragment
)
664 ds
->off
+= (total_fid_size
+ 3) & ~0x03;
666 ds
->off
= (total_fid_size
- frag_size
+ 3) & ~0x03;
672 udf_closedir(struct udf_dirstream
*ds
)
678 if (ds
->fid_fragment
&& ds
->buf
!= NULL
)
679 kfree(ds
->buf
, M_UDFFID
);
685 udf_readdir(struct vop_readdir_args
*a
)
689 struct udf_node
*node
;
690 struct udf_mnt
*udfmp
;
691 struct fileid_desc
*fid
;
692 struct udf_uiodir uiodir
;
693 struct udf_dirstream
*ds
;
694 off_t
*cookies
= NULL
;
701 if ((error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
)) != 0)
709 if (a
->a_ncookies
!= NULL
) {
711 * Guess how many entries are needed. If we run out, this
712 * function will be called again and thing will pick up were
715 ncookies
= uio
->uio_resid
/ 8 + 1;
718 cookies
= kmalloc(sizeof(off_t
) * ncookies
, M_TEMP
, M_WAITOK
);
719 uiodir
.ncookies
= ncookies
;
720 uiodir
.cookies
= cookies
;
723 uiodir
.cookies
= NULL
;
726 * Iterate through the file id descriptors. Give the parent dir
727 * entry special attention.
729 ds
= udf_opendir(node
, uio
->uio_offset
, node
->fentry
->inf_len
,
732 name
= kmalloc(NAME_MAX
, M_TEMP
, M_WAITOK
);
734 while ((fid
= udf_getfid(ds
)) != NULL
) {
736 /* XXX Should we return an error on a bad fid? */
737 if (udf_checktag(&fid
->tag
, TAGID_FID
)) {
738 kprintf("Invalid FID tag\n");
743 /* Is this a deleted file? */
744 if (fid
->file_char
& UDF_FILE_CHAR_DEL
)
747 if ((fid
->l_fi
== 0) && (fid
->file_char
& UDF_FILE_CHAR_PAR
)) {
748 /* Do up the '.' and '..' entries. Dummy values are
749 * used for the cookies since the offset here is
750 * usually zero, and NFS doesn't like that value
752 if (uiodir
.cookies
!= NULL
) {
753 if (++uiodir
.acookies
> uiodir
.ncookies
) {
757 *uiodir
.cookies
++ = 1;
759 if (vop_write_dirent(&error
, uio
, node
->hash_id
, DT_DIR
,
768 if (uiodir
.cookies
!= NULL
) {
769 if (++uiodir
.acookies
> uiodir
.ncookies
) {
773 *uiodir
.cookies
++ = 2;
775 if (vop_write_dirent(&error
, uio
, udf_getid(&fid
->icb
),
785 uint8_t d_type
= (fid
->file_char
& UDF_FILE_CHAR_DIR
) ?
787 uint16_t namelen
= udf_transname(&fid
->data
[fid
->l_iu
],
788 name
, fid
->l_fi
, udfmp
);
790 if (uiodir
.cookies
!= NULL
) {
791 if (++uiodir
.acookies
> uiodir
.ncookies
) {
795 *uiodir
.cookies
++ = ds
->this_off
;
797 if (vop_write_dirent(&error
, uio
, udf_getid(&fid
->icb
),
798 d_type
, namelen
, name
)) {
808 kprintf("uiomove returned %d\n", error
);
816 /* tell the calling layer whether we need to be called again */
817 *a
->a_eofflag
= uiodir
.eofflag
;
818 uio
->uio_offset
= ds
->offset
+ ds
->off
;
825 if (a
->a_ncookies
!= NULL
) {
827 kfree(cookies
, M_TEMP
);
829 *a
->a_ncookies
= uiodir
.acookies
;
830 *a
->a_cookies
= cookies
;
838 /* Are there any implementations out there that do soft-links? */
840 udf_readlink(struct vop_readlink_args
*ap
)
842 kprintf("%s called\n", __func__
);
847 udf_strategy(struct vop_strategy_args
*ap
)
853 struct udf_node
*node
;
862 nbio
= push_bio(bio
);
863 if (nbio
->bio_offset
== NOOFFSET
) {
865 * Files that are embedded in the fentry don't translate well
866 * to a block number. Reject.
868 if (udf_bmap_internal(node
,
870 &dblkno
, &maxsize
)) {
872 nbio
->bio_offset
= NOOFFSET
;
874 nbio
->bio_offset
= dbtob(dblkno
);
877 if (nbio
->bio_offset
== NOOFFSET
) {
878 /* I/O was never started on nbio, must biodone(bio) */
882 vn_strategy(node
->i_devvp
, nbio
);
887 udf_bmap(struct vop_bmap_args
*a
)
889 struct udf_node
*node
;
894 node
= VTON(a
->a_vp
);
896 if (a
->a_doffsetp
== NULL
)
899 KKASSERT(a
->a_loffset
% node
->udfmp
->bsize
== 0);
901 error
= udf_bmap_internal(node
, a
->a_loffset
, &lsector
, &max_size
);
905 /* Translate logical to physical sector number */
906 *a
->a_doffsetp
= (off_t
)lsector
<< node
->udfmp
->bshift
;
908 /* Punt on read-ahead for now */
917 * The all powerful VOP_LOOKUP().
920 udf_lookup(struct vop_old_lookup_args
*a
)
923 struct vnode
*tdp
= NULL
;
924 struct vnode
**vpp
= a
->a_vpp
;
925 struct udf_node
*node
;
926 struct udf_mnt
*udfmp
;
927 struct fileid_desc
*fid
= NULL
;
928 struct udf_dirstream
*ds
;
930 globaldata_t gd
= mycpu
;
936 int offset
, error
= 0;
937 int numdirpasses
, fsize
;
942 nameiop
= a
->a_cnp
->cn_nameiop
;
943 flags
= a
->a_cnp
->cn_flags
;
944 nameptr
= a
->a_cnp
->cn_nameptr
;
945 namelen
= a
->a_cnp
->cn_namelen
;
946 fsize
= node
->fentry
->inf_len
;
947 td
= a
->a_cnp
->cn_td
;
952 * If this is a LOOKUP and we've already partially searched through
953 * the directory, pick up where we left off and flag that the
954 * directory may need to be searched twice. For a full description,
955 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup()
957 if (nameiop
!= NAMEI_LOOKUP
|| node
->diroff
== 0 ||
958 node
->diroff
> fsize
) {
962 offset
= node
->diroff
;
964 gd
->gd_nchstats
->ncs_2passes
++;
968 ds
= udf_opendir(node
, offset
, fsize
, udfmp
);
970 while ((fid
= udf_getfid(ds
)) != NULL
) {
971 /* XXX Should we return an error on a bad fid? */
972 if (udf_checktag(&fid
->tag
, TAGID_FID
)) {
973 kprintf("udf_lookup: Invalid tag\n");
978 /* Is this a deleted file? */
979 if (fid
->file_char
& UDF_FILE_CHAR_DEL
)
982 if ((fid
->l_fi
== 0) && (fid
->file_char
& UDF_FILE_CHAR_PAR
)) {
983 if (flags
& CNP_ISDOTDOT
) {
984 id
= udf_getid(&fid
->icb
);
988 if (!(udf_cmpname(&fid
->data
[fid
->l_iu
],
989 nameptr
, fid
->l_fi
, namelen
, udfmp
))) {
990 id
= udf_getid(&fid
->icb
);
999 /* XXX Bail out here? */
1005 /* Did we have a match? */
1007 error
= udf_vget(udfmp
->im_mountp
, id
, &tdp
);
1010 * Remember where this entry was if it's the final
1013 if (nameiop
== NAMEI_LOOKUP
)
1014 node
->diroff
= ds
->offset
+ ds
->off
;
1015 if (numdirpasses
== 2)
1016 gd
->gd_nchstats
->ncs_pass2
++;
1017 if ((flags
& CNP_LOCKPARENT
) == 0) {
1018 a
->a_cnp
->cn_flags
|= CNP_PDIRUNLOCK
;
1025 /* Name wasn't found on this pass. Do another pass? */
1026 if (numdirpasses
== 2) {
1032 if (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
) {
1044 udf_reclaim(struct vop_reclaim_args
*a
)
1047 struct udf_node
*unode
;
1052 if (unode
!= NULL
) {
1054 if (unode
->i_devvp
) {
1055 vrele(unode
->i_devvp
);
1059 if (unode
->fentry
!= NULL
)
1060 kfree(unode
->fentry
, M_UDFFENTRY
);
1061 kfree(unode
, M_UDFNODE
);
1069 * Read the block and then set the data pointer to correspond with the
1070 * offset passed in. Only read in at most 'size' bytes, and then set 'size'
1071 * to the number of bytes pointed to. If 'size' is zero, try to read in a
1074 * Note that *bp may be assigned error or not.
1076 * XXX 'size' is limited to the logical block size for now due to problems
1080 udf_readatoffset(struct udf_node
*node
, int *size
, int offset
, struct buf
**bp
,
1083 struct udf_mnt
*udfmp
;
1084 struct file_entry
*fentry
= NULL
;
1090 udfmp
= node
->udfmp
;
1093 error
= udf_bmap_internal(node
, offset
, §or
, &max_size
);
1094 if (error
== UDF_INVALID_BMAP
) {
1096 * This error means that the file *data* is stored in the
1097 * allocation descriptor field of the file entry.
1099 fentry
= node
->fentry
;
1100 *data
= &fentry
->data
[fentry
->l_ea
];
1101 *size
= fentry
->l_ad
;
1103 } else if (error
!= 0) {
1107 /* Adjust the size so that it is within range */
1108 if (*size
== 0 || *size
> max_size
)
1110 *size
= min(*size
, MAXBSIZE
);
1112 if ((error
= udf_readlblks(udfmp
, sector
, *size
, bp
))) {
1113 kprintf("warning: udf_readlblks returned error %d\n", error
);
1114 /* note: *bp may be non-NULL */
1119 *data
= (uint8_t *)&bp1
->b_data
[offset
% udfmp
->bsize
];
1124 * Translate a file offset into a logical block and then into a physical
1128 udf_bmap_internal(struct udf_node
*node
, uint32_t offset
, daddr_t
*sector
, uint32_t *max_size
)
1130 struct udf_mnt
*udfmp
;
1131 struct file_entry
*fentry
;
1133 struct icb_tag
*tag
;
1134 uint32_t icblen
= 0;
1136 int ad_offset
, ad_num
= 0;
1139 udfmp
= node
->udfmp
;
1140 fentry
= node
->fentry
;
1141 tag
= &fentry
->icbtag
;
1143 switch (tag
->strat_type
) {
1148 kprintf("Cannot deal with strategy4096 yet!\n");
1152 kprintf("Unknown strategy type %d\n", tag
->strat_type
);
1156 switch (tag
->flags
& 0x7) {
1159 * The allocation descriptor field is filled with short_ad's.
1160 * If the offset is beyond the current extent, look for the
1165 ad_offset
= sizeof(struct short_ad
) * ad_num
;
1166 if (ad_offset
> fentry
->l_ad
) {
1167 kprintf("File offset out of bounds\n");
1170 icb
= GETICB(long_ad
, fentry
, fentry
->l_ea
+ ad_offset
);
1171 icblen
= GETICBLEN(short_ad
, icb
);
1173 } while(offset
>= icblen
);
1175 lsector
= (offset
>> udfmp
->bshift
) +
1176 ((struct short_ad
*)(icb
))->pos
;
1178 *max_size
= GETICBLEN(short_ad
, icb
);
1183 * The allocation descriptor field is filled with long_ad's
1184 * If the offset is beyond the current extent, look for the
1189 ad_offset
= sizeof(struct long_ad
) * ad_num
;
1190 if (ad_offset
> fentry
->l_ad
) {
1191 kprintf("File offset out of bounds\n");
1194 icb
= GETICB(long_ad
, fentry
, fentry
->l_ea
+ ad_offset
);
1195 icblen
= GETICBLEN(long_ad
, icb
);
1197 } while(offset
>= icblen
);
1199 lsector
= (offset
>> udfmp
->bshift
) +
1200 ((struct long_ad
*)(icb
))->loc
.lb_num
;
1202 *max_size
= GETICBLEN(long_ad
, icb
);
1207 * This type means that the file *data* is stored in the
1208 * allocation descriptor field of the file entry.
1211 *sector
= node
->hash_id
+ udfmp
->part_start
;
1213 return(UDF_INVALID_BMAP
);
1215 /* DirectCD does not use extended_ad's */
1217 kprintf("Unsupported allocation descriptor %d\n",
1222 *sector
= lsector
+ udfmp
->part_start
;
1225 * Check the sparing table. Each entry represents the beginning of
1228 if (udfmp
->s_table
!= NULL
) {
1229 for (i
= 0; i
< udfmp
->s_table_entries
; i
++) {
1230 p_offset
= lsector
- udfmp
->s_table
->entries
[i
].org
;
1231 if ((p_offset
< udfmp
->p_sectors
) && (p_offset
>= 0)) {
1232 *sector
= udfmp
->s_table
->entries
[i
].map
+