xref: /openbsd-src/sys/isofs/udf/udf_vnops.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: udf_vnops.c,v 1.44 2011/07/04 20:35:35 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: src/sys/fs/udf/udf_vnops.c,v 1.50 2005/01/28 14:42:16 phk Exp $
29  */
30 
31 /*
32  * Ported to OpenBSD by Pedro Martelletto in February 2005.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/namei.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <sys/mutex.h>
41 #include <sys/stat.h>
42 #include <sys/buf.h>
43 #include <sys/pool.h>
44 #include <sys/lock.h>
45 #include <sys/mount.h>
46 #include <sys/vnode.h>
47 #include <sys/dirent.h>
48 #include <sys/queue.h>
49 #include <sys/unistd.h>
50 #include <sys/endian.h>
51 #include <sys/specdev.h>
52 
53 #include <isofs/udf/ecma167-udf.h>
54 #include <isofs/udf/udf.h>
55 #include <isofs/udf/udf_extern.h>
56 
57 int udf_bmap_internal(struct unode *, off_t, daddr64_t *, uint32_t *);
58 
59 struct vops udf_vops = {
60 	.vop_access	= udf_access,
61 	.vop_bmap	= udf_bmap,
62 	.vop_lookup	= udf_lookup,
63 	.vop_getattr	= udf_getattr,
64 	.vop_open	= udf_open,
65 	.vop_close	= udf_close,
66 	.vop_ioctl	= udf_ioctl,
67 	.vop_read	= udf_read,
68 	.vop_readdir	= udf_readdir,
69 	.vop_readlink	= udf_readlink,
70 	.vop_inactive	= udf_inactive,
71 	.vop_reclaim	= udf_reclaim,
72 	.vop_strategy	= udf_strategy,
73 	.vop_lock	= udf_lock,
74 	.vop_unlock	= udf_unlock,
75 	.vop_islocked	= udf_islocked,
76 	.vop_print	= udf_print
77 };
78 
79 #define UDF_INVALID_BMAP	-1
80 
81 /* Look up a unode based on the ino_t passed in and return its vnode */
82 int
83 udf_hashlookup(struct umount *ump, ino_t id, int flags, struct vnode **vpp)
84 {
85 	struct unode *up;
86 	struct udf_hash_lh *lh;
87 	struct proc *p = curproc;
88 	int error;
89 
90 	*vpp = NULL;
91 
92 loop:
93 	mtx_enter(&ump->um_hashmtx);
94 	lh = &ump->um_hashtbl[id & ump->um_hashsz];
95 	if (lh == NULL) {
96 		mtx_leave(&ump->um_hashmtx);
97 		return (ENOENT);
98 	}
99 
100 	LIST_FOREACH(up, lh, u_le) {
101 		if (up->u_ino == id) {
102 			mtx_leave(&ump->um_hashmtx);
103 			error = vget(up->u_vnode, flags, p);
104 			if (error == ENOENT)
105 				goto loop;
106 			if (error)
107 				return (error);
108 			*vpp = up->u_vnode;
109 			return (0);
110 		}
111 	}
112 
113 	mtx_leave(&ump->um_hashmtx);
114 
115 	return (0);
116 }
117 
118 int
119 udf_hashins(struct unode *up)
120 {
121 	struct umount *ump;
122 	struct udf_hash_lh *lh;
123 	struct proc *p = curproc;
124 
125 	ump = up->u_ump;
126 
127 	vn_lock(up->u_vnode, LK_EXCLUSIVE | LK_RETRY, p);
128 	mtx_enter(&ump->um_hashmtx);
129 	lh = &ump->um_hashtbl[up->u_ino & ump->um_hashsz];
130 	if (lh == NULL)
131 		panic("hash entry is NULL, up->u_ino = %d", up->u_ino);
132 	LIST_INSERT_HEAD(lh, up, u_le);
133 	mtx_leave(&ump->um_hashmtx);
134 
135 	return (0);
136 }
137 
138 int
139 udf_hashrem(struct unode *up)
140 {
141 	struct umount *ump;
142 	struct udf_hash_lh *lh;
143 
144 	ump = up->u_ump;
145 
146 	mtx_enter(&ump->um_hashmtx);
147 	lh = &ump->um_hashtbl[up->u_ino & ump->um_hashsz];
148 	if (lh == NULL)
149 		panic("hash entry is NULL, up->u_ino = %d", up->u_ino);
150 	LIST_REMOVE(up, u_le);
151 	mtx_leave(&ump->um_hashmtx);
152 
153 	return (0);
154 }
155 
156 int
157 udf_allocv(struct mount *mp, struct vnode **vpp, struct proc *p)
158 {
159 	int error;
160 	struct vnode *vp;
161 
162 	error = getnewvnode(VT_UDF, mp, &udf_vops, &vp);
163 	if (error) {
164 		printf("udf_allocv: failed to allocate new vnode\n");
165 		return (error);
166 	}
167 
168 	*vpp = vp;
169 	return (0);
170 }
171 
172 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */
173 static mode_t
174 udf_permtomode(struct unode *up)
175 {
176 	uint32_t perm;
177 	uint16_t flags;
178 	mode_t mode;
179 
180 	perm = letoh32(up->u_fentry->perm);
181 	flags = letoh16(up->u_fentry->icbtag.flags);
182 
183 	mode = perm & UDF_FENTRY_PERM_USER_MASK;
184 	mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2);
185 	mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4);
186 	mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4);
187 	mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6);
188 	mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8);
189 
190 	return (mode);
191 }
192 
193 int
194 udf_access(void *v)
195 {
196 	struct vop_access_args *ap = v;
197 	struct vnode *vp;
198 	struct unode *up;
199 	mode_t a_mode, mode;
200 
201 	vp = ap->a_vp;
202 	up = VTOU(vp);
203 	a_mode = ap->a_mode;
204 
205 	if (a_mode & VWRITE) {
206 		switch (vp->v_type) {
207 		case VDIR:
208 		case VLNK:
209 		case VREG:
210 			return (EROFS);
211 			/* NOTREACHED */
212 		default:
213 			break;
214 		}
215 	}
216 
217 	mode = udf_permtomode(up);
218 
219 	return (vaccess(vp->v_type, mode, up->u_fentry->uid, up->u_fentry->gid,
220 	    a_mode, ap->a_cred));
221 }
222 
223 static int mon_lens[2][12] = {
224 	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
225 	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
226 };
227 
228 static int
229 udf_isaleapyear(int year)
230 {
231 	int i;
232 
233 	i = (year % 4) ? 0 : 1;
234 	i &= (year % 100) ? 1 : 0;
235 	i |= (year % 400) ? 0 : 1;
236 
237 	return (i);
238 }
239 
240 /*
241  * This is just a rough hack.  Daylight savings isn't calculated and tv_nsec
242  * is ignored.
243  * Timezone calculation compliments of Julian Elischer <julian@elischer.org>.
244  */
245 static void
246 udf_timetotimespec(struct timestamp *time, struct timespec *t)
247 {
248 	int i, lpyear, daysinyear, year;
249 	union {
250 		uint16_t	u_tz_offset;
251 		int16_t		s_tz_offset;
252 	} tz;
253 
254 	t->tv_nsec = 0;
255 
256 	/* DirectCD seems to like using bogus year values */
257 	year = letoh16(time->year);
258 	if (year < 1970) {
259 		t->tv_sec = 0;
260 		return;
261 	}
262 
263 	/* Calculate the time and day */
264 	t->tv_sec = time->second;
265 	t->tv_sec += time->minute * 60;
266 	t->tv_sec += time->hour * 3600;
267 	t->tv_sec += time->day * 3600 * 24;
268 
269 	/* Calculate the month */
270 	lpyear = udf_isaleapyear(year);
271 	for (i = 1; i < time->month; i++)
272 		t->tv_sec += mon_lens[lpyear][i] * 3600 * 24;
273 
274 	/* Speed up the calculation */
275 	if (year > 1979)
276 		t->tv_sec += 315532800;
277 	if (year > 1989)
278 		t->tv_sec += 315619200;
279 	if (year > 1999)
280 		t->tv_sec += 315532800;
281 	for (i = 2000; i < year; i++) {
282 		daysinyear = udf_isaleapyear(i) + 365 ;
283 		t->tv_sec += daysinyear * 3600 * 24;
284 	}
285 
286 	/*
287 	 * Calculate the time zone.  The timezone is 12 bit signed 2's
288 	 * compliment, so we gotta do some extra magic to handle it right.
289 	 */
290 	tz.u_tz_offset = letoh16(time->type_tz);
291 	tz.u_tz_offset &= 0x0fff;
292 	if (tz.u_tz_offset & 0x0800)
293 		tz.u_tz_offset |= 0xf000;	/* extend the sign to 16 bits */
294 	if ((time->type_tz & 0x1000) && (tz.s_tz_offset != -2047))
295 		t->tv_sec -= tz.s_tz_offset * 60;
296 
297 	return;
298 }
299 
300 int
301 udf_getattr(void *v)
302 {
303 	struct vop_getattr_args *ap = v;
304 	struct vnode *vp;
305 	struct unode *up;
306 	struct vattr *vap;
307 	struct extfile_entry *xfentry;
308 	struct file_entry *fentry;
309 	struct timespec ts;
310 
311 	ts.tv_sec = 0;
312 
313 	vp = ap->a_vp;
314 	vap = ap->a_vap;
315 	up = VTOU(vp);
316 
317 	xfentry = up->u_fentry;
318 	fentry = (struct file_entry *)up->u_fentry;
319 
320 	vap->va_fsid = up->u_dev;
321 	vap->va_fileid = up->u_ino;
322 	vap->va_mode = udf_permtomode(up);
323 	vap->va_nlink = letoh16(fentry->link_cnt);
324 	/*
325 	 * The spec says that -1 is valid for uid/gid and indicates an
326 	 * invalid uid/gid.  How should this be represented?
327 	 */
328 	vap->va_uid = (letoh32(fentry->uid) == -1) ? 0 : letoh32(fentry->uid);
329 	vap->va_gid = (letoh32(fentry->gid) == -1) ? 0 : letoh32(fentry->gid);
330 	vap->va_rdev = 0;
331 	if (vp->v_type & VDIR) {
332 		vap->va_nlink++; /* Count a reference to ourselves */
333 		/*
334 		 * Directories that are recorded within their ICB will show
335 		 * as having 0 blocks recorded.  Since tradition dictates
336 		 * that directories consume at least one logical block,
337 		 * make it appear so.
338 		 */
339 		vap->va_size = up->u_ump->um_bsize;
340 	} else
341 		vap->va_size = letoh64(fentry->inf_len);
342 	if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0) {
343 		udf_timetotimespec(&xfentry->atime, &vap->va_atime);
344 		udf_timetotimespec(&xfentry->mtime, &vap->va_mtime);
345 		if ((vp->v_type & VDIR) && xfentry->logblks_rec != 0)
346 			vap->va_size =
347 				    letoh64(xfentry->logblks_rec) * up->u_ump->um_bsize;
348 	} else {
349 		udf_timetotimespec(&fentry->atime, &vap->va_atime);
350 		udf_timetotimespec(&fentry->mtime, &vap->va_mtime);
351 		if ((vp->v_type & VDIR) && fentry->logblks_rec != 0)
352 			vap->va_size =
353 				    letoh64(fentry->logblks_rec) * up->u_ump->um_bsize;
354 	}
355 	vap->va_ctime = vap->va_mtime; /* Stored as an Extended Attribute */
356 	vap->va_flags = 0;
357 	vap->va_gen = 1;
358 	vap->va_blocksize = up->u_ump->um_bsize;
359 	vap->va_bytes = letoh64(fentry->inf_len);
360 	vap->va_type = vp->v_type;
361 	vap->va_filerev = 0;
362 
363 	return (0);
364 }
365 
366 int
367 udf_open(void *v)
368 {
369 	return (0); /* Nothing to be done at this point */
370 }
371 
372 int
373 udf_close(void *v)
374 {
375 	return (0); /* Nothing to be done at this point */
376 }
377 
378 /*
379  * File specific ioctls.
380  */
381 int
382 udf_ioctl(void *v)
383 {
384 	return (ENOTTY);
385 }
386 
387 /*
388  * I'm not sure that this has much value in a read-only filesystem, but
389  * cd9660 has it too.
390  */
391 #if 0
392 static int
393 udf_pathconf(struct vop_pathconf_args *a)
394 {
395 
396 	switch (ap->a_name) {
397 	case _PC_LINK_MAX:
398 		*ap->a_retval = 65535;
399 		return (0);
400 	case _PC_NAME_MAX:
401 		*ap->a_retval = NAME_MAX;
402 		return (0);
403 	case _PC_PATH_MAX:
404 		*ap->a_retval = PATH_MAX;
405 		return (0);
406 	case _PC_NO_TRUNC:
407 		*ap->a_retval = 1;
408 		return (0);
409 	default:
410 		return (EINVAL);
411 	}
412 }
413 #endif
414 
415 int
416 udf_read(void *v)
417 {
418 	struct vop_read_args *ap = v;
419 	struct vnode *vp = ap->a_vp;
420 	struct uio *uio = ap->a_uio;
421 	struct unode *up = VTOU(vp);
422 	struct buf *bp;
423 	uint8_t *data;
424 	off_t fsize, offset;
425 	int error = 0;
426 	int size;
427 
428 	if (uio->uio_offset < 0)
429 		return (EINVAL);
430 
431 	fsize = letoh64(up->u_fentry->inf_len);
432 
433 	while (uio->uio_offset < fsize && uio->uio_resid > 0) {
434 		offset = uio->uio_offset;
435 		if (uio->uio_resid + offset <= fsize)
436 			size = uio->uio_resid;
437 		else
438 			size = fsize - offset;
439 		error = udf_readatoffset(up, &size, offset, &bp, &data);
440 		if (error == 0)
441 			error = uiomove(data, size, uio);
442 		if (bp != NULL) {
443 			brelse(bp);
444 			bp = NULL;
445 		}
446 		if (error)
447 			break;
448 	};
449 
450 	return (error);
451 }
452 
453 /*
454  * Translate the name from a CS0 dstring to a 16-bit Unicode String.
455  * Hooks need to be placed in here to translate from Unicode to the encoding
456  * that the kernel/user expects.  Return the length of the translated string.
457  */
458 int
459 udf_transname(char *cs0string, char *destname, int len, struct umount *ump)
460 {
461 	unicode_t *transname;
462 	int i, unilen = 0, destlen;
463 
464 	if (len > MAXNAMLEN) {
465 #ifdef DIAGNOSTIC
466 		printf("udf_transname(): name too long\n");
467 #endif
468 		return (0);
469 	}
470 
471 	/* allocate a buffer big enough to hold an 8->16 bit expansion */
472 	transname = pool_get(&udf_trans_pool, PR_WAITOK);
473 
474 	if ((unilen = udf_rawnametounicode(len, cs0string, transname)) == -1) {
475 #ifdef DIAGNOSTIC
476 		printf("udf_transname(): Unicode translation failed\n");
477 #endif
478 		pool_put(&udf_trans_pool, transname);
479 		return (0);
480 	}
481 
482 	/* Pack it back to 8-bit Unicode. */
483 	for (i = 0; i < unilen ; i++)
484 		if (transname[i] & 0xff00)
485 			destname[i] = '?';	/* Fudge the 16bit chars */
486 		else
487 			destname[i] = transname[i] & 0xff;
488 
489 	pool_put(&udf_trans_pool, transname);
490 
491 	/* Don't forget to terminate the string. */
492 	destname[unilen] = 0;
493 	destlen = unilen;
494 
495 	return (destlen);
496 }
497 
498 /*
499  * Compare a CS0 dstring with a name passed in from the VFS layer.  Return
500  * 0 on a successful match, nonzero otherwise.  Unicode work may need to be
501  * done here also.
502  */
503 static int
504 udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct umount *ump)
505 {
506 	char *transname;
507 	int error = 0;
508 
509 	/* This is overkill, but not worth creating a new pool */
510 	transname = pool_get(&udf_trans_pool, PR_WAITOK);
511 
512 	cs0len = udf_transname(cs0string, transname, cs0len, ump);
513 
514 	/* Easy check.  If they aren't the same length, they aren't equal */
515 	if ((cs0len == 0) || (cs0len != cmplen))
516 		error = -1;
517 	else
518 		error = bcmp(transname, cmpname, cmplen);
519 
520 	pool_put(&udf_trans_pool, transname);
521 
522 	return (error);
523 }
524 
525 struct udf_uiodir {
526 	struct dirent *dirent;
527 	u_long *cookies;
528 	int ncookies;
529 	int acookies;
530 	int eofflag;
531 };
532 
533 static int
534 udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie)
535 {
536 	if (uiodir->cookies != NULL) {
537 		if (++uiodir->acookies > uiodir->ncookies) {
538 			uiodir->eofflag = 0;
539 			return (-1);
540 		}
541 		*uiodir->cookies++ = cookie;
542 	}
543 
544 	if (uio->uio_resid < de_size) {
545 		uiodir->eofflag = 0;
546 		return (-1);
547 	}
548 
549 	return (uiomove(uiodir->dirent, de_size, uio));
550 }
551 
552 static struct udf_dirstream *
553 udf_opendir(struct unode *up, int offset, int fsize, struct umount *ump)
554 {
555 	struct udf_dirstream *ds;
556 
557 	ds = pool_get(&udf_ds_pool, PR_WAITOK | PR_ZERO);
558 
559 	ds->node = up;
560 	ds->offset = offset;
561 	ds->ump = ump;
562 	ds->fsize = fsize;
563 
564 	return (ds);
565 }
566 
567 static struct fileid_desc *
568 udf_getfid(struct udf_dirstream *ds)
569 {
570 	struct fileid_desc *fid;
571 	int error, frag_size = 0, total_fid_size;
572 
573 	/* End of directory? */
574 	if (ds->offset + ds->off >= ds->fsize) {
575 		ds->error = 0;
576 		return (NULL);
577 	}
578 
579 	/* Grab the first extent of the directory */
580 	if (ds->off == 0) {
581 		ds->size = 0;
582 		error = udf_readatoffset(ds->node, &ds->size, ds->offset,
583 		    &ds->bp, &ds->data);
584 		if (error) {
585 			ds->error = error;
586 			if (ds->bp != NULL) {
587 				brelse(ds->bp);
588 				ds->bp = NULL;
589 			}
590 			return (NULL);
591 		}
592 	}
593 
594 	/*
595 	 * Clean up from a previous fragmented FID.
596 	 * Is this the right place for this?
597 	 */
598 	if (ds->fid_fragment && ds->buf != NULL) {
599 		ds->fid_fragment = 0;
600 		free(ds->buf, M_UDFFID);
601 	}
602 
603 	fid = (struct fileid_desc*)&ds->data[ds->off];
604 
605 	/*
606 	 * Check to see if the fid is fragmented. The first test
607 	 * ensures that we don't wander off the end of the buffer
608 	 * looking for the l_iu and l_fi fields.
609 	 */
610 	if (ds->off + UDF_FID_SIZE > ds->size ||
611 	    ds->off + letoh16(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){
612 
613 		/* Copy what we have of the fid into a buffer */
614 		frag_size = ds->size - ds->off;
615 		if (frag_size >= ds->ump->um_bsize) {
616 			printf("udf: invalid FID fragment\n");
617 			ds->error = EINVAL;
618 			return (NULL);
619 		}
620 
621 		/*
622 		 * File ID descriptors can only be at most one
623 		 * logical sector in size.
624 		 */
625 		ds->buf = malloc(ds->ump->um_bsize, M_UDFFID, M_WAITOK|M_ZERO);
626 		bcopy(fid, ds->buf, frag_size);
627 
628 		/* Reduce all of the casting magic */
629 		fid = (struct fileid_desc*)ds->buf;
630 
631 		if (ds->bp != NULL) {
632 			brelse(ds->bp);
633 			ds->bp = NULL;
634 		}
635 
636 		/* Fetch the next allocation */
637 		ds->offset += ds->size;
638 		ds->size = 0;
639 		error = udf_readatoffset(ds->node, &ds->size, ds->offset,
640 		    &ds->bp, &ds->data);
641 		if (error) {
642 			ds->error = error;
643 			if (ds->bp != NULL) {
644 				brelse(ds->bp);
645 				ds->bp = NULL;
646 			}
647 			return (NULL);
648 		}
649 
650 		/*
651 		 * If the fragment was so small that we didn't get
652 		 * the l_iu and l_fi fields, copy those in.
653 		 */
654 		if (frag_size < UDF_FID_SIZE)
655 			bcopy(ds->data, &ds->buf[frag_size],
656 			    UDF_FID_SIZE - frag_size);
657 
658 		/*
659 		 * Now that we have enough of the fid to work with,
660 		 * copy in the rest of the fid from the new
661 		 * allocation.
662 		 */
663 		total_fid_size = UDF_FID_SIZE + letoh16(fid->l_iu) + fid->l_fi;
664 		if (total_fid_size > ds->ump->um_bsize) {
665 			printf("udf: invalid FID\n");
666 			ds->error = EIO;
667 			return (NULL);
668 		}
669 		bcopy(ds->data, &ds->buf[frag_size],
670 		    total_fid_size - frag_size);
671 
672 		ds->fid_fragment = 1;
673 	} else {
674 		total_fid_size = letoh16(fid->l_iu) + fid->l_fi + UDF_FID_SIZE;
675 	}
676 
677 	/*
678 	 * Update the offset. Align on a 4 byte boundary because the
679 	 * UDF spec says so.
680 	 */
681 	ds->this_off = ds->off;
682 	if (!ds->fid_fragment) {
683 		ds->off += (total_fid_size + 3) & ~0x03;
684 	} else {
685 		ds->off = (total_fid_size - frag_size + 3) & ~0x03;
686 	}
687 
688 	return (fid);
689 }
690 
691 static void
692 udf_closedir(struct udf_dirstream *ds)
693 {
694 
695 	if (ds->bp != NULL) {
696 		brelse(ds->bp);
697 		ds->bp = NULL;
698 	}
699 
700 	if (ds->fid_fragment && ds->buf != NULL)
701 		free(ds->buf, M_UDFFID);
702 
703 	pool_put(&udf_ds_pool, ds);
704 }
705 
706 int
707 udf_readdir(void *v)
708 {
709 	struct vop_readdir_args *ap = v;
710 	struct vnode *vp;
711 	struct uio *uio;
712 	struct dirent dir;
713 	struct unode *up;
714 	struct umount *ump;
715 	struct fileid_desc *fid;
716 	struct udf_uiodir uiodir;
717 	struct udf_dirstream *ds;
718 	u_long *cookies = NULL;
719 	int ncookies;
720 	int error = 0;
721 
722 #define GENERIC_DIRSIZ(dp) \
723     ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
724 
725 	vp = ap->a_vp;
726 	uio = ap->a_uio;
727 	up = VTOU(vp);
728 	ump = up->u_ump;
729 	uiodir.eofflag = 1;
730 
731 	if (ap->a_ncookies != NULL) {
732 		/*
733 		 * Guess how many entries are needed.  If we run out, this
734 		 * function will be called again and thing will pick up were
735 		 * it left off.
736 		 */
737 		ncookies = uio->uio_resid / 8;
738 		cookies = malloc(sizeof(u_long) * ncookies, M_TEMP, M_WAITOK);
739 		uiodir.ncookies = ncookies;
740 		uiodir.cookies = cookies;
741 		uiodir.acookies = 0;
742 	} else {
743 		uiodir.cookies = NULL;
744 	}
745 
746 	/*
747 	 * Iterate through the file id descriptors.  Give the parent dir
748 	 * entry special attention.
749 	 */
750 	if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
751 		up->u_ump->um_start += up->u_ump->um_meta_start;
752 		up->u_ump->um_len = up->u_ump->um_meta_len;
753 	}
754 	ds = udf_opendir(up, uio->uio_offset,
755 	    letoh64(up->u_fentry->inf_len), up->u_ump);
756 
757 	while ((fid = udf_getfid(ds)) != NULL) {
758 
759 		/* Should we return an error on a bad fid? */
760 		if (udf_checktag(&fid->tag, TAGID_FID)) {
761 			printf("Invalid FID tag (%d)\n", fid->tag.id);
762 			error = EIO;
763 			break;
764 		}
765 
766 		/* Is this a deleted file? */
767 		if (fid->file_char & UDF_FILE_CHAR_DEL)
768 			continue;
769 
770 		if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
771 			/* Do up the '.' and '..' entries.  Dummy values are
772 			 * used for the cookies since the offset here is
773 			 * usually zero, and NFS doesn't like that value
774 			 */
775 			dir.d_fileno = up->u_ino;
776 			dir.d_type = DT_DIR;
777 			dir.d_name[0] = '.';
778 			dir.d_name[1] = '\0';
779 			dir.d_namlen = 1;
780 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
781 			uiodir.dirent = &dir;
782 			error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1);
783 			if (error)
784 				break;
785 
786 			dir.d_fileno = udf_getid(&fid->icb);
787 			dir.d_type = DT_DIR;
788 			dir.d_name[0] = '.';
789 			dir.d_name[1] = '.';
790 			dir.d_name[2] = '\0';
791 			dir.d_namlen = 2;
792 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
793 			uiodir.dirent = &dir;
794 			error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2);
795 		} else {
796 			dir.d_namlen = udf_transname(&fid->data[fid->l_iu],
797 			    &dir.d_name[0], fid->l_fi, ump);
798 			dir.d_fileno = udf_getid(&fid->icb);
799 			dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ?
800 			    DT_DIR : DT_UNKNOWN;
801 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
802 			uiodir.dirent = &dir;
803 			error = udf_uiodir(&uiodir, dir.d_reclen, uio,
804 			    ds->this_off);
805 		}
806 		if (error) {
807 			printf("uiomove returned %d\n", error);
808 			break;
809 		}
810 
811 	}
812 
813 #undef GENERIC_DIRSIZ
814 
815 	/* tell the calling layer whether we need to be called again */
816 	*ap->a_eofflag = uiodir.eofflag;
817 	uio->uio_offset = ds->offset + ds->off;
818 
819 	if (!error)
820 		error = ds->error;
821 
822 	udf_closedir(ds);
823 	if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
824 		up->u_ump->um_start = up->u_ump->um_realstart;
825 		up->u_ump->um_len = up->u_ump->um_reallen;
826 	}
827 
828 	if (ap->a_ncookies != NULL) {
829 		if (error)
830 			free(cookies, M_TEMP);
831 		else {
832 			*ap->a_ncookies = uiodir.acookies;
833 			*ap->a_cookies = cookies;
834 		}
835 	}
836 
837 	return (error);
838 }
839 
840 /* Are there any implementations out there that do soft-links? */
841 int
842 udf_readlink(void *v)
843 {
844 	return (EOPNOTSUPP);
845 }
846 
847 int
848 udf_strategy(void *v)
849 {
850 	struct vop_strategy_args *ap = v;
851 	struct buf *bp;
852 	struct vnode *vp;
853 	struct unode *up;
854 	int maxsize, s, error;
855 
856 	bp = ap->a_bp;
857 	vp = bp->b_vp;
858 	up = VTOU(vp);
859 
860 	/* cd9660 has this test reversed, but it seems more logical this way */
861 	if (bp->b_blkno != bp->b_lblkno) {
862 		/*
863 		 * Files that are embedded in the fentry don't translate well
864 		 * to a block number.  Reject.
865 		 */
866 		if (udf_bmap_internal(up, bp->b_lblkno * up->u_ump->um_bsize,
867 		    &bp->b_lblkno, &maxsize)) {
868 			clrbuf(bp);
869 			bp->b_blkno = -1;
870 		}
871 	} else {
872 		error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
873 		if (error) {
874 			bp->b_error = error;
875 			bp->b_flags |= B_ERROR;
876 			s = splbio();
877 			biodone(bp);
878 			splx(s);
879 			return (error);
880 		}
881 
882 		if ((long)bp->b_blkno == -1)
883 			clrbuf(bp);
884 	}
885 
886 	if ((long)bp->b_blkno == -1) {
887 		s = splbio();
888 		biodone(bp);
889 		splx(s);
890 	} else {
891 		bp->b_dev = vp->v_rdev;
892 		(up->u_devvp->v_op->vop_strategy)(ap);
893 	}
894 
895 	return (0);
896 }
897 
898 int
899 udf_lock(void *v)
900 {
901 	struct vop_lock_args *ap = v;
902 
903 	struct vnode *vp = ap->a_vp;
904 
905 	return (lockmgr(&VTOU(vp)->u_lock, ap->a_flags, NULL));
906 }
907 
908 int
909 udf_unlock(void *v)
910 {
911 	struct vop_unlock_args *ap = v;
912 
913 	struct vnode *vp = ap->a_vp;
914 
915 	return (lockmgr(&VTOU(vp)->u_lock, ap->a_flags | LK_RELEASE, NULL));
916 }
917 
918 int
919 udf_islocked(void *v)
920 {
921 	struct vop_islocked_args *ap = v;
922 
923 	return (lockstatus(&VTOU(ap->a_vp)->u_lock));
924 }
925 
926 int
927 udf_print(void *v)
928 {
929 	struct vop_print_args *ap = v;
930 	struct vnode *vp = ap->a_vp;
931 	struct unode *up = VTOU(vp);
932 
933 	/*
934 	 * Complete the information given by vprint().
935 	 */
936 	printf("tag VT_UDF, hash id %u\n", up->u_ino);
937 #ifdef DIAGNOSTIC
938 	lockmgr_printinfo(&up->u_lock);
939 	printf("\n");
940 #endif
941 	return (0);
942 }
943 
944 int
945 udf_bmap(void *v)
946 {
947 	struct vop_bmap_args *ap = v;
948 	struct unode *up;
949 	uint32_t max_size;
950 	daddr64_t lsector;
951 	int error;
952 
953 	up = VTOU(ap->a_vp);
954 
955 	if (ap->a_vpp != NULL)
956 		*ap->a_vpp = up->u_devvp;
957 	if (ap->a_bnp == NULL)
958 		return (0);
959 
960 	error = udf_bmap_internal(up, ap->a_bn * up->u_ump->um_bsize,
961 	    &lsector, &max_size);
962 	if (error)
963 		return (error);
964 
965 	/* Translate logical to physical sector number */
966 	*ap->a_bnp = lsector << (up->u_ump->um_bshift - DEV_BSHIFT);
967 
968 	/* Punt on read-ahead for now */
969 	if (ap->a_runp)
970 		*ap->a_runp = 0;
971 
972 	return (0);
973 }
974 
975 /*
976  * The all powerful VOP_LOOKUP().
977  */
978 int
979 udf_lookup(void *v)
980 {
981 	struct vop_lookup_args *ap = v;
982 	struct vnode *dvp;
983 	struct vnode *tdp = NULL;
984 	struct vnode **vpp = ap->a_vpp;
985 	struct unode *up;
986 	struct umount *ump;
987 	struct fileid_desc *fid = NULL;
988 	struct udf_dirstream *ds;
989 	struct proc *p;
990 	u_long nameiop;
991 	u_long flags;
992 	char *nameptr;
993 	long namelen;
994 	ino_t id = 0;
995 	int offset, error = 0;
996 	int numdirpasses, fsize;
997 
998 	extern struct nchstats nchstats;
999 
1000 	dvp = ap->a_dvp;
1001 	up = VTOU(dvp);
1002 	ump = up->u_ump;
1003 	nameiop = ap->a_cnp->cn_nameiop;
1004 	flags = ap->a_cnp->cn_flags;
1005 	nameptr = ap->a_cnp->cn_nameptr;
1006 	namelen = ap->a_cnp->cn_namelen;
1007 	fsize = letoh64(up->u_fentry->inf_len);
1008 	p = ap->a_cnp->cn_proc;
1009 	*vpp = NULL;
1010 
1011 	/*
1012 	 * Make sure the process can scan the requested directory.
1013 	 */
1014 	error = VOP_ACCESS(dvp, VEXEC, ap->a_cnp->cn_cred, p);
1015 	if (error)
1016 		return (error);
1017 
1018 	/*
1019 	 * Check if the (directory, name) tuple has been already cached.
1020 	 */
1021 	error = cache_lookup(dvp, vpp, ap->a_cnp);
1022 	if (error >= 0)
1023 		return (error);
1024 	else
1025 		error = 0;
1026 
1027 	/*
1028 	 * If dvp is what's being looked up, then return it.
1029 	 */
1030 	if (ap->a_cnp->cn_namelen == 1 && ap->a_cnp->cn_nameptr[0] == '.') {
1031 		vref(dvp);
1032 		*vpp = dvp;
1033 		return (0);
1034 	}
1035 
1036 	/*
1037 	 * If this is a LOOKUP and we've already partially searched through
1038 	 * the directory, pick up where we left off and flag that the
1039 	 * directory may need to be searched twice.  For a full description,
1040 	 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup()
1041 	 */
1042 	if (nameiop != LOOKUP || up->u_diroff == 0 || up->u_diroff > fsize) {
1043 		offset = 0;
1044 		numdirpasses = 1;
1045 	} else {
1046 		offset = up->u_diroff;
1047 		numdirpasses = 2;
1048 		nchstats.ncs_2passes++;
1049 	}
1050 
1051 	if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
1052 		up->u_ump->um_start += up->u_ump->um_meta_start;
1053 		up->u_ump->um_len = up->u_ump->um_meta_len;
1054 	}
1055 lookloop:
1056 	ds = udf_opendir(up, offset, fsize, ump);
1057 
1058 	while ((fid = udf_getfid(ds)) != NULL) {
1059 		/* Check for a valid FID tag. */
1060 		if (udf_checktag(&fid->tag, TAGID_FID)) {
1061 			printf("udf_lookup: Invalid tag\n");
1062 			error = EIO;
1063 			break;
1064 		}
1065 
1066 		/* Is this a deleted file? */
1067 		if (fid->file_char & UDF_FILE_CHAR_DEL)
1068 			continue;
1069 
1070 		if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
1071 			if (flags & ISDOTDOT) {
1072 				id = udf_getid(&fid->icb);
1073 				break;
1074 			}
1075 		} else {
1076 			if (!(udf_cmpname(&fid->data[fid->l_iu],
1077 			    nameptr, fid->l_fi, namelen, ump))) {
1078 				id = udf_getid(&fid->icb);
1079 				break;
1080 			}
1081 		}
1082 	}
1083 
1084 	if (!error)
1085 		error = ds->error;
1086 
1087 	if (error) {
1088 		udf_closedir(ds);
1089 		if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
1090 			up->u_ump->um_start = up->u_ump->um_realstart;
1091 			up->u_ump->um_len = up->u_ump->um_reallen;
1092 		}
1093 		return (error);
1094 	}
1095 
1096 	/* Did we have a match? */
1097 	if (id) {
1098 		error = udf_vget(ump->um_mountp, id, &tdp);
1099 		if (!error) {
1100 			/*
1101 			 * Remember where this entry was if it's the final
1102 			 * component.
1103 			 */
1104 			if ((flags & ISLASTCN) && nameiop == LOOKUP)
1105 				up->u_diroff = ds->offset + ds->off;
1106 			if (numdirpasses == 2)
1107 				nchstats.ncs_pass2++;
1108 			if (!(flags & LOCKPARENT) || !(flags & ISLASTCN)) {
1109 				ap->a_cnp->cn_flags |= PDIRUNLOCK;
1110 				VOP_UNLOCK(dvp, 0, p);
1111 			}
1112 
1113 			*vpp = tdp;
1114 		}
1115 	} else {
1116 		/* Name wasn't found on this pass.  Do another pass? */
1117 		if (numdirpasses == 2) {
1118 			numdirpasses--;
1119 			offset = 0;
1120 			udf_closedir(ds);
1121 			goto lookloop;
1122 		}
1123 
1124 		if ((flags & ISLASTCN) &&
1125 		    (nameiop == CREATE || nameiop == RENAME)) {
1126 			error = EROFS;
1127 		} else {
1128 			error = ENOENT;
1129 		}
1130 	}
1131 
1132 	/*
1133 	 * Cache the result of this lookup.
1134 	 */
1135 	if (flags & MAKEENTRY)
1136 		cache_enter(dvp, *vpp, ap->a_cnp);
1137 
1138 	udf_closedir(ds);
1139 	if (ISSET(up->u_ump->um_flags, UDF_MNT_USES_META)) {
1140 		up->u_ump->um_start = up->u_ump->um_realstart;
1141 		up->u_ump->um_len = up->u_ump->um_reallen;
1142 	}
1143 
1144 	return (error);
1145 }
1146 
1147 int
1148 udf_inactive(void *v)
1149 {
1150 	struct vop_inactive_args *ap = v;
1151 	struct vnode *vp = ap->a_vp;
1152 	struct proc *p = ap->a_p;
1153 
1154 	/*
1155 	 * No need to sync anything, so just unlock the vnode and return.
1156 	 */
1157 	VOP_UNLOCK(vp, 0, p);
1158 
1159 	return (0);
1160 }
1161 
1162 int
1163 udf_reclaim(void *v)
1164 {
1165 	struct vop_reclaim_args *ap = v;
1166 	struct vnode *vp;
1167 	struct unode *up;
1168 
1169 	vp = ap->a_vp;
1170 	up = VTOU(vp);
1171 
1172 	if (up != NULL) {
1173 		udf_hashrem(up);
1174 		if (up->u_devvp) {
1175 			vrele(up->u_devvp);
1176 			up->u_devvp = 0;
1177 		}
1178 
1179 		if (up->u_fentry != NULL)
1180 			free(up->u_fentry, M_UDFFENTRY);
1181 
1182 		pool_put(&unode_pool, up);
1183 		vp->v_data = NULL;
1184 	}
1185 
1186 	return (0);
1187 }
1188 
1189 /*
1190  * Read the block and then set the data pointer to correspond with the
1191  * offset passed in.  Only read in at most 'size' bytes, and then set 'size'
1192  * to the number of bytes pointed to.  If 'size' is zero, try to read in a
1193  * whole extent.
1194  *
1195  * Note that *bp may be assigned error or not.
1196  *
1197  */
1198 int
1199 udf_readatoffset(struct unode *up, int *size, off_t offset,
1200     struct buf **bp, uint8_t **data)
1201 {
1202 	struct umount *ump;
1203 	struct extfile_entry *xfentry = NULL;
1204 	struct file_entry *fentry = NULL;
1205 	struct buf *bp1;
1206 	uint32_t max_size;
1207 	daddr64_t sector;
1208 	int error;
1209 
1210 	ump = up->u_ump;
1211 
1212 	*bp = NULL;
1213 	error = udf_bmap_internal(up, offset, &sector, &max_size);
1214 	if (error == UDF_INVALID_BMAP) {
1215 		/*
1216 		 * This error means that the file *data* is stored in the
1217 		 * allocation descriptor field of the file entry.
1218 		 */
1219 		if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0) {
1220 			xfentry = up->u_fentry;
1221 			*data = &xfentry->data[letoh32(xfentry->l_ea)];
1222 			*size = letoh32(xfentry->l_ad);
1223 		} else {
1224 			fentry = (struct file_entry *)up->u_fentry;
1225 			*data = &fentry->data[letoh32(fentry->l_ea)];
1226 			*size = letoh32(fentry->l_ad);
1227 		}
1228 		return (0);
1229 	} else if (error != 0) {
1230 		return (error);
1231 	}
1232 
1233 	/* Adjust the size so that it is within range */
1234 	if (*size == 0 || *size > max_size)
1235 		*size = max_size;
1236 	*size = min(*size, MAXBSIZE);
1237 
1238 	if ((error = udf_readlblks(ump, sector, *size, bp))) {
1239 		printf("warning: udf_readlblks returned error %d\n", error);
1240 		/* note: *bp may be non-NULL */
1241 		return (error);
1242 	}
1243 
1244 	bp1 = *bp;
1245 	*data = (uint8_t *)&bp1->b_data[offset % ump->um_bsize];
1246 	return (0);
1247 }
1248 
1249 /*
1250  * Translate a file offset into a logical block and then into a physical
1251  * block.
1252  */
1253 int
1254 udf_bmap_internal(struct unode *up, off_t offset, daddr64_t *sector,
1255     uint32_t *max_size)
1256 {
1257 	struct umount *ump;
1258 	struct extfile_entry *xfentry;
1259 	struct file_entry *fentry;
1260 	void *icb;
1261 	struct icb_tag *tag;
1262 	uint32_t icblen = 0;
1263 	daddr64_t lsector;
1264 	int ad_offset, ad_num = 0;
1265 	int i, p_offset, l_ea, l_ad;
1266 
1267 	ump = up->u_ump;
1268 	xfentry = up->u_fentry;
1269 	fentry = (struct file_entry *)up->u_fentry;
1270 	tag = &fentry->icbtag;
1271 	if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0) {
1272 		l_ea = letoh32(xfentry->l_ea);
1273 		l_ad = letoh32(xfentry->l_ad);
1274 	} else {
1275 		l_ea = letoh32(fentry->l_ea);
1276 		l_ad = letoh32(fentry->l_ad);
1277 	}
1278 
1279 	switch (letoh16(tag->strat_type)) {
1280 	case 4:
1281 		break;
1282 
1283 	case 4096:
1284 		printf("Cannot deal with strategy4096 yet!\n");
1285 		return (ENODEV);
1286 
1287 	default:
1288 		printf("Unknown strategy type %d\n", tag->strat_type);
1289 		return (ENODEV);
1290 	}
1291 
1292 	switch (letoh16(tag->flags) & 0x7) {
1293 	case 0:
1294 		/*
1295 		 * The allocation descriptor field is filled with short_ad's.
1296 		 * If the offset is beyond the current extent, look for the
1297 		 * next extent.
1298 		 */
1299 		do {
1300 			offset -= icblen;
1301 			ad_offset = sizeof(struct short_ad) * ad_num;
1302 			if (ad_offset > l_ad) {
1303 				printf("SFile offset out of bounds (%d > %d)\n",
1304 				    ad_offset, l_ad);
1305 				return (EINVAL);
1306 			}
1307 
1308 			if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0)
1309 				icb = GETICB(short_ad, xfentry, l_ea + ad_offset);
1310 			else
1311 				icb = GETICB(short_ad, fentry, l_ea + ad_offset);
1312 
1313 			icblen = GETICBLEN(short_ad, icb);
1314 			ad_num++;
1315 		} while(offset >= icblen);
1316 
1317 		lsector = (offset  >> ump->um_bshift) +
1318 		    letoh32(((struct short_ad *)(icb))->lb_num);
1319 
1320 		*max_size = GETICBLEN(short_ad, icb);
1321 
1322 		break;
1323 	case 1:
1324 		/*
1325 		 * The allocation descriptor field is filled with long_ad's
1326 		 * If the offset is beyond the current extent, look for the
1327 		 * next extent.
1328 		 */
1329 		do {
1330 			offset -= icblen;
1331 			ad_offset = sizeof(struct long_ad) * ad_num;
1332 			if (ad_offset > l_ad) {
1333 				printf("LFile offset out of bounds (%d > %d)\n",
1334 				    ad_offset, l_ad);
1335 				return (EINVAL);
1336 			}
1337 			if (udf_checktag(&up->u_fentry->tag, TAGID_EXTFENTRY) == 0)
1338 				icb = GETICB(long_ad, xfentry, l_ea + ad_offset);
1339 			else
1340 				icb = GETICB(long_ad, fentry, l_ea + ad_offset);
1341 			icblen = GETICBLEN(long_ad, icb);
1342 			ad_num++;
1343 		} while(offset >= icblen);
1344 
1345 		lsector = (offset >> ump->um_bshift) +
1346 		    letoh32(((struct long_ad *)(icb))->loc.lb_num);
1347 
1348 		*max_size = GETICBLEN(long_ad, icb);
1349 
1350 		break;
1351 	case 3:
1352 		/*
1353 		 * This type means that the file *data* is stored in the
1354 		 * allocation descriptor field of the file entry.
1355 		 */
1356 		*max_size = 0;
1357 		*sector = up->u_ino + ump->um_start;
1358 
1359 		return (UDF_INVALID_BMAP);
1360 	case 2:
1361 		/* DirectCD does not use extended_ad's */
1362 	default:
1363 		printf("Unsupported allocation descriptor %d\n",
1364 		       tag->flags & 0x7);
1365 		return (ENODEV);
1366 	}
1367 
1368 	*sector = lsector + ump->um_start;
1369 
1370 	/*
1371 	 * Check the sparing table.  Each entry represents the beginning of
1372 	 * a packet.
1373 	 */
1374 	if (ump->um_stbl != NULL) {
1375 		for (i = 0; i< ump->um_stbl_len; i++) {
1376 			p_offset =
1377 			    lsector - letoh32(ump->um_stbl->entries[i].org);
1378 			if ((p_offset < ump->um_psecs) && (p_offset >= 0)) {
1379 				*sector =
1380 				   letoh32(ump->um_stbl->entries[i].map) +
1381 				    p_offset;
1382 				break;
1383 			}
1384 		}
1385 	}
1386 
1387 	return (0);
1388 }
1389