File: | isofs/udf/udf_subr.c |
Warning: | line 158, column 6 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: udf_subr.c,v 1.25 2014/12/16 18:30:03 tedu 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/lock.h> | |||
39 | #include <sys/dirent.h> | |||
40 | #include <sys/disklabel.h> | |||
41 | ||||
42 | #include <crypto/siphash.h> | |||
43 | ||||
44 | #include <isofs/udf/ecma167-udf.h> | |||
45 | #include <isofs/udf/udf.h> | |||
46 | #include <isofs/udf/udf_extern.h> | |||
47 | ||||
48 | int udf_vat_read(struct umount *, uint32_t *); | |||
49 | ||||
50 | /* | |||
51 | * Convert a CS0 dstring to a 16-bit Unicode string. | |||
52 | * Returns the length of the Unicode string, in unicode characters (not | |||
53 | * bytes!), or -1 if an error arises. | |||
54 | * Note that the transname destination buffer is expected to be large | |||
55 | * enough to hold the result, and will not be terminated in any way. | |||
56 | */ | |||
57 | int | |||
58 | udf_rawnametounicode(u_int len, char *cs0string, unicode_t *transname) | |||
59 | { | |||
60 | unicode_t *origname = transname; | |||
61 | ||||
62 | if (len-- == 0) | |||
63 | return (-1); | |||
64 | ||||
65 | switch (*cs0string++) { | |||
66 | case 8: /* bytes string */ | |||
67 | while (len-- != 0) | |||
68 | *transname++ = (unicode_t)*cs0string++; | |||
69 | break; | |||
70 | case 16: /* 16 bit unicode string */ | |||
71 | if (len & 1) | |||
72 | return (-1); | |||
73 | len >>= 1; | |||
74 | while (len-- != 0) { | |||
75 | unicode_t tmpchar; | |||
76 | ||||
77 | tmpchar = (unicode_t)*cs0string++; | |||
78 | tmpchar = (tmpchar << 8) | (unicode_t)*cs0string++; | |||
79 | *transname++ = tmpchar; | |||
80 | } | |||
81 | break; | |||
82 | default: | |||
83 | return (-1); | |||
84 | } | |||
85 | ||||
86 | return (transname - origname); | |||
87 | } | |||
88 | ||||
89 | /* | |||
90 | * Do a lazy probe on the underlying media to check if it's a UDF volume, in | |||
91 | * which case we fake a disk label for it. | |||
92 | */ | |||
93 | int | |||
94 | udf_disklabelspoof(dev_t dev, void (*strat)(struct buf *), | |||
95 | struct disklabel *lp) | |||
96 | { | |||
97 | char vid[32]; | |||
98 | int i, bsize = 2048, error = EINVAL22; | |||
99 | uint32_t sector = 256, mvds_start, mvds_end; | |||
100 | struct buf *bp; | |||
101 | struct anchor_vdp avdp; | |||
102 | struct pri_vol_desc *pvd; | |||
103 | ||||
104 | /* | |||
105 | * Get a buffer to work with. | |||
106 | */ | |||
107 | bp = geteblk(bsize); | |||
108 | bp->b_dev = dev; | |||
109 | ||||
110 | /* | |||
111 | * Look for an Anchor Volume Descriptor at sector 256. | |||
112 | */ | |||
113 | bp->b_blkno = sector * btodb(bsize)((bsize) >> 9); | |||
114 | bp->b_bcount = bsize; | |||
115 | CLR(bp->b_flags, B_READ | B_WRITE | B_DONE)((bp->b_flags) &= ~(0x00008000 | 0x00000000 | 0x00000100 )); | |||
116 | SET(bp->b_flags, B_BUSY | B_READ | B_RAW)((bp->b_flags) |= (0x00000010 | 0x00008000 | 0x00004000)); | |||
117 | bp->b_resid = bp->b_blkno / lp->d_secpercyl; | |||
118 | ||||
119 | (*strat)(bp); | |||
120 | if (biowait(bp)) | |||
| ||||
121 | goto out; | |||
122 | ||||
123 | if (udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)) | |||
124 | goto out; | |||
125 | ||||
126 | bcopy(bp->b_data, &avdp, sizeof(avdp)); | |||
127 | mvds_start = letoh32(avdp.main_vds_ex.loc)((__uint32_t)(avdp.main_vds_ex.loc)); | |||
128 | mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len)((__uint32_t)(avdp.main_vds_ex.len)) - 1) / bsize; | |||
129 | ||||
130 | /* | |||
131 | * Then try to find a reference to a Primary Volume Descriptor. | |||
132 | */ | |||
133 | for (sector = mvds_start; sector < mvds_end; sector++) { | |||
134 | bp->b_blkno = sector * btodb(bsize)((bsize) >> 9); | |||
135 | bp->b_bcount = bsize; | |||
136 | CLR(bp->b_flags, B_READ | B_WRITE | B_DONE)((bp->b_flags) &= ~(0x00008000 | 0x00000000 | 0x00000100 )); | |||
137 | SET(bp->b_flags, B_BUSY | B_READ | B_RAW)((bp->b_flags) |= (0x00000010 | 0x00008000 | 0x00004000)); | |||
138 | bp->b_resid = bp->b_blkno / lp->d_secpercyl; | |||
139 | ||||
140 | (*strat)(bp); | |||
141 | if (biowait(bp)) | |||
142 | goto out; | |||
143 | ||||
144 | pvd = (struct pri_vol_desc *)bp->b_data; | |||
145 | if (!udf_checktag(&pvd->tag, TAGID_PRI_VOL)) | |||
146 | break; | |||
147 | } | |||
148 | ||||
149 | /* | |||
150 | * If we couldn't find a reference, bail out. | |||
151 | */ | |||
152 | if (sector == mvds_end) | |||
153 | goto out; | |||
154 | ||||
155 | /* | |||
156 | * Okay, it's a UDF volume. Spoof a disk label for it. | |||
157 | */ | |||
158 | if (udf_transname(pvd->vol_id, vid, sizeof(pvd->vol_id) - 1, NULL((void *)0))) | |||
| ||||
159 | strlcpy(lp->d_typename, vid, sizeof(lp->d_typename)); | |||
160 | ||||
161 | for (i = 0; i < MAXPARTITIONS16; i++) { | |||
162 | DL_SETPSIZE(&lp->d_partitions[i], 0)do { u_int64_t __x = (0); (&lp->d_partitions[i])->p_sizeh = __x >> 32; (&lp->d_partitions[i])->p_size = __x; } while (0); | |||
163 | DL_SETPOFFSET(&lp->d_partitions[i], 0)do { u_int64_t __x = (0); (&lp->d_partitions[i])->p_offseth = __x >> 32; (&lp->d_partitions[i])->p_offset = __x; } while (0); | |||
164 | } | |||
165 | ||||
166 | /* | |||
167 | * Fake two partitions, 'a' and 'c'. | |||
168 | */ | |||
169 | DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp))do { u_int64_t __x = ((((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit)); (&lp->d_partitions[0]) ->p_sizeh = __x >> 32; (&lp->d_partitions[0]) ->p_size = __x; } while (0); | |||
170 | lp->d_partitions[0].p_fstype = FS_UDF21; | |||
171 | DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp))do { u_int64_t __x = ((((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit)); (&lp->d_partitions[2]) ->p_sizeh = __x >> 32; (&lp->d_partitions[2]) ->p_size = __x; } while (0); | |||
172 | lp->d_partitions[RAW_PART2].p_fstype = FS_UDF21; | |||
173 | lp->d_npartitions = MAXPARTITIONS16; | |||
174 | lp->d_version = 1; | |||
175 | ||||
176 | lp->d_bbsize = 8192; /* Fake. */ | |||
177 | lp->d_sbsize = 64*1024; /* Fake. */ | |||
178 | lp->d_magic = DISKMAGIC((u_int32_t)0x82564557); | |||
179 | lp->d_magic2 = DISKMAGIC((u_int32_t)0x82564557); | |||
180 | lp->d_checksum = dkcksum(lp); | |||
181 | ||||
182 | error = 0; | |||
183 | out: | |||
184 | bp->b_flags |= B_INVAL0x00000800; | |||
185 | brelse(bp); | |||
186 | ||||
187 | return (error); | |||
188 | } | |||
189 | ||||
190 | /* Get a vnode for the Virtual Allocation Table (VAT) */ | |||
191 | int | |||
192 | udf_vat_get(struct umount *ump, uint32_t lb) | |||
193 | { | |||
194 | struct vnode *vp; | |||
195 | struct unode *up; | |||
196 | int error; | |||
197 | ||||
198 | error = udf_vget(ump->um_mountp, lb - ump->um_start - 3, &vp); | |||
199 | if (error) | |||
200 | return (error); | |||
201 | ||||
202 | up = VTOU(vp)((struct unode *)((vp)->v_data)); | |||
203 | up->u_vatlenun_u.u_vatlen = (letoh64(up->u_fentry->inf_len)((__uint64_t)(up->u_fentry->inf_len)) - 36) >> 2; | |||
204 | ||||
205 | ump->um_vat = malloc(sizeof(struct unode), M_UDFMOUNT140, M_WAITOK0x0001); | |||
206 | *ump->um_vat = *up; | |||
207 | ||||
208 | ump->um_flags &= ~UDF_MNT_FIND_VAT0x01; | |||
209 | ump->um_flags |= UDF_MNT_USES_VAT0x02; | |||
210 | ||||
211 | vput(vp); | |||
212 | ||||
213 | return (0); | |||
214 | } | |||
215 | ||||
216 | /* Look up a sector in the VAT */ | |||
217 | int | |||
218 | udf_vat_map(struct umount *ump, uint32_t *sector) | |||
219 | { | |||
220 | /* If there's no VAT, then it's easy */ | |||
221 | if (!(ump->um_flags & UDF_MNT_USES_VAT0x02)) { | |||
222 | *sector += ump->um_start; | |||
223 | return (0); | |||
224 | } | |||
225 | ||||
226 | /* Sanity check the given sector */ | |||
227 | if (*sector >= ump->um_vat->u_vatlenun_u.u_vatlen) | |||
228 | return (EINVAL22); | |||
229 | ||||
230 | return (udf_vat_read(ump, sector)); | |||
231 | } | |||
232 | ||||
233 | /* Read from the VAT */ | |||
234 | int | |||
235 | udf_vat_read(struct umount *ump, uint32_t *sector) | |||
236 | { | |||
237 | struct buf *bp; | |||
238 | uint8_t *data; | |||
239 | int error, size; | |||
240 | ||||
241 | size = 4; | |||
242 | ||||
243 | /* | |||
244 | * Note that we rely on the buffer cache to keep frequently accessed | |||
245 | * buffers around to avoid reading them from the disk all the time. | |||
246 | */ | |||
247 | error = udf_readatoffset(ump->um_vat, &size, *sector << 2, &bp, &data); | |||
248 | if (error) { | |||
249 | if (bp != NULL((void *)0)) | |||
250 | brelse(bp); | |||
251 | ||||
252 | return (error); | |||
253 | } | |||
254 | ||||
255 | /* Make sure we read at least a whole entry */ | |||
256 | if (size < 4) { | |||
257 | if (bp != NULL((void *)0)) | |||
258 | brelse(bp); | |||
259 | ||||
260 | return (EINVAL22); | |||
261 | } | |||
262 | ||||
263 | /* Map the sector */ | |||
264 | *sector = letoh32(*(uint32_t *)data)((__uint32_t)(*(uint32_t *)data)) + ump->um_start; | |||
265 | ||||
266 | brelse(bp); | |||
267 | ||||
268 | return (0); | |||
269 | } |