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
];
146 LIST_INSERT_HEAD(lh
, node
, le
);
147 lwkt_reltoken(&hashlock
);
153 udf_hashrem(struct udf_node
*node
)
155 struct udf_mnt
*udfmp
;
156 struct udf_hash_lh
*lh
;
157 lwkt_tokref hashlock
;
161 lwkt_gettoken(&hashlock
, &udfmp
->hash_token
);
162 lh
= &udfmp
->hashtbl
[node
->hash_id
% udfmp
->hashsz
];
164 panic("hash entry is NULL, node->hash_id= %"PRId64
"\n", node
->hash_id
);
165 LIST_REMOVE(node
, le
);
166 lwkt_reltoken(&hashlock
);
172 udf_allocv(struct mount
*mp
, struct vnode
**vpp
)
177 error
= getnewvnode(VT_UDF
, mp
, &vp
, 0, 0);
179 kprintf("udf_allocv: failed to allocate new vnode\n");
187 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */
189 udf_permtomode(struct udf_node
*node
)
195 perm
= node
->fentry
->perm
;
196 flags
= node
->fentry
->icbtag
.flags
;
198 mode
= perm
& UDF_FENTRY_PERM_USER_MASK
;
199 mode
|= ((perm
& UDF_FENTRY_PERM_GRP_MASK
) >> 2);
200 mode
|= ((perm
& UDF_FENTRY_PERM_OWNER_MASK
) >> 4);
201 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_STICKY
) << 4);
202 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_SETGID
) << 6);
203 mode
|= ((flags
& UDF_ICB_TAG_FLAGS_SETUID
) << 8);
209 udf_access(struct vop_access_args
*a
)
212 struct udf_node
*node
;
216 KKASSERT(vp
->v_mount
->mnt_flag
& MNT_RDONLY
);
217 return (vop_helper_access(a
, node
->fentry
->uid
, node
->fentry
->gid
,
218 udf_permtomode(node
), 0));
221 static int mon_lens
[2][12] = {
222 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
223 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
227 udf_isaleapyear(int year
)
231 i
= (year
% 4) ? 0 : 1;
232 i
&= (year
% 100) ? 1 : 0;
233 i
|= (year
% 400) ? 0 : 1;
239 * XXX This is just a rough hack. Daylight savings isn't calculated and tv_nsec
241 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>.
244 udf_timetotimespec(struct timestamp
*time
, struct timespec
*t
)
246 int i
, lpyear
, daysinyear
;
248 uint16_t u_tz_offset
;
254 /* DirectCD seems to like using bogus year values */
255 if (time
->year
< 1970) {
260 /* Calculate the time and day */
261 t
->tv_sec
= time
->second
;
262 t
->tv_sec
+= time
->minute
* 60;
263 t
->tv_sec
+= time
->hour
* 3600;
264 t
->tv_sec
+= time
->day
* 3600 * 24;
266 /* Calclulate the month */
267 lpyear
= udf_isaleapyear(time
->year
);
268 for (i
= 1; i
< time
->month
; i
++)
269 t
->tv_sec
+= mon_lens
[lpyear
][i
] * 3600 * 24;
271 /* Speed up the calculation */
272 if (time
->year
> 1979)
273 t
->tv_sec
+= 315532800;
274 if (time
->year
> 1989)
275 t
->tv_sec
+= 315619200;
276 if (time
->year
> 1999)
277 t
->tv_sec
+= 315532800;
278 for (i
= 2000; i
< time
->year
; i
++) {
279 daysinyear
= udf_isaleapyear(i
) + 365 ;
280 t
->tv_sec
+= daysinyear
* 3600 * 24;
284 * Calculate the time zone. The timezone is 12 bit signed 2's
285 * compliment, so we gotta do some extra magic to handle it right.
287 tz
.u_tz_offset
= time
->type_tz
;
288 tz
.u_tz_offset
&= 0x0fff;
289 if (tz
.u_tz_offset
& 0x0800)
290 tz
.u_tz_offset
|= 0xf000; /* extend the sign to 16 bits */
291 if ((time
->type_tz
& 0x1000) && (tz
.s_tz_offset
!= -2047))
292 t
->tv_sec
-= tz
.s_tz_offset
* 60;
298 udf_getattr(struct vop_getattr_args
*a
)
301 struct udf_node
*node
;
303 struct file_entry
*fentry
;
311 fentry
= node
->fentry
;
313 vap
->va_fsid
= dev2udev(node
->i_dev
);
314 vap
->va_fileid
= node
->hash_id
;
315 vap
->va_mode
= udf_permtomode(node
);
316 vap
->va_nlink
= fentry
->link_cnt
;
318 * XXX The spec says that -1 is valid for uid/gid and indicates an
319 * invalid uid/gid. How should this be represented?
321 vap
->va_uid
= (fentry
->uid
== 0xffffffff) ? 0 : fentry
->uid
;
322 vap
->va_gid
= (fentry
->gid
== 0xffffffff) ? 0 : fentry
->gid
;
323 udf_timetotimespec(&fentry
->atime
, &vap
->va_atime
);
324 udf_timetotimespec(&fentry
->mtime
, &vap
->va_mtime
);
325 vap
->va_ctime
= vap
->va_mtime
; /* XXX Stored as an Extended Attribute */
326 vap
->va_rmajor
= VNOVAL
;
327 vap
->va_rminor
= VNOVAL
;
328 if (vp
->v_type
& VDIR
) {
330 * Directories that are recorded within their ICB will show
331 * as having 0 blocks recorded. Since tradition dictates
332 * that directories consume at least one logical block,
335 if (fentry
->logblks_rec
!= 0)
336 vap
->va_size
= fentry
->logblks_rec
* node
->udfmp
->bsize
;
338 vap
->va_size
= node
->udfmp
->bsize
;
340 vap
->va_size
= fentry
->inf_len
;
343 vap
->va_blocksize
= node
->udfmp
->bsize
;
344 vap
->va_bytes
= fentry
->inf_len
;
345 vap
->va_type
= vp
->v_type
;
346 vap
->va_filerev
= 0; /* XXX */
351 * File specific ioctls. DeCSS candidate?
354 udf_ioctl(struct vop_ioctl_args
*a
)
356 kprintf("%s called\n", __func__
);
361 * I'm not sure that this has much value in a read-only filesystem, but
365 udf_pathconf(struct vop_pathconf_args
*a
)
370 *a
->a_retval
= 65535;
373 *a
->a_retval
= NAME_MAX
;
376 *a
->a_retval
= PATH_MAX
;
387 udf_read(struct vop_read_args
*a
)
389 struct vnode
*vp
= a
->a_vp
;
390 struct uio
*uio
= a
->a_uio
;
391 struct udf_node
*node
= VTON(vp
);
395 int size
, fsize
, offset
;
397 if (uio
->uio_offset
< 0)
400 fsize
= node
->fentry
->inf_len
;
402 while (uio
->uio_offset
< fsize
&& uio
->uio_resid
> 0) {
403 offset
= uio
->uio_offset
;
404 size
= uio
->uio_resid
;
405 error
= udf_readatoffset(node
, &size
, offset
, &bp
, &data
);
407 error
= uiomove(data
, size
, uio
);
418 * Call the OSTA routines to translate the name from a CS0 dstring to a
419 * 16-bit Unicode String. Hooks need to be placed in here to translate from
420 * Unicode to the encoding that the kernel/user expects. Return the length
421 * of the translated string.
424 udf_transname(char *cs0string
, char *destname
, int len
, struct udf_mnt
*udfmp
)
426 unicode_t
*transname
;
427 int i
, unilen
= 0, destlen
;
429 /* Convert 16-bit Unicode to destname */
430 /* allocate a buffer big enough to hold an 8->16 bit expansion */
431 transname
= kmalloc(NAME_MAX
* sizeof(unicode_t
), M_TEMP
, M_WAITOK
| M_ZERO
);
433 if ((unilen
= udf_UncompressUnicode(len
, cs0string
, transname
)) == -1) {
434 kprintf("udf: Unicode translation failed\n");
435 kfree(transname
, M_TEMP
);
439 for (i
= 0; i
< unilen
; i
++)
440 if (transname
[i
] & 0xff00)
441 destname
[i
] = '.'; /* Fudge the 16bit chars */
443 destname
[i
] = transname
[i
] & 0xff;
444 kfree(transname
, M_TEMP
);
445 destname
[unilen
] = 0;
452 * Compare a CS0 dstring with a name passed in from the VFS layer. Return
453 * 0 on a successful match, nonzero therwise. Unicode work may need to be done
457 udf_cmpname(char *cs0string
, char *cmpname
, int cs0len
, int cmplen
, struct udf_mnt
*udfmp
)
462 /* This is overkill, but not worth creating a new zone */
464 transname
= kmalloc(NAME_MAX
* sizeof(unicode_t
), M_TEMP
,
467 cs0len
= udf_transname(cs0string
, transname
, cs0len
, udfmp
);
469 /* Easy check. If they aren't the same length, they aren't equal */
470 if ((cs0len
== 0) || (cs0len
!= cmplen
))
473 error
= bcmp(transname
, cmpname
, cmplen
);
475 kfree(transname
, M_TEMP
);
480 struct dirent
*dirent
;
487 static struct udf_dirstream
*
488 udf_opendir(struct udf_node
*node
, int offset
, int fsize
, struct udf_mnt
*udfmp
)
490 struct udf_dirstream
*ds
;
492 ds
= kmalloc(sizeof(*ds
), M_UDFDS
, M_WAITOK
| M_ZERO
);
502 static struct fileid_desc
*
503 udf_getfid(struct udf_dirstream
*ds
)
505 struct fileid_desc
*fid
;
506 int error
, frag_size
= 0, total_fid_size
;
508 /* End of directory? */
509 if (ds
->offset
+ ds
->off
>= ds
->fsize
) {
514 /* Grab the first extent of the directory */
519 error
= udf_readatoffset(ds
->node
, &ds
->size
, ds
->offset
,
528 * Clean up from a previous fragmented FID.
529 * XXX Is this the right place for this?
531 if (ds
->fid_fragment
&& ds
->buf
!= NULL
) {
532 ds
->fid_fragment
= 0;
533 kfree(ds
->buf
, M_UDFFID
);
536 fid
= (struct fileid_desc
*)&ds
->data
[ds
->off
];
539 * Check to see if the fid is fragmented. The first test
540 * ensures that we don't wander off the end of the buffer
541 * looking for the l_iu and l_fi fields.
543 if (ds
->off
+ UDF_FID_SIZE
> ds
->size
||
544 ds
->off
+ fid
->l_iu
+ fid
->l_fi
+ UDF_FID_SIZE
> ds
->size
) {
546 /* Copy what we have of the fid into a buffer */
547 frag_size
= ds
->size
- ds
->off
;
548 if (frag_size
>= ds
->udfmp
->bsize
) {
549 kprintf("udf: invalid FID fragment\n");
555 * File ID descriptors can only be at most one
556 * logical sector in size.
558 ds
->buf
= kmalloc(ds
->udfmp
->bsize
, M_UDFFID
, M_WAITOK
| M_ZERO
);
559 bcopy(fid
, ds
->buf
, frag_size
);
561 /* Reduce all of the casting magic */
562 fid
= (struct fileid_desc
*)ds
->buf
;
567 /* Fetch the next allocation */
568 ds
->offset
+= ds
->size
;
570 error
= udf_readatoffset(ds
->node
, &ds
->size
, ds
->offset
,
578 * If the fragment was so small that we didn't get
579 * the l_iu and l_fi fields, copy those in.
581 if (frag_size
< UDF_FID_SIZE
)
582 bcopy(ds
->data
, &ds
->buf
[frag_size
],
583 UDF_FID_SIZE
- frag_size
);
586 * Now that we have enough of the fid to work with,
587 * copy in the rest of the fid from the new
590 total_fid_size
= UDF_FID_SIZE
+ fid
->l_iu
+ fid
->l_fi
;
591 if (total_fid_size
> ds
->udfmp
->bsize
) {
592 kprintf("udf: invalid FID\n");
596 bcopy(ds
->data
, &ds
->buf
[frag_size
],
597 total_fid_size
- frag_size
);
599 ds
->fid_fragment
= 1;
601 total_fid_size
= fid
->l_iu
+ fid
->l_fi
+ UDF_FID_SIZE
;
604 * Update the offset. Align on a 4 byte boundary because the
607 ds
->this_off
= ds
->off
;
608 if (!ds
->fid_fragment
)
609 ds
->off
+= (total_fid_size
+ 3) & ~0x03;
611 ds
->off
= (total_fid_size
- frag_size
+ 3) & ~0x03;
617 udf_closedir(struct udf_dirstream
*ds
)
623 if (ds
->fid_fragment
&& ds
->buf
!= NULL
)
624 kfree(ds
->buf
, M_UDFFID
);
630 udf_readdir(struct vop_readdir_args
*a
)
634 struct udf_node
*node
;
635 struct udf_mnt
*udfmp
;
636 struct fileid_desc
*fid
;
637 struct udf_uiodir uiodir
;
638 struct udf_dirstream
*ds
;
639 off_t
*cookies
= NULL
;
646 if ((error
= vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
)) != 0)
654 if (a
->a_ncookies
!= NULL
) {
656 * Guess how many entries are needed. If we run out, this
657 * function will be called again and thing will pick up were
660 ncookies
= uio
->uio_resid
/ 8 + 1;
663 cookies
= kmalloc(sizeof(off_t
) * ncookies
, M_TEMP
, M_WAITOK
);
664 uiodir
.ncookies
= ncookies
;
665 uiodir
.cookies
= cookies
;
668 uiodir
.cookies
= NULL
;
673 * Iterate through the file id descriptors. Give the parent dir
674 * entry special attention.
676 ds
= udf_opendir(node
, uio
->uio_offset
, node
->fentry
->inf_len
,
679 name
= kmalloc(NAME_MAX
, M_TEMP
, M_WAITOK
);
681 while ((fid
= udf_getfid(ds
)) != NULL
) {
683 /* XXX Should we return an error on a bad fid? */
684 if (udf_checktag(&fid
->tag
, TAGID_FID
)) {
685 kprintf("Invalid FID tag\n");
690 /* Is this a deleted file? */
691 if (fid
->file_char
& UDF_FILE_CHAR_DEL
)
694 if ((fid
->l_fi
== 0) && (fid
->file_char
& UDF_FILE_CHAR_PAR
)) {
695 /* Do up the '.' and '..' entries. Dummy values are
696 * used for the cookies since the offset here is
697 * usually zero, and NFS doesn't like that value
699 if (uiodir
.cookies
!= NULL
) {
700 if (++uiodir
.acookies
> uiodir
.ncookies
) {
704 *uiodir
.cookies
++ = 1;
706 if (vop_write_dirent(&error
, uio
, node
->hash_id
, DT_DIR
,
715 if (uiodir
.cookies
!= NULL
) {
716 if (++uiodir
.acookies
> uiodir
.ncookies
) {
720 *uiodir
.cookies
++ = 2;
722 if (vop_write_dirent(&error
, uio
, udf_getid(&fid
->icb
),
732 uint8_t d_type
= (fid
->file_char
& UDF_FILE_CHAR_DIR
) ?
734 uint16_t namelen
= udf_transname(&fid
->data
[fid
->l_iu
],
735 name
, fid
->l_fi
, udfmp
);
737 if (uiodir
.cookies
!= NULL
) {
738 if (++uiodir
.acookies
> uiodir
.ncookies
) {
742 *uiodir
.cookies
++ = ds
->this_off
;
744 if (vop_write_dirent(&error
, uio
, udf_getid(&fid
->icb
),
745 d_type
, namelen
, name
)) {
755 kprintf("uiomove returned %d\n", error
);
763 /* tell the calling layer whether we need to be called again */
764 *a
->a_eofflag
= uiodir
.eofflag
;
765 uio
->uio_offset
= ds
->offset
+ ds
->off
;
772 if (a
->a_ncookies
!= NULL
) {
774 kfree(cookies
, M_TEMP
);
776 *a
->a_ncookies
= uiodir
.acookies
;
777 *a
->a_cookies
= cookies
;
785 /* Are there any implementations out there that do soft-links? */
787 udf_readlink(struct vop_readlink_args
*ap
)
789 kprintf("%s called\n", __func__
);
794 udf_strategy(struct vop_strategy_args
*ap
)
800 struct udf_node
*node
;
809 nbio
= push_bio(bio
);
810 if (nbio
->bio_offset
== NOOFFSET
) {
812 * Files that are embedded in the fentry don't translate well
813 * to a block number. Reject.
815 if (udf_bmap_internal(node
,
817 &dblkno
, &maxsize
)) {
819 nbio
->bio_offset
= NOOFFSET
;
821 nbio
->bio_offset
= dbtob(dblkno
);
824 if (nbio
->bio_offset
== NOOFFSET
) {
825 /* I/O was never started on nbio, must biodone(bio) */
829 vn_strategy(node
->i_devvp
, nbio
);
834 udf_bmap(struct vop_bmap_args
*a
)
836 struct udf_node
*node
;
841 node
= VTON(a
->a_vp
);
843 if (a
->a_doffsetp
== NULL
)
846 KKASSERT(a
->a_loffset
% node
->udfmp
->bsize
== 0);
848 error
= udf_bmap_internal(node
, a
->a_loffset
, &lsector
, &max_size
);
852 /* Translate logical to physical sector number */
853 *a
->a_doffsetp
= (off_t
)lsector
<< node
->udfmp
->bshift
;
855 /* Punt on read-ahead for now */
864 * The all powerful VOP_LOOKUP().
867 udf_lookup(struct vop_old_lookup_args
*a
)
870 struct vnode
*tdp
= NULL
;
871 struct vnode
**vpp
= a
->a_vpp
;
872 struct udf_node
*node
;
873 struct udf_mnt
*udfmp
;
874 struct fileid_desc
*fid
= NULL
;
875 struct udf_dirstream
*ds
;
877 globaldata_t gd
= mycpu
;
883 int offset
, error
= 0;
884 int numdirpasses
, fsize
;
889 nameiop
= a
->a_cnp
->cn_nameiop
;
890 flags
= a
->a_cnp
->cn_flags
;
891 nameptr
= a
->a_cnp
->cn_nameptr
;
892 namelen
= a
->a_cnp
->cn_namelen
;
893 fsize
= node
->fentry
->inf_len
;
894 td
= a
->a_cnp
->cn_td
;
899 * If this is a LOOKUP and we've already partially searched through
900 * the directory, pick up where we left off and flag that the
901 * directory may need to be searched twice. For a full description,
902 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup()
904 if (nameiop
!= NAMEI_LOOKUP
|| node
->diroff
== 0 ||
905 node
->diroff
> fsize
) {
909 offset
= node
->diroff
;
911 gd
->gd_nchstats
->ncs_2passes
++;
915 ds
= udf_opendir(node
, offset
, fsize
, udfmp
);
917 while ((fid
= udf_getfid(ds
)) != NULL
) {
918 /* XXX Should we return an error on a bad fid? */
919 if (udf_checktag(&fid
->tag
, TAGID_FID
)) {
920 kprintf("udf_lookup: Invalid tag\n");
925 /* Is this a deleted file? */
926 if (fid
->file_char
& UDF_FILE_CHAR_DEL
)
929 if ((fid
->l_fi
== 0) && (fid
->file_char
& UDF_FILE_CHAR_PAR
)) {
930 if (flags
& CNP_ISDOTDOT
) {
931 id
= udf_getid(&fid
->icb
);
935 if (!(udf_cmpname(&fid
->data
[fid
->l_iu
],
936 nameptr
, fid
->l_fi
, namelen
, udfmp
))) {
937 id
= udf_getid(&fid
->icb
);
946 /* XXX Bail out here? */
952 /* Did we have a match? */
954 error
= udf_vget(udfmp
->im_mountp
, NULL
, id
, &tdp
);
957 * Remember where this entry was if it's the final
960 if (nameiop
== NAMEI_LOOKUP
)
961 node
->diroff
= ds
->offset
+ ds
->off
;
962 if (numdirpasses
== 2)
963 gd
->gd_nchstats
->ncs_pass2
++;
964 if ((flags
& CNP_LOCKPARENT
) == 0) {
965 a
->a_cnp
->cn_flags
|= CNP_PDIRUNLOCK
;
972 /* Name wasn't found on this pass. Do another pass? */
973 if (numdirpasses
== 2) {
979 if (nameiop
== NAMEI_CREATE
|| nameiop
== NAMEI_RENAME
) {
991 udf_reclaim(struct vop_reclaim_args
*a
)
994 struct udf_node
*unode
;
1001 if (unode
->i_devvp
) {
1002 vrele(unode
->i_devvp
);
1006 if (unode
->fentry
!= NULL
)
1007 kfree(unode
->fentry
, M_UDFFENTRY
);
1008 kfree(unode
, M_UDFNODE
);
1016 * Read the block and then set the data pointer to correspond with the
1017 * offset passed in. Only read in at most 'size' bytes, and then set 'size'
1018 * to the number of bytes pointed to. If 'size' is zero, try to read in a
1021 * Note that *bp may be assigned error or not.
1023 * XXX 'size' is limited to the logical block size for now due to problems
1027 udf_readatoffset(struct udf_node
*node
, int *size
, int offset
, struct buf
**bp
,
1030 struct udf_mnt
*udfmp
;
1031 struct file_entry
*fentry
= NULL
;
1037 udfmp
= node
->udfmp
;
1040 error
= udf_bmap_internal(node
, offset
, §or
, &max_size
);
1041 if (error
== UDF_INVALID_BMAP
) {
1043 * This error means that the file *data* is stored in the
1044 * allocation descriptor field of the file entry.
1046 fentry
= node
->fentry
;
1047 *data
= &fentry
->data
[fentry
->l_ea
];
1048 *size
= fentry
->l_ad
;
1050 } else if (error
!= 0) {
1054 /* Adjust the size so that it is within range */
1055 if (*size
== 0 || *size
> max_size
)
1057 *size
= min(*size
, MAXBSIZE
);
1059 if ((error
= udf_readlblks(udfmp
, sector
, *size
, bp
))) {
1060 kprintf("warning: udf_readlblks returned error %d\n", error
);
1061 /* note: *bp may be non-NULL */
1066 *data
= (uint8_t *)&bp1
->b_data
[offset
% udfmp
->bsize
];
1071 * Translate a file offset into a logical block and then into a physical
1075 udf_bmap_internal(struct udf_node
*node
, uint32_t offset
, daddr_t
*sector
, uint32_t *max_size
)
1077 struct udf_mnt
*udfmp
;
1078 struct file_entry
*fentry
;
1080 struct icb_tag
*tag
;
1081 uint32_t icblen
= 0;
1083 int ad_offset
, ad_num
= 0;
1086 udfmp
= node
->udfmp
;
1087 fentry
= node
->fentry
;
1088 tag
= &fentry
->icbtag
;
1090 switch (tag
->strat_type
) {
1095 kprintf("Cannot deal with strategy4096 yet!\n");
1099 kprintf("Unknown strategy type %d\n", tag
->strat_type
);
1103 switch (tag
->flags
& 0x7) {
1106 * The allocation descriptor field is filled with short_ad's.
1107 * If the offset is beyond the current extent, look for the
1112 ad_offset
= sizeof(struct short_ad
) * ad_num
;
1113 if (ad_offset
> fentry
->l_ad
) {
1114 kprintf("File offset out of bounds\n");
1117 icb
= GETICB(long_ad
, fentry
, fentry
->l_ea
+ ad_offset
);
1118 icblen
= GETICBLEN(short_ad
, icb
);
1120 } while(offset
>= icblen
);
1122 lsector
= (offset
>> udfmp
->bshift
) +
1123 ((struct short_ad
*)(icb
))->pos
;
1125 *max_size
= GETICBLEN(short_ad
, icb
);
1130 * The allocation descriptor field is filled with long_ad's
1131 * If the offset is beyond the current extent, look for the
1136 ad_offset
= sizeof(struct long_ad
) * ad_num
;
1137 if (ad_offset
> fentry
->l_ad
) {
1138 kprintf("File offset out of bounds\n");
1141 icb
= GETICB(long_ad
, fentry
, fentry
->l_ea
+ ad_offset
);
1142 icblen
= GETICBLEN(long_ad
, icb
);
1144 } while(offset
>= icblen
);
1146 lsector
= (offset
>> udfmp
->bshift
) +
1147 ((struct long_ad
*)(icb
))->loc
.lb_num
;
1149 *max_size
= GETICBLEN(long_ad
, icb
);
1154 * This type means that the file *data* is stored in the
1155 * allocation descriptor field of the file entry.
1158 *sector
= node
->hash_id
+ udfmp
->part_start
;
1160 return(UDF_INVALID_BMAP
);
1162 /* DirectCD does not use extended_ad's */
1164 kprintf("Unsupported allocation descriptor %d\n",
1169 *sector
= lsector
+ udfmp
->part_start
;
1172 * Check the sparing table. Each entry represents the beginning of
1175 if (udfmp
->s_table
!= NULL
) {
1176 for (i
= 0; i
< udfmp
->s_table_entries
; i
++) {
1177 p_offset
= lsector
- udfmp
->s_table
->entries
[i
].org
;
1178 if ((p_offset
< udfmp
->p_sectors
) && (p_offset
>= 0)) {
1179 *sector
= udfmp
->s_table
->entries
[i
].map
+