xref: /freebsd/sys/fs/udf/udf_vnops.c (revision 7562eaabc01a48e6b11d5b558c41e3b92dae5c2d)
1 /*-
2  * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 
29 /* udf_vnops.c */
30 /* Take care of the vnode side of things */
31 
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>
37 #include <sys/stat.h>
38 #include <sys/bio.h>
39 #include <sys/buf.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>
46 #include <sys/endian.h>
47 
48 #include <vm/uma.h>
49 
50 #include <fs/udf/ecma167-udf.h>
51 #include <fs/udf/osta.h>
52 #include <fs/udf/udf.h>
53 #include <fs/udf/udf_mount.h>
54 
55 extern struct iconv_functions *udf_iconv;
56 
57 static int udf_access(struct vop_access_args *);
58 static int udf_getattr(struct vop_getattr_args *);
59 static int udf_ioctl(struct vop_ioctl_args *);
60 static int udf_pathconf(struct vop_pathconf_args *);
61 static int udf_read(struct vop_read_args *);
62 static int udf_readdir(struct vop_readdir_args *);
63 static int udf_readlink(struct vop_readlink_args *ap);
64 static int udf_strategy(struct vop_strategy_args *);
65 static int udf_bmap(struct vop_bmap_args *);
66 static int udf_lookup(struct vop_cachedlookup_args *);
67 static int udf_reclaim(struct vop_reclaim_args *);
68 static int udf_readatoffset(struct udf_node *, int *, int, struct buf **, uint8_t **);
69 static int udf_bmap_internal(struct udf_node *, uint32_t, daddr_t *, uint32_t *);
70 
71 vop_t **udf_vnodeop_p;
72 static struct vnodeopv_entry_desc udf_vnodeop_entries[] = {
73 	{ &vop_default_desc,		(vop_t *) vop_defaultop },
74 	{ &vop_access_desc,		(vop_t *) udf_access },
75 	{ &vop_bmap_desc,		(vop_t *) udf_bmap },
76 	{ &vop_cachedlookup_desc,	(vop_t *) udf_lookup },
77 	{ &vop_getattr_desc,		(vop_t *) udf_getattr },
78 	{ &vop_ioctl_desc,		(vop_t *) udf_ioctl },
79 	{ &vop_lookup_desc,		(vop_t *) vfs_cache_lookup },
80 	{ &vop_pathconf_desc,		(vop_t *) udf_pathconf },
81 	{ &vop_read_desc,		(vop_t *) udf_read },
82 	{ &vop_readdir_desc,		(vop_t *) udf_readdir },
83 	{ &vop_readlink_desc,		(vop_t *) udf_readlink },
84 	{ &vop_reclaim_desc,		(vop_t *) udf_reclaim },
85 	{ &vop_strategy_desc,		(vop_t *) udf_strategy },
86 	{ NULL, NULL }
87 };
88 static struct vnodeopv_desc udf_vnodeop_opv_desc =
89 	{ &udf_vnodeop_p, udf_vnodeop_entries };
90 VNODEOP_SET(udf_vnodeop_opv_desc);
91 
92 MALLOC_DEFINE(M_UDFFID, "UDF FID", "UDF FileId structure");
93 MALLOC_DEFINE(M_UDFDS, "UDF DS", "UDF Dirstream structure");
94 
95 #define UDF_INVALID_BMAP	-1
96 
97 /* Look up a udf_node based on the ino_t passed in and return it's vnode */
98 int
99 udf_hashlookup(struct udf_mnt *udfmp, ino_t id, int flags, struct vnode **vpp)
100 {
101 	struct udf_node *node;
102 	struct udf_hash_lh *lh;
103 	int error;
104 
105 	*vpp = NULL;
106 
107 loop:
108 	mtx_lock(&udfmp->hash_mtx);
109 	lh = &udfmp->hashtbl[id % udfmp->hashsz];
110 	if (lh == NULL)
111 		return (ENOENT);
112 	LIST_FOREACH(node, lh, le) {
113 		if (node->hash_id == id) {
114 			VI_LOCK(node->i_vnode);
115 			mtx_unlock(&udfmp->hash_mtx);
116 			error = vget(node->i_vnode, flags | LK_INTERLOCK,
117 			    curthread);
118 			if (error == ENOENT)
119 				goto loop;
120 			if (error)
121 				return (error);
122 			*vpp = node->i_vnode;
123 			return (0);
124 		}
125 	}
126 
127 	mtx_unlock(&udfmp->hash_mtx);
128 	return (0);
129 }
130 
131 int
132 udf_hashins(struct udf_node *node)
133 {
134 	struct udf_mnt *udfmp;
135 	struct udf_hash_lh *lh;
136 
137 	udfmp = node->udfmp;
138 
139 	vn_lock(node->i_vnode, LK_EXCLUSIVE | LK_RETRY, curthread);
140 	mtx_lock(&udfmp->hash_mtx);
141 	lh = &udfmp->hashtbl[node->hash_id % udfmp->hashsz];
142 	if (lh == NULL)
143 		LIST_INIT(lh);
144 	LIST_INSERT_HEAD(lh, node, le);
145 	mtx_unlock(&udfmp->hash_mtx);
146 
147 	return (0);
148 }
149 
150 int
151 udf_hashrem(struct udf_node *node)
152 {
153 	struct udf_mnt *udfmp;
154 	struct udf_hash_lh *lh;
155 
156 	udfmp = node->udfmp;
157 
158 	mtx_lock(&udfmp->hash_mtx);
159 	lh = &udfmp->hashtbl[node->hash_id % udfmp->hashsz];
160 	if (lh == NULL)
161 		panic("hash entry is NULL, node->hash_id= %d\n", node->hash_id);
162 	LIST_REMOVE(node, le);
163 	mtx_unlock(&udfmp->hash_mtx);
164 
165 	return (0);
166 }
167 
168 int
169 udf_allocv(struct mount *mp, struct vnode **vpp, struct thread *td)
170 {
171 	int error;
172 	struct vnode *vp;
173 
174 	error = getnewvnode("udf", mp, udf_vnodeop_p, &vp);
175 	if (error) {
176 		printf("udf_allocv: failed to allocate new vnode\n");
177 		return (error);
178 	}
179 
180 	*vpp = vp;
181 	return (0);
182 }
183 
184 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */
185 static mode_t
186 udf_permtomode(struct udf_node *node)
187 {
188 	uint32_t perm;
189 	uint16_t flags;
190 	mode_t mode;
191 
192 	perm = le32toh(node->fentry->perm);
193 	flags = le16toh(node->fentry->icbtag.flags);
194 
195 	mode = perm & UDF_FENTRY_PERM_USER_MASK;
196 	mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2);
197 	mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4);
198 	mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4);
199 	mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6);
200 	mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8);
201 
202 	return (mode);
203 }
204 
205 static int
206 udf_access(struct vop_access_args *a)
207 {
208 	struct vnode *vp;
209 	struct udf_node *node;
210 	mode_t a_mode, mode;
211 
212 	vp = a->a_vp;
213 	node = VTON(vp);
214 	a_mode = a->a_mode;
215 
216 	if (a_mode & VWRITE) {
217 		switch (vp->v_type) {
218 		case VDIR:
219 		case VLNK:
220 		case VREG:
221 			return (EROFS);
222 			/* NOT REACHED */
223 		default:
224 			break;
225 		}
226 	}
227 
228 	mode = udf_permtomode(node);
229 
230 	return (vaccess(vp->v_type, mode, node->fentry->uid, node->fentry->gid,
231 	    a_mode, a->a_cred, NULL));
232 }
233 
234 static int mon_lens[2][12] = {
235 	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
236 	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
237 };
238 
239 static int
240 udf_isaleapyear(int year)
241 {
242 	int i;
243 
244 	i = (year % 4) ? 0 : 1;
245 	i &= (year % 100) ? 1 : 0;
246 	i |= (year % 400) ? 0 : 1;
247 
248 	return i;
249 }
250 
251 /*
252  * XXX This is just a rough hack.  Daylight savings isn't calculated and tv_nsec
253  * is ignored.
254  * Timezone calculation compliments of Julian Elischer <julian@elischer.org>.
255  */
256 static void
257 udf_timetotimespec(struct timestamp *time, struct timespec *t)
258 {
259 	int i, lpyear, daysinyear, year;
260 	union {
261 		uint16_t	u_tz_offset;
262 		int16_t		s_tz_offset;
263 	} tz;
264 
265 	t->tv_nsec = 0;
266 
267 	/* DirectCD seems to like using bogus year values */
268 	year = le16toh(time->year);
269 	if (year < 1970) {
270 		t->tv_sec = 0;
271 		return;
272 	}
273 
274 	/* Calculate the time and day */
275 	t->tv_sec = time->second;
276 	t->tv_sec += time->minute * 60;
277 	t->tv_sec += time->hour * 3600;
278 	t->tv_sec += time->day * 3600 * 24;
279 
280 	/* Calclulate the month */
281 	lpyear = udf_isaleapyear(year);
282 	for (i = 1; i < time->month; i++)
283 		t->tv_sec += mon_lens[lpyear][i] * 3600 * 24;
284 
285 	/* Speed up the calculation */
286 	if (year > 1979)
287 		t->tv_sec += 315532800;
288 	if (year > 1989)
289 		t->tv_sec += 315619200;
290 	if (year > 1999)
291 		t->tv_sec += 315532800;
292 	for (i = 2000; i < year; i++) {
293 		daysinyear = udf_isaleapyear(i) + 365 ;
294 		t->tv_sec += daysinyear * 3600 * 24;
295 	}
296 
297 	/*
298 	 * Calculate the time zone.  The timezone is 12 bit signed 2's
299 	 * compliment, so we gotta do some extra magic to handle it right.
300 	 */
301 	tz.u_tz_offset = le16toh(time->type_tz);
302 	tz.u_tz_offset &= 0x0fff;
303 	if (tz.u_tz_offset & 0x0800)
304 		tz.u_tz_offset |= 0xf000;	/* extend the sign to 16 bits */
305 	if ((time->type_tz & 0x1000) && (tz.s_tz_offset != -2047))
306 		t->tv_sec -= tz.s_tz_offset * 60;
307 
308 	return;
309 }
310 
311 static int
312 udf_getattr(struct vop_getattr_args *a)
313 {
314 	struct vnode *vp;
315 	struct udf_node *node;
316 	struct vattr *vap;
317 	struct file_entry *fentry;
318 	struct timespec ts;
319 
320 	ts.tv_sec = 0;
321 
322 	vp = a->a_vp;
323 	vap = a->a_vap;
324 	node = VTON(vp);
325 	fentry = node->fentry;
326 
327 	vap->va_fsid = dev2udev(node->i_dev);
328 	vap->va_fileid = node->hash_id;
329 	vap->va_mode = udf_permtomode(node);
330 	vap->va_nlink = le16toh(fentry->link_cnt);
331 	/*
332 	 * XXX The spec says that -1 is valid for uid/gid and indicates an
333 	 * invalid uid/gid.  How should this be represented?
334 	 */
335 	vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid);
336 	vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid);
337 	udf_timetotimespec(&fentry->atime, &vap->va_atime);
338 	udf_timetotimespec(&fentry->mtime, &vap->va_mtime);
339 	vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */
340 	vap->va_rdev = 0; /* XXX */
341 	if (vp->v_type & VDIR) {
342 		/*
343 		 * Directories that are recorded within their ICB will show
344 		 * as having 0 blocks recorded.  Since tradition dictates
345 		 * that directories consume at least one logical block,
346 		 * make it appear so.
347 		 */
348 		if (fentry->logblks_rec != 0) {
349 			vap->va_size =
350 			    le64toh(fentry->logblks_rec) * node->udfmp->bsize;
351 		} else {
352 			vap->va_size = node->udfmp->bsize;
353 		}
354 	} else {
355 		vap->va_size = le64toh(fentry->inf_len);
356 	}
357 	vap->va_flags = 0;
358 	vap->va_gen = 1;
359 	vap->va_blocksize = node->udfmp->bsize;
360 	vap->va_bytes = le64toh(fentry->inf_len);
361 	vap->va_type = vp->v_type;
362 	vap->va_filerev = 0; /* XXX */
363 	return (0);
364 }
365 
366 /*
367  * File specific ioctls.
368  */
369 static int
370 udf_ioctl(struct vop_ioctl_args *a)
371 {
372 	printf("%s called\n", __func__);
373 	return (ENOTTY);
374 }
375 
376 /*
377  * I'm not sure that this has much value in a read-only filesystem, but
378  * cd9660 has it too.
379  */
380 static int
381 udf_pathconf(struct vop_pathconf_args *a)
382 {
383 
384 	switch (a->a_name) {
385 	case _PC_LINK_MAX:
386 		*a->a_retval = 65535;
387 		return (0);
388 	case _PC_NAME_MAX:
389 		*a->a_retval = NAME_MAX;
390 		return (0);
391 	case _PC_PATH_MAX:
392 		*a->a_retval = PATH_MAX;
393 		return (0);
394 	case _PC_NO_TRUNC:
395 		*a->a_retval = 1;
396 		return (0);
397 	default:
398 		return (EINVAL);
399 	}
400 }
401 
402 static int
403 udf_read(struct vop_read_args *a)
404 {
405 	struct vnode *vp = a->a_vp;
406 	struct uio *uio = a->a_uio;
407 	struct udf_node *node = VTON(vp);
408 	struct buf *bp;
409 	uint8_t *data;
410 	int error = 0;
411 	int size, fsize, offset;
412 
413 	if (uio->uio_offset < 0)
414 		return (EINVAL);
415 
416 	fsize = le64toh(node->fentry->inf_len);
417 
418 	while (uio->uio_offset < fsize && uio->uio_resid > 0) {
419 		offset = uio->uio_offset;
420 		size = uio->uio_resid;
421 		error = udf_readatoffset(node, &size, offset, &bp, &data);
422 		if (error == 0)
423 			error = uiomove(data, size, uio);
424 		if (bp != NULL)
425 			brelse(bp);
426 		if (error)
427 			break;
428 	};
429 
430 	return (error);
431 }
432 
433 /*
434  * Call the OSTA routines to translate the name from a CS0 dstring to a
435  * 16-bit Unicode String.  Hooks need to be placed in here to translate from
436  * Unicode to the encoding that the kernel/user expects.  Return the length
437  * of the translated string.
438  */
439 static int
440 udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp)
441 {
442 	unicode_t *transname;
443 	char *unibuf, *unip;
444 	int i, unilen = 0, destlen;
445 	size_t destleft = MAXNAMLEN;
446 
447 	/* Convert 16-bit Unicode to destname */
448 	if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) {
449 		/* allocate a buffer big enough to hold an 8->16 bit expansion */
450 		unibuf = uma_zalloc(udf_zone_trans, M_WAITOK);
451 		unip = unibuf;
452 		if ((unilen = udf_UncompressUnicodeByte(len, cs0string, unibuf)) == -1) {
453 			printf("udf: Unicode translation failed\n");
454 			uma_zfree(udf_zone_trans, unibuf);
455 			return 0;
456 		}
457 
458 		while (unilen > 0 && destleft > 0) {
459 			udf_iconv->conv(udfmp->im_d2l, (const char **)&unibuf,
460 				(size_t *)&unilen, (char **)&destname, &destleft);
461 			/* Unconverted character found */
462 			if (unilen > 0 && destleft > 0) {
463 				*destname++ = '?';
464 				destleft--;
465 				unibuf += 2;
466 				unilen -= 2;
467 			}
468 		}
469 		uma_zfree(udf_zone_trans, unip);
470 		*destname = '\0';
471 		destlen = MAXNAMLEN - (int)destleft;
472 	} else {
473 		/* allocate a buffer big enough to hold an 8->16 bit expansion */
474 		transname = uma_zalloc(udf_zone_trans, M_WAITOK);
475 
476 		if ((unilen = udf_UncompressUnicode(len, cs0string, transname)) == -1) {
477 			printf("udf: Unicode translation failed\n");
478 			uma_zfree(udf_zone_trans, transname);
479 			return 0;
480 		}
481 
482 		for (i = 0; i < unilen ; i++) {
483 			if (transname[i] & 0xff00) {
484 				destname[i] = '.';	/* Fudge the 16bit chars */
485 			} else {
486 				destname[i] = transname[i] & 0xff;
487 			}
488 		}
489 		uma_zfree(udf_zone_trans, transname);
490 		destname[unilen] = 0;
491 		destlen = unilen;
492 	}
493 
494 	return (destlen);
495 }
496 
497 /*
498  * Compare a CS0 dstring with a name passed in from the VFS layer.  Return
499  * 0 on a successful match, nonzero therwise.  Unicode work may need to be done
500  * here also.
501  */
502 static int
503 udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp)
504 {
505 	char *transname;
506 	int error = 0;
507 
508 	/* This is overkill, but not worth creating a new zone */
509 	transname = uma_zalloc(udf_zone_trans, M_WAITOK);
510 
511 	cs0len = udf_transname(cs0string, transname, cs0len, udfmp);
512 
513 	/* Easy check.  If they aren't the same length, they aren't equal */
514 	if ((cs0len == 0) || (cs0len != cmplen))
515 		error = -1;
516 	else
517 		error = bcmp(transname, cmpname, cmplen);
518 
519 	uma_zfree(udf_zone_trans, transname);
520 	return (error);
521 }
522 
523 struct udf_uiodir {
524 	struct dirent *dirent;
525 	u_long *cookies;
526 	int ncookies;
527 	int acookies;
528 	int eofflag;
529 };
530 
531 static int
532 udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie)
533 {
534 	if (uiodir->cookies != NULL) {
535 		if (++uiodir->acookies > uiodir->ncookies) {
536 			uiodir->eofflag = 0;
537 			return (-1);
538 		}
539 		*uiodir->cookies++ = cookie;
540 	}
541 
542 	if (uio->uio_resid < de_size) {
543 		uiodir->eofflag = 0;
544 		return (-1);
545 	}
546 
547 	return (uiomove(uiodir->dirent, de_size, uio));
548 }
549 
550 static struct udf_dirstream *
551 udf_opendir(struct udf_node *node, int offset, int fsize, struct udf_mnt *udfmp)
552 {
553 	struct udf_dirstream *ds;
554 
555 	ds = uma_zalloc(udf_zone_ds, M_WAITOK | M_ZERO);
556 
557 	ds->node = node;
558 	ds->offset = offset;
559 	ds->udfmp = udfmp;
560 	ds->fsize = fsize;
561 
562 	return (ds);
563 }
564 
565 static struct fileid_desc *
566 udf_getfid(struct udf_dirstream *ds)
567 {
568 	struct fileid_desc *fid;
569 	int error, frag_size = 0, total_fid_size;
570 
571 	/* End of directory? */
572 	if (ds->offset + ds->off >= ds->fsize) {
573 		ds->error = 0;
574 		return (NULL);
575 	}
576 
577 	/* Grab the first extent of the directory */
578 	if (ds->off == 0) {
579 		ds->size = 0;
580 		error = udf_readatoffset(ds->node, &ds->size, ds->offset,
581 		    &ds->bp, &ds->data);
582 		if (error) {
583 			ds->error = error;
584 			if (ds->bp != NULL)
585 				brelse(ds->bp);
586 			return (NULL);
587 		}
588 	}
589 
590 	/*
591 	 * Clean up from a previous fragmented FID.
592 	 * XXX Is this the right place for this?
593 	 */
594 	if (ds->fid_fragment && ds->buf != NULL) {
595 		ds->fid_fragment = 0;
596 		FREE(ds->buf, M_UDFFID);
597 	}
598 
599 	fid = (struct fileid_desc*)&ds->data[ds->off];
600 
601 	/*
602 	 * Check to see if the fid is fragmented. The first test
603 	 * ensures that we don't wander off the end of the buffer
604 	 * looking for the l_iu and l_fi fields.
605 	 */
606 	if (ds->off + UDF_FID_SIZE > ds->size ||
607 	    ds->off + le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){
608 
609 		/* Copy what we have of the fid into a buffer */
610 		frag_size = ds->size - ds->off;
611 		if (frag_size >= ds->udfmp->bsize) {
612 			printf("udf: invalid FID fragment\n");
613 			ds->error = EINVAL;
614 			return (NULL);
615 		}
616 
617 		/*
618 		 * File ID descriptors can only be at most one
619 		 * logical sector in size.
620 		 */
621 		MALLOC(ds->buf, uint8_t*, ds->udfmp->bsize, M_UDFFID,
622 		     M_WAITOK | M_ZERO);
623 		bcopy(fid, ds->buf, frag_size);
624 
625 		/* Reduce all of the casting magic */
626 		fid = (struct fileid_desc*)ds->buf;
627 
628 		if (ds->bp != NULL)
629 			brelse(ds->bp);
630 
631 		/* Fetch the next allocation */
632 		ds->offset += ds->size;
633 		ds->size = 0;
634 		error = udf_readatoffset(ds->node, &ds->size, ds->offset,
635 		    &ds->bp, &ds->data);
636 		if (error) {
637 			ds->error = error;
638 			return (NULL);
639 		}
640 
641 		/*
642 		 * If the fragment was so small that we didn't get
643 		 * the l_iu and l_fi fields, copy those in.
644 		 */
645 		if (frag_size < UDF_FID_SIZE)
646 			bcopy(ds->data, &ds->buf[frag_size],
647 			    UDF_FID_SIZE - frag_size);
648 
649 		/*
650 		 * Now that we have enough of the fid to work with,
651 		 * copy in the rest of the fid from the new
652 		 * allocation.
653 		 */
654 		total_fid_size = UDF_FID_SIZE + le16toh(fid->l_iu) + fid->l_fi;
655 		if (total_fid_size > ds->udfmp->bsize) {
656 			printf("udf: invalid FID\n");
657 			ds->error = EIO;
658 			return (NULL);
659 		}
660 		bcopy(ds->data, &ds->buf[frag_size],
661 		    total_fid_size - frag_size);
662 
663 		ds->fid_fragment = 1;
664 	} else {
665 		total_fid_size = le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE;
666 	}
667 
668 	/*
669 	 * Update the offset. Align on a 4 byte boundary because the
670 	 * UDF spec says so.
671 	 */
672 	ds->this_off = ds->off;
673 	if (!ds->fid_fragment) {
674 		ds->off += (total_fid_size + 3) & ~0x03;
675 	} else {
676 		ds->off = (total_fid_size - frag_size + 3) & ~0x03;
677 	}
678 
679 	return (fid);
680 }
681 
682 static void
683 udf_closedir(struct udf_dirstream *ds)
684 {
685 
686 	if (ds->bp != NULL)
687 		brelse(ds->bp);
688 
689 	if (ds->fid_fragment && ds->buf != NULL)
690 		FREE(ds->buf, M_UDFFID);
691 
692 	uma_zfree(udf_zone_ds, ds);
693 }
694 
695 static int
696 udf_readdir(struct vop_readdir_args *a)
697 {
698 	struct vnode *vp;
699 	struct uio *uio;
700 	struct dirent dir;
701 	struct udf_node *node;
702 	struct udf_mnt *udfmp;
703 	struct fileid_desc *fid;
704 	struct udf_uiodir uiodir;
705 	struct udf_dirstream *ds;
706 	u_long *cookies = NULL;
707 	int ncookies;
708 	int error = 0;
709 
710 	vp = a->a_vp;
711 	uio = a->a_uio;
712 	node = VTON(vp);
713 	udfmp = node->udfmp;
714 	uiodir.eofflag = 1;
715 
716 	if (a->a_ncookies != NULL) {
717 		/*
718 		 * Guess how many entries are needed.  If we run out, this
719 		 * function will be called again and thing will pick up were
720 		 * it left off.
721 		 */
722 		ncookies = uio->uio_resid / 8;
723 		MALLOC(cookies, u_long *, sizeof(u_long) * ncookies,
724 		    M_TEMP, M_WAITOK);
725 		if (cookies == NULL)
726 			return (ENOMEM);
727 		uiodir.ncookies = ncookies;
728 		uiodir.cookies = cookies;
729 		uiodir.acookies = 0;
730 	} else {
731 		uiodir.cookies = NULL;
732 	}
733 
734 	/*
735 	 * Iterate through the file id descriptors.  Give the parent dir
736 	 * entry special attention.
737 	 */
738 	ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len),
739 	    node->udfmp);
740 
741 	while ((fid = udf_getfid(ds)) != NULL) {
742 
743 		/* XXX Should we return an error on a bad fid? */
744 		if (udf_checktag(&fid->tag, TAGID_FID)) {
745 			printf("Invalid FID tag\n");
746 			hexdump(fid, UDF_FID_SIZE, NULL, 0);
747 			error = EIO;
748 			break;
749 		}
750 
751 		/* Is this a deleted file? */
752 		if (fid->file_char & UDF_FILE_CHAR_DEL)
753 			continue;
754 
755 		if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
756 			/* Do up the '.' and '..' entries.  Dummy values are
757 			 * used for the cookies since the offset here is
758 			 * usually zero, and NFS doesn't like that value
759 			 */
760 			dir.d_fileno = node->hash_id;
761 			dir.d_type = DT_DIR;
762 			dir.d_name[0] = '.';
763 			dir.d_namlen = 1;
764 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
765 			uiodir.dirent = &dir;
766 			error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1);
767 			if (error)
768 				break;
769 
770 			dir.d_fileno = udf_getid(&fid->icb);
771 			dir.d_type = DT_DIR;
772 			dir.d_name[0] = '.';
773 			dir.d_name[1] = '.';
774 			dir.d_namlen = 2;
775 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
776 			uiodir.dirent = &dir;
777 			error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2);
778 		} else {
779 			dir.d_namlen = udf_transname(&fid->data[fid->l_iu],
780 			    &dir.d_name[0], fid->l_fi, udfmp);
781 			dir.d_fileno = udf_getid(&fid->icb);
782 			dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ?
783 			    DT_DIR : DT_UNKNOWN;
784 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
785 			uiodir.dirent = &dir;
786 			error = udf_uiodir(&uiodir, dir.d_reclen, uio,
787 			    ds->this_off);
788 		}
789 		if (error) {
790 			printf("uiomove returned %d\n", error);
791 			break;
792 		}
793 
794 	}
795 
796 	/* tell the calling layer whether we need to be called again */
797 	*a->a_eofflag = uiodir.eofflag;
798 	uio->uio_offset = ds->offset + ds->off;
799 
800 	if (!error)
801 		error = ds->error;
802 
803 	udf_closedir(ds);
804 
805 	if (a->a_ncookies != NULL) {
806 		if (error)
807 			FREE(cookies, M_TEMP);
808 		else {
809 			*a->a_ncookies = uiodir.acookies;
810 			*a->a_cookies = cookies;
811 		}
812 	}
813 
814 	return (error);
815 }
816 
817 /* Are there any implementations out there that do soft-links? */
818 static int
819 udf_readlink(struct vop_readlink_args *ap)
820 {
821 	printf("%s called\n", __func__);
822 	return (EOPNOTSUPP);
823 }
824 
825 static int
826 udf_strategy(struct vop_strategy_args *a)
827 {
828 	struct buf *bp;
829 	struct vnode *vp;
830 	struct udf_node *node;
831 	int maxsize;
832 	struct bufobj *bo;
833 
834 	bp = a->a_bp;
835 	vp = a->a_vp;
836 	node = VTON(vp);
837 
838 	/* cd9660 has this test reversed, but it seems more logical this way */
839 	if (bp->b_blkno != bp->b_lblkno) {
840 		/*
841 		 * Files that are embedded in the fentry don't translate well
842 		 * to a block number.  Reject.
843 		 */
844 		if (udf_bmap_internal(node, bp->b_lblkno * node->udfmp->bsize,
845 		    &bp->b_lblkno, &maxsize)) {
846 			clrbuf(bp);
847 			bp->b_blkno = -1;
848 		}
849 	}
850 	if ((long)bp->b_blkno == -1) {
851 		bufdone(bp);
852 		return (0);
853 	}
854 	bo = node->udfmp->im_bo;
855 	bp->b_iooffset = dbtob(bp->b_blkno);
856 	bo->bo_ops->bop_strategy(bo, bp);
857 	return (0);
858 }
859 
860 static int
861 udf_bmap(struct vop_bmap_args *a)
862 {
863 	struct udf_node *node;
864 	uint32_t max_size;
865 	daddr_t lsector;
866 	int error;
867 
868 	node = VTON(a->a_vp);
869 
870 	if (a->a_vpp != NULL)
871 		*a->a_vpp = node->i_devvp;
872 	if (a->a_bnp == NULL)
873 		return (0);
874 	if (a->a_runb)
875 		*a->a_runb = 0;
876 
877 	error = udf_bmap_internal(node, a->a_bn * node->udfmp->bsize, &lsector,
878 	    &max_size);
879 	if (error)
880 		return (error);
881 
882 	/* Translate logical to physical sector number */
883 	*a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT);
884 
885 	/* Punt on read-ahead for now */
886 	if (a->a_runp)
887 		*a->a_runp = 0;
888 
889 	return (0);
890 }
891 
892 /*
893  * The all powerful VOP_LOOKUP().
894  */
895 static int
896 udf_lookup(struct vop_cachedlookup_args *a)
897 {
898 	struct vnode *dvp;
899 	struct vnode *tdp = NULL;
900 	struct vnode **vpp = a->a_vpp;
901 	struct udf_node *node;
902 	struct udf_mnt *udfmp;
903 	struct fileid_desc *fid = NULL;
904 	struct udf_dirstream *ds;
905 	struct thread *td;
906 	u_long nameiop;
907 	u_long flags;
908 	char *nameptr;
909 	long namelen;
910 	ino_t id = 0;
911 	int offset, error = 0;
912 	int numdirpasses, fsize;
913 
914 	dvp = a->a_dvp;
915 	node = VTON(dvp);
916 	udfmp = node->udfmp;
917 	nameiop = a->a_cnp->cn_nameiop;
918 	flags = a->a_cnp->cn_flags;
919 	nameptr = a->a_cnp->cn_nameptr;
920 	namelen = a->a_cnp->cn_namelen;
921 	fsize = le64toh(node->fentry->inf_len);
922 	td = a->a_cnp->cn_thread;
923 
924 	/*
925 	 * If this is a LOOKUP and we've already partially searched through
926 	 * the directory, pick up where we left off and flag that the
927 	 * directory may need to be searched twice.  For a full description,
928 	 * see /sys/isofs/cd9660/cd9660_lookup.c:cd9660_lookup()
929 	 */
930 	if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) {
931 		offset = 0;
932 		numdirpasses = 1;
933 	} else {
934 		offset = node->diroff;
935 		numdirpasses = 2;
936 		nchstats.ncs_2passes++;
937 	}
938 
939 lookloop:
940 	ds = udf_opendir(node, offset, fsize, udfmp);
941 
942 	while ((fid = udf_getfid(ds)) != NULL) {
943 
944 		/* XXX Should we return an error on a bad fid? */
945 		if (udf_checktag(&fid->tag, TAGID_FID)) {
946 			printf("udf_lookup: Invalid tag\n");
947 			error = EIO;
948 			break;
949 		}
950 
951 		/* Is this a deleted file? */
952 		if (fid->file_char & UDF_FILE_CHAR_DEL)
953 			continue;
954 
955 		if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
956 			if (flags & ISDOTDOT) {
957 				id = udf_getid(&fid->icb);
958 				break;
959 			}
960 		} else {
961 			if (!(udf_cmpname(&fid->data[fid->l_iu],
962 			    nameptr, fid->l_fi, namelen, udfmp))) {
963 				id = udf_getid(&fid->icb);
964 				break;
965 			}
966 		}
967 	}
968 
969 	if (!error)
970 		error = ds->error;
971 
972 	/* XXX Bail out here? */
973 	if (error) {
974 		udf_closedir(ds);
975 		return (error);
976 	}
977 
978 	/* Did we have a match? */
979 	if (id) {
980 		error = udf_vget(udfmp->im_mountp, id, LK_EXCLUSIVE, &tdp);
981 		if (!error) {
982 			/*
983 			 * Remember where this entry was if it's the final
984 			 * component.
985 			 */
986 			if ((flags & ISLASTCN) && nameiop == LOOKUP)
987 				node->diroff = ds->offset + ds->off;
988 			if (numdirpasses == 2)
989 				nchstats.ncs_pass2++;
990 			if (!(flags & LOCKPARENT) || !(flags & ISLASTCN)) {
991 				a->a_cnp->cn_flags |= PDIRUNLOCK;
992 				VOP_UNLOCK(dvp, 0, td);
993 			}
994 
995 			*vpp = tdp;
996 
997 			/* Put this entry in the cache */
998 			if (flags & MAKEENTRY)
999 				cache_enter(dvp, *vpp, a->a_cnp);
1000 		}
1001 	} else {
1002 		/* Name wasn't found on this pass.  Do another pass? */
1003 		if (numdirpasses == 2) {
1004 			numdirpasses--;
1005 			offset = 0;
1006 			udf_closedir(ds);
1007 			goto lookloop;
1008 		}
1009 
1010 		/* Enter name into cache as non-existant */
1011 		if (flags & MAKEENTRY)
1012 			cache_enter(dvp, *vpp, a->a_cnp);
1013 
1014 		if ((flags & ISLASTCN) &&
1015 		    (nameiop == CREATE || nameiop == RENAME)) {
1016 			error = EROFS;
1017 		} else {
1018 			error = ENOENT;
1019 		}
1020 	}
1021 
1022 	udf_closedir(ds);
1023 	return (error);
1024 }
1025 
1026 static int
1027 udf_reclaim(struct vop_reclaim_args *a)
1028 {
1029 	struct vnode *vp;
1030 	struct udf_node *unode;
1031 
1032 	vp = a->a_vp;
1033 	unode = VTON(vp);
1034 
1035 	if (unode != NULL) {
1036 		udf_hashrem(unode);
1037 		if (unode->i_devvp) {
1038 			vrele(unode->i_devvp);
1039 			unode->i_devvp = 0;
1040 		}
1041 
1042 		if (unode->fentry != NULL)
1043 			FREE(unode->fentry, M_UDFFENTRY);
1044 		uma_zfree(udf_zone_node, unode);
1045 		vp->v_data = NULL;
1046 	}
1047 
1048 	return (0);
1049 }
1050 
1051 /*
1052  * Read the block and then set the data pointer to correspond with the
1053  * offset passed in.  Only read in at most 'size' bytes, and then set 'size'
1054  * to the number of bytes pointed to.  If 'size' is zero, try to read in a
1055  * whole extent.
1056  *
1057  * Note that *bp may be assigned error or not.
1058  *
1059  */
1060 static int
1061 udf_readatoffset(struct udf_node *node, int *size, int offset, struct buf **bp, uint8_t **data)
1062 {
1063 	struct udf_mnt *udfmp;
1064 	struct file_entry *fentry = NULL;
1065 	struct buf *bp1;
1066 	uint32_t max_size;
1067 	daddr_t sector;
1068 	int error;
1069 
1070 	udfmp = node->udfmp;
1071 
1072 	*bp = NULL;
1073 	error = udf_bmap_internal(node, offset, &sector, &max_size);
1074 	if (error == UDF_INVALID_BMAP) {
1075 		/*
1076 		 * This error means that the file *data* is stored in the
1077 		 * allocation descriptor field of the file entry.
1078 		 */
1079 		fentry = node->fentry;
1080 		*data = &fentry->data[le32toh(fentry->l_ea)];
1081 		*size = le32toh(fentry->l_ad);
1082 		return (0);
1083 	} else if (error != 0) {
1084 		return (error);
1085 	}
1086 
1087 	/* Adjust the size so that it is within range */
1088 	if (*size == 0 || *size > max_size)
1089 		*size = max_size;
1090 	*size = min(*size, MAXBSIZE);
1091 
1092 	if ((error = udf_readlblks(udfmp, sector, *size, bp))) {
1093 		printf("warning: udf_readlblks returned error %d\n", error);
1094 		/* note: *bp may be non-NULL */
1095 		return (error);
1096 	}
1097 
1098 	bp1 = *bp;
1099 	*data = (uint8_t *)&bp1->b_data[offset % udfmp->bsize];
1100 	return (0);
1101 }
1102 
1103 /*
1104  * Translate a file offset into a logical block and then into a physical
1105  * block.
1106  */
1107 static int
1108 udf_bmap_internal(struct udf_node *node, uint32_t offset, daddr_t *sector, uint32_t *max_size)
1109 {
1110 	struct udf_mnt *udfmp;
1111 	struct file_entry *fentry;
1112 	void *icb;
1113 	struct icb_tag *tag;
1114 	uint32_t icblen = 0;
1115 	daddr_t lsector;
1116 	int ad_offset, ad_num = 0;
1117 	int i, p_offset;
1118 
1119 	udfmp = node->udfmp;
1120 	fentry = node->fentry;
1121 	tag = &fentry->icbtag;
1122 
1123 	switch (le16toh(tag->strat_type)) {
1124 	case 4:
1125 		break;
1126 
1127 	case 4096:
1128 		printf("Cannot deal with strategy4096 yet!\n");
1129 		return (ENODEV);
1130 
1131 	default:
1132 		printf("Unknown strategy type %d\n", tag->strat_type);
1133 		return (ENODEV);
1134 	}
1135 
1136 	switch (le16toh(tag->flags) & 0x7) {
1137 	case 0:
1138 		/*
1139 		 * The allocation descriptor field is filled with short_ad's.
1140 		 * If the offset is beyond the current extent, look for the
1141 		 * next extent.
1142 		 */
1143 		do {
1144 			offset -= icblen;
1145 			ad_offset = sizeof(struct short_ad) * ad_num;
1146 			if (ad_offset > le32toh(fentry->l_ad)) {
1147 				printf("File offset out of bounds\n");
1148 				return (EINVAL);
1149 			}
1150 			icb = GETICB(long_ad, fentry,
1151 			    le32toh(fentry->l_ea) + ad_offset);
1152 			icblen = GETICBLEN(short_ad, icb);
1153 			ad_num++;
1154 		} while(offset >= icblen);
1155 
1156 		lsector = (offset  >> udfmp->bshift) +
1157 		    ((struct short_ad *)(icb))->pos;
1158 
1159 		*max_size = GETICBLEN(short_ad, icb);
1160 
1161 		break;
1162 	case 1:
1163 		/*
1164 		 * The allocation descriptor field is filled with long_ad's
1165 		 * If the offset is beyond the current extent, look for the
1166 		 * next extent.
1167 		 */
1168 		do {
1169 			offset -= icblen;
1170 			ad_offset = sizeof(struct long_ad) * ad_num;
1171 			if (ad_offset > le32toh(fentry->l_ad)) {
1172 				printf("File offset out of bounds\n");
1173 				return (EINVAL);
1174 			}
1175 			icb = GETICB(long_ad, fentry,
1176 			    le32toh(fentry->l_ea) + ad_offset);
1177 			icblen = GETICBLEN(long_ad, icb);
1178 			ad_num++;
1179 		} while(offset >= icblen);
1180 
1181 		lsector = (offset >> udfmp->bshift) +
1182 		    le32toh(((struct long_ad *)(icb))->loc.lb_num);
1183 
1184 		*max_size = GETICBLEN(long_ad, icb);
1185 
1186 		break;
1187 	case 3:
1188 		/*
1189 		 * This type means that the file *data* is stored in the
1190 		 * allocation descriptor field of the file entry.
1191 		 */
1192 		*max_size = 0;
1193 		*sector = node->hash_id + udfmp->part_start;
1194 
1195 		return (UDF_INVALID_BMAP);
1196 	case 2:
1197 		/* DirectCD does not use extended_ad's */
1198 	default:
1199 		printf("Unsupported allocation descriptor %d\n",
1200 		       tag->flags & 0x7);
1201 		return (ENODEV);
1202 	}
1203 
1204 	*sector = lsector + udfmp->part_start;
1205 
1206 	/*
1207 	 * Check the sparing table.  Each entry represents the beginning of
1208 	 * a packet.
1209 	 */
1210 	if (udfmp->s_table != NULL) {
1211 		for (i = 0; i< udfmp->s_table_entries; i++) {
1212 			p_offset =
1213 			    lsector - le32toh(udfmp->s_table->entries[i].org);
1214 			if ((p_offset < udfmp->p_sectors) && (p_offset >= 0)) {
1215 				*sector =
1216 				   le32toh(udfmp->s_table->entries[i].map) +
1217 				    p_offset;
1218 				break;
1219 			}
1220 		}
1221 	}
1222 
1223 	return (0);
1224 }
1225