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 $
30 /* Take care of the vnode side of things */
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/namei.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
38 #include <sys/module.h>
40 #include <sys/iconv.h>
41 #include <sys/mount.h>
42 #include <sys/vnode.h>
43 #include <sys/dirent.h>
44 #include <sys/queue.h>
45 #include <sys/unistd.h>
47 #include <machine/inttypes.h>
51 #include <vfs/udf/ecma167-udf.h>
52 #include <vfs/udf/osta.h>
53 #include <vfs/udf/udf.h>
54 #include <vfs/udf/udf_mount.h>
56 static int udf_access(struct vop_access_args
*);
57 static int udf_getattr(struct vop_getattr_args
*);
58 static int udf_ioctl(struct vop_ioctl_args
*);
59 static int udf_pathconf(struct vop_pathconf_args
*);
60 static int udf_read(struct vop_read_args
*);
61 static int udf_readdir(struct vop_readdir_args
*);
62 static int udf_readlink(struct vop_readlink_args
*ap
);
63 static int udf_strategy(struct vop_strategy_args
*);
64 static int udf_bmap(struct vop_bmap_args
*);
65 static int udf_lookup(struct vop_old_lookup_args
*);
66 static int udf_reclaim(struct vop_reclaim_args
*);
67 static int udf_readatoffset(struct udf_node
*, int *, int, struct buf
**, uint8_t **);
68 static int udf_bmap_internal(struct udf_node
*, uint32_t, daddr_t
*, uint32_t *);
70 struct vop_ops udf_vnode_vops
= {
71 .vop_default
= vop_defaultop
,
72 .vop_access
= udf_access
,
74 .vop_old_lookup
= udf_lookup
,
75 .vop_getattr
= udf_getattr
,
76 .vop_ioctl
= udf_ioctl
,
77 .vop_pathconf
= udf_pathconf
,
79 .vop_readdir
= udf_readdir
,
80 .vop_readlink
= udf_readlink
,
81 .vop_reclaim
= udf_reclaim
,
82 .vop_strategy
= udf_strategy
85 MALLOC_DEFINE(M_UDFFID
, "UDF FID", "UDF FileId structure");
86 MALLOC_DEFINE(M_UDFDS
, "UDF DS", "UDF Dirstream structure");
88 #define UDF_INVALID_BMAP -1
90 /* Look up a udf_node based on the ino_t passed in and return it's vnode */
92 udf_hashlookup(struct udf_mnt
*udfmp
, ino_t id
, struct vnode
**vpp
)
94 struct udf_node
*node
;
95 struct udf_hash_lh
*lh
;
100 lwkt_gettoken(&udfmp
->hash_token
);
102 lh
= &udfmp
->hashtbl
[id
% udfmp
->hashsz
];
104 lwkt_reltoken(&udfmp
->hash_token
);
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(&udfmp
->hash_token
);
131 lwkt_reltoken(&udfmp
->hash_token
);
136 udf_hashins(struct udf_node
*node
)
138 struct udf_mnt
*udfmp
;
139 struct udf_hash_lh
*lh
;
143 lwkt_gettoken(&udfmp
->hash_token
);
144 lh
= &udfmp
->hashtbl
[node
->hash_id
% udfmp
->hashsz
];
145 LIST_INSERT_HEAD(lh
, node
, le
);
146 lwkt_reltoken(&udfmp
->hash_token
);
152 udf_hashrem(struct udf_node
*node
)
154 struct udf_mnt
*udfmp
;
155 struct udf_hash_lh
*lh
;
159 lwkt_gettoken(&udfmp
->hash_token
);
160 lh
= &udfmp
->hashtbl
[node
->hash_id
% udfmp
->hashsz
];
162 panic("hash entry is NULL, node->hash_id= %"PRId64
, node
->hash_id
);
163 LIST_REMOVE(node
, le
);
164 lwkt_reltoken(&udfmp
->hash_token
);
170 udf_allocv(struct mount
*mp
, struct vnode
**vpp
)
175 error
= getnewvnode(VT_UDF
, mp
, &vp
, 0, 0);
177 kprintf("udf_allocv: failed to allocate new vnode\n");
185 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */
187 udf_permtomode(struct udf_node
*node
)
193 perm
= node
->fentry
->perm
;
194 flags
= node
->fentry
->icbtag
.flags
;
196 mode
= perm
& UDF_FENTRY_PERM_USER_MASK
;
197 mode
|= ((perm
& UDF_FENTRY_PERM_GRP_MASK
) >> 2);
198 mode
|= ((perm
& UDF_FENTRY_PERM_OWNER_MASK
) >> 4);
199 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_STICKY
) << 4);
200 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_SETGID
) << 6);
201 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_SETUID
) << 8);
207 udf_access(struct vop_access_args
*a
)
210 struct udf_node
*node
;
214 KKASSERT(vp
->v_mount
->mnt_flag
& MNT_RDONLY
);
215 return (vop_helper_access(a
, node
->fentry
->uid
, node
->fentry
->gid
,
216 udf_permtomode(node
), 0));
219 static int mon_lens
[2][12] = {
220 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
221 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
225 udf_isaleapyear(int year
)
229 i
= (year
% 4) ? 0 : 1;
230 i
&= (year
% 100) ? 1 : 0;
231 i
|= (year
% 400) ? 0 : 1;
237 * XXX This is just a rough hack. Daylight savings isn't calculated and tv_nsec
239 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>.
242 udf_timetotimespec(struct timestamp
*time
, struct timespec
*t
)
244 int i
, lpyear
, daysinyear
;
246 uint16_t u_tz_offset
;
252 /* DirectCD seems to like using bogus year values */
253 if (time
->year
< 1970) {
258 /* Calculate the time and day */
259 t
->tv_sec
= time
->second
;
260 t
->tv_sec
+= time
->minute
* 60;
261 t
->tv_sec
+= time
->hour
* 3600;
262 t
->tv_sec
+= time
->day
* 3600 * 24;
264 /* Calclulate the month */
265 lpyear
= udf_isaleapyear(time
->year
);
266 for (i
= 1; i
< time
->month
; i
++)
267 t
->tv_sec
+= mon_lens
[lpyear
][i
] * 3600 * 24;
269 /* Speed up the calculation */
270 if (time
->year
> 1979)
271 t
->tv_sec
+= 315532800;
272 if (time
->year
> 1989)
273 t
->tv_sec
+= 315619200;
274 if (time
->year
> 1999)
275 t
->tv_sec
+= 315532800;
276 for (i
= 2000; i
< time
->year
; i
++) {
277 daysinyear
= udf_isaleapyear(i
) + 365 ;
278 t
->tv_sec
+= daysinyear
* 3600 * 24;
282 * Calculate the time zone. The timezone is 12 bit signed 2's
283 * compliment, so we gotta do some extra magic to handle it right.
285 tz
.u_tz_offset
= time
->type_tz
;
286 tz
.u_tz_offset
&= 0x0fff;
287 if (tz
.u_tz_offset
& 0x0800)
288 tz
.u_tz_offset
|= 0xf000; /* extend the sign to 16 bits */
289 if ((time
->type_tz
& 0x1000) && (tz
.s_tz_offset
!= -2047))
290 t
->tv_sec
-= tz
.s_tz_offset
* 60;
296 udf_getattr(struct vop_getattr_args
*a
)
299 struct udf_node
*node
;
301 struct file_entry
*fentry
;
306 fentry
= node
->fentry
;
308 vap
->va_fsid
= dev2udev(node
->i_dev
);
309 vap
->va_fileid
= node
->hash_id
;
310 vap
->va_mode
= udf_permtomode(node
);
311 vap
->va_nlink
= fentry
->link_cnt
;
313 * XXX The spec says that -1 is valid for uid/gid and indicates an
314 * invalid uid/gid. How should this be represented?
316 vap
->va_uid
= (fentry
->uid
== 0xffffffff) ? 0 : fentry
->uid
;
317 vap
->va_gid
= (fentry
->gid
== 0xffffffff) ? 0 : fentry
->gid
;
318 udf_timetotimespec(&fentry
->atime
, &vap
->va_atime
);
319 udf_timetotimespec(&fentry
->mtime
, &vap
->va_mtime
);
320 vap
->va_ctime
= vap
->va_mtime
; /* XXX Stored as an Extended Attribute */
321 vap
->va_rmajor
= VNOVAL
;
322 vap
->va_rminor
= VNOVAL
;
323 if (vp
->v_type
& VDIR
) {
325 * Directories that are recorded within their ICB will show
326 * as having 0 blocks recorded. Since tradition dictates
327 * that directories consume at least one logical block,
330 if (fentry
->logblks_rec
!= 0)
331 vap
->va_size
= fentry
->logblks_rec
* node
->udfmp
->bsize
;
333 vap
->va_size
= node
->udfmp
->bsize
;
335 vap
->va_size
= fentry
->inf_len
;
338 vap
->va_blocksize
= node
->udfmp
->bsize
;
339 vap
->va_bytes
= fentry
->inf_len
;
340 vap
->va_type
= vp
->v_type
;
341 vap
->va_filerev
= 0; /* XXX */
346 * File specific ioctls. DeCSS candidate?
349 udf_ioctl(struct vop_ioctl_args
*a
)
351 kprintf("%s called\n", __func__
);
356 * I'm not sure that this has much value in a read-only filesystem, but
360 udf_pathconf(struct vop_pathconf_args
*a
)
365 *a
->a_retval
= 65535;
368 *a
->a_retval
= NAME_MAX
;
371 *a
->a_retval
= PATH_MAX
;
382 udf_read(struct vop_read_args
*a
)
384 struct vnode
*vp
= a
->a_vp
;
385 struct uio
*uio
= a
->a_uio
;
386 struct udf_node
*node
= VTON(vp
);
390 int size
, fsize
, offset
;
392 if (uio
->uio_offset
< 0)
395 fsize
= node
->fentry
->inf_len
;
397 while (uio
->uio_offset
< fsize
&& uio
->uio_resid
> 0) {
398 offset
= uio
->uio_offset
;
399 size
= uio
->uio_resid
;
400 error
= udf_readatoffset(node
, &size
, offset
, &bp
, &data
);
402 error
= uiomove(data
, size
, uio
);
413 * Call the OSTA routines to translate the name from a CS0 dstring to a
414 * 16-bit Unicode String. Hooks need to be placed in here to translate from
415 * Unicode to the encoding that the kernel/user expects. Return the length
416 * of the translated string.
419 udf_transname(char *cs0string
, char *destname
, int len
, struct udf_mnt
*udfmp
)
421 unicode_t
*transname
;
422 int i
, unilen
= 0, destlen
;
424 /* Convert 16-bit Unicode to destname */
425 /* allocate a buffer big enough to hold an 8->16 bit expansion */
426 transname
= kmalloc(NAME_MAX
* sizeof(unicode_t
), M_TEMP
, M_WAITOK
| M_ZERO
);
428 if ((unilen
= udf_UncompressUnicode(len
, cs0string
, transname
)) == -1) {
429 kprintf("udf: Unicode translation failed\n");
430 kfree(transname
, M_TEMP
);
434 for (i
= 0; i
< unilen
; i
++)
435 if (transname
[i
] & 0xff00)
436 destname
[i
] = '.'; /* Fudge the 16bit chars */
438 destname
[i
] = transname
[i
] & 0xff;
439 kfree(transname
, M_TEMP
);
440 destname
[unilen
] = 0;
447 * Compare a CS0 dstring with a name passed in from the VFS layer. Return
448 * 0 on a successful match, nonzero therwise. Unicode work may need to be done
452 udf_cmpname(char *cs0string
, char *cmpname
, int cs0len
, int cmplen
, struct udf_mnt
*udfmp
)
457 /* This is overkill, but not worth creating a new zone */
459 transname
= kmalloc(NAME_MAX
* sizeof(unicode_t
), M_TEMP
,
462 cs0len
= udf_transname(cs0string
, transname
, cs0len
, udfmp
);
464 /* Easy check. If they aren't the same length, they aren't equal */
465 if ((cs0len
== 0) || (cs0len
!= cmplen
))
468 error
= bcmp(transname
, cmpname
, cmplen
);
470 kfree(transname
, M_TEMP
);
475 struct dirent
*dirent
;
482 static struct udf_dirstream
*
483 udf_opendir(struct udf_node
*node
, int offset
, int fsize
, struct udf_mnt
*udfmp
)
485 struct udf_dirstream
*ds
;
487 ds
= kmalloc(sizeof(*ds
), M_UDFDS
, M_WAITOK
| M_ZERO
);
497 static struct fileid_desc
*
498 udf_getfid(struct udf_dirstream
*ds
)
500 struct fileid_desc
*fid
;
501 int error
, frag_size
= 0, total_fid_size
;
503 /* End of directory? */
504 if (ds
->offset
+ ds
->off
>= ds
->fsize
) {
509 /* Grab the first extent of the directory */
514 error
= udf_readatoffset(ds
->node
, &ds
->size
, ds
->offset
,
523 * Clean up from a previous fragmented FID.
524 * XXX Is this the right place for this?
526 if (ds
->fid_fragment
&& ds
->buf
!= NULL
) {
527 ds
->fid_fragment
= 0;
528 kfree(ds
->buf
, M_UDFFID
);
531 fid
= (struct fileid_desc
*)&ds
->data
[ds
->off
];
534 * Check to see if the fid is fragmented. The first test
535 * ensures that we don't wander off the end of the buffer
536 * looking for the l_iu and l_fi fields.
538 if (ds
->off
+ UDF_FID_SIZE
> ds
->size
||
539 ds
->off
+ fid
->l_iu
+ fid
->l_fi
+ UDF_FID_SIZE
> ds
->size
) {
541 /* Copy what we have of the fid into a buffer */
542 frag_size
= ds
->size
- ds
->off
;
543 if (frag_size
>= ds
->udfmp
->bsize
) {
544 kprintf("udf: invalid FID fragment\n");
550 * File ID descriptors can only be at most one
551 * logical sector in size.
553 ds
->buf
= kmalloc(ds
->udfmp
->bsize
, M_UDFFID
, M_WAITOK
| M_ZERO
);
554 bcopy(fid
, ds
->buf
, frag_size
);
556 /* Reduce all of the casting magic */
557 fid
= (struct fileid_desc
*)ds
->buf
;
562 /* Fetch the next allocation */
563 ds
->offset
+= ds
->size
;
565 error
= udf_readatoffset(ds
->node
, &ds
->size
, ds
->offset
,
573 * If the fragment was so small that we didn't get
574 * the l_iu and l_fi fields, copy those in.
576 if (frag_size
< UDF_FID_SIZE
)
577 bcopy(ds
->data
, &ds
->buf
[frag_size
],
578 UDF_FID_SIZE
- frag_size
);
581 * Now that we have enough of the fid to work with,
582 * copy in the rest of the fid from the new
585 total_fid_size
= UDF_FID_SIZE
+ fid
->l_iu
+ fid
->l_fi
;
586 if (total_fid_size
> ds
->udfmp
->bsize
) {
587 kprintf("udf: invalid FID\n");
591 bcopy(ds
->data
, &ds
->buf
[frag_size
],
592 total_fid_size
- frag_size
);
594 ds
->fid_fragment
= 1;
596 total_fid_size
= fid
->l_iu
+ fid
->l_fi
+ UDF_FID_SIZE
;
599 * Update the offset. Align on a 4 byte boundary because the
602 ds
->this_off
= ds
->off
;
603 if (!ds
->fid_fragment
)
604 ds
->off
+= (total_fid_size
+ 3) & ~0x03;
606 ds
->off
= (total_fid_size
- frag_size
+ 3) & ~0x03;
612 udf_closedir(struct udf_dirstream
*ds
)
618 if (ds
->fid_fragment
&& ds
->buf
!= NULL
)
619 kfree(ds
->buf
, M_UDFFID
);
625 udf_readdir(struct vop_readdir_args
*a
)
629 struct udf_node
*node
;
630 struct udf_mnt
*udfmp
;
631 struct fileid_desc
*fid
;
632 struct udf_uiodir uiodir
;
633 struct udf_dirstream
*ds
;
634 off_t
*cookies
= NULL
;
641 error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
| LK_FAILRECLAIM
);
650 if (a
->a_ncookies
!= NULL
) {
652 * Guess how many entries are needed. If we run out, this
653 * function will be called again and thing will pick up were
656 ncookies
= uio
->uio_resid
/ 8 + 1;
659 cookies
= kmalloc(sizeof(off_t
) * ncookies
, M_TEMP
, M_WAITOK
);
660 uiodir
.ncookies
= ncookies
;
661 uiodir
.cookies
= cookies
;
664 uiodir
.cookies
= NULL
;
669 * Iterate through the file id descriptors. Give the parent dir
670 * entry special attention.
672 ds
= udf_opendir(node
, uio
->uio_offset
, node
->fentry
->inf_len
,
675 name
= kmalloc(NAME_MAX
, M_TEMP
, M_WAITOK
);
677 while ((fid
= udf_getfid(ds
)) != NULL
) {
679 /* XXX Should we return an error on a bad fid? */
680 if (udf_checktag(&fid
->tag
, TAGID_FID
)) {
681 kprintf("Invalid FID tag\n");
686 /* Is this a deleted file? */
687 if (fid
->file_char
& UDF_FILE_CHAR_DEL
)
690 if ((fid
->l_fi
== 0) && (fid
->file_char
& UDF_FILE_CHAR_PAR
)) {
691 /* Do up the '.' and '..' entries. Dummy values are
692 * used for the cookies since the offset here is
693 * usually zero, and NFS doesn't like that value
695 if (uiodir
.cookies
!= NULL
) {
696 if (++uiodir
.acookies
> uiodir
.ncookies
) {
700 *uiodir
.cookies
++ = 1;
702 if (vop_write_dirent(&error
, uio
, node
->hash_id
, DT_DIR
,
711 if (uiodir
.cookies
!= NULL
) {
712 if (++uiodir
.acookies
> uiodir
.ncookies
) {
716 *uiodir
.cookies
++ = 2;
718 if (vop_write_dirent(&error
, uio
, udf_getid(&fid
->icb
),
728 uint8_t d_type
= (fid
->file_char
& UDF_FILE_CHAR_DIR
) ?
730 uint16_t namelen
= udf_transname(&fid
->data
[fid
->l_iu
],
731 name
, fid
->l_fi
, udfmp
);
733 if (uiodir
.cookies
!= NULL
) {
734 if (++uiodir
.acookies
> uiodir
.ncookies
) {
738 *uiodir
.cookies
++ = ds
->this_off
;
740 if (vop_write_dirent(&error
, uio
, udf_getid(&fid
->icb
),
741 d_type
, namelen
, name
)) {
751 kprintf("uiomove returned %d\n", error
);
759 /* tell the calling layer whether we need to be called again */
760 *a
->a_eofflag
= uiodir
.eofflag
;
761 uio
->uio_offset
= ds
->offset
+ ds
->off
;
768 if (a
->a_ncookies
!= NULL
) {
770 kfree(cookies
, M_TEMP
);
772 *a
->a_ncookies
= uiodir
.acookies
;
773 *a
->a_cookies
= cookies
;
781 /* Are there any implementations out there that do soft-links? */
783 udf_readlink(struct vop_readlink_args
*ap
)
785 kprintf("%s called\n", __func__
);
790 udf_strategy(struct vop_strategy_args
*ap
)
796 struct udf_node
*node
;
805 nbio
= push_bio(bio
);
806 if (nbio
->bio_offset
== NOOFFSET
) {
808 * Files that are embedded in the fentry don't translate well
809 * to a block number. Reject.
811 if (udf_bmap_internal(node
,
813 &dblkno
, &maxsize
)) {
815 nbio
->bio_offset
= NOOFFSET
;
817 nbio
->bio_offset
= dbtob(dblkno
);
820 if (nbio
->bio_offset
== NOOFFSET
) {
821 /* I/O was never started on nbio, must biodone(bio) */
825 vn_strategy(node
->i_devvp
, nbio
);
830 udf_bmap(struct vop_bmap_args
*a
)
832 struct udf_node
*node
;
837 node
= VTON(a
->a_vp
);
839 if (a
->a_doffsetp
== NULL
)
842 KKASSERT(a
->a_loffset
% node
->udfmp
->bsize
== 0);
844 error
= udf_bmap_internal(node
, a
->a_loffset
, &lsector
, &max_size
);
848 /* Translate logical to physical sector number */
849 *a
->a_doffsetp
= (off_t
)lsector
<< node
->udfmp
->bshift
;
851 /* Punt on read-ahead for now */
860 * The all powerful VOP_LOOKUP().
863 udf_lookup(struct vop_old_lookup_args
*a
)
866 struct vnode
*tdp
= NULL
;
867 struct vnode
**vpp
= a
->a_vpp
;
868 struct udf_node
*node
;
869 struct udf_mnt
*udfmp
;
870 struct fileid_desc
*fid
= NULL
;
871 struct udf_dirstream
*ds
;
877 int offset
, error
= 0;
878 int numdirpasses
, fsize
;
883 nameiop
= a
->a_cnp
->cn_nameiop
;
884 flags
= a
->a_cnp
->cn_flags
;
885 nameptr
= a
->a_cnp
->cn_nameptr
;
886 namelen
= a
->a_cnp
->cn_namelen
;
887 fsize
= node
->fentry
->inf_len
;
892 * If this is a LOOKUP and we've already partially searched through
893 * the directory, pick up where we left off and flag that the
894 * directory may need to be searched twice. For a full description,
895 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup()
897 if (nameiop
!= NAMEI_LOOKUP
|| node
->diroff
== 0 ||
898 node
->diroff
> fsize
) {
902 offset
= node
->diroff
;
907 ds
= udf_opendir(node
, offset
, fsize
, udfmp
);
909 while ((fid
= udf_getfid(ds
)) != NULL
) {
910 /* XXX Should we return an error on a bad fid? */
911 if (udf_checktag(&fid
->tag
, TAGID_FID
)) {
912 kprintf("udf_lookup: Invalid tag\n");
917 /* Is this a deleted file? */
918 if (fid
->file_char
& UDF_FILE_CHAR_DEL
)
921 if ((fid
->l_fi
== 0) && (fid
->file_char
& UDF_FILE_CHAR_PAR
)) {
922 if (flags
& CNP_ISDOTDOT
) {
923 id
= udf_getid(&fid
->icb
);
927 if (!(udf_cmpname(&fid
->data
[fid
->l_iu
],
928 nameptr
, fid
->l_fi
, namelen
, udfmp
))) {
929 id
= udf_getid(&fid
->icb
);
938 /* XXX Bail out here? */
944 /* Did we have a match? */
946 error
= udf_vget(udfmp
->im_mountp
, NULL
, id
, &tdp
);
949 * Remember where this entry was if it's the final
952 if (nameiop
== NAMEI_LOOKUP
)
953 node
->diroff
= ds
->offset
+ ds
->off
;
954 if ((flags
& CNP_LOCKPARENT
) == 0) {
955 a
->a_cnp
->cn_flags
|= CNP_PDIRUNLOCK
;
962 /* Name wasn't found on this pass. Do another pass? */
963 if (numdirpasses
== 2) {
969 if (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
) {
981 udf_reclaim(struct vop_reclaim_args
*a
)
984 struct udf_node
*unode
;
991 if (unode
->i_devvp
) {
992 vrele(unode
->i_devvp
);
996 if (unode
->fentry
!= NULL
)
997 kfree(unode
->fentry
, M_UDFFENTRY
);
998 kfree(unode
, M_UDFNODE
);
1006 * Read the block and then set the data pointer to correspond with the
1007 * offset passed in. Only read in at most 'size' bytes, and then set 'size'
1008 * to the number of bytes pointed to. If 'size' is zero, try to read in a
1011 * Note that *bp may be assigned error or not.
1013 * XXX 'size' is limited to the logical block size for now due to problems
1017 udf_readatoffset(struct udf_node
*node
, int *size
, int offset
, struct buf
**bp
,
1020 struct udf_mnt
*udfmp
;
1021 struct file_entry
*fentry
= NULL
;
1027 udfmp
= node
->udfmp
;
1030 error
= udf_bmap_internal(node
, offset
, §or
, &max_size
);
1031 if (error
== UDF_INVALID_BMAP
) {
1033 * This error means that the file *data* is stored in the
1034 * allocation descriptor field of the file entry.
1036 fentry
= node
->fentry
;
1037 *data
= &fentry
->data
[fentry
->l_ea
];
1038 *size
= fentry
->l_ad
;
1040 } else if (error
!= 0) {
1044 /* Adjust the size so that it is within range */
1045 if (*size
== 0 || *size
> max_size
)
1047 *size
= min(*size
, MAXBSIZE
);
1049 if ((error
= udf_readlblks(udfmp
, sector
, *size
, bp
))) {
1050 kprintf("warning: udf_readlblks returned error %d\n", error
);
1051 /* note: *bp may be non-NULL */
1056 *data
= (uint8_t *)&bp1
->b_data
[offset
% udfmp
->bsize
];
1061 * Translate a file offset into a logical block and then into a physical
1065 udf_bmap_internal(struct udf_node
*node
, uint32_t offset
, daddr_t
*sector
, uint32_t *max_size
)
1067 struct udf_mnt
*udfmp
;
1068 struct file_entry
*fentry
;
1070 struct icb_tag
*tag
;
1071 uint32_t icblen
= 0;
1073 int ad_offset
, ad_num
= 0;
1076 udfmp
= node
->udfmp
;
1077 fentry
= node
->fentry
;
1078 tag
= &fentry
->icbtag
;
1080 switch (tag
->strat_type
) {
1085 kprintf("Cannot deal with strategy4096 yet!\n");
1089 kprintf("Unknown strategy type %d\n", tag
->strat_type
);
1093 switch (tag
->flags
& 0x7) {
1096 * The allocation descriptor field is filled with short_ad's.
1097 * If the offset is beyond the current extent, look for the
1102 ad_offset
= sizeof(struct short_ad
) * ad_num
;
1103 if (ad_offset
> fentry
->l_ad
) {
1104 kprintf("File offset out of bounds\n");
1107 icb
= GETICB(long_ad
, fentry
, fentry
->l_ea
+ ad_offset
);
1108 icblen
= GETICBLEN(short_ad
, icb
);
1110 } while(offset
>= icblen
);
1112 lsector
= (offset
>> udfmp
->bshift
) +
1113 ((struct short_ad
*)(icb
))->pos
;
1115 *max_size
= GETICBLEN(short_ad
, icb
);
1120 * The allocation descriptor field is filled with long_ad's
1121 * If the offset is beyond the current extent, look for the
1126 ad_offset
= sizeof(struct long_ad
) * ad_num
;
1127 if (ad_offset
> fentry
->l_ad
) {
1128 kprintf("File offset out of bounds\n");
1131 icb
= GETICB(long_ad
, fentry
, fentry
->l_ea
+ ad_offset
);
1132 icblen
= GETICBLEN(long_ad
, icb
);
1134 } while(offset
>= icblen
);
1136 lsector
= (offset
>> udfmp
->bshift
) +
1137 ((struct long_ad
*)(icb
))->loc
.lb_num
;
1139 *max_size
= GETICBLEN(long_ad
, icb
);
1144 * This type means that the file *data* is stored in the
1145 * allocation descriptor field of the file entry.
1148 *sector
= node
->hash_id
+ udfmp
->part_start
;
1150 return(UDF_INVALID_BMAP
);
1152 /* DirectCD does not use extended_ad's */
1154 kprintf("Unsupported allocation descriptor %d\n",
1159 *sector
= lsector
+ udfmp
->part_start
;
1162 * Check the sparing table. Each entry represents the beginning of
1165 if (udfmp
->s_table
!= NULL
) {
1166 for (i
= 0; i
< udfmp
->s_table_entries
; i
++) {
1167 p_offset
= lsector
- udfmp
->s_table
->entries
[i
].org
;
1168 if ((p_offset
< udfmp
->p_sectors
) && (p_offset
>= 0)) {
1169 *sector
= udfmp
->s_table
->entries
[i
].map
+