Annotation of sys/isofs/udf/udf_vfsops.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: udf_vfsops.c,v 1.23 2006/08/07 15:50:42 pedro Exp $ */
2:
3: /*
4: * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org>
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: *
28: * $FreeBSD: src/sys/fs/udf/udf_vfsops.c,v 1.25 2005/01/25 15:52:03 phk Exp $
29: */
30:
31: /*
32: * Ported to OpenBSD by Pedro Martelletto <pedro@openbsd.org> in February 2005.
33: */
34:
35: /*
36: * Ok, here's how it goes. The UDF specs are pretty clear on how each data
37: * structure is made up, but not very clear on how they relate to each other.
38: * Here is the skinny... This demostrates a filesystem with one file in the
39: * root directory. Subdirectories are treated just as normal files, but they
40: * have File Id Descriptors of their children as their file data. As for the
41: * Anchor Volume Descriptor Pointer, it can exist in two of the following three
42: * places: sector 256, sector n (the max sector of the disk), or sector
43: * n - 256. It's a pretty good bet that one will exist at sector 256 though.
44: * One caveat is unclosed CD media. For that, sector 256 cannot be written,
45: * so the Anchor Volume Descriptor Pointer can exist at sector 512 until the
46: * media is closed.
47: */
48:
49: #include <sys/types.h>
50: #include <sys/param.h>
51: #include <sys/systm.h>
52: #include <sys/uio.h>
53: #include <sys/buf.h>
54: #include <sys/conf.h>
55: #include <sys/dirent.h>
56: #include <sys/fcntl.h>
57: #include <sys/kernel.h>
58: #include <sys/malloc.h>
59: #include <sys/mutex.h>
60: #include <sys/mount.h>
61: #include <sys/namei.h>
62: #include <sys/pool.h>
63: #include <sys/proc.h>
64: #include <sys/lock.h>
65: #include <sys/queue.h>
66: #include <sys/vnode.h>
67: #include <sys/endian.h>
68:
69: #include <miscfs/specfs/specdev.h>
70:
71: #include <isofs/udf/ecma167-udf.h>
72: #include <isofs/udf/udf.h>
73: #include <isofs/udf/udf_extern.h>
74:
75: struct pool udf_trans_pool;
76: struct pool unode_pool;
77: struct pool udf_ds_pool;
78:
79: int udf_find_partmaps(struct umount *, struct logvol_desc *);
80: int udf_get_vpartmap(struct umount *, struct part_map_virt *);
81: int udf_get_spartmap(struct umount *, struct part_map_spare *);
82: int udf_mountfs(struct vnode *, struct mount *, uint32_t, struct proc *);
83:
84: const struct vfsops udf_vfsops = {
85: .vfs_fhtovp = udf_fhtovp,
86: .vfs_init = udf_init,
87: .vfs_mount = udf_mount,
88: .vfs_start = udf_start,
89: .vfs_root = udf_root,
90: .vfs_quotactl = udf_quotactl,
91: .vfs_statfs = udf_statfs,
92: .vfs_sync = udf_sync,
93: .vfs_unmount = udf_unmount,
94: .vfs_vget = udf_vget,
95: .vfs_vptofh = udf_vptofh,
96: .vfs_sysctl = udf_sysctl,
97: .vfs_checkexp = udf_checkexp,
98: };
99:
100: int
101: udf_init(struct vfsconf *foo)
102: {
103: pool_init(&udf_trans_pool, MAXNAMLEN * sizeof(unicode_t), 0, 0, 0,
104: "udftrpl", &pool_allocator_nointr);
105: pool_init(&unode_pool, sizeof(struct unode), 0, 0, 0,
106: "udfndpl", &pool_allocator_nointr);
107: pool_init(&udf_ds_pool, sizeof(struct udf_dirstream), 0, 0, 0,
108: "udfdspl", &pool_allocator_nointr);
109:
110: return (0);
111: }
112:
113: int
114: udf_start(struct mount *mp, int flags, struct proc *p)
115: {
116: return (0);
117: }
118:
119: int
120: udf_mount(struct mount *mp, const char *path, void *data,
121: struct nameidata *ndp, struct proc *p)
122: {
123: struct vnode *devvp; /* vnode of the mount device */
124: struct udf_args args;
125: size_t len;
126: int error;
127:
128: if ((mp->mnt_flag & MNT_RDONLY) == 0) {
129: mp->mnt_flag |= MNT_RDONLY;
130: printf("udf_mount: enforcing read-only mode\n");
131: }
132:
133: /*
134: * No root filesystem support. Probably not a big deal, since the
135: * bootloader doesn't understand UDF.
136: */
137: if (mp->mnt_flag & MNT_ROOTFS)
138: return (EOPNOTSUPP);
139:
140: error = copyin(data, &args, sizeof(struct udf_args));
141: if (error)
142: return (error);
143:
144: if (args.fspec == NULL)
145: return (EINVAL);
146:
147: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
148: if ((error = namei(ndp)))
149: return (error);
150:
151: devvp = ndp->ni_vp;
152: if (devvp->v_type != VBLK) {
153: vrele(devvp);
154: return (ENOTBLK);
155: }
156:
157: if (major(devvp->v_rdev) >= nblkdev) {
158: vrele(devvp);
159: return (ENXIO);
160: }
161:
162: /* Check the access rights on the mount device */
163: if (p->p_ucred->cr_uid) {
164: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
165: error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p);
166: VOP_UNLOCK(devvp, 0, p);
167: if (error) {
168: vrele(devvp);
169: return (error);
170: }
171: }
172:
173: if ((error = udf_mountfs(devvp, mp, args.lastblock, p))) {
174: vrele(devvp);
175: return (error);
176: }
177:
178: /*
179: * Keep a copy of the mount information.
180: */
181: copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &len);
182: bzero(mp->mnt_stat.f_mntonname + len, MNAMELEN - len);
183: copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &len);
184: bzero(mp->mnt_stat.f_mntfromname + len, MNAMELEN - len);
185:
186: return (0);
187: };
188:
189: /*
190: * Check the descriptor tag for both the correct id and correct checksum.
191: * Return zero if all is good, EINVAL if not.
192: */
193: int
194: udf_checktag(struct desc_tag *tag, uint16_t id)
195: {
196: uint8_t *itag;
197: uint8_t i, cksum = 0;
198:
199: itag = (uint8_t *)tag;
200:
201: if (letoh16(tag->id) != id)
202: return (EINVAL);
203:
204: for (i = 0; i < 15; i++)
205: cksum = cksum + itag[i];
206: cksum = cksum - itag[4];
207:
208: if (cksum == tag->cksum)
209: return (0);
210:
211: return (EINVAL);
212: }
213:
214: int
215: udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
216: {
217: struct buf *bp = NULL;
218: struct anchor_vdp avdp;
219: struct umount *ump = NULL;
220: struct part_desc *pd;
221: struct logvol_desc *lvd;
222: struct fileset_desc *fsd;
223: struct file_entry *root_fentry;
224: uint32_t sector, size, mvds_start, mvds_end;
225: uint32_t fsd_offset = 0;
226: uint16_t part_num = 0, fsd_part = 0;
227: int error = EINVAL;
228: int logvol_found = 0, part_found = 0, fsd_found = 0;
229: int bsize;
230:
231: /*
232: * Disallow multiple mounts of the same device.
233: * Disallow mounting of a device that is currently in use
234: * (except for root, which might share swap device for miniroot).
235: * Flush out any old buffers remaining from a previous use.
236: */
237: if ((error = vfs_mountedon(devvp)))
238: return (error);
239: if (vcount(devvp) > 1 && devvp != rootvp)
240: return (EBUSY);
241: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
242: error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
243: VOP_UNLOCK(devvp, 0, p);
244: if (error)
245: return (error);
246:
247: error = VOP_OPEN(devvp, FREAD, FSCRED, p);
248: if (error)
249: return (error);
250:
251: MALLOC(ump, struct umount *, sizeof(struct umount), M_UDFMOUNT,
252: M_WAITOK);
253: bzero(ump, sizeof(struct umount));
254:
255: mp->mnt_data = (qaddr_t) ump;
256: mp->mnt_stat.f_fsid.val[0] = devvp->v_rdev;
257: mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_UDF);
258: mp->mnt_flag |= MNT_LOCAL;
259:
260: ump->um_mountp = mp;
261: ump->um_dev = devvp->v_rdev;
262: ump->um_devvp = devvp;
263:
264: bsize = 2048; /* Should probe the media for its size. */
265:
266: /*
267: * Get the Anchor Volume Descriptor Pointer from sector 256.
268: * Should also check sector n - 256, n, and 512.
269: */
270: sector = 256;
271: if ((error = bread(devvp, sector * btodb(bsize), bsize, NOCRED,
272: &bp)) != 0)
273: goto bail;
274: if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
275: goto bail;
276:
277: bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
278: brelse(bp);
279: bp = NULL;
280:
281: /*
282: * Extract the Partition Descriptor and Logical Volume Descriptor
283: * from the Volume Descriptor Sequence.
284: * Should we care about the partition type right now?
285: * What about multiple partitions?
286: */
287: mvds_start = letoh32(avdp.main_vds_ex.loc);
288: mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
289: for (sector = mvds_start; sector < mvds_end; sector++) {
290: if ((error = bread(devvp, sector * btodb(bsize), bsize,
291: NOCRED, &bp)) != 0) {
292: printf("Can't read sector %d of VDS\n", sector);
293: goto bail;
294: }
295: lvd = (struct logvol_desc *)bp->b_data;
296: if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
297: ump->um_bsize = letoh32(lvd->lb_size);
298: ump->um_bmask = ump->um_bsize - 1;
299: ump->um_bshift = ffs(ump->um_bsize) - 1;
300: fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num);
301: fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num);
302: if (udf_find_partmaps(ump, lvd))
303: break;
304: logvol_found = 1;
305: }
306: pd = (struct part_desc *)bp->b_data;
307: if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
308: part_found = 1;
309: part_num = letoh16(pd->part_num);
310: ump->um_len = letoh32(pd->part_len);
311: ump->um_start = letoh32(pd->start_loc);
312: }
313:
314: brelse(bp);
315: bp = NULL;
316: if ((part_found) && (logvol_found))
317: break;
318: }
319:
320: if (!part_found || !logvol_found) {
321: error = EINVAL;
322: goto bail;
323: }
324:
325: if (fsd_part != part_num) {
326: printf("FSD does not lie within the partition!\n");
327: error = EINVAL;
328: goto bail;
329: }
330:
331: mtx_init(&ump->um_hashmtx, IPL_NONE);
332: ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE, M_UDFMOUNT, M_WAITOK,
333: &ump->um_hashsz);
334:
335: /* Get the VAT, if needed */
336: if (ump->um_flags & UDF_MNT_FIND_VAT) {
337: error = udf_vat_get(ump, lb);
338: if (error)
339: goto bail;
340: }
341:
342: /*
343: * Grab the Fileset Descriptor
344: * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
345: * me in the right direction here.
346: */
347: sector = fsd_offset;
348: udf_vat_map(ump, §or);
349: if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
350: printf("Cannot read sector %d of FSD\n", sector);
351: goto bail;
352: }
353: fsd = (struct fileset_desc *)bp->b_data;
354: if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
355: fsd_found = 1;
356: bcopy(&fsd->rootdir_icb, &ump->um_root_icb,
357: sizeof(struct long_ad));
358: }
359:
360: brelse(bp);
361: bp = NULL;
362:
363: if (!fsd_found) {
364: printf("Couldn't find the fsd\n");
365: error = EINVAL;
366: goto bail;
367: }
368:
369: /*
370: * Find the file entry for the root directory.
371: */
372: sector = letoh32(ump->um_root_icb.loc.lb_num);
373: size = letoh32(ump->um_root_icb.len);
374: udf_vat_map(ump, §or);
375: if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) {
376: printf("Cannot read sector %d\n", sector);
377: goto bail;
378: }
379:
380: root_fentry = (struct file_entry *)bp->b_data;
381: if ((error = udf_checktag(&root_fentry->tag, TAGID_FENTRY))) {
382: printf("Invalid root file entry!\n");
383: goto bail;
384: }
385:
386: brelse(bp);
387: bp = NULL;
388:
389: devvp->v_specmountpoint = mp;
390:
391: return (0);
392:
393: bail:
394: if (ump->um_hashtbl != NULL)
395: free(ump->um_hashtbl, M_UDFMOUNT);
396:
397: if (ump != NULL) {
398: FREE(ump, M_UDFMOUNT);
399: mp->mnt_data = NULL;
400: mp->mnt_flag &= ~MNT_LOCAL;
401: }
402: if (bp != NULL)
403: brelse(bp);
404: VOP_CLOSE(devvp, FREAD, FSCRED, p);
405:
406: return (error);
407: }
408:
409: int
410: udf_unmount(struct mount *mp, int mntflags, struct proc *p)
411: {
412: struct umount *ump;
413: struct vnode *devvp;
414: int error, flags = 0;
415:
416: ump = VFSTOUDFFS(mp);
417: devvp = ump->um_devvp;
418:
419: if (mntflags & MNT_FORCE)
420: flags |= FORCECLOSE;
421:
422: if ((error = vflush(mp, NULL, flags)))
423: return (error);
424:
425: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
426: vinvalbuf(devvp, V_SAVE, NOCRED, p, 0, 0);
427: error = VOP_CLOSE(devvp, FREAD, NOCRED, p);
428: VOP_UNLOCK(devvp, 0, p);
429: if (error)
430: return (error);
431:
432: devvp->v_specmountpoint = NULL;
433: vrele(devvp);
434:
435: if (ump->um_flags & UDF_MNT_USES_VAT)
436: free(ump->um_vat, M_UDFMOUNT);
437:
438: if (ump->um_stbl != NULL)
439: free(ump->um_stbl, M_UDFMOUNT);
440:
441: if (ump->um_hashtbl != NULL)
442: free(ump->um_hashtbl, M_UDFMOUNT);
443:
444: FREE(ump, M_UDFMOUNT);
445:
446: mp->mnt_data = (qaddr_t)0;
447: mp->mnt_flag &= ~MNT_LOCAL;
448:
449: return (0);
450: }
451:
452: int
453: udf_root(struct mount *mp, struct vnode **vpp)
454: {
455: struct umount *ump;
456: struct vnode *vp;
457: ino_t id;
458: int error;
459:
460: ump = VFSTOUDFFS(mp);
461:
462: id = udf_getid(&ump->um_root_icb);
463:
464: error = udf_vget(mp, id, vpp);
465: if (error)
466: return (error);
467:
468: vp = *vpp;
469: vp->v_flag |= VROOT;
470:
471: return (0);
472: }
473:
474: int
475: udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
476: struct proc *p)
477: {
478: return (EOPNOTSUPP);
479: }
480:
481: int
482: udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
483: {
484: struct umount *ump;
485:
486: ump = VFSTOUDFFS(mp);
487:
488: sbp->f_bsize = ump->um_bsize;
489: sbp->f_iosize = ump->um_bsize;
490: sbp->f_blocks = ump->um_len;
491: sbp->f_bfree = 0;
492: sbp->f_bavail = 0;
493: sbp->f_files = 0;
494: sbp->f_ffree = 0;
495:
496: return (0);
497: }
498:
499: int
500: udf_sync(struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)
501: {
502: return (0);
503: }
504:
505: int
506: udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
507: {
508: struct buf *bp;
509: struct vnode *devvp;
510: struct umount *ump;
511: struct proc *p;
512: struct vnode *vp;
513: struct unode *up;
514: struct file_entry *fe;
515: int error, sector, size;
516:
517: p = curproc;
518: bp = NULL;
519: *vpp = NULL;
520: ump = VFSTOUDFFS(mp);
521:
522: /* See if we already have this in the cache */
523: if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE, vpp)) != 0)
524: return (error);
525: if (*vpp != NULL)
526: return (0);
527:
528: /*
529: * Allocate memory and check the tag id's before grabbing a new
530: * vnode, since it's hard to roll back if there is a problem.
531: */
532: up = pool_get(&unode_pool, PR_WAITOK);
533: bzero(up, sizeof(struct unode));
534:
535: /*
536: * Copy in the file entry. Per the spec, the size can only be 1 block.
537: */
538: sector = ino;
539: devvp = ump->um_devvp;
540: udf_vat_map(ump, §or);
541: if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)) != 0) {
542: printf("Cannot read sector %d\n", sector);
543: pool_put(&unode_pool, up);
544: if (bp != NULL)
545: brelse(bp);
546: return (error);
547: }
548:
549: fe = (struct file_entry *)bp->b_data;
550: if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
551: printf("Invalid file entry!\n");
552: pool_put(&unode_pool, up);
553: brelse(bp);
554: return (ENOMEM);
555: }
556:
557: size = UDF_FENTRY_SIZE + letoh32(fe->l_ea) + letoh32(fe->l_ad);
558:
559: up->u_fentry = malloc(size, M_UDFFENTRY, M_NOWAIT);
560: if (up->u_fentry == NULL) {
561: pool_put(&unode_pool, up);
562: brelse(bp);
563: return (ENOMEM); /* Cannot allocate file entry block */
564: }
565:
566: bcopy(bp->b_data, up->u_fentry, size);
567:
568: brelse(bp);
569: bp = NULL;
570:
571: if ((error = udf_allocv(mp, &vp, p))) {
572: free(up->u_fentry, M_UDFFENTRY);
573: pool_put(&unode_pool, up);
574: return (error); /* Error from udf_allocv() */
575: }
576:
577: up->u_vnode = vp;
578: up->u_ino = ino;
579: up->u_devvp = ump->um_devvp;
580: up->u_dev = ump->um_dev;
581: up->u_ump = ump;
582: vp->v_data = up;
583: VREF(ump->um_devvp);
584:
585: lockinit(&up->u_lock, PINOD, "unode", 0, 0);
586:
587: /*
588: * udf_hashins() will lock the vnode for us.
589: */
590: udf_hashins(up);
591:
592: switch (up->u_fentry->icbtag.file_type) {
593: default:
594: vp->v_type = VBAD;
595: break;
596: case UDF_ICB_TYPE_DIR:
597: vp->v_type = VDIR;
598: break;
599: case UDF_ICB_TYPE_FILE:
600: vp->v_type = VREG;
601: break;
602: case UDF_ICB_TYPE_BLKDEV:
603: vp->v_type = VBLK;
604: break;
605: case UDF_ICB_TYPE_CHRDEV:
606: vp->v_type = VCHR;
607: break;
608: case UDF_ICB_TYPE_FIFO:
609: vp->v_type = VFIFO;
610: break;
611: case UDF_ICB_TYPE_SOCKET:
612: vp->v_type = VSOCK;
613: break;
614: case UDF_ICB_TYPE_SYMLINK:
615: vp->v_type = VLNK;
616: break;
617: case UDF_ICB_TYPE_VAT_150:
618: vp->v_type = VREG;
619: break;
620: }
621:
622: *vpp = vp;
623:
624: return (0);
625: }
626:
627: struct ifid {
628: u_short ifid_len;
629: u_short ifid_pad;
630: int ifid_ino;
631: long ifid_start;
632: };
633:
634: int
635: udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
636: {
637: struct ifid *ifhp;
638: struct vnode *nvp;
639: int error;
640:
641: ifhp = (struct ifid *)fhp;
642:
643: if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
644: *vpp = NULLVP;
645: return (error);
646: }
647:
648: *vpp = nvp;
649:
650: return (0);
651: }
652:
653: int
654: udf_vptofh(struct vnode *vp, struct fid *fhp)
655: {
656: struct unode *up;
657: struct ifid *ifhp;
658:
659: up = VTOU(vp);
660: ifhp = (struct ifid *)fhp;
661: ifhp->ifid_len = sizeof(struct ifid);
662: ifhp->ifid_ino = up->u_ino;
663:
664: return (0);
665: }
666:
667: int
668: udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
669: size_t newlen, struct proc *p)
670: {
671: return (EINVAL);
672: }
673:
674: int
675: udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
676: struct ucred **credanonp)
677: {
678: return (EACCES); /* For the time being */
679: }
680:
681: /* Handle a virtual partition map */
682: int
683: udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv)
684: {
685: ump->um_flags |= UDF_MNT_FIND_VAT; /* Should do more than this */
686: return (0);
687: }
688:
689: /* Handle a sparable partition map */
690: int
691: udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
692: {
693: struct buf *bp;
694: int i, error;
695:
696: ump->um_stbl = malloc(letoh32(pms->st_size), M_UDFMOUNT, M_NOWAIT);
697: if (ump->um_stbl == NULL)
698: return (ENOMEM);
699:
700: bzero(ump->um_stbl, letoh32(pms->st_size));
701:
702: /* Calculate the number of sectors per packet */
703: ump->um_psecs = letoh16(pms->packet_len) / ump->um_bsize;
704:
705: error = udf_readlblks(ump, letoh32(pms->st_loc[0]),
706: letoh32(pms->st_size), &bp);
707:
708: if (error) {
709: if (bp != NULL)
710: brelse(bp);
711: free(ump->um_stbl, M_UDFMOUNT);
712: return (error); /* Failed to read sparing table */
713: }
714:
715: bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size));
716: brelse(bp);
717:
718: if (udf_checktag(&ump->um_stbl->tag, 0)) {
719: free(ump->um_stbl, M_UDFMOUNT);
720: return (EINVAL); /* Invalid sparing table found */
721: }
722:
723: /*
724: * See how many valid entries there are here. The list is
725: * supposed to be sorted, 0xfffffff0 and higher are not valid.
726: */
727: for (i = 0; i < letoh16(ump->um_stbl->rt_l); i++) {
728: ump->um_stbl_len = i;
729: if (letoh32(ump->um_stbl->entries[i].org) >= 0xfffffff0)
730: break;
731: }
732:
733: return (0);
734: }
735:
736: /* Scan the partition maps */
737: int
738: udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd)
739: {
740: struct regid *pmap_id;
741: unsigned char regid_id[UDF_REGID_ID_SIZE + 1];
742: int i, ptype, psize, error;
743: uint8_t *pmap = (uint8_t *) &lvd->maps[0];
744:
745: for (i = 0; i < letoh32(lvd->n_pm); i++) {
746: ptype = pmap[0];
747: psize = pmap[1];
748:
749: if (ptype != 1 && ptype != 2)
750: return (EINVAL); /* Invalid partition map type */
751:
752: if (psize != UDF_PMAP_TYPE1_SIZE &&
753: psize != UDF_PMAP_TYPE2_SIZE)
754: return (EINVAL); /* Invalid partition map size */
755:
756: if (ptype == 1) {
757: pmap += UDF_PMAP_TYPE1_SIZE;
758: continue;
759: }
760:
761: /* Type 2 map. Find out the details */
762: pmap_id = (struct regid *) &pmap[4];
763: regid_id[UDF_REGID_ID_SIZE] = '\0';
764: bcopy(&pmap_id->id[0], ®id_id[0], UDF_REGID_ID_SIZE);
765:
766: if (!bcmp(®id_id[0], "*UDF Virtual Partition",
767: UDF_REGID_ID_SIZE))
768: error = udf_get_vpartmap(ump,
769: (struct part_map_virt *) pmap);
770: else if (!bcmp(®id_id[0], "*UDF Sparable Partition",
771: UDF_REGID_ID_SIZE))
772: error = udf_get_spartmap(ump,
773: (struct part_map_spare *) pmap);
774: else
775: return (EINVAL); /* Unsupported partition map */
776:
777: if (error)
778: return (error); /* Error getting partition */
779:
780: pmap += UDF_PMAP_TYPE2_SIZE;
781: }
782:
783: return (0);
784: }
CVSweb