Bug Summary

File:ntfs/ntfs_vfsops.c
Warning:line 589, column 2
Undefined or garbage value returned to caller

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) {
1
Assuming the condition is false
2
Taking false branch
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)
3
Assuming 'err' is 0
4
Taking false branch
161 goto error_1;
162
163 if (disk_map(fspec, fname, sizeof(fname), DM_OPENBLCK0x2) == -1)
5
Assuming the condition is false
6
Taking false branch
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) {
7
Assuming 'err' is 0
8
Taking false branch
169 /* can't get devvp!*/
170 goto error_1;
171 }
172
173 devvp = ndp->ni_vp;
174
175 if (devvp->v_type != VBLK) {
9
Assuming field 'v_type' is equal to VBLK
10
Taking false branch
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
) {
11
Assuming the condition is false
12
Taking false branch
181 err = ENXIO6;
182 goto error_2;
183 }
184
185 if (mp->mnt_flag & MNT_UPDATE0x00010000) {
13
Taking false branch
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
13.1
'err' is 0
) {
14
Taking true branch
227 err = ntfs_mountfs(devvp, mp, args, p);
15
Calling 'ntfs_mountfs'
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)
16
Assuming 'error' is 0
17
Taking false branch
277 return (error);
278 ncount = vcount(devvp);
279 if (ncount > 1 && devvp != rootvp)
18
Assuming 'ncount' is <= 1
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)
19
Assuming 'error' is 0
20
Taking false branch
285 return (error);
286
287 error = VOP_OPEN(devvp, FREAD0x0001, FSCRED((struct ucred *)-2), p);
288 if (error)
21
Assuming 'error' is 0
22
Taking false branch
289 return (error);
290
291 bp = NULL((void *)0);
292
293 error = bread(devvp, BBLOCK0, BBSIZE1024, &bp);
294 if (error)
23
Assuming 'error' is 0
24
Taking false branch
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)) {
25
Assuming the condition is false
26
Taking false branch
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 )
27
Assuming 'cpr' is > 0
28
Taking true branch
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)
;
29
Loop condition is false. Exiting loop
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++) {
30
Loop condition is true. Entering loop body
33
Loop condition is true. Entering loop body
36
Loop condition is true. Entering loop body
39
Loop condition is false. Execution continues on line 359
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)
31
Assuming 'error' is 0
32
Taking false branch
34
Assuming 'error' is 0
35
Taking false branch
37
Assuming 'error' is 0
38
Taking false branch
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)))
40
Assuming 'error' is 0
41
Taking false branch
360 goto out1;
361
362 /*
363 * Scan $BitMap and count free clusters
364 */
365 error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
42
Calling 'ntfs_calccfree'
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;
43
'error' declared without an initial value
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)
44
Assuming the condition is false
45
Taking false branch
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) {
46
Assuming 'offset' is >= 'bmsize'
47
Loop condition is false. Execution continues on line 585
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);
48
Undefined or garbage value returned to caller
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),
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;
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) {
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)) {
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) {
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)) {
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)) {
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) {
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;
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};