FreeBSD/Linux Kernel Cross Reference
sys/fs/udf/udf_vnops.c
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/conf.h>
40 #include <sys/buf.h>
41 #include <sys/iconv.h>
42 #include <sys/mount.h>
43 #include <sys/vnode.h>
44 #include <sys/dirent.h>
45 #include <sys/queue.h>
46 #include <sys/unistd.h>
47 #include <sys/endian.h>
48
49 #include <vm/uma.h>
50
51 #include <fs/udf/ecma167-udf.h>
52 #include <fs/udf/osta.h>
53 #include <fs/udf/udf.h>
54 #include <fs/udf/udf_mount.h>
55
56 extern struct iconv_functions *udf_iconv;
57
58 static vop_access_t udf_access;
59 static vop_getattr_t udf_getattr;
60 static vop_open_t udf_open;
61 static vop_ioctl_t udf_ioctl;
62 static vop_pathconf_t udf_pathconf;
63 static vop_print_t udf_print;
64 static vop_read_t udf_read;
65 static vop_readdir_t udf_readdir;
66 static vop_readlink_t udf_readlink;
67 static vop_setattr_t udf_setattr;
68 static vop_strategy_t udf_strategy;
69 static vop_bmap_t udf_bmap;
70 static vop_cachedlookup_t udf_lookup;
71 static vop_reclaim_t udf_reclaim;
72 static vop_vptofh_t udf_vptofh;
73 static int udf_readatoffset(struct udf_node *node, int *size, off_t offset,
74 struct buf **bp, uint8_t **data);
75 static int udf_bmap_internal(struct udf_node *node, off_t offset,
76 daddr_t *sector, uint32_t *max_size);
77
78 static struct vop_vector udf_vnodeops = {
79 .vop_default = &default_vnodeops,
80
81 .vop_access = udf_access,
82 .vop_bmap = udf_bmap,
83 .vop_cachedlookup = udf_lookup,
84 .vop_getattr = udf_getattr,
85 .vop_ioctl = udf_ioctl,
86 .vop_lookup = vfs_cache_lookup,
87 .vop_open = udf_open,
88 .vop_pathconf = udf_pathconf,
89 .vop_print = udf_print,
90 .vop_read = udf_read,
91 .vop_readdir = udf_readdir,
92 .vop_readlink = udf_readlink,
93 .vop_reclaim = udf_reclaim,
94 .vop_setattr = udf_setattr,
95 .vop_strategy = udf_strategy,
96 .vop_vptofh = udf_vptofh,
97 };
98
99 struct vop_vector udf_fifoops = {
100 .vop_default = &fifo_specops,
101 .vop_access = udf_access,
102 .vop_getattr = udf_getattr,
103 .vop_pathconf = udf_pathconf,
104 .vop_print = udf_print,
105 .vop_reclaim = udf_reclaim,
106 .vop_setattr = udf_setattr,
107 .vop_vptofh = udf_vptofh,
108 };
109
110 static MALLOC_DEFINE(M_UDFFID, "udf_fid", "UDF FileId structure");
111 static MALLOC_DEFINE(M_UDFDS, "udf_ds", "UDF Dirstream structure");
112
113 #define UDF_INVALID_BMAP -1
114
115 int
116 udf_allocv(struct mount *mp, struct vnode **vpp, struct thread *td)
117 {
118 int error;
119 struct vnode *vp;
120
121 error = getnewvnode("udf", mp, &udf_vnodeops, &vp);
122 if (error) {
123 printf("udf_allocv: failed to allocate new vnode\n");
124 return (error);
125 }
126
127 *vpp = vp;
128 return (0);
129 }
130
131 /* Convert file entry permission (5 bits per owner/group/user) to a mode_t */
132 static mode_t
133 udf_permtomode(struct udf_node *node)
134 {
135 uint32_t perm;
136 uint16_t flags;
137 mode_t mode;
138
139 perm = le32toh(node->fentry->perm);
140 flags = le16toh(node->fentry->icbtag.flags);
141
142 mode = perm & UDF_FENTRY_PERM_USER_MASK;
143 mode |= ((perm & UDF_FENTRY_PERM_GRP_MASK) >> 2);
144 mode |= ((perm & UDF_FENTRY_PERM_OWNER_MASK) >> 4);
145 mode |= ((flags & UDF_ICB_TAG_FLAGS_STICKY) << 4);
146 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETGID) << 6);
147 mode |= ((flags & UDF_ICB_TAG_FLAGS_SETUID) << 8);
148
149 return (mode);
150 }
151
152 static int
153 udf_access(struct vop_access_args *a)
154 {
155 struct vnode *vp;
156 struct udf_node *node;
157 accmode_t accmode;
158 mode_t mode;
159
160 vp = a->a_vp;
161 node = VTON(vp);
162 accmode = a->a_accmode;
163
164 if (accmode & VWRITE) {
165 switch (vp->v_type) {
166 case VDIR:
167 case VLNK:
168 case VREG:
169 return (EROFS);
170 /* NOT REACHED */
171 default:
172 break;
173 }
174 }
175
176 mode = udf_permtomode(node);
177
178 return (vaccess(vp->v_type, mode, node->fentry->uid, node->fentry->gid,
179 accmode, a->a_cred, NULL));
180 }
181
182 static int
183 udf_open(struct vop_open_args *ap) {
184 struct udf_node *np = VTON(ap->a_vp);
185 off_t fsize;
186
187 fsize = le64toh(np->fentry->inf_len);
188 vnode_create_vobject(ap->a_vp, fsize, ap->a_td);
189 return 0;
190 }
191
192 static const int mon_lens[2][12] = {
193 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
194 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
195 };
196
197 static int
198 udf_isaleapyear(int year)
199 {
200 int i;
201
202 i = (year % 4) ? 0 : 1;
203 i &= (year % 100) ? 1 : 0;
204 i |= (year % 400) ? 0 : 1;
205
206 return i;
207 }
208
209 /*
210 * Timezone calculation compliments of Julian Elischer <julian@elischer.org>.
211 */
212 static void
213 udf_timetotimespec(struct timestamp *time, struct timespec *t)
214 {
215 int i, lpyear, daysinyear, year, startyear;
216 union {
217 uint16_t u_tz_offset;
218 int16_t s_tz_offset;
219 } tz;
220
221 /*
222 * DirectCD seems to like using bogus year values.
223 * Don't trust time->month as it will be used for an array index.
224 */
225 year = le16toh(time->year);
226 if (year < 1970 || time->month < 1 || time->month > 12) {
227 t->tv_sec = 0;
228 t->tv_nsec = 0;
229 return;
230 }
231
232 /* Calculate the time and day */
233 t->tv_sec = time->second;
234 t->tv_sec += time->minute * 60;
235 t->tv_sec += time->hour * 3600;
236 t->tv_sec += (time->day - 1) * 3600 * 24;
237
238 /* Calculate the month */
239 lpyear = udf_isaleapyear(year);
240 t->tv_sec += mon_lens[lpyear][time->month - 1] * 3600 * 24;
241
242 /* Speed up the calculation */
243 startyear = 1970;
244 if (year > 2009) {
245 t->tv_sec += 1262304000;
246 startyear += 40;
247 } else if (year > 1999) {
248 t->tv_sec += 946684800;
249 startyear += 30;
250 } else if (year > 1989) {
251 t->tv_sec += 631152000;
252 startyear += 20;
253 } else if (year > 1979) {
254 t->tv_sec += 315532800;
255 startyear += 10;
256 }
257
258 daysinyear = (year - startyear) * 365;
259 for (i = startyear; i < year; i++)
260 daysinyear += udf_isaleapyear(i);
261 t->tv_sec += daysinyear * 3600 * 24;
262
263 /* Calculate microseconds */
264 t->tv_nsec = time->centisec * 10000 + time->hund_usec * 100 +
265 time->usec;
266
267 /*
268 * Calculate the time zone. The timezone is 12 bit signed 2's
269 * complement, so we gotta do some extra magic to handle it right.
270 */
271 tz.u_tz_offset = le16toh(time->type_tz);
272 tz.u_tz_offset &= 0x0fff;
273 if (tz.u_tz_offset & 0x0800)
274 tz.u_tz_offset |= 0xf000; /* extend the sign to 16 bits */
275 if ((le16toh(time->type_tz) & 0x1000) && (tz.s_tz_offset != -2047))
276 t->tv_sec -= tz.s_tz_offset * 60;
277
278 return;
279 }
280
281 static int
282 udf_getattr(struct vop_getattr_args *a)
283 {
284 struct vnode *vp;
285 struct udf_node *node;
286 struct vattr *vap;
287 struct file_entry *fentry;
288 struct timespec ts;
289
290 ts.tv_sec = 0;
291
292 vp = a->a_vp;
293 vap = a->a_vap;
294 node = VTON(vp);
295 fentry = node->fentry;
296
297 vap->va_fsid = dev2udev(node->udfmp->im_dev);
298 vap->va_fileid = node->hash_id;
299 vap->va_mode = udf_permtomode(node);
300 vap->va_nlink = le16toh(fentry->link_cnt);
301 /*
302 * XXX The spec says that -1 is valid for uid/gid and indicates an
303 * invalid uid/gid. How should this be represented?
304 */
305 vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid);
306 vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid);
307 udf_timetotimespec(&fentry->atime, &vap->va_atime);
308 udf_timetotimespec(&fentry->mtime, &vap->va_mtime);
309 vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */
310 vap->va_rdev = NODEV;
311 if (vp->v_type & VDIR) {
312 /*
313 * Directories that are recorded within their ICB will show
314 * as having 0 blocks recorded. Since tradition dictates
315 * that directories consume at least one logical block,
316 * make it appear so.
317 */
318 if (fentry->logblks_rec != 0) {
319 vap->va_size =
320 le64toh(fentry->logblks_rec) * node->udfmp->bsize;
321 } else {
322 vap->va_size = node->udfmp->bsize;
323 }
324 } else {
325 vap->va_size = le64toh(fentry->inf_len);
326 }
327 vap->va_flags = 0;
328 vap->va_gen = 1;
329 vap->va_blocksize = node->udfmp->bsize;
330 vap->va_bytes = le64toh(fentry->inf_len);
331 vap->va_type = vp->v_type;
332 vap->va_filerev = 0; /* XXX */
333 return (0);
334 }
335
336 static int
337 udf_setattr(struct vop_setattr_args *a)
338 {
339 struct vnode *vp;
340 struct vattr *vap;
341
342 vp = a->a_vp;
343 vap = a->a_vap;
344 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
345 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
346 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
347 return (EROFS);
348 if (vap->va_size != (u_quad_t)VNOVAL) {
349 switch (vp->v_type) {
350 case VDIR:
351 return (EISDIR);
352 case VLNK:
353 case VREG:
354 return (EROFS);
355 case VCHR:
356 case VBLK:
357 case VSOCK:
358 case VFIFO:
359 case VNON:
360 case VBAD:
361 case VMARKER:
362 return (0);
363 }
364 }
365 return (0);
366 }
367
368 /*
369 * File specific ioctls.
370 */
371 static int
372 udf_ioctl(struct vop_ioctl_args *a)
373 {
374 printf("%s called\n", __func__);
375 return (ENOTTY);
376 }
377
378 /*
379 * I'm not sure that this has much value in a read-only filesystem, but
380 * cd9660 has it too.
381 */
382 static int
383 udf_pathconf(struct vop_pathconf_args *a)
384 {
385
386 switch (a->a_name) {
387 case _PC_FILESIZEBITS:
388 *a->a_retval = 64;
389 return (0);
390 case _PC_LINK_MAX:
391 *a->a_retval = 65535;
392 return (0);
393 case _PC_NAME_MAX:
394 *a->a_retval = NAME_MAX;
395 return (0);
396 case _PC_SYMLINK_MAX:
397 *a->a_retval = MAXPATHLEN;
398 return (0);
399 case _PC_NO_TRUNC:
400 *a->a_retval = 1;
401 return (0);
402 case _PC_PIPE_BUF:
403 if (a->a_vp->v_type == VDIR || a->a_vp->v_type == VFIFO) {
404 *a->a_retval = PIPE_BUF;
405 return (0);
406 }
407 return (EINVAL);
408 default:
409 return (vop_stdpathconf(a));
410 }
411 }
412
413 static int
414 udf_print(struct vop_print_args *ap)
415 {
416 struct vnode *vp = ap->a_vp;
417 struct udf_node *node = VTON(vp);
418
419 printf(" ino %lu, on dev %s", (u_long)node->hash_id,
420 devtoname(node->udfmp->im_dev));
421 if (vp->v_type == VFIFO)
422 fifo_printinfo(vp);
423 printf("\n");
424 return (0);
425 }
426
427 #define lblkno(udfmp, loc) ((loc) >> (udfmp)->bshift)
428 #define blkoff(udfmp, loc) ((loc) & (udfmp)->bmask)
429 #define lblktosize(udfmp, blk) ((blk) << (udfmp)->bshift)
430
431 static inline int
432 is_data_in_fentry(const struct udf_node *node)
433 {
434 const struct file_entry *fentry = node->fentry;
435
436 return ((le16toh(fentry->icbtag.flags) & 0x7) == 3);
437 }
438
439 static int
440 udf_read(struct vop_read_args *ap)
441 {
442 struct vnode *vp = ap->a_vp;
443 struct uio *uio = ap->a_uio;
444 struct udf_node *node = VTON(vp);
445 struct udf_mnt *udfmp;
446 struct file_entry *fentry;
447 struct buf *bp;
448 uint8_t *data;
449 daddr_t lbn, rablock;
450 off_t diff, fsize;
451 ssize_t n;
452 int error = 0;
453 long size, on;
454
455 if (uio->uio_resid == 0)
456 return (0);
457 if (uio->uio_offset < 0)
458 return (EINVAL);
459
460 if (is_data_in_fentry(node)) {
461 fentry = node->fentry;
462 data = &fentry->data[le32toh(fentry->l_ea)];
463 fsize = le32toh(fentry->l_ad);
464
465 n = uio->uio_resid;
466 diff = fsize - uio->uio_offset;
467 if (diff <= 0)
468 return (0);
469 if (diff < n)
470 n = diff;
471 error = uiomove(data + uio->uio_offset, (int)n, uio);
472 return (error);
473 }
474
475 fsize = le64toh(node->fentry->inf_len);
476 udfmp = node->udfmp;
477 do {
478 lbn = lblkno(udfmp, uio->uio_offset);
479 on = blkoff(udfmp, uio->uio_offset);
480 n = min((u_int)(udfmp->bsize - on),
481 uio->uio_resid);
482 diff = fsize - uio->uio_offset;
483 if (diff <= 0)
484 return (0);
485 if (diff < n)
486 n = diff;
487 size = udfmp->bsize;
488 rablock = lbn + 1;
489 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
490 if (lblktosize(udfmp, rablock) < fsize) {
491 error = cluster_read(vp, fsize, lbn, size,
492 NOCRED, uio->uio_resid,
493 (ap->a_ioflag >> 16), 0, &bp);
494 } else {
495 error = bread(vp, lbn, size, NOCRED, &bp);
496 }
497 } else {
498 error = bread(vp, lbn, size, NOCRED, &bp);
499 }
500 if (error != 0) {
501 brelse(bp);
502 return (error);
503 }
504 n = min(n, size - bp->b_resid);
505
506 error = uiomove(bp->b_data + on, (int)n, uio);
507 brelse(bp);
508 } while (error == 0 && uio->uio_resid > 0 && n != 0);
509 return (error);
510 }
511
512 /*
513 * Call the OSTA routines to translate the name from a CS0 dstring to a
514 * 16-bit Unicode String. Hooks need to be placed in here to translate from
515 * Unicode to the encoding that the kernel/user expects. Return the length
516 * of the translated string.
517 */
518 static int
519 udf_transname(char *cs0string, char *destname, int len, struct udf_mnt *udfmp)
520 {
521 unicode_t *transname;
522 char *unibuf, *unip;
523 int i, destlen;
524 ssize_t unilen = 0;
525 size_t destleft = MAXNAMLEN;
526
527 /* Convert 16-bit Unicode to destname */
528 if (udfmp->im_flags & UDFMNT_KICONV && udf_iconv) {
529 /* allocate a buffer big enough to hold an 8->16 bit expansion */
530 unibuf = uma_zalloc(udf_zone_trans, M_WAITOK);
531 unip = unibuf;
532 if ((unilen = (ssize_t)udf_UncompressUnicodeByte(len, cs0string, unibuf)) == -1) {
533 printf("udf: Unicode translation failed\n");
534 uma_zfree(udf_zone_trans, unibuf);
535 return 0;
536 }
537
538 while (unilen > 0 && destleft > 0) {
539 udf_iconv->conv(udfmp->im_d2l, __DECONST(const char **,
540 &unibuf), (size_t *)&unilen, (char **)&destname,
541 &destleft);
542 /* Unconverted character found */
543 if (unilen > 0 && destleft > 0) {
544 *destname++ = '?';
545 destleft--;
546 unibuf += 2;
547 unilen -= 2;
548 }
549 }
550 uma_zfree(udf_zone_trans, unip);
551 *destname = '\0';
552 destlen = MAXNAMLEN - (int)destleft;
553 } else {
554 /* allocate a buffer big enough to hold an 8->16 bit expansion */
555 transname = uma_zalloc(udf_zone_trans, M_WAITOK);
556
557 if ((unilen = (ssize_t)udf_UncompressUnicode(len, cs0string, transname)) == -1) {
558 printf("udf: Unicode translation failed\n");
559 uma_zfree(udf_zone_trans, transname);
560 return 0;
561 }
562
563 for (i = 0; i < unilen ; i++) {
564 if (transname[i] & 0xff00) {
565 destname[i] = '.'; /* Fudge the 16bit chars */
566 } else {
567 destname[i] = transname[i] & 0xff;
568 }
569 }
570 uma_zfree(udf_zone_trans, transname);
571 destname[unilen] = 0;
572 destlen = (int)unilen;
573 }
574
575 return (destlen);
576 }
577
578 /*
579 * Compare a CS0 dstring with a name passed in from the VFS layer. Return
580 * 0 on a successful match, nonzero otherwise. Unicode work may need to be done
581 * here also.
582 */
583 static int
584 udf_cmpname(char *cs0string, char *cmpname, int cs0len, int cmplen, struct udf_mnt *udfmp)
585 {
586 char *transname;
587 int error = 0;
588
589 /* This is overkill, but not worth creating a new zone */
590 transname = uma_zalloc(udf_zone_trans, M_WAITOK);
591
592 cs0len = udf_transname(cs0string, transname, cs0len, udfmp);
593
594 /* Easy check. If they aren't the same length, they aren't equal */
595 if ((cs0len == 0) || (cs0len != cmplen))
596 error = -1;
597 else
598 error = bcmp(transname, cmpname, cmplen);
599
600 uma_zfree(udf_zone_trans, transname);
601 return (error);
602 }
603
604 struct udf_uiodir {
605 struct dirent *dirent;
606 u_long *cookies;
607 int ncookies;
608 int acookies;
609 int eofflag;
610 };
611
612 static int
613 udf_uiodir(struct udf_uiodir *uiodir, int de_size, struct uio *uio, long cookie)
614 {
615 if (uiodir->cookies != NULL) {
616 if (++uiodir->acookies > uiodir->ncookies) {
617 uiodir->eofflag = 0;
618 return (-1);
619 }
620 *uiodir->cookies++ = cookie;
621 }
622
623 if (uio->uio_resid < de_size) {
624 uiodir->eofflag = 0;
625 return (-1);
626 }
627
628 return (uiomove(uiodir->dirent, de_size, uio));
629 }
630
631 static struct udf_dirstream *
632 udf_opendir(struct udf_node *node, int offset, int fsize, struct udf_mnt *udfmp)
633 {
634 struct udf_dirstream *ds;
635
636 ds = uma_zalloc(udf_zone_ds, M_WAITOK | M_ZERO);
637
638 ds->node = node;
639 ds->offset = offset;
640 ds->udfmp = udfmp;
641 ds->fsize = fsize;
642
643 return (ds);
644 }
645
646 static struct fileid_desc *
647 udf_getfid(struct udf_dirstream *ds)
648 {
649 struct fileid_desc *fid;
650 int error, frag_size = 0, total_fid_size;
651
652 /* End of directory? */
653 if (ds->offset + ds->off >= ds->fsize) {
654 ds->error = 0;
655 return (NULL);
656 }
657
658 /* Grab the first extent of the directory */
659 if (ds->off == 0) {
660 ds->size = 0;
661 error = udf_readatoffset(ds->node, &ds->size, ds->offset,
662 &ds->bp, &ds->data);
663 if (error) {
664 ds->error = error;
665 if (ds->bp != NULL)
666 brelse(ds->bp);
667 return (NULL);
668 }
669 }
670
671 /*
672 * Clean up from a previous fragmented FID.
673 * XXX Is this the right place for this?
674 */
675 if (ds->fid_fragment && ds->buf != NULL) {
676 ds->fid_fragment = 0;
677 free(ds->buf, M_UDFFID);
678 }
679
680 fid = (struct fileid_desc*)&ds->data[ds->off];
681
682 /*
683 * Check to see if the fid is fragmented. The first test
684 * ensures that we don't wander off the end of the buffer
685 * looking for the l_iu and l_fi fields.
686 */
687 if (ds->off + UDF_FID_SIZE > ds->size ||
688 ds->off + le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE > ds->size){
689
690 /* Copy what we have of the fid into a buffer */
691 frag_size = ds->size - ds->off;
692 if (frag_size >= ds->udfmp->bsize) {
693 printf("udf: invalid FID fragment\n");
694 ds->error = EINVAL;
695 return (NULL);
696 }
697
698 /*
699 * File ID descriptors can only be at most one
700 * logical sector in size.
701 */
702 ds->buf = malloc(ds->udfmp->bsize, M_UDFFID,
703 M_WAITOK | M_ZERO);
704 bcopy(fid, ds->buf, frag_size);
705
706 /* Reduce all of the casting magic */
707 fid = (struct fileid_desc*)ds->buf;
708
709 if (ds->bp != NULL)
710 brelse(ds->bp);
711
712 /* Fetch the next allocation */
713 ds->offset += ds->size;
714 ds->size = 0;
715 error = udf_readatoffset(ds->node, &ds->size, ds->offset,
716 &ds->bp, &ds->data);
717 if (error) {
718 ds->error = error;
719 return (NULL);
720 }
721
722 /*
723 * If the fragment was so small that we didn't get
724 * the l_iu and l_fi fields, copy those in.
725 */
726 if (frag_size < UDF_FID_SIZE)
727 bcopy(ds->data, &ds->buf[frag_size],
728 UDF_FID_SIZE - frag_size);
729
730 /*
731 * Now that we have enough of the fid to work with,
732 * copy in the rest of the fid from the new
733 * allocation.
734 */
735 total_fid_size = UDF_FID_SIZE + le16toh(fid->l_iu) + fid->l_fi;
736 if (total_fid_size > ds->udfmp->bsize) {
737 printf("udf: invalid FID\n");
738 ds->error = EIO;
739 return (NULL);
740 }
741 bcopy(ds->data, &ds->buf[frag_size],
742 total_fid_size - frag_size);
743
744 ds->fid_fragment = 1;
745 } else {
746 total_fid_size = le16toh(fid->l_iu) + fid->l_fi + UDF_FID_SIZE;
747 }
748
749 /*
750 * Update the offset. Align on a 4 byte boundary because the
751 * UDF spec says so.
752 */
753 ds->this_off = ds->offset + ds->off;
754 if (!ds->fid_fragment) {
755 ds->off += (total_fid_size + 3) & ~0x03;
756 } else {
757 ds->off = (total_fid_size - frag_size + 3) & ~0x03;
758 }
759
760 return (fid);
761 }
762
763 static void
764 udf_closedir(struct udf_dirstream *ds)
765 {
766
767 if (ds->bp != NULL)
768 brelse(ds->bp);
769
770 if (ds->fid_fragment && ds->buf != NULL)
771 free(ds->buf, M_UDFFID);
772
773 uma_zfree(udf_zone_ds, ds);
774 }
775
776 static int
777 udf_readdir(struct vop_readdir_args *a)
778 {
779 struct vnode *vp;
780 struct uio *uio;
781 struct dirent dir;
782 struct udf_node *node;
783 struct udf_mnt *udfmp;
784 struct fileid_desc *fid;
785 struct udf_uiodir uiodir;
786 struct udf_dirstream *ds;
787 u_long *cookies = NULL;
788 int ncookies;
789 int error = 0;
790
791 vp = a->a_vp;
792 uio = a->a_uio;
793 node = VTON(vp);
794 udfmp = node->udfmp;
795 uiodir.eofflag = 1;
796
797 if (a->a_ncookies != NULL) {
798 /*
799 * Guess how many entries are needed. If we run out, this
800 * function will be called again and thing will pick up were
801 * it left off.
802 */
803 ncookies = uio->uio_resid / 8;
804 cookies = malloc(sizeof(u_long) * ncookies,
805 M_TEMP, M_WAITOK);
806 if (cookies == NULL)
807 return (ENOMEM);
808 uiodir.ncookies = ncookies;
809 uiodir.cookies = cookies;
810 uiodir.acookies = 0;
811 } else {
812 uiodir.cookies = NULL;
813 }
814
815 /*
816 * Iterate through the file id descriptors. Give the parent dir
817 * entry special attention.
818 */
819 ds = udf_opendir(node, uio->uio_offset, le64toh(node->fentry->inf_len),
820 node->udfmp);
821
822 while ((fid = udf_getfid(ds)) != NULL) {
823
824 /* XXX Should we return an error on a bad fid? */
825 if (udf_checktag(&fid->tag, TAGID_FID)) {
826 printf("Invalid FID tag\n");
827 hexdump(fid, UDF_FID_SIZE, NULL, 0);
828 error = EIO;
829 break;
830 }
831
832 /* Is this a deleted file? */
833 if (fid->file_char & UDF_FILE_CHAR_DEL)
834 continue;
835
836 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
837 /* Do up the '.' and '..' entries. Dummy values are
838 * used for the cookies since the offset here is
839 * usually zero, and NFS doesn't like that value
840 */
841 dir.d_fileno = node->hash_id;
842 dir.d_type = DT_DIR;
843 dir.d_name[0] = '.';
844 dir.d_namlen = 1;
845 dir.d_reclen = GENERIC_DIRSIZ(&dir);
846 dirent_terminate(&dir);
847 uiodir.dirent = &dir;
848 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1);
849 if (error)
850 break;
851
852 dir.d_fileno = udf_getid(&fid->icb);
853 dir.d_type = DT_DIR;
854 dir.d_name[0] = '.';
855 dir.d_name[1] = '.';
856 dir.d_namlen = 2;
857 dir.d_reclen = GENERIC_DIRSIZ(&dir);
858 dirent_terminate(&dir);
859 uiodir.dirent = &dir;
860 error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2);
861 } else {
862 dir.d_namlen = udf_transname(&fid->data[fid->l_iu],
863 &dir.d_name[0], fid->l_fi, udfmp);
864 dir.d_fileno = udf_getid(&fid->icb);
865 dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ?
866 DT_DIR : DT_UNKNOWN;
867 dir.d_reclen = GENERIC_DIRSIZ(&dir);
868 dirent_terminate(&dir);
869 uiodir.dirent = &dir;
870 error = udf_uiodir(&uiodir, dir.d_reclen, uio,
871 ds->this_off);
872 }
873 if (error)
874 break;
875 uio->uio_offset = ds->offset + ds->off;
876 }
877
878 /* tell the calling layer whether we need to be called again */
879 *a->a_eofflag = uiodir.eofflag;
880
881 if (error < 0)
882 error = 0;
883 if (!error)
884 error = ds->error;
885
886 udf_closedir(ds);
887
888 if (a->a_ncookies != NULL) {
889 if (error)
890 free(cookies, M_TEMP);
891 else {
892 *a->a_ncookies = uiodir.acookies;
893 *a->a_cookies = cookies;
894 }
895 }
896
897 return (error);
898 }
899
900 static int
901 udf_readlink(struct vop_readlink_args *ap)
902 {
903 struct path_component *pc, *end;
904 struct vnode *vp;
905 struct uio uio;
906 struct iovec iov[1];
907 struct udf_node *node;
908 void *buf;
909 char *cp;
910 int error, len, root;
911
912 /*
913 * A symbolic link in UDF is a list of variable-length path
914 * component structures. We build a pathname in the caller's
915 * uio by traversing this list.
916 */
917 vp = ap->a_vp;
918 node = VTON(vp);
919 len = le64toh(node->fentry->inf_len);
920 buf = malloc(len, M_DEVBUF, M_WAITOK);
921 iov[0].iov_len = len;
922 iov[0].iov_base = buf;
923 uio.uio_iov = iov;
924 uio.uio_iovcnt = 1;
925 uio.uio_offset = 0;
926 uio.uio_resid = iov[0].iov_len;
927 uio.uio_segflg = UIO_SYSSPACE;
928 uio.uio_rw = UIO_READ;
929 uio.uio_td = curthread;
930 error = VOP_READ(vp, &uio, 0, ap->a_cred);
931 if (error)
932 goto error;
933
934 pc = buf;
935 end = (void *)((char *)buf + len);
936 root = 0;
937 while (pc < end) {
938 switch (pc->type) {
939 case UDF_PATH_ROOT:
940 /* Only allow this at the beginning of a path. */
941 if ((void *)pc != buf) {
942 error = EINVAL;
943 goto error;
944 }
945 cp = "/";
946 len = 1;
947 root = 1;
948 break;
949 case UDF_PATH_DOT:
950 cp = ".";
951 len = 1;
952 break;
953 case UDF_PATH_DOTDOT:
954 cp = "..";
955 len = 2;
956 break;
957 case UDF_PATH_PATH:
958 if (pc->length == 0) {
959 error = EINVAL;
960 goto error;
961 }
962 /*
963 * XXX: We only support CS8 which appears to map
964 * to ASCII directly.
965 */
966 switch (pc->identifier[0]) {
967 case 8:
968 cp = pc->identifier + 1;
969 len = pc->length - 1;
970 break;
971 default:
972 error = EOPNOTSUPP;
973 goto error;
974 }
975 break;
976 default:
977 error = EINVAL;
978 goto error;
979 }
980
981 /*
982 * If this is not the first component, insert a path
983 * separator.
984 */
985 if (pc != buf) {
986 /* If we started with root we already have a "/". */
987 if (root)
988 goto skipslash;
989 root = 0;
990 if (ap->a_uio->uio_resid < 1) {
991 error = ENAMETOOLONG;
992 goto error;
993 }
994 error = uiomove("/", 1, ap->a_uio);
995 if (error)
996 break;
997 }
998 skipslash:
999
1000 /* Append string at 'cp' of length 'len' to our path. */
1001 if (len > ap->a_uio->uio_resid) {
1002 error = ENAMETOOLONG;
1003 goto error;
1004 }
1005 error = uiomove(cp, len, ap->a_uio);
1006 if (error)
1007 break;
1008
1009 /* Advance to next component. */
1010 pc = (void *)((char *)pc + 4 + pc->length);
1011 }
1012 error:
1013 free(buf, M_DEVBUF);
1014 return (error);
1015 }
1016
1017 static int
1018 udf_strategy(struct vop_strategy_args *a)
1019 {
1020 struct buf *bp;
1021 struct vnode *vp;
1022 struct udf_node *node;
1023 struct bufobj *bo;
1024 off_t offset;
1025 uint32_t maxsize;
1026 daddr_t sector;
1027 int error;
1028
1029 bp = a->a_bp;
1030 vp = a->a_vp;
1031 node = VTON(vp);
1032
1033 if (bp->b_blkno == bp->b_lblkno) {
1034 offset = lblktosize(node->udfmp, bp->b_lblkno);
1035 error = udf_bmap_internal(node, offset, §or, &maxsize);
1036 if (error) {
1037 clrbuf(bp);
1038 bp->b_blkno = -1;
1039 bufdone(bp);
1040 return (0);
1041 }
1042 /* bmap gives sector numbers, bio works with device blocks */
1043 bp->b_blkno = sector << (node->udfmp->bshift - DEV_BSHIFT);
1044 }
1045 bo = node->udfmp->im_bo;
1046 bp->b_iooffset = dbtob(bp->b_blkno);
1047 BO_STRATEGY(bo, bp);
1048 return (0);
1049 }
1050
1051 static int
1052 udf_bmap(struct vop_bmap_args *a)
1053 {
1054 struct udf_node *node;
1055 uint32_t max_size;
1056 daddr_t lsector;
1057 int nblk;
1058 int error;
1059
1060 node = VTON(a->a_vp);
1061
1062 if (a->a_bop != NULL)
1063 *a->a_bop = &node->udfmp->im_devvp->v_bufobj;
1064 if (a->a_bnp == NULL)
1065 return (0);
1066 if (a->a_runb)
1067 *a->a_runb = 0;
1068
1069 /*
1070 * UDF_INVALID_BMAP means data embedded into fentry, this is an internal
1071 * error that should not be propagated to calling code.
1072 * Most obvious mapping for this error is EOPNOTSUPP as we can not truly
1073 * translate block numbers in this case.
1074 * Incidentally, this return code will make vnode pager to use VOP_READ
1075 * to get data for mmap-ed pages and udf_read knows how to do the right
1076 * thing for this kind of files.
1077 */
1078 error = udf_bmap_internal(node, a->a_bn << node->udfmp->bshift,
1079 &lsector, &max_size);
1080 if (error == UDF_INVALID_BMAP)
1081 return (EOPNOTSUPP);
1082 if (error)
1083 return (error);
1084
1085 /* Translate logical to physical sector number */
1086 *a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT);
1087
1088 /*
1089 * Determine maximum number of readahead blocks following the
1090 * requested block.
1091 */
1092 if (a->a_runp) {
1093 nblk = (max_size >> node->udfmp->bshift) - 1;
1094 if (nblk <= 0)
1095 *a->a_runp = 0;
1096 else if (nblk >= (MAXBSIZE >> node->udfmp->bshift))
1097 *a->a_runp = (MAXBSIZE >> node->udfmp->bshift) - 1;
1098 else
1099 *a->a_runp = nblk;
1100 }
1101
1102 if (a->a_runb) {
1103 *a->a_runb = 0;
1104 }
1105
1106 return (0);
1107 }
1108
1109 /*
1110 * The all powerful VOP_LOOKUP().
1111 */
1112 static int
1113 udf_lookup(struct vop_cachedlookup_args *a)
1114 {
1115 struct vnode *dvp;
1116 struct vnode *tdp = NULL;
1117 struct vnode **vpp = a->a_vpp;
1118 struct udf_node *node;
1119 struct udf_mnt *udfmp;
1120 struct fileid_desc *fid = NULL;
1121 struct udf_dirstream *ds;
1122 u_long nameiop;
1123 u_long flags;
1124 char *nameptr;
1125 long namelen;
1126 ino_t id = 0;
1127 int offset, error = 0;
1128 int fsize, lkflags, ltype, numdirpasses;
1129
1130 dvp = a->a_dvp;
1131 node = VTON(dvp);
1132 udfmp = node->udfmp;
1133 nameiop = a->a_cnp->cn_nameiop;
1134 flags = a->a_cnp->cn_flags;
1135 lkflags = a->a_cnp->cn_lkflags;
1136 nameptr = a->a_cnp->cn_nameptr;
1137 namelen = a->a_cnp->cn_namelen;
1138 fsize = le64toh(node->fentry->inf_len);
1139
1140 /*
1141 * If this is a LOOKUP and we've already partially searched through
1142 * the directory, pick up where we left off and flag that the
1143 * directory may need to be searched twice. For a full description,
1144 * see /sys/fs/cd9660/cd9660_lookup.c:cd9660_lookup()
1145 */
1146 if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) {
1147 offset = 0;
1148 numdirpasses = 1;
1149 } else {
1150 offset = node->diroff;
1151 numdirpasses = 2;
1152 nchstats.ncs_2passes++;
1153 }
1154
1155 lookloop:
1156 ds = udf_opendir(node, offset, fsize, udfmp);
1157
1158 while ((fid = udf_getfid(ds)) != NULL) {
1159
1160 /* XXX Should we return an error on a bad fid? */
1161 if (udf_checktag(&fid->tag, TAGID_FID)) {
1162 printf("udf_lookup: Invalid tag\n");
1163 error = EIO;
1164 break;
1165 }
1166
1167 /* Is this a deleted file? */
1168 if (fid->file_char & UDF_FILE_CHAR_DEL)
1169 continue;
1170
1171 if ((fid->l_fi == 0) && (fid->file_char & UDF_FILE_CHAR_PAR)) {
1172 if (flags & ISDOTDOT) {
1173 id = udf_getid(&fid->icb);
1174 break;
1175 }
1176 } else {
1177 if (!(udf_cmpname(&fid->data[fid->l_iu],
1178 nameptr, fid->l_fi, namelen, udfmp))) {
1179 id = udf_getid(&fid->icb);
1180 break;
1181 }
1182 }
1183 }
1184
1185 if (!error)
1186 error = ds->error;
1187
1188 /* XXX Bail out here? */
1189 if (error) {
1190 udf_closedir(ds);
1191 return (error);
1192 }
1193
1194 /* Did we have a match? */
1195 if (id) {
1196 /*
1197 * Remember where this entry was if it's the final
1198 * component.
1199 */
1200 if ((flags & ISLASTCN) && nameiop == LOOKUP)
1201 node->diroff = ds->offset + ds->off;
1202 if (numdirpasses == 2)
1203 nchstats.ncs_pass2++;
1204 udf_closedir(ds);
1205
1206 if (flags & ISDOTDOT) {
1207 error = vn_vget_ino(dvp, id, lkflags, &tdp);
1208 } else if (node->hash_id == id) {
1209 VREF(dvp); /* we want ourself, ie "." */
1210 /*
1211 * When we lookup "." we still can be asked to lock it
1212 * differently.
1213 */
1214 ltype = lkflags & LK_TYPE_MASK;
1215 if (ltype != VOP_ISLOCKED(dvp)) {
1216 if (ltype == LK_EXCLUSIVE)
1217 vn_lock(dvp, LK_UPGRADE | LK_RETRY);
1218 else /* if (ltype == LK_SHARED) */
1219 vn_lock(dvp, LK_DOWNGRADE | LK_RETRY);
1220 }
1221 tdp = dvp;
1222 } else
1223 error = udf_vget(udfmp->im_mountp, id, lkflags, &tdp);
1224 if (!error) {
1225 *vpp = tdp;
1226 /* Put this entry in the cache */
1227 if (flags & MAKEENTRY)
1228 cache_enter(dvp, *vpp, a->a_cnp);
1229 }
1230 } else {
1231 /* Name wasn't found on this pass. Do another pass? */
1232 if (numdirpasses == 2) {
1233 numdirpasses--;
1234 offset = 0;
1235 udf_closedir(ds);
1236 goto lookloop;
1237 }
1238 udf_closedir(ds);
1239
1240 /* Enter name into cache as non-existant */
1241 if (flags & MAKEENTRY)
1242 cache_enter(dvp, *vpp, a->a_cnp);
1243
1244 if ((flags & ISLASTCN) &&
1245 (nameiop == CREATE || nameiop == RENAME)) {
1246 error = EROFS;
1247 } else {
1248 error = ENOENT;
1249 }
1250 }
1251
1252 return (error);
1253 }
1254
1255 static int
1256 udf_reclaim(struct vop_reclaim_args *a)
1257 {
1258 struct vnode *vp;
1259 struct udf_node *unode;
1260
1261 vp = a->a_vp;
1262 unode = VTON(vp);
1263
1264 /*
1265 * Destroy the vm object and flush associated pages.
1266 */
1267 vnode_destroy_vobject(vp);
1268
1269 if (unode != NULL) {
1270 vfs_hash_remove(vp);
1271
1272 if (unode->fentry != NULL)
1273 free(unode->fentry, M_UDFFENTRY);
1274 uma_zfree(udf_zone_node, unode);
1275 vp->v_data = NULL;
1276 }
1277
1278 return (0);
1279 }
1280
1281 static int
1282 udf_vptofh(struct vop_vptofh_args *a)
1283 {
1284 struct udf_node *node;
1285 struct ifid *ifhp;
1286
1287 node = VTON(a->a_vp);
1288 ifhp = (struct ifid *)a->a_fhp;
1289 ifhp->ifid_len = sizeof(struct ifid);
1290 ifhp->ifid_ino = node->hash_id;
1291
1292 return (0);
1293 }
1294
1295 /*
1296 * Read the block and then set the data pointer to correspond with the
1297 * offset passed in. Only read in at most 'size' bytes, and then set 'size'
1298 * to the number of bytes pointed to. If 'size' is zero, try to read in a
1299 * whole extent.
1300 *
1301 * Note that *bp may be assigned error or not.
1302 *
1303 */
1304 static int
1305 udf_readatoffset(struct udf_node *node, int *size, off_t offset,
1306 struct buf **bp, uint8_t **data)
1307 {
1308 struct udf_mnt *udfmp = node->udfmp;
1309 struct vnode *vp = node->i_vnode;
1310 struct file_entry *fentry;
1311 struct buf *bp1;
1312 uint32_t max_size;
1313 daddr_t sector;
1314 off_t off;
1315 int adj_size;
1316 int error;
1317
1318 /*
1319 * This call is made *not* only to detect UDF_INVALID_BMAP case,
1320 * max_size is used as an ad-hoc read-ahead hint for "normal" case.
1321 */
1322 error = udf_bmap_internal(node, offset, §or, &max_size);
1323 if (error == UDF_INVALID_BMAP) {
1324 /*
1325 * This error means that the file *data* is stored in the
1326 * allocation descriptor field of the file entry.
1327 */
1328 fentry = node->fentry;
1329 *data = &fentry->data[le32toh(fentry->l_ea)];
1330 *size = le32toh(fentry->l_ad);
1331 if (offset >= *size)
1332 *size = 0;
1333 else {
1334 *data += offset;
1335 *size -= offset;
1336 }
1337 return (0);
1338 } else if (error != 0) {
1339 return (error);
1340 }
1341
1342 /* Adjust the size so that it is within range */
1343 if (*size == 0 || *size > max_size)
1344 *size = max_size;
1345
1346 /*
1347 * Because we will read starting at block boundary, we need to adjust
1348 * how much we need to read so that all promised data is in.
1349 * Also, we can't promise to read more than MAXBSIZE bytes starting
1350 * from block boundary, so adjust what we promise too.
1351 */
1352 off = blkoff(udfmp, offset);
1353 *size = min(*size, MAXBSIZE - off);
1354 adj_size = (*size + off + udfmp->bmask) & ~udfmp->bmask;
1355 *bp = NULL;
1356 if ((error = bread(vp, lblkno(udfmp, offset), adj_size, NOCRED, bp))) {
1357 printf("warning: udf_readlblks returned error %d\n", error);
1358 /* note: *bp may be non-NULL */
1359 return (error);
1360 }
1361
1362 bp1 = *bp;
1363 *data = (uint8_t *)&bp1->b_data[offset & udfmp->bmask];
1364 return (0);
1365 }
1366
1367 /*
1368 * Translate a file offset into a logical block and then into a physical
1369 * block.
1370 * max_size - maximum number of bytes that can be read starting from given
1371 * offset, rather than beginning of calculated sector number
1372 */
1373 static int
1374 udf_bmap_internal(struct udf_node *node, off_t offset, daddr_t *sector,
1375 uint32_t *max_size)
1376 {
1377 struct udf_mnt *udfmp;
1378 struct file_entry *fentry;
1379 void *icb;
1380 struct icb_tag *tag;
1381 uint32_t icblen = 0;
1382 daddr_t lsector;
1383 int ad_offset, ad_num = 0;
1384 int i, p_offset;
1385
1386 udfmp = node->udfmp;
1387 fentry = node->fentry;
1388 tag = &fentry->icbtag;
1389
1390 switch (le16toh(tag->strat_type)) {
1391 case 4:
1392 break;
1393
1394 case 4096:
1395 printf("Cannot deal with strategy4096 yet!\n");
1396 return (ENODEV);
1397
1398 default:
1399 printf("Unknown strategy type %d\n", tag->strat_type);
1400 return (ENODEV);
1401 }
1402
1403 switch (le16toh(tag->flags) & 0x7) {
1404 case 0:
1405 /*
1406 * The allocation descriptor field is filled with short_ad's.
1407 * If the offset is beyond the current extent, look for the
1408 * next extent.
1409 */
1410 do {
1411 offset -= icblen;
1412 ad_offset = sizeof(struct short_ad) * ad_num;
1413 if (ad_offset > le32toh(fentry->l_ad)) {
1414 printf("File offset out of bounds\n");
1415 return (EINVAL);
1416 }
1417 icb = GETICB(short_ad, fentry,
1418 le32toh(fentry->l_ea) + ad_offset);
1419 icblen = GETICBLEN(short_ad, icb);
1420 ad_num++;
1421 } while(offset >= icblen);
1422
1423 lsector = (offset >> udfmp->bshift) +
1424 le32toh(((struct short_ad *)(icb))->pos);
1425
1426 *max_size = icblen - offset;
1427
1428 break;
1429 case 1:
1430 /*
1431 * The allocation descriptor field is filled with long_ad's
1432 * If the offset is beyond the current extent, look for the
1433 * next extent.
1434 */
1435 do {
1436 offset -= icblen;
1437 ad_offset = sizeof(struct long_ad) * ad_num;
1438 if (ad_offset > le32toh(fentry->l_ad)) {
1439 printf("File offset out of bounds\n");
1440 return (EINVAL);
1441 }
1442 icb = GETICB(long_ad, fentry,
1443 le32toh(fentry->l_ea) + ad_offset);
1444 icblen = GETICBLEN(long_ad, icb);
1445 ad_num++;
1446 } while(offset >= icblen);
1447
1448 lsector = (offset >> udfmp->bshift) +
1449 le32toh(((struct long_ad *)(icb))->loc.lb_num);
1450
1451 *max_size = icblen - offset;
1452
1453 break;
1454 case 3:
1455 /*
1456 * This type means that the file *data* is stored in the
1457 * allocation descriptor field of the file entry.
1458 */
1459 *max_size = 0;
1460 *sector = node->hash_id + udfmp->part_start;
1461
1462 return (UDF_INVALID_BMAP);
1463 case 2:
1464 /* DirectCD does not use extended_ad's */
1465 default:
1466 printf("Unsupported allocation descriptor %d\n",
1467 tag->flags & 0x7);
1468 return (ENODEV);
1469 }
1470
1471 *sector = lsector + udfmp->part_start;
1472
1473 /*
1474 * Check the sparing table. Each entry represents the beginning of
1475 * a packet.
1476 */
1477 if (udfmp->s_table != NULL) {
1478 for (i = 0; i< udfmp->s_table_entries; i++) {
1479 p_offset =
1480 lsector - le32toh(udfmp->s_table->entries[i].org);
1481 if ((p_offset < udfmp->p_sectors) && (p_offset >= 0)) {
1482 *sector =
1483 le32toh(udfmp->s_table->entries[i].map) +
1484 p_offset;
1485 break;
1486 }
1487 }
1488 }
1489
1490 return (0);
1491 }
Cache object: ecc2e700e57ecfe7dc6644d3e474d36d
|