Bug Summary

File:ntfs/ntfs_vfsops.c
Warning:line 758, column 13
Assigned value is garbage or undefined

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 ntfs_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/ntfs/ntfs_vfsops.c
1/* $OpenBSD: ntfs_vfsops.c,v 1.65 2022/01/11 03:13:59 jsg Exp $ */
2/* $NetBSD: ntfs_vfsops.c,v 1.7 2003/04/24 07:50:19 christos Exp $ */
3
4/*-
5 * Copyright (c) 1998, 1999 Semen Ustimenko
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * Id: ntfs_vfsops.c,v 1.7 1999/05/31 11:28:30 phk Exp
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/namei.h>
35#include <sys/proc.h>
36#include <sys/kernel.h>
37#include <sys/vnode.h>
38#include <sys/lock.h>
39#include <sys/mount.h>
40#include <sys/buf.h>
41#include <sys/disk.h>
42#include <sys/fcntl.h>
43#include <sys/malloc.h>
44#include <sys/device.h>
45#include <sys/conf.h>
46#include <sys/specdev.h>
47
48/*#define NTFS_DEBUG 1*/
49#include <ntfs/ntfs.h>
50#include <ntfs/ntfs_inode.h>
51#include <ntfs/ntfs_subr.h>
52#include <ntfs/ntfs_vfsops.h>
53#include <ntfs/ntfs_ihash.h>
54
55int ntfs_mount(struct mount *, const char *, void *,
56 struct nameidata *, struct proc *);
57int ntfs_quotactl(struct mount *, int, uid_t, caddr_t,
58 struct proc *);
59int ntfs_root(struct mount *, struct vnode **);
60int ntfs_start(struct mount *, int, struct proc *);
61int ntfs_statfs(struct mount *, struct statfs *,
62 struct proc *);
63int ntfs_sync(struct mount *, int, int, struct ucred *,
64 struct proc *);
65int ntfs_unmount(struct mount *, int, struct proc *);
66int ntfs_vget(struct mount *mp, ino_t ino,
67 struct vnode **vpp);
68int ntfs_mountfs(struct vnode *, struct mount *,
69 struct ntfs_args *, struct proc *);
70int ntfs_vptofh(struct vnode *, struct fid *);
71
72int ntfs_init(struct vfsconf *);
73int ntfs_fhtovp(struct mount *, struct fid *,
74 struct vnode **);
75int ntfs_checkexp(struct mount *, struct mbuf *,
76 int *, struct ucred **);
77int ntfs_sysctl(int *, u_int, void *, size_t *, void *,
78 size_t, struct proc *);
79
80/*
81 * Verify a remote client has export rights and return these rights via.
82 * exflagsp and credanonp.
83 */
84int
85ntfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
86 struct ucred **credanonp)
87{
88 struct netcred *np;
89 struct ntfsmount *ntm = VFSTONTFS(mp)((struct ntfsmount *)((mp)->mnt_data));
90
91 /*
92 * Get the export permission structure for this <mp, client> tuple.
93 */
94 np = vfs_export_lookup(mp, &ntm->ntm_export, nam);
95 if (np == NULL((void *)0))
96 return (EACCES13);
97
98 *exflagsp = np->netc_exflags;
99 *credanonp = &np->netc_anon;
100 return (0);
101}
102
103int
104ntfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
105 size_t newlen, struct proc *p)
106{
107 return (EINVAL22);
108}
109
110int
111ntfs_init(struct vfsconf *vcp)
112{
113 return 0;
114}
115
116int
117ntfs_mount(struct mount *mp, const char *path, void *data,
118 struct nameidata *ndp, struct proc *p)
119{
120 int err = 0;
121 struct vnode *devvp;
122 struct ntfs_args *args = data;
123 char fname[MNAMELEN90];
124 char fspec[MNAMELEN90];
125
126 ntfs_nthashinit();
127
128 /*
129 ***
130 * Mounting non-root file system or updating a file system
131 ***
132 */
133
134 /*
135 * If updating, check whether changing from read-only to
136 * read/write; if there is no device name, that's all we do.
137 */
138 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
139 /* if not updating name...*/
140 if (args && args->fspec == NULL((void *)0)) {
141 /*
142 * Process export requests. Jumping to "success"
143 * will return the vfs_export() error code.
144 */
145 struct ntfsmount *ntm = VFSTONTFS(mp)((struct ntfsmount *)((mp)->mnt_data));
146 err = vfs_export(mp, &ntm->ntm_export, &args->export_info);
147 goto success;
148 }
149
150 printf("ntfs_mount(): MNT_UPDATE not supported\n");
151 err = EINVAL22;
152 goto error_1;
153 }
154
155 /*
156 * Not an update, or updating the name: look up the name
157 * and verify that it refers to a sensible block device.
158 */
159 err = copyinstr(args->fspec, fspec, sizeof(fspec), NULL((void *)0));
160 if (err)
161 goto error_1;
162
163 if (disk_map(fspec, fname, sizeof(fname), DM_OPENBLCK0x2) == -1)
164 bcopy(fspec, fname, sizeof(fname));
165
166 NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fname, p)ndinitat(ndp, 0, 0x0040, UIO_SYSSPACE, -100, fname, p);
167 err = namei(ndp);
168 if (err) {
169 /* can't get devvp!*/
170 goto error_1;
171 }
172
173 devvp = ndp->ni_vp;
174
175 if (devvp->v_type != VBLK) {
176 err = ENOTBLK15;
177 goto error_2;
178 }
179
180 if (major(devvp->v_rdev)(((unsigned)(devvp->v_un.vu_specinfo->si_rdev) >>
8) & 0xff)
>= nblkdev) {
181 err = ENXIO6;
182 goto error_2;
183 }
184
185 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
186#if 0
187 /*
188 ********************
189 * UPDATE
190 ********************
191 */
192
193 if (devvp != ntmp->um_devvp)
194 err = EINVAL22; /* needs translation */
195 else
196 vrele(devvp);
197 /*
198 * Update device name only on success
199 */
200 if( !err) {
201 err = set_statfs_info(NULL((void *)0), UIO_USERSPACE, args->fspec,
202 UIO_USERSPACE, mp, p);
203 }
204#endif
205 } else {
206 /*
207 ********************
208 * NEW MOUNT
209 ********************
210 */
211
212 /*
213 * Since this is a new mount, we want the names for
214 * the device and the mount point copied in. If an
215 * error occurs, the mountpoint is discarded by the
216 * upper level code.
217 */
218 /* Save "last mounted on" info for mount point (NULL pad)*/
219 bzero(mp->mnt_stat.f_mntonname, MNAMELEN)__builtin_bzero((mp->mnt_stat.f_mntonname), (90));
220 strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN90);
221 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN)__builtin_bzero((mp->mnt_stat.f_mntfromname), (90));
222 strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN90);
223 bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN)__builtin_bzero((mp->mnt_stat.f_mntfromspec), (90));
224 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN90);
225 bcopy(args, &mp->mnt_stat.mount_info.ntfs_args, sizeof(*args));
226 if ( !err) {
227 err = ntfs_mountfs(devvp, mp, args, p);
228 }
229 }
230 if (err) {
231 goto error_2;
232 }
233
234 /*
235 * Initialize FS stat information in mount struct; uses both
236 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
237 *
238 * This code is common to root and non-root mounts
239 */
240 (void)VFS_STATFS(mp, &mp->mnt_stat, p)(*(mp)->mnt_op->vfs_statfs)(mp, &mp->mnt_stat, p
)
;
241
242 goto success;
243
244
245error_2: /* error with devvp held*/
246
247 /* release devvp before failing*/
248 vrele(devvp);
249
250error_1: /* no state to back out*/
251
252success:
253 return(err);
254}
255
256/*
257 * Common code for mount and mountroot
258 */
259int
260ntfs_mountfs(struct vnode *devvp, struct mount *mp, struct ntfs_args *argsp,
261 struct proc *p)
262{
263 struct buf *bp;
264 struct ntfsmount *ntmp = NULL((void *)0);
265 dev_t dev = devvp->v_rdevv_un.vu_specinfo->si_rdev;
266 int error, ncount, i;
267 struct vnode *vp;
268
269 /*
270 * Disallow multiple mounts of the same device.
271 * Disallow mounting of a device that is currently in use
272 * (except for root, which might share swap device for miniroot).
273 * Flush out any old buffers remaining from a previous use.
274 */
275 error = vfs_mountedon(devvp);
276 if (error)
277 return (error);
278 ncount = vcount(devvp);
279 if (ncount > 1 && devvp != rootvp)
280 return (EBUSY16);
281 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
282 error = vinvalbuf(devvp, V_SAVE0x0001, p->p_ucred, p, 0, INFSLP0xffffffffffffffffULL);
283 VOP_UNLOCK(devvp);
284 if (error)
285 return (error);
286
287 error = VOP_OPEN(devvp, FREAD0x0001, FSCRED((struct ucred *)-2), p);
288 if (error)
289 return (error);
290
291 bp = NULL((void *)0);
292
293 error = bread(devvp, BBLOCK0, BBSIZE1024, &bp);
294 if (error)
295 goto out;
296 ntmp = malloc(sizeof *ntmp, M_NTFSMNT128, M_WAITOK0x0001 | M_ZERO0x0008);
297 bcopy(bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile));
298 brelse(bp);
299 bp = NULL((void *)0);
300
301 if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID"NTFS ", NTFS_BBIDLEN8)) {
302 error = EINVAL22;
303 DPRINTF("ntfs_mountfs: invalid boot block\n");
304 goto out;
305 }
306
307 {
308 int8_t cpr = ntmp->ntm_mftrecszntm_bootfile.bf_mftrecsz;
309 if( cpr > 0 )
310 ntmp->ntm_bpmftrec = ntmp->ntm_spcntm_bootfile.bf_spc * cpr;
311 else
312 ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bpsntm_bootfile.bf_bps;
313 }
314 DPRINTF("ntfs_mountfs(): bps: %u, spc: %u, media: %x, "
315 "mftrecsz: %u (%u sects)\n", ntmp->ntm_bps, ntmp->ntm_spc,
316 ntmp->ntm_bootfile.bf_media, ntmp->ntm_mftrecsz,
317 ntmp->ntm_bpmftrec);
318 DPRINTF("ntfs_mountfs(): mftcn: 0x%llx|0x%llx\n",
319 ntmp->ntm_mftcn, ntmp->ntm_mftmirrcn);
320
321 ntmp->ntm_mountp = mp;
322 ntmp->ntm_dev = dev;
323 ntmp->ntm_devvp = devvp;
324 ntmp->ntm_uid = argsp->uid;
325 ntmp->ntm_gid = argsp->gid;
326 ntmp->ntm_mode = argsp->mode;
327 ntmp->ntm_flag = argsp->flag;
328 mp->mnt_data = ntmp;
329 TAILQ_INIT(&ntmp->ntm_ntnodeq)do { (&ntmp->ntm_ntnodeq)->tqh_first = ((void *)0);
(&ntmp->ntm_ntnodeq)->tqh_last = &(&ntmp->
ntm_ntnodeq)->tqh_first; } while (0)
;
330
331 /* set file name encode/decode hooks XXX utf-8 only for now */
332 ntmp->ntm_wget = ntfs_utf8_wget;
333 ntmp->ntm_wput = ntfs_utf8_wput;
334 ntmp->ntm_wcmp = ntfs_utf8_wcmp;
335
336 DPRINTF("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
337 (ntmp->ntm_flag & NTFS_MFLAG_CASEINS) ? "insens." : "sens.",
338 (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES) ? " allnames," : "",
339 ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode);
340
341 /*
342 * We read in some system nodes to do not allow
343 * reclaim them and to have everytime access to them.
344 */
345 {
346 int pi[3] = { NTFS_MFTINO0, NTFS_ROOTINO5, NTFS_BITMAPINO6 };
347 for (i=0; i<3; i++) {
348 error = VFS_VGET(mp, pi[i], &(ntmp->ntm_sysvn[pi[i]]))(*(mp)->mnt_op->vfs_vget)(mp, pi[i], &(ntmp->ntm_sysvn
[pi[i]]))
;
349 if(error)
350 goto out1;
351 ntmp->ntm_sysvn[pi[i]]->v_flag |= VSYSTEM0x0004;
352 vref(ntmp->ntm_sysvn[pi[i]]);
353 vput(ntmp->ntm_sysvn[pi[i]]);
354 }
355 }
356
357 /* read the Unicode lowercase --> uppercase translation table,
358 * if necessary */
359 if ((error = ntfs_toupper_use(mp, ntmp, p)))
360 goto out1;
361
362 /*
363 * Scan $BitMap and count free clusters
364 */
365 error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
366 if(error)
367 goto out1;
368
369 /*
370 * Read and translate to internal format attribute
371 * definition file.
372 */
373 {
374 int num,j;
375 struct attrdef ad;
376
377 /* Open $AttrDef */
378 error = VFS_VGET(mp, NTFS_ATTRDEFINO, &vp )(*(mp)->mnt_op->vfs_vget)(mp, 4, &vp);
379 if(error)
380 goto out1;
381
382 /* Count valid entries */
383 for(num = 0; ; num++) {
384 error = ntfs_readattr(ntmp, VTONT(vp)((((struct fnode *)((vp)->v_data)))->f_ip),
385 NTFS_A_DATA0x80, NULL((void *)0), num * sizeof(ad), sizeof(ad),
386 &ad, NULL((void *)0));
387 if (error)
388 goto out1;
389 if (ad.ad_name[0] == 0)
390 break;
391 }
392
393 /* Alloc memory for attribute definitions */
394 ntmp->ntm_ad = mallocarray(num, sizeof(struct ntvattrdef),
395 M_NTFSMNT128, M_WAITOK0x0001);
396
397 ntmp->ntm_adnum = num;
398
399 /* Read them and translate */
400 for(i = 0; i < num; i++){
401 error = ntfs_readattr(ntmp, VTONT(vp)((((struct fnode *)((vp)->v_data)))->f_ip),
402 NTFS_A_DATA0x80, NULL((void *)0), i * sizeof(ad), sizeof(ad),
403 &ad, NULL((void *)0));
404 if (error)
405 goto out1;
406 j = 0;
407 do {
408 ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
409 } while(ad.ad_name[j++]);
410 ntmp->ntm_ad[i].ad_namelen = j - 1;
411 ntmp->ntm_ad[i].ad_type = ad.ad_type;
412 }
413
414 vput(vp);
415 }
416
417 mp->mnt_stat.f_fsid.val[0] = dev;
418 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
419 mp->mnt_stat.f_namemax = NTFS_MAXFILENAME255;
420 mp->mnt_flag |= MNT_LOCAL0x00001000;
421 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = mp;
422 return (0);
423
424out1:
425 for (i = 0; i < NTFS_SYSNODESNUM0x0B; i++)
426 if (ntmp->ntm_sysvn[i])
427 vrele(ntmp->ntm_sysvn[i]);
428
429 if (vflush(mp,NULLVP((struct vnode *)((void *)0)),0))
430 DPRINTF("ntfs_mountfs: vflush failed\n");
431
432out:
433 if (devvp->v_specinfov_un.vu_specinfo)
434 devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = NULL((void *)0);
435 if (bp)
436 brelse(bp);
437
438 if (ntmp != NULL((void *)0)) {
439 if (ntmp->ntm_ad != NULL((void *)0))
440 free(ntmp->ntm_ad, M_NTFSMNT128, 0);
441 free(ntmp, M_NTFSMNT128, 0);
442 mp->mnt_data = NULL((void *)0);
443 }
444
445 /* lock the device vnode before calling VOP_CLOSE() */
446 vn_lock(devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
447 (void)VOP_CLOSE(devvp, FREAD0x0001, NOCRED((struct ucred *)-1), p);
448 VOP_UNLOCK(devvp);
449
450 return (error);
451}
452
453int
454ntfs_start(struct mount *mp, int flags, struct proc *p)
455{
456 return (0);
457}
458
459int
460ntfs_unmount(struct mount *mp, int mntflags, struct proc *p)
461{
462 struct ntfsmount *ntmp;
463 int error, flags, i;
464
465 DPRINTF("ntfs_unmount: unmounting...\n");
466 ntmp = VFSTONTFS(mp)((struct ntfsmount *)((mp)->mnt_data));
467
468 flags = 0;
469 if(mntflags & MNT_FORCE0x00080000)
470 flags |= FORCECLOSE0x0002;
471
472 DPRINTF("ntfs_unmount: vflushing...\n");
473 error = vflush(mp,NULLVP((struct vnode *)((void *)0)),flags | SKIPSYSTEM0x0001);
474 if (error) {
475 DPRINTF("ntfs_unmount: vflush failed: %d\n", error);
476 return (error);
477 }
478
479 /* Check if system vnodes are still referenced */
480 for(i=0;i<NTFS_SYSNODESNUM0x0B;i++) {
481 if(((mntflags & MNT_FORCE0x00080000) == 0) && (ntmp->ntm_sysvn[i] &&
482 ntmp->ntm_sysvn[i]->v_usecount > 1))
483 return (EBUSY16);
484 }
485
486 /* Dereference all system vnodes */
487 for(i=0;i<NTFS_SYSNODESNUM0x0B;i++)
488 if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
489
490 /* vflush system vnodes */
491 error = vflush(mp,NULLVP((struct vnode *)((void *)0)),flags);
492 if (error) {
493 /* XXX should this be panic() ? */
494 printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
495 }
496
497 /* Check if the type of device node isn't VBAD before
498 * touching v_specinfo. If the device vnode is revoked, the
499 * field is NULL and touching it causes null pointer dereference.
500 */
501 if (ntmp->ntm_devvp->v_type != VBAD)
502 ntmp->ntm_devvp->v_specmountpointv_un.vu_specinfo->si_mountpoint = NULL((void *)0);
503
504 /* lock the device vnode before calling VOP_CLOSE() */
505 vn_lock(ntmp->ntm_devvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL);
506 vinvalbuf(ntmp->ntm_devvp, V_SAVE0x0001, NOCRED((struct ucred *)-1), p, 0, INFSLP0xffffffffffffffffULL);
507 (void)VOP_CLOSE(ntmp->ntm_devvp, FREAD0x0001, NOCRED((struct ucred *)-1), p);
508 vput(ntmp->ntm_devvp);
509
510 /* free the toupper table, if this has been last mounted ntfs volume */
511 ntfs_toupper_unuse(p);
512
513 DPRINTF("ntfs_unmount: freeing memory...\n");
514 free(ntmp->ntm_ad, M_NTFSMNT128, 0);
515 free(ntmp, M_NTFSMNT128, 0);
516 mp->mnt_data = NULL((void *)0);
517 mp->mnt_flag &= ~MNT_LOCAL0x00001000;
518 return (0);
519}
520
521int
522ntfs_root(struct mount *mp, struct vnode **vpp)
523{
524 struct vnode *nvp;
525 int error = 0;
526
527 DPRINTF("ntfs_root(): sysvn: %p\n",
528 VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]);
529 error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, &nvp)(*(mp)->mnt_op->vfs_vget)(mp, (ino_t)5, &nvp);
530 if(error) {
531 printf("ntfs_root: VFS_VGET failed: %d\n",error);
532 return (error);
533 }
534
535 *vpp = nvp;
536 return (0);
537}
538
539/*
540 * Do operations associated with quotas, not supported
541 */
542int
543ntfs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
544 struct proc *p)
545{
546 return EOPNOTSUPP45;
547}
548
549int
550ntfs_calccfree(struct ntfsmount *ntmp, cn_t *cfreep)
551{
552 struct vnode *vp;
553 u_int8_t *tmp;
554 int j, error;
555 cn_t cfree = 0;
556 uint64_t bmsize, offset;
557 size_t chunksize, i;
558
559 vp = ntmp->ntm_sysvn[NTFS_BITMAPINO6];
560
561 bmsize = VTOF(vp)((struct fnode *)((vp)->v_data))->f_size;
562
563 if (bmsize > 1024 * 1024)
564 chunksize = 1024 * 1024;
565 else
566 chunksize = bmsize;
567
568 tmp = malloc(chunksize, M_TEMP127, M_WAITOK0x0001);
569
570 for (offset = 0; offset < bmsize; offset += chunksize) {
571 if (chunksize > bmsize - offset)
572 chunksize = bmsize - offset;
573
574 error = ntfs_readattr(ntmp, VTONT(vp)((((struct fnode *)((vp)->v_data)))->f_ip), NTFS_A_DATA0x80, NULL((void *)0),
575 offset, chunksize, tmp, NULL((void *)0));
576 if (error)
577 goto out;
578
579 for (i = 0; i < chunksize; i++)
580 for (j = 0; j < 8; j++)
581 if (~tmp[i] & (1 << j))
582 cfree++;
583 }
584
585 *cfreep = cfree;
586
587 out:
588 free(tmp, M_TEMP127, 0);
589 return(error);
590}
591
592int
593ntfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
594{
595 struct ntfsmount *ntmp = VFSTONTFS(mp)((struct ntfsmount *)((mp)->mnt_data));
596 u_int64_t mftallocated;
597
598 DPRINTF("ntfs_statfs():\n");
599
600 mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])((struct fnode *)((ntmp->ntm_sysvn[0])->v_data))->f_allocated;
601
602 sbp->f_bsize = ntmp->ntm_bpsntm_bootfile.bf_bps;
603 sbp->f_iosize = ntmp->ntm_bpsntm_bootfile.bf_bps * ntmp->ntm_spcntm_bootfile.bf_spc;
604 sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
605 sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree)(daddr_t)((ntmp->ntm_cfree) * (ntmp->ntm_bootfile.bf_spc
))
;
606 sbp->f_ffree = sbp->f_favail = sbp->f_bfree / ntmp->ntm_bpmftrec;
607 sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec)(int32_t)((ntmp->ntm_bpmftrec) * (ntmp)->ntm_bootfile.bf_bps
)
+
608 sbp->f_ffree;
609 copy_statfs_info(sbp, mp);
610
611 return (0);
612}
613
614int
615ntfs_sync(struct mount *mp, int waitfor, int stall, struct ucred *cred, struct proc *p)
616{
617 /*DPRINTF("ntfs_sync():\n");*/
618 return (0);
619}
620
621int
622ntfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
623{
624 struct ntfid *ntfhp = (struct ntfid *)fhp;
625 int error;
626
627 DDPRINTF("ntfs_fhtovp(): %s: %u\n",
628 mp->mnt_stat.f_mntonname, ntfhp->ntfid_ino);
629
630 error = ntfs_vgetex(mp, ntfhp->ntfid_ino, ntfhp->ntfid_attr, NULL((void *)0),
1
Calling 'ntfs_vgetex'
631 LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL, 0, vpp); /* XXX */
632 if (error != 0) {
633 *vpp = NULLVP((struct vnode *)((void *)0));
634 return (error);
635 }
636
637 /* XXX as unlink/rmdir/mkdir/creat are not currently possible
638 * with NTFS, we don't need to check anything else for now */
639 return (0);
640}
641
642int
643ntfs_vptofh(struct vnode *vp, struct fid *fhp)
644{
645 struct ntnode *ntp;
646 struct ntfid *ntfhp;
647 struct fnode *fn;
648
649 DDPRINTF("ntfs_fhtovp(): %s: %p\n",
650 vp->v_mount->mnt_stat.f_mntonname, vp);
651
652 fn = VTOF(vp)((struct fnode *)((vp)->v_data));
653 ntp = VTONT(vp)((((struct fnode *)((vp)->v_data)))->f_ip);
654 ntfhp = (struct ntfid *)fhp;
655 ntfhp->ntfid_len = sizeof(struct ntfid);
656 ntfhp->ntfid_ino = ntp->i_number;
657 ntfhp->ntfid_attr = fn->f_attrtype;
658#ifdef notyet
659 ntfhp->ntfid_gen = ntp->i_gen;
660#endif
661 return (0);
662}
663
664int
665ntfs_vgetex(struct mount *mp, ntfsino_t ino, u_int32_t attrtype, char *attrname,
666 u_long lkflags, u_long flags, struct vnode **vpp)
667{
668 int error;
669 struct ntfsmount *ntmp;
670 struct ntnode *ip;
671 struct fnode *fp;
672 struct vnode *vp;
673 enum vtype f_type;
2
'f_type' declared without an initial value
674
675 DPRINTF("ntfs_vgetex: ino: %u, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
676 ino, attrtype, attrname ? attrname : "", lkflags, flags);
677
678 ntmp = VFSTONTFS(mp)((struct ntfsmount *)((mp)->mnt_data));
679 *vpp = NULL((void *)0);
680
681 /* Get ntnode */
682 error = ntfs_ntlookup(ntmp, ino, &ip);
683 if (error) {
3
Assuming 'error' is 0
4
Taking false branch
684 printf("ntfs_vget: ntfs_ntget failed\n");
685 return (error);
686 }
687
688 /* It may be not initialized fully, so force load it */
689 if (!(flags & VG_DONTLOADIN0x0001) && !(ip->i_flag & IN_LOADED0x8000)) {
5
Assuming the condition is false
6
Taking false branch
690 error = ntfs_loadntnode(ntmp, ip);
691 if(error) {
692 printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n",
693 ip->i_number);
694 ntfs_ntput(ip);
695
696 return (error);
697 }
698 }
699
700 error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
701 if (error) {
7
Assuming 'error' is 0
8
Taking false branch
702 printf("ntfs_vget: ntfs_fget failed\n");
703 ntfs_ntput(ip);
704
705 return (error);
706 }
707
708 if (!(flags & VG_DONTVALIDFN0x0002) && !(fp->f_flag & FN_VALID0x0002)) {
9
Assuming the condition is false
10
Taking false branch
709 if ((ip->i_frflag & NTFS_FRFLAG_DIR0x0002) &&
710 (fp->f_attrtype == NTFS_A_DATA0x80 && fp->f_attrname == NULL((void *)0))) {
711 f_type = VDIR;
712 } else if (flags & VG_EXT0x0004) {
713 f_type = VNON;
714 fp->f_size = fp->f_allocated = 0;
715 } else {
716 f_type = VREG;
717
718 error = ntfs_filesize(ntmp, fp,
719 &fp->f_size, &fp->f_allocated);
720 if (error) {
721 ntfs_ntput(ip);
722
723 return (error);
724 }
725 }
726
727 fp->f_flag |= FN_VALID0x0002;
728 }
729
730 /*
731 * We may be calling vget() now. To avoid potential deadlock, we need
732 * to release ntnode lock, since due to locking order vnode
733 * lock has to be acquired first.
734 * ntfs_fget() bumped ntnode usecount, so ntnode won't be recycled
735 * prematurely.
736 */
737 ntfs_ntput(ip);
738
739 if (FTOV(fp)((fp)->f_vp)) {
11
Assuming field 'f_vp' is null
12
Taking false branch
740 /* vget() returns error if the vnode has been recycled */
741 if (vget(FTOV(fp)((fp)->f_vp), lkflags) == 0) {
742 *vpp = FTOV(fp)((fp)->f_vp);
743 return (0);
744 }
745 }
746
747 error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, &ntfs_vops, &vp);
748 if(error) {
13
Assuming 'error' is 0
14
Taking false branch
749 ntfs_frele(fp);
750 ntfs_ntput(ip);
751
752 return (error);
753 }
754 DPRINTF("ntfs_vget: vnode: %p for ntnode: %u\n", vp, ino);
755
756 fp->f_vp = vp;
757 vp->v_data = fp;
758 vp->v_type = f_type;
15
Assigned value is garbage or undefined
759
760 if (ino == NTFS_ROOTINO5)
761 vp->v_flag |= VROOT0x0001;
762
763 if (lkflags & LK_TYPE_MASK(0x0001UL|0x0002UL)) {
764 error = vn_lock(vp, lkflags);
765 if (error) {
766 vput(vp);
767 return (error);
768 }
769 }
770
771 *vpp = vp;
772 return (0);
773}
774
775int
776ntfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
777{
778 if (ino > (ntfsino_t)-1)
779 panic("ntfs_vget: alien ino_t %llu", (unsigned long long)ino);
780 return ntfs_vgetex(mp, ino, NTFS_A_DATA0x80, NULL((void *)0),
781 LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL, 0, vpp); /* XXX */
782}
783
784const struct vfsops ntfs_vfsops = {
785 .vfs_mount = ntfs_mount,
786 .vfs_start = ntfs_start,
787 .vfs_unmount = ntfs_unmount,
788 .vfs_root = ntfs_root,
789 .vfs_quotactl = ntfs_quotactl,
790 .vfs_statfs = ntfs_statfs,
791 .vfs_sync = ntfs_sync,
792 .vfs_vget = ntfs_vget,
793 .vfs_fhtovp = ntfs_fhtovp,
794 .vfs_vptofh = ntfs_vptofh,
795 .vfs_init = ntfs_init,
796 .vfs_sysctl = ntfs_sysctl,
797 .vfs_checkexp = ntfs_checkexp,
798};