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