Bug Summary

File:isofs/udf/udf_vfsops.c
Warning:line 327, column 8
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name udf_vfsops.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/isofs/udf/udf_vfsops.c
1/* $OpenBSD: udf_vfsops.c,v 1.70 2022/01/11 03:13:59 jsg 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 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 demonstrates 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/param.h>
50#include <sys/systm.h>
51#include <sys/uio.h>
52#include <sys/buf.h>
53#include <sys/dirent.h>
54#include <sys/fcntl.h>
55#include <sys/kernel.h>
56#include <sys/malloc.h>
57#include <sys/mutex.h>
58#include <sys/mount.h>
59#include <sys/namei.h>
60#include <sys/pool.h>
61#include <sys/proc.h>
62#include <sys/lock.h>
63#include <sys/queue.h>
64#include <sys/vnode.h>
65#include <sys/lock.h>
66#include <sys/endian.h>
67#include <sys/specdev.h>
68
69#include <crypto/siphash.h>
70
71#include <isofs/udf/ecma167-udf.h>
72#include <isofs/udf/udf.h>
73#include <isofs/udf/udf_extern.h>
74
75struct pool udf_trans_pool;
76struct pool unode_pool;
77struct pool udf_ds_pool;
78
79int udf_find_partmaps(struct umount *, struct logvol_desc *);
80int udf_get_vpartmap(struct umount *, struct part_map_virt *);
81int udf_get_spartmap(struct umount *, struct part_map_spare *);
82int udf_get_mpartmap(struct umount *, struct part_map_meta *);
83int udf_mountfs(struct vnode *, struct mount *, uint32_t, struct proc *);
84
85const struct vfsops udf_vfsops = {
86 .vfs_mount = udf_mount,
87 .vfs_start = udf_start,
88 .vfs_unmount = udf_unmount,
89 .vfs_root = udf_root,
90 .vfs_quotactl = udf_quotactl,
91 .vfs_statfs = udf_statfs,
92 .vfs_sync = udf_sync,
93 .vfs_vget = udf_vget,
94 .vfs_fhtovp = udf_fhtovp,
95 .vfs_vptofh = udf_vptofh,
96 .vfs_init = udf_init,
97 .vfs_sysctl = udf_sysctl,
98 .vfs_checkexp = udf_checkexp,
99};
100
101int
102udf_init(struct vfsconf *foo)
103{
104 pool_init(&udf_trans_pool, MAXNAMLEN255 * sizeof(unicode_t), 0, IPL_NONE0x0,
105 PR_WAITOK0x0001, "udftrpl", NULL((void *)0));
106 pool_init(&unode_pool, sizeof(struct unode), 0, IPL_NONE0x0,
107 PR_WAITOK0x0001, "udfndpl", NULL((void *)0));
108 pool_init(&udf_ds_pool, sizeof(struct udf_dirstream), 0, IPL_NONE0x0,
109 PR_WAITOK0x0001, "udfdspl", NULL((void *)0));
110
111 return (0);
112}
113
114int
115udf_start(struct mount *mp, int flags, struct proc *p)
116{
117 return (0);
118}
119
120int
121udf_mount(struct mount *mp, const char *path, void *data,
122 struct nameidata *ndp, struct proc *p)
123{
124 struct vnode *devvp; /* vnode of the mount device */
125 struct udf_args *args = data;
126 char fspec[MNAMELEN90];
127 int error;
128
129 if ((mp->mnt_flag & MNT_RDONLY0x00000001) == 0) {
130 mp->mnt_flag |= MNT_RDONLY0x00000001;
131#ifdef UDF_DEBUG
132 printf("udf_mount: enforcing read-only mode\n");
133#endif
134 }
135
136 /*
137 * No root filesystem support. Probably not a big deal, since the
138 * bootloader doesn't understand UDF.
139 */
140 if (mp->mnt_flag & MNT_ROOTFS0x00004000)
141 return (EOPNOTSUPP45);
142
143 /*
144 * If updating, check whether changing from read-only to
145 * read/write; if there is no device name, that's all we do.
146 */
147 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
148 return (0);
149 }
150
151 error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL((void *)0));
152 if (error)
153 return (error);
154
155 NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p)ndinitat(ndp, 0, 0x0040, UIO_SYSSPACE, -100, fspec, p);
156 if ((error = namei(ndp)))
157 return (error);
158
159 devvp = ndp->ni_vp;
160 if (devvp->v_type != VBLK) {
161 vrele(devvp);
162 return (ENOTBLK15);
163 }
164
165 if (major(devvp->v_rdev)(((unsigned)(devvp->v_un.vu_specinfo->si_rdev) >>
8) & 0xff)
>= nblkdev) {
166 vrele(devvp);
167 return (ENXIO6);
168 }
169
170 if ((error = udf_mountfs(devvp, mp, args->lastblock, p))) {
171 vrele(devvp);
172 return (error);
173 }
174
175 /*
176 * Keep a copy of the mount information.
177 */
178 bzero(mp->mnt_stat.f_mntonname, MNAMELEN)__builtin_bzero((mp->mnt_stat.f_mntonname), (90));
179 strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN90);
180 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN)__builtin_bzero((mp->mnt_stat.f_mntfromname), (90));
181 strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN90);
182 bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN)__builtin_bzero((mp->mnt_stat.f_mntfromspec), (90));
183 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN90);
184
185 return (0);
186};
187
188/*
189 * Check the descriptor tag for both the correct id and correct checksum.
190 * Return zero if all is good, EINVAL if not.
191 */
192int
193udf_checktag(struct desc_tag *tag, uint16_t id)
194{
195 uint8_t *itag;
196 uint8_t i, cksum = 0;
197
198 itag = (uint8_t *)tag;
199
200 if (letoh16(tag->id)((__uint16_t)(tag->id)) != id)
201 return (EINVAL22);
202
203 for (i = 0; i < 15; i++)
204 cksum = cksum + itag[i];
205 cksum = cksum - itag[4];
206
207 if (cksum == tag->cksum)
208 return (0);
209
210 return (EINVAL22);
211}
212
213int
214udf_mountfs(struct vnode *devvp, struct mount *mp, uint32_t lb, struct proc *p)
215{
216 struct buf *bp = NULL((void *)0);
217 struct anchor_vdp avdp;
218 struct umount *ump = NULL((void *)0);
219 struct part_desc *pd;
220 struct logvol_desc *lvd;
221 struct fileset_desc *fsd;
222 struct extfile_entry *xfentry;
223 struct file_entry *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 = EINVAL22;
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 (EBUSY16);
241 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
242 error = vinvalbuf(devvp, V_SAVE0x0001, p->p_ucred, p, 0, INFSLP0xffffffffffffffffULL);
243 VOP_UNLOCK(devvp);
244 if (error)
245 return (error);
246
247 error = VOP_OPEN(devvp, FREAD0x0001, FSCRED((struct ucred *)-2), p);
248 if (error)
249 return (error);
250
251 ump = malloc(sizeof(*ump), M_UDFMOUNT140, M_WAITOK0x0001 | M_ZERO0x0008);
252
253 mp->mnt_data = ump;
254 mp->mnt_stat.f_fsid.val[0] = devvp->v_rdevv_un.vu_specinfo->si_rdev;
255 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
256 mp->mnt_stat.f_namemax = NAME_MAX255;
257 mp->mnt_flag |= MNT_LOCAL0x00001000;
258
259 ump->um_mountp = mp;
260 ump->um_dev = devvp->v_rdevv_un.vu_specinfo->si_rdev;
261 ump->um_devvp = devvp;
262
263 bsize = 2048; /* Should probe the media for its size. */
264
265 /*
266 * Get the Anchor Volume Descriptor Pointer from sector 256.
267 * Should also check sector n - 256, n, and 512.
268 */
269 sector = 256;
270 if ((error = bread(devvp, sector * btodb(bsize)((bsize) >> 9), bsize, &bp)) != 0)
271 goto bail;
272 if ((error = udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)))
273 goto bail;
274
275 bcopy(bp->b_data, &avdp, sizeof(struct anchor_vdp));
276 brelse(bp);
277 bp = NULL((void *)0);
278
279 /*
280 * Extract the Partition Descriptor and Logical Volume Descriptor
281 * from the Volume Descriptor Sequence.
282 * Should we care about the partition type right now?
283 * What about multiple partitions?
284 */
285 mvds_start = letoh32(avdp.main_vds_ex.loc)((__uint32_t)(avdp.main_vds_ex.loc));
286 mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len)((__uint32_t)(avdp.main_vds_ex.len)) - 1) / bsize;
287 for (sector = mvds_start; sector < mvds_end; sector++) {
288 if ((error = bread(devvp, sector * btodb(bsize)((bsize) >> 9), bsize,
289 &bp)) != 0) {
290 printf("Can't read sector %d of VDS\n", sector);
291 goto bail;
292 }
293 lvd = (struct logvol_desc *)bp->b_data;
294 if (!udf_checktag(&lvd->tag, TAGID_LOGVOL)) {
295 ump->um_bsize = letoh32(lvd->lb_size)((__uint32_t)(lvd->lb_size));
296 ump->um_bmask = ump->um_bsize - 1;
297 ump->um_bshift = ffs(ump->um_bsize) - 1;
298 fsd_part = letoh16(lvd->_lvd_use.fsd_loc.loc.part_num)((__uint16_t)(lvd->_lvd_use.fsd_loc.loc.part_num));
299 fsd_offset = letoh32(lvd->_lvd_use.fsd_loc.loc.lb_num)((__uint32_t)(lvd->_lvd_use.fsd_loc.loc.lb_num));
300 if (udf_find_partmaps(ump, lvd))
301 break;
302 logvol_found = 1;
303 }
304 pd = (struct part_desc *)bp->b_data;
305 if (!udf_checktag(&pd->tag, TAGID_PARTITION)) {
306 part_found = 1;
307 part_num = letoh16(pd->part_num)((__uint16_t)(pd->part_num));
308 ump->um_len = ump->um_reallen = letoh32(pd->part_len)((__uint32_t)(pd->part_len));
309 ump->um_start = ump->um_realstart = letoh32(pd->start_loc)((__uint32_t)(pd->start_loc));
310 }
311
312 brelse(bp);
313 bp = NULL((void *)0);
314 if ((part_found) && (logvol_found))
315 break;
316 }
317
318 if (!part_found || !logvol_found) {
319 error = EINVAL22;
320 goto bail;
321 }
322
323 if (ISSET(ump->um_flags, UDF_MNT_USES_META)((ump->um_flags) & (0x04))) {
324 /* Read Metadata File 'File Entry' to find Metadata file. */
325 struct long_ad *la;
326 sector = ump->um_start + ump->um_meta_start; /* Set in udf_get_mpartmap() */
327 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)bread(devvp, ((daddr_t)(sector) << ump->um_bshift) /
(1 << 9), ump->um_bsize, &bp)
) != 0) {
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'
328 printf("Cannot read sector %d for Metadata File Entry\n", sector);
329 error = EINVAL22;
330 goto bail;
331 }
332 xfentry = (struct extfile_entry *)bp->b_data;
333 fentry = (struct file_entry *)bp->b_data;
334 if (udf_checktag(&xfentry->tag, TAGID_EXTFENTRY) == 0)
335 la = (struct long_ad *)&xfentry->data[letoh32(xfentry->l_ea)((__uint32_t)(xfentry->l_ea))];
336 else if (udf_checktag(&fentry->tag, TAGID_FENTRY) == 0)
337 la = (struct long_ad *)&fentry->data[letoh32(fentry->l_ea)((__uint32_t)(fentry->l_ea))];
338 else {
339 printf("Invalid Metadata File FE @ sector %d! (tag.id %d)\n",
340 sector, fentry->tag.id);
341 error = EINVAL22;
342 goto bail;
343 }
344 ump->um_meta_start = letoh32(la->loc.lb_num)((__uint32_t)(la->loc.lb_num));
345 ump->um_meta_len = letoh32(la->len)((__uint32_t)(la->len));
346 if (bp != NULL((void *)0)) {
347 brelse(bp);
348 bp = NULL((void *)0);
349 }
350 } else if (fsd_part != part_num) {
351 printf("FSD does not lie within the partition!\n");
352 error = EINVAL22;
353 goto bail;
354 }
355
356 mtx_init(&ump->um_hashmtx, IPL_NONE)do { (void)(((void *)0)); (void)(0); __mtx_init((&ump->
um_hashmtx), ((((0x0)) > 0x0 && ((0x0)) < 0x9) ?
0x9 : ((0x0)))); } while (0)
;
357 ump->um_hashtbl = hashinit(UDF_HASHTBLSIZE100, M_UDFMOUNT140, M_WAITOK0x0001,
358 &ump->um_hashsz);
359 arc4random_buf(&ump->um_hashkey, sizeof(ump->um_hashkey));
360
361 /* Get the VAT, if needed */
362 if (ump->um_flags & UDF_MNT_FIND_VAT0x01) {
363 error = udf_vat_get(ump, lb);
364 if (error)
365 goto bail;
366 }
367
368 /*
369 * Grab the Fileset Descriptor
370 * Thanks to Chuck McCrobie <mccrobie@cablespeed.com> for pointing
371 * me in the right direction here.
372 */
373
374 if (ISSET(ump->um_flags, UDF_MNT_USES_META)((ump->um_flags) & (0x04)))
375 sector = ump->um_meta_start;
376 else
377 sector = fsd_offset;
378 udf_vat_map(ump, &sector);
379 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)bread(devvp, ((daddr_t)(sector) << ump->um_bshift) /
(1 << 9), ump->um_bsize, &bp)
) != 0) {
380 printf("Cannot read sector %d of FSD\n", sector);
381 goto bail;
382 }
383 fsd = (struct fileset_desc *)bp->b_data;
384 if (!udf_checktag(&fsd->tag, TAGID_FSD)) {
385 fsd_found = 1;
386 bcopy(&fsd->rootdir_icb, &ump->um_root_icb,
387 sizeof(struct long_ad));
388 if (ISSET(ump->um_flags, UDF_MNT_USES_META)((ump->um_flags) & (0x04))) {
389 ump->um_root_icb.loc.lb_num += ump->um_meta_start;
390 ump->um_root_icb.loc.part_num = part_num;
391 }
392 }
393
394 brelse(bp);
395 bp = NULL((void *)0);
396
397 if (!fsd_found) {
398 printf("Couldn't find the fsd\n");
399 error = EINVAL22;
400 goto bail;
401 }
402
403 /*
404 * Find the file entry for the root directory.
405 */
406 sector = letoh32(ump->um_root_icb.loc.lb_num)((__uint32_t)(ump->um_root_icb.loc.lb_num));
407 size = letoh32(ump->um_root_icb.len)((__uint32_t)(ump->um_root_icb.len));
408 udf_vat_map(ump, &sector);
409 if ((error = udf_readlblks(ump, sector, size, &bp)) != 0) {
410 printf("Cannot read sector %d\n", sector);
411 goto bail;
412 }
413
414 xfentry = (struct extfile_entry *)bp->b_data;
415 fentry = (struct file_entry *)bp->b_data;
416 error = udf_checktag(&xfentry->tag, TAGID_EXTFENTRY);
417 if (error) {
418 error = udf_checktag(&fentry->tag, TAGID_FENTRY);
419 if (error) {
420 printf("Invalid root file entry!\n");
421 goto bail;
422 }
423 }
424
425 brelse(bp);
426 bp = NULL((void *)0);
427
428 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = mp;
429
430 return (0);
431
432bail:
433 if (ump != NULL((void *)0)) {
434 hashfree(ump->um_hashtbl, UDF_HASHTBLSIZE100, M_UDFMOUNT140);
435 free(ump, M_UDFMOUNT140, 0);
436 mp->mnt_data = NULL((void *)0);
437 mp->mnt_flag &= ~MNT_LOCAL0x00001000;
438 }
439 if (devvp->v_specinfov_un.vu_specinfo)
440 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = NULL((void *)0);
441 if (bp != NULL((void *)0))
442 brelse(bp);
443
444 vn_lock(devvp, LK_EXCLUSIVE0x0001UL|LK_RETRY0x2000UL);
445 VOP_CLOSE(devvp, FREAD0x0001, FSCRED((struct ucred *)-2), p);
446 VOP_UNLOCK(devvp);
447
448 return (error);
449}
450
451int
452udf_unmount(struct mount *mp, int mntflags, struct proc *p)
453{
454 struct umount *ump;
455 struct vnode *devvp;
456 int error, flags = 0;
457
458 ump = VFSTOUDFFS(mp)((struct umount *)((mp)->mnt_data));
459 devvp = ump->um_devvp;
460
461 if (mntflags & MNT_FORCE0x00080000)
462 flags |= FORCECLOSE0x0002;
463
464 if ((error = vflush(mp, NULL((void *)0), flags)))
465 return (error);
466
467 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
468 vinvalbuf(devvp, V_SAVE0x0001, NOCRED((struct ucred *)-1), p, 0, INFSLP0xffffffffffffffffULL);
469 (void)VOP_CLOSE(devvp, FREAD0x0001, NOCRED((struct ucred *)-1), p);
470 VOP_UNLOCK(devvp);
471
472 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = NULL((void *)0);
473 vrele(devvp);
474
475 if (ump->um_flags & UDF_MNT_USES_VAT0x02)
476 free(ump->um_vat, M_UDFMOUNT140, 0);
477
478 if (ump->um_stbl != NULL((void *)0))
479 free(ump->um_stbl, M_UDFMOUNT140, 0);
480
481 hashfree(ump->um_hashtbl, UDF_HASHTBLSIZE100, M_UDFMOUNT140);
482 free(ump, M_UDFMOUNT140, 0);
483
484 mp->mnt_data = NULL((void *)0);
485 mp->mnt_flag &= ~MNT_LOCAL0x00001000;
486
487 return (0);
488}
489
490int
491udf_root(struct mount *mp, struct vnode **vpp)
492{
493 struct umount *ump;
494 struct vnode *vp;
495 udfino_t id;
496 int error;
497
498 ump = VFSTOUDFFS(mp)((struct umount *)((mp)->mnt_data));
499
500 id = udf_getid(&ump->um_root_icb);
501
502 error = udf_vget(mp, id, vpp);
503 if (error)
504 return (error);
505
506 vp = *vpp;
507 vp->v_flag |= VROOT0x0001;
508
509 return (0);
510}
511
512int
513udf_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
514 struct proc *p)
515{
516 return (EOPNOTSUPP45);
517}
518
519int
520udf_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
521{
522 struct umount *ump;
523
524 ump = VFSTOUDFFS(mp)((struct umount *)((mp)->mnt_data));
525
526 sbp->f_bsize = ump->um_bsize;
527 sbp->f_iosize = ump->um_bsize;
528 sbp->f_blocks = ump->um_len;
529 sbp->f_bfree = 0;
530 sbp->f_bavail = 0;
531 sbp->f_files = 0;
532 sbp->f_ffree = 0;
533 sbp->f_favail = 0;
534 copy_statfs_info(sbp, mp);
535
536 return (0);
537}
538
539int
540udf_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p)
541{
542 return (0);
543}
544
545int
546udf_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
547{
548 struct buf *bp;
549 struct vnode *devvp;
550 struct umount *ump;
551 struct proc *p;
552 struct vnode *vp, *nvp;
553 struct unode *up;
554 struct extfile_entry *xfe;
555 struct file_entry *fe;
556 uint32_t sector;
557 int error, size;
558
559 if (ino > (udfino_t)-1)
560 panic("udf_vget: alien ino_t %llu", (unsigned long long)ino);
561
562 p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
;
563 bp = NULL((void *)0);
564 *vpp = NULL((void *)0);
565 ump = VFSTOUDFFS(mp)((struct umount *)((mp)->mnt_data));
566
567 /* See if we already have this in the cache */
568 if ((error = udf_hashlookup(ump, ino, LK_EXCLUSIVE0x0001UL, vpp)) != 0)
569 return (error);
570 if (*vpp != NULL((void *)0))
571 return (0);
572
573 /*
574 * Allocate memory and check the tag id's before grabbing a new
575 * vnode, since it's hard to roll back if there is a problem.
576 */
577 up = pool_get(&unode_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
578
579 /*
580 * Copy in the file entry. Per the spec, the size can only be 1 block.
581 */
582 sector = ino;
583 devvp = ump->um_devvp;
584 udf_vat_map(ump, &sector);
585 if ((error = RDSECTOR(devvp, sector, ump->um_bsize, &bp)bread(devvp, ((daddr_t)(sector) << ump->um_bshift) /
(1 << 9), ump->um_bsize, &bp)
) != 0) {
586 printf("Cannot read sector %d\n", sector);
587 pool_put(&unode_pool, up);
588 if (bp != NULL((void *)0))
589 brelse(bp);
590 return (error);
591 }
592
593 xfe = (struct extfile_entry *)bp->b_data;
594 fe = (struct file_entry *)bp->b_data;
595 error = udf_checktag(&xfe->tag, TAGID_EXTFENTRY);
596 if (error == 0) {
597 size = letoh32(xfe->l_ea)((__uint32_t)(xfe->l_ea)) + letoh32(xfe->l_ad)((__uint32_t)(xfe->l_ad));
598 } else {
599 error = udf_checktag(&fe->tag, TAGID_FENTRY);
600 if (error) {
601 printf("Invalid file entry!\n");
602 pool_put(&unode_pool, up);
603 if (bp != NULL((void *)0))
604 brelse(bp);
605 return (ENOMEM12);
606 } else
607 size = letoh32(fe->l_ea)((__uint32_t)(fe->l_ea)) + letoh32(fe->l_ad)((__uint32_t)(fe->l_ad));
608 }
609
610 /* Allocate max size of FE/XFE. */
611 up->u_fentry = malloc(size + UDF_EXTFENTRY_SIZE216, M_UDFFENTRY141, M_NOWAIT0x0002 | M_ZERO0x0008);
612 if (up->u_fentry == NULL((void *)0)) {
613 pool_put(&unode_pool, up);
614 if (bp != NULL((void *)0))
615 brelse(bp);
616 return (ENOMEM12); /* Cannot allocate file entry block */
617 }
618
619 if (udf_checktag(&xfe->tag, TAGID_EXTFENTRY) == 0)
620 bcopy(bp->b_data, up->u_fentry, size + UDF_EXTFENTRY_SIZE216);
621 else
622 bcopy(bp->b_data, up->u_fentry, size + UDF_FENTRY_SIZE176);
623
624 brelse(bp);
625 bp = NULL((void *)0);
626
627 if ((error = udf_allocv(mp, &vp, p))) {
628 free(up->u_fentry, M_UDFFENTRY141, 0);
629 pool_put(&unode_pool, up);
630 return (error); /* Error from udf_allocv() */
631 }
632
633 up->u_vnode = vp;
634 up->u_ino = ino;
635 up->u_devvp = ump->um_devvp;
636 up->u_dev = ump->um_dev;
637 up->u_ump = ump;
638 vp->v_data = up;
639 vref(ump->um_devvp);
640
641 rrw_init_flags(&up->u_lock, "unode", RWL_DUPOK | RWL_IS_VNODE)_rrw_init_flags(&up->u_lock, "unode", 0, ((void *)0));
642
643 /*
644 * udf_hashins() will lock the vnode for us.
645 */
646 udf_hashins(up);
647
648 switch (up->u_fentry->icbtag.file_type) {
649 default:
650 printf("Unrecognized file type (%d)\n", vp->v_type);
651 vp->v_type = VREG;
652 break;
653 case UDF_ICB_FILETYPE_DIRECTORY4:
654 vp->v_type = VDIR;
655 break;
656 case UDF_ICB_FILETYPE_BLOCKDEVICE6:
657 vp->v_type = VBLK;
658 break;
659 case UDF_ICB_FILETYPE_CHARDEVICE7:
660 vp->v_type = VCHR;
661 break;
662 case UDF_ICB_FILETYPE_FIFO9:
663 vp->v_type = VFIFO;
664 break;
665 case UDF_ICB_FILETYPE_SOCKET10:
666 vp->v_type = VSOCK;
667 break;
668 case UDF_ICB_FILETYPE_SYMLINK12:
669 vp->v_type = VLNK;
670 break;
671 case UDF_ICB_FILETYPE_RANDOMACCESS5:
672 case UDF_ICB_FILETYPE_REALTIME249:
673 case UDF_ICB_FILETYPE_UNKNOWN0:
674 vp->v_type = VREG;
675 break;
676 }
677
678 /* check if this is a vnode alias */
679 if ((nvp = checkalias(vp, up->u_dev, ump->um_mountp)) != NULL((void *)0)) {
680 printf("found a vnode alias\n");
681 /*
682 * Discard unneeded vnode, but save its udf_node.
683 * Note that the lock is carried over in the udf_node
684 */
685 nvp->v_data = vp->v_data;
686 vp->v_data = NULL((void *)0);
687 vp->v_op = &spec_vops;
688 vrele(vp);
689 vgone(vp);
690 /*
691 * Reinitialize aliased inode.
692 */
693 vp = nvp;
694 ump->um_devvp = vp;
695 }
696
697 *vpp = vp;
698
699 return (0);
700}
701
702struct ifid {
703 u_short ifid_len;
704 u_short ifid_pad;
705 int ifid_ino;
706 long ifid_start;
707};
708
709int
710udf_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
711{
712 struct ifid *ifhp;
713 struct vnode *nvp;
714 int error;
715
716 ifhp = (struct ifid *)fhp;
717
718 if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)(*(mp)->mnt_op->vfs_vget)(mp, ifhp->ifid_ino, &nvp
)
) != 0) {
719 *vpp = NULLVP((struct vnode *)((void *)0));
720 return (error);
721 }
722
723 *vpp = nvp;
724
725 return (0);
726}
727
728int
729udf_vptofh(struct vnode *vp, struct fid *fhp)
730{
731 struct unode *up;
732 struct ifid *ifhp;
733
734 up = VTOU(vp)((struct unode *)((vp)->v_data));
735 ifhp = (struct ifid *)fhp;
736 ifhp->ifid_len = sizeof(struct ifid);
737 ifhp->ifid_ino = up->u_ino;
738
739 return (0);
740}
741
742int
743udf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
744 size_t newlen, struct proc *p)
745{
746 return (EINVAL22);
747}
748
749int
750udf_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
751 struct ucred **credanonp)
752{
753 return (EACCES13); /* For the time being */
754}
755
756/* Handle a virtual partition map */
757int
758udf_get_vpartmap(struct umount *ump, struct part_map_virt *pmv)
759{
760 ump->um_flags |= UDF_MNT_FIND_VAT0x01; /* Should do more than this */
761 return (0);
762}
763
764/* Handle a sparable partition map */
765int
766udf_get_spartmap(struct umount *ump, struct part_map_spare *pms)
767{
768 struct buf *bp;
769 int i, error;
770
771 ump->um_stbl = malloc(letoh32(pms->st_size)((__uint32_t)(pms->st_size)), M_UDFMOUNT140, M_NOWAIT0x0002);
772 if (ump->um_stbl == NULL((void *)0))
773 return (ENOMEM12);
774
775 bzero(ump->um_stbl, letoh32(pms->st_size))__builtin_bzero((ump->um_stbl), (((__uint32_t)(pms->st_size
))))
;
776
777 /* Calculate the number of sectors per packet */
778 ump->um_psecs = letoh16(pms->packet_len)((__uint16_t)(pms->packet_len)) / ump->um_bsize;
779
780 error = udf_readlblks(ump, letoh32(pms->st_loc[0])((__uint32_t)(pms->st_loc[0])),
781 letoh32(pms->st_size)((__uint32_t)(pms->st_size)), &bp);
782
783 if (error) {
784 if (bp != NULL((void *)0))
785 brelse(bp);
786 free(ump->um_stbl, M_UDFMOUNT140, 0);
787 return (error); /* Failed to read sparing table */
788 }
789
790 bcopy(bp->b_data, ump->um_stbl, letoh32(pms->st_size)((__uint32_t)(pms->st_size)));
791 brelse(bp);
792 bp = NULL((void *)0);
793
794 if (udf_checktag(&ump->um_stbl->tag, 0)) {
795 free(ump->um_stbl, M_UDFMOUNT140, 0);
796 return (EINVAL22); /* Invalid sparing table found */
797 }
798
799 /*
800 * See how many valid entries there are here. The list is
801 * supposed to be sorted, 0xfffffff0 and higher are not valid.
802 */
803 for (i = 0; i < letoh16(ump->um_stbl->rt_l)((__uint16_t)(ump->um_stbl->rt_l)); i++) {
804 ump->um_stbl_len = i;
805 if (letoh32(ump->um_stbl->entries[i].org)((__uint32_t)(ump->um_stbl->entries[i].org)) >= 0xfffffff0)
806 break;
807 }
808
809 return (0);
810}
811
812/* Handle a metadata partition map */
813int
814udf_get_mpartmap(struct umount *ump, struct part_map_meta *pmm)
815{
816 ump->um_flags |= UDF_MNT_USES_META0x04;
817 ump->um_meta_start = pmm->meta_file_lbn;
818 return (0);
819}
820
821/* Scan the partition maps */
822int
823udf_find_partmaps(struct umount *ump, struct logvol_desc *lvd)
824{
825 struct regid *pmap_id;
826 unsigned char regid_id[UDF_REGID_ID_SIZE23 + 1];
827 int i, ptype, psize, error;
828 uint8_t *pmap = (uint8_t *) &lvd->maps[0];
829
830 for (i = 0; i < letoh32(lvd->n_pm)((__uint32_t)(lvd->n_pm)); i++) {
831 ptype = pmap[0];
832 psize = pmap[1];
833
834 if (ptype != 1 && ptype != 2)
835 return (EINVAL22); /* Invalid partition map type */
836
837 if (psize != sizeof(struct part_map_1) &&
838 psize != sizeof(struct part_map_2))
839 return (EINVAL22); /* Invalid partition map size */
840
841 if (ptype == 1) {
842 pmap += sizeof(struct part_map_1);
843 continue;
844 }
845
846 /* Type 2 map. Find out the details */
847 pmap_id = (struct regid *) &pmap[4];
848 regid_id[UDF_REGID_ID_SIZE23] = '\0';
849 bcopy(&pmap_id->id[0], &regid_id[0], UDF_REGID_ID_SIZE23);
850
851 if (!bcmp(&regid_id[0], "*UDF Virtual Partition",
852 UDF_REGID_ID_SIZE23))
853 error = udf_get_vpartmap(ump,
854 (struct part_map_virt *) pmap);
855 else if (!bcmp(&regid_id[0], "*UDF Sparable Partition",
856 UDF_REGID_ID_SIZE23))
857 error = udf_get_spartmap(ump,
858 (struct part_map_spare *) pmap);
859 else if (!bcmp(&regid_id[0], "*UDF Metadata Partition",
860 UDF_REGID_ID_SIZE23))
861 error = udf_get_mpartmap(ump,
862 (struct part_map_meta *) pmap);
863 else
864 return (EINVAL22); /* Unsupported partition map */
865
866 if (error)
867 return (error); /* Error getting partition */
868
869 pmap += sizeof(struct part_map_2);
870 }
871
872 return (0);
873}