Annotation of sys/isofs/udf/udf_subr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: udf_subr.c,v 1.13 2007/06/08 05:35:32 deraadt Exp $ */
2:
3: /*
4: * Copyright (c) 2006, Miodrag Vallat
5: * Copyright (c) 2006, Pedro Martelletto
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 ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: #include <sys/param.h>
30: #include <sys/systm.h>
31: #include <sys/buf.h>
32: #include <sys/kernel.h>
33: #include <sys/malloc.h>
34: #include <sys/mutex.h>
35: #include <sys/stat.h>
36: #include <sys/mount.h>
37: #include <sys/vnode.h>
38: #include <sys/dirent.h>
39: #include <sys/unistd.h>
40: #include <sys/disklabel.h>
41:
42: #include <isofs/udf/ecma167-udf.h>
43: #include <isofs/udf/udf.h>
44: #include <isofs/udf/udf_extern.h>
45:
46: int udf_vat_read(struct umount *, uint32_t *);
47:
48: /*
49: * Convert a CS0 dstring to a 16-bit Unicode string.
50: * Returns the length of the Unicode string, in unicode characters (not
51: * bytes!), or -1 if an error arises.
52: * Note that the transname destination buffer is expected to be large
53: * enough to hold the result, and will not be terminated in any way.
54: */
55: int
56: udf_rawnametounicode(u_int len, char *cs0string, unicode_t *transname)
57: {
58: unicode_t *origname = transname;
59:
60: if (len-- == 0)
61: return (-1);
62:
63: switch (*cs0string++) {
64: case 8: /* bytes string */
65: while (len-- != 0)
66: *transname++ = (unicode_t)*cs0string++;
67: break;
68: case 16: /* 16 bit unicode string */
69: if (len & 1)
70: return (-1);
71: len >>= 1;
72: while (len-- != 0) {
73: unicode_t tmpchar;
74:
75: tmpchar = (unicode_t)*cs0string++;
76: tmpchar = (tmpchar << 8) | (unicode_t)*cs0string++;
77: *transname++ = tmpchar;
78: }
79: break;
80: default:
81: return (-1);
82: }
83:
84: return (transname - origname);
85: }
86:
87: /*
88: * Do a lazy probe on the underlying media to check if it's a UDF volume, in
89: * which case we fake a disk label for it.
90: */
91: int
92: udf_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
93: struct disklabel *lp)
94: {
95: char vid[32];
96: int i, bsize = 2048, error = EINVAL;
97: uint32_t sector = 256, mvds_start, mvds_end;
98: struct buf *bp;
99: struct anchor_vdp avdp;
100: struct pri_vol_desc *pvd;
101:
102: /*
103: * Get a buffer to work with.
104: */
105: bp = geteblk(bsize);
106: bp->b_dev = dev;
107:
108: /*
109: * Look for an Anchor Volume Descriptor at sector 256.
110: */
111: bp->b_blkno = sector * btodb(bsize);
112: bp->b_bcount = bsize;
113: bp->b_flags = B_BUSY | B_READ;
114: bp->b_resid = bp->b_blkno / lp->d_secpercyl;
115:
116: (*strat)(bp);
117: if (biowait(bp))
118: goto out;
119:
120: if (udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR))
121: goto out;
122:
123: bcopy(bp->b_data, &avdp, sizeof(avdp));
124: mvds_start = letoh32(avdp.main_vds_ex.loc);
125: mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;
126:
127: /*
128: * Then try to find a reference to a Primary Volume Descriptor.
129: */
130: for (sector = mvds_start; sector < mvds_end; sector++) {
131: bp->b_blkno = sector * btodb(bsize);
132: bp->b_bcount = bsize;
133: bp->b_flags = B_BUSY | B_READ;
134: bp->b_resid = bp->b_blkno / lp->d_secpercyl;
135:
136: (*strat)(bp);
137: if (biowait(bp))
138: goto out;
139:
140: pvd = (struct pri_vol_desc *)bp->b_data;
141: if (!udf_checktag(&pvd->tag, TAGID_PRI_VOL))
142: break;
143: }
144:
145: /*
146: * If we couldn't find a reference, bail out.
147: */
148: if (sector == mvds_end)
149: goto out;
150:
151: /*
152: * Okay, it's a UDF volume. Spoof a disk label for it.
153: */
154: if (udf_transname(pvd->vol_id, vid, sizeof(pvd->vol_id) - 1, NULL))
155: strlcpy(lp->d_typename, vid, sizeof(lp->d_typename));
156:
157: for (i = 0; i < MAXPARTITIONS; i++) {
158: DL_SETPSIZE(&lp->d_partitions[i], 0);
159: DL_SETPOFFSET(&lp->d_partitions[i], 0);
160: }
161:
162: /*
163: * Fake two partitions, 'a' and 'c'.
164: */
165: DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp));
166: lp->d_partitions[0].p_fstype = FS_UDF;
167: DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
168: lp->d_partitions[RAW_PART].p_fstype = FS_UDF;
169: lp->d_npartitions = RAW_PART + 1;
170: lp->d_version = 1;
171:
172: lp->d_bbsize = 8192; /* Fake. */
173: lp->d_sbsize = 64*1024; /* Fake. */
174: lp->d_magic = DISKMAGIC;
175: lp->d_magic2 = DISKMAGIC;
176: lp->d_checksum = dkcksum(lp);
177:
178: error = 0;
179: out:
180: bp->b_flags |= B_INVAL;
181: brelse(bp);
182:
183: return (error);
184: }
185:
186: /* Get a vnode for the Virtual Allocation Table (VAT) */
187: int
188: udf_vat_get(struct umount *ump, uint32_t lb)
189: {
190: struct vnode *vp;
191: struct unode *up;
192: int error;
193:
194: error = udf_vget(ump->um_mountp, lb - ump->um_start - 3, &vp);
195: if (error)
196: return (error);
197:
198: up = VTOU(vp);
199: up->u_vatlen = (letoh64(up->u_fentry->inf_len) - 36) >> 2;
200:
201: ump->um_vat = malloc(sizeof(struct unode), M_UDFMOUNT, M_WAITOK);
202: *ump->um_vat = *up;
203:
204: ump->um_flags &= ~UDF_MNT_FIND_VAT;
205: ump->um_flags |= UDF_MNT_USES_VAT;
206:
207: vput(vp);
208:
209: return (0);
210: }
211:
212: /* Look up a sector in the VAT */
213: int
214: udf_vat_map(struct umount *ump, uint32_t *sector)
215: {
216: /* If there's no VAT, then it's easy */
217: if (!(ump->um_flags & UDF_MNT_USES_VAT)) {
218: *sector += ump->um_start;
219: return (0);
220: }
221:
222: /* Sanity check the given sector */
223: if (*sector >= ump->um_vat->u_vatlen)
224: return (EINVAL);
225:
226: return (udf_vat_read(ump, sector));
227: }
228:
229: /* Read from the VAT */
230: int
231: udf_vat_read(struct umount *ump, uint32_t *sector)
232: {
233: struct buf *bp;
234: uint8_t *data;
235: int error, size;
236:
237: size = 4;
238:
239: /*
240: * Note that we rely on the buffer cache to keep frequently accessed
241: * buffers around to avoid reading them from the disk all the time.
242: */
243: error = udf_readatoffset(ump->um_vat, &size, *sector << 2, &bp, &data);
244: if (error) {
245: if (bp != NULL)
246: brelse(bp);
247:
248: return (error);
249: }
250:
251: /* Make sure we read at least a whole entry */
252: if (size < 4) {
253: if (bp != NULL)
254: brelse(bp);
255:
256: return (EINVAL);
257: }
258:
259: /* Map the sector */
260: *sector = letoh32(*(uint32_t *)data) + ump->um_start;
261:
262: brelse(bp);
263:
264: return (0);
265: }
CVSweb