Bug Summary

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