Bug Summary

File:ntfs/ntfs_vnops.c
Warning:line 425, column 2
Value stored to 'off' is never read

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_vnops.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_vnops.c
1/* $OpenBSD: ntfs_vnops.c,v 1.47 2021/10/15 06:30:06 semarie Exp $ */
2/* $NetBSD: ntfs_vnops.c,v 1.6 2003/04/10 21:57:26 jdolecek Exp $ */
3
4/*
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * John Heidemann of the UCLA Ficus project.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * Id: ntfs_vnops.c,v 1.5 1999/05/12 09:43:06 semenu Exp
36 *
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/time.h>
42#include <sys/stat.h>
43#include <sys/vnode.h>
44#include <sys/lock.h>
45#include <sys/mount.h>
46#include <sys/namei.h>
47#include <sys/malloc.h>
48#include <sys/buf.h>
49#include <sys/dirent.h>
50#include <sys/specdev.h>
51
52/*#define NTFS_DEBUG 1*/
53#include <ntfs/ntfs.h>
54#include <ntfs/ntfs_inode.h>
55#include <ntfs/ntfs_subr.h>
56
57#include <sys/unistd.h> /* for pathconf(2) constants */
58
59int ntfs_read(void *);
60int ntfs_getattr(void *);
61int ntfs_inactive(void *);
62int ntfs_print(void *);
63int ntfs_reclaim(void *);
64int ntfs_strategy(void *);
65int ntfs_access(void *v);
66int ntfs_open(void *v);
67int ntfs_close(void *);
68int ntfs_readdir(void *);
69int ntfs_lookup(void *);
70int ntfs_bmap(void *);
71int ntfs_fsync(void *);
72int ntfs_pathconf(void *);
73
74int ntfs_prtactive = 0; /* 1 => print out reclaim of active vnodes */
75
76/*
77 * This is a noop, simply returning what one has been given.
78 */
79int
80ntfs_bmap(void *v)
81{
82 struct vop_bmap_args *ap = v;
83 DPRINTF("ntfs_bmap: vn: %p, blk: %lld\n",
84 ap->a_vp, (long long)ap->a_bn);
85 if (ap->a_vpp != NULL((void *)0))
86 *ap->a_vpp = ap->a_vp;
87 if (ap->a_bnp != NULL((void *)0))
88 *ap->a_bnp = ap->a_bn;
89 if (ap->a_runp != NULL((void *)0))
90 *ap->a_runp = 0;
91 return (0);
92}
93
94int
95ntfs_read(void *v)
96{
97 struct vop_read_args *ap = v;
98 struct vnode *vp = ap->a_vp;
99 struct fnode *fp = VTOF(vp)((struct fnode *)((vp)->v_data));
100 struct ntnode *ip = FTONT(fp)((fp)->f_ip);
101 struct uio *uio = ap->a_uio;
102 struct ntfsmount *ntmp = ip->i_mp;
103 u_int64_t toread;
104 int error;
105
106 DPRINTF("ntfs_read: ino: %u, off: %lld resid: %zu, segflg: %d\n",
107 ip->i_number, uio->uio_offset, uio->uio_resid, uio->uio_segflg);
108
109 DPRINTF("ntfs_read: filesize: %llu", fp->f_size);
110
111 /* don't allow reading after end of file */
112 if (uio->uio_offset > fp->f_size)
113 toread = 0;
114 else
115 toread = MIN(uio->uio_resid, fp->f_size - uio->uio_offset)(((uio->uio_resid)<(fp->f_size - uio->uio_offset)
)?(uio->uio_resid):(fp->f_size - uio->uio_offset))
;
116
117 DPRINTF(", toread: %llu\n", toread);
118
119 if (toread == 0)
120 return (0);
121
122 error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
123 fp->f_attrname, uio->uio_offset, toread, NULL((void *)0), uio);
124 if (error) {
125 printf("ntfs_read: ntfs_readattr failed: %d\n",error);
126 return (error);
127 }
128
129 return (0);
130}
131
132int
133ntfs_getattr(void *v)
134{
135 struct vop_getattr_args *ap = v;
136 struct vnode *vp = ap->a_vp;
137 struct fnode *fp = VTOF(vp)((struct fnode *)((vp)->v_data));
138 struct ntnode *ip = FTONT(fp)((fp)->f_ip);
139 struct vattr *vap = ap->a_vap;
140
141 DPRINTF("ntfs_getattr: %u, flags: %u\n", ip->i_number, ip->i_flag);
142
143 vap->va_fsid = ip->i_dev;
144 vap->va_fileid = ip->i_number;
145 vap->va_mode = ip->i_mp->ntm_mode;
146 vap->va_nlink = ip->i_nlink;
147 vap->va_uid = ip->i_mp->ntm_uid;
148 vap->va_gid = ip->i_mp->ntm_gid;
149 vap->va_rdev = 0; /* XXX UNODEV ? */
150 vap->va_size = fp->f_size;
151 vap->va_bytes = fp->f_allocated;
152 vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
153 vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
154 vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
155 vap->va_flags = ip->i_flag;
156 vap->va_gen = 0;
157 vap->va_blocksize = ip->i_mp->ntm_spcntm_bootfile.bf_spc * ip->i_mp->ntm_bpsntm_bootfile.bf_bps;
158 vap->va_type = vp->v_type;
159 vap->va_filerev = 0;
160
161 /*
162 * Ensure that a directory link count is always 1 so that things
163 * like fts_read() do not try to be smart and end up skipping over
164 * directories. Additionally, ip->i_nlink will not be initialised
165 * until the ntnode has been loaded for the file.
166 */
167 if (vp->v_type == VDIR || ip->i_nlink < 1)
168 vap->va_nlink = 1;
169
170 return (0);
171}
172
173
174/*
175 * Last reference to an ntnode. If necessary, write or delete it.
176 */
177int
178ntfs_inactive(void *v)
179{
180 struct vop_inactive_args *ap = v;
181 struct vnode *vp = ap->a_vp;
182#ifdef NTFS_DEBUG
183 struct ntnode *ip = VTONT(vp)((((struct fnode *)((vp)->v_data)))->f_ip);
184#endif
185
186 DPRINTF("ntfs_inactive: vnode: %p, ntnode: %u\n", vp, ip->i_number);
187
188#ifdef DIAGNOSTIC1
189 if (ntfs_prtactive && vp->v_usecount != 0)
190 vprint("ntfs_inactive: pushing active", vp);
191#endif
192
193 VOP_UNLOCK(vp);
194
195 /* XXX since we don't support any filesystem changes
196 * right now, nothing more needs to be done
197 */
198 return (0);
199}
200
201/*
202 * Reclaim an fnode/ntnode so that it can be used for other purposes.
203 */
204int
205ntfs_reclaim(void *v)
206{
207 struct vop_reclaim_args *ap = v;
208 struct vnode *vp = ap->a_vp;
209 struct fnode *fp = VTOF(vp)((struct fnode *)((vp)->v_data));
210 struct ntnode *ip = FTONT(fp)((fp)->f_ip);
211 int error;
212
213 DPRINTF("ntfs_reclaim: vnode: %p, ntnode: %u\n", vp, ip->i_number);
214
215#ifdef DIAGNOSTIC1
216 if (ntfs_prtactive && vp->v_usecount != 0)
217 vprint("ntfs_reclaim: pushing active", vp);
218#endif
219
220 if ((error = ntfs_ntget(ip)) != 0)
221 return (error);
222
223 /* Purge old data structures associated with the inode. */
224 cache_purge(vp);
225
226 ntfs_frele(fp);
227 ntfs_ntput(ip);
228
229 vp->v_data = NULL((void *)0);
230
231 return (0);
232}
233
234int
235ntfs_print(void *v)
236{
237 struct vop_print_args *ap = v;
238 struct ntnode *ip = VTONT(ap->a_vp)((((struct fnode *)((ap->a_vp)->v_data)))->f_ip);
239
240 printf("tag VT_NTFS, ino %u, flag %#x, usecount %d, nlink %ld\n",
241 ip->i_number, ip->i_flag, ip->i_usecount, ip->i_nlink);
242
243 return (0);
244}
245
246/*
247 * Calculate the logical to physical mapping if not done already,
248 * then call the device strategy routine.
249 */
250int
251ntfs_strategy(void *v)
252{
253 struct vop_strategy_args *ap = v;
254 struct buf *bp = ap->a_bp;
255 struct vnode *vp = bp->b_vp;
256 struct fnode *fp = VTOF(vp)((struct fnode *)((vp)->v_data));
257 struct ntnode *ip = FTONT(fp)((fp)->f_ip);
258 struct ntfsmount *ntmp = ip->i_mp;
259 int error, s;
260
261 DPRINTF("ntfs_strategy: blkno: %lld, lblkno: %lld\n",
262 (long long)bp->b_blkno, (long long)bp->b_lblkno);
263
264 DPRINTF("strategy: bcount: %ld flags: 0x%lx\n",
265 bp->b_bcount, bp->b_flags);
266
267 if (bp->b_flags & B_READ0x00008000) {
268 u_int32_t toread;
269
270 if (ntfs_cntob(bp->b_blkno)(off_t)((bp->b_blkno) * (ntmp)->ntm_bootfile.bf_spc * (
ntmp)->ntm_bootfile.bf_bps)
>= fp->f_size) {
271 clrbuf(bp){ __builtin_bzero(((bp)->b_data), ((bp)->b_bcount)); (bp
)->b_resid = 0; }
;
272 error = 0;
273 } else {
274 toread = MIN(bp->b_bcount,(((bp->b_bcount)<(fp->f_size - (off_t)((bp->b_blkno
) * (ntmp)->ntm_bootfile.bf_spc * (ntmp)->ntm_bootfile.
bf_bps)))?(bp->b_bcount):(fp->f_size - (off_t)((bp->
b_blkno) * (ntmp)->ntm_bootfile.bf_spc * (ntmp)->ntm_bootfile
.bf_bps)))
275 fp->f_size - ntfs_cntob(bp->b_blkno))(((bp->b_bcount)<(fp->f_size - (off_t)((bp->b_blkno
) * (ntmp)->ntm_bootfile.bf_spc * (ntmp)->ntm_bootfile.
bf_bps)))?(bp->b_bcount):(fp->f_size - (off_t)((bp->
b_blkno) * (ntmp)->ntm_bootfile.bf_spc * (ntmp)->ntm_bootfile
.bf_bps)))
;
276 DPRINTF("ntfs_strategy: toread: %u, fsize: %llu\n",
277 toread, fp->f_size);
278
279 error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
280 fp->f_attrname, ntfs_cntob(bp->b_blkno)(off_t)((bp->b_blkno) * (ntmp)->ntm_bootfile.bf_spc * (
ntmp)->ntm_bootfile.bf_bps)
,
281 toread, bp->b_data, NULL((void *)0));
282
283 if (error) {
284 printf("ntfs_strategy: ntfs_readattr failed\n");
285 bp->b_error = error;
286 bp->b_flags |= B_ERROR0x00000400;
287 }
288
289 bzero(bp->b_data + toread, bp->b_bcount - toread)__builtin_bzero((bp->b_data + toread), (bp->b_bcount - toread
))
;
290 }
291 } else {
292 bp->b_error = error = EROFS30;
293 bp->b_flags |= B_ERROR0x00000400;
294 }
295 s = splbio()splraise(0x6);
296 biodone(bp);
297 splx(s)spllower(s);
298 return (error);
299}
300
301int
302ntfs_access(void *v)
303{
304 struct vop_access_args *ap = v;
305 struct vnode *vp = ap->a_vp;
306 struct ntnode *ip = VTONT(vp)((((struct fnode *)((vp)->v_data)))->f_ip);
307 struct ucred *cred = ap->a_cred;
308 mode_t mask, mode = ap->a_mode;
309 gid_t *gp;
310 int i;
311
312 DPRINTF("ntfs_access: %u\n", ip->i_number);
313
314 /*
315 * Disallow write attempts unless the file is a socket, fifo, or
316 * a block or character device resident on the file system.
317 */
318 if (mode & VWRITE00200) {
319 switch ((int)vp->v_type) {
320 case VDIR:
321 case VLNK:
322 case VREG:
323 return (EROFS30);
324 }
325 }
326
327 /* Otherwise, user id 0 always gets access. */
328 if (cred->cr_uid == 0)
329 return (0);
330
331 mask = 0;
332
333 /* Otherwise, check the owner. */
334 if (cred->cr_uid == ip->i_mp->ntm_uid) {
335 if (mode & VEXEC00100)
336 mask |= S_IXUSR0000100;
337 if (mode & VREAD00400)
338 mask |= S_IRUSR0000400;
339 if (mode & VWRITE00200)
340 mask |= S_IWUSR0000200;
341 return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES13);
342 }
343
344 /* Otherwise, check the groups. */
345 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
346 if (ip->i_mp->ntm_gid == *gp) {
347 if (mode & VEXEC00100)
348 mask |= S_IXGRP0000010;
349 if (mode & VREAD00400)
350 mask |= S_IRGRP0000040;
351 if (mode & VWRITE00200)
352 mask |= S_IWGRP0000020;
353 return ((ip->i_mp->ntm_mode&mask) == mask ? 0 : EACCES13);
354 }
355
356 /* Otherwise, check everyone else. */
357 if (mode & VEXEC00100)
358 mask |= S_IXOTH0000001;
359 if (mode & VREAD00400)
360 mask |= S_IROTH0000004;
361 if (mode & VWRITE00200)
362 mask |= S_IWOTH0000002;
363 return ((ip->i_mp->ntm_mode & mask) == mask ? 0 : EACCES13);
364}
365
366/*
367 * Open called.
368 *
369 * Nothing to do.
370 */
371int
372ntfs_open(void *v)
373{
374#if NTFS_DEBUG
375 struct vop_open_args *ap = v;
376 struct vnode *vp = ap->a_vp;
377 struct ntnode *ip = VTONT(vp)((((struct fnode *)((vp)->v_data)))->f_ip);
378
379 printf("ntfs_open: %d\n",ip->i_number);
380#endif
381
382 /*
383 * Files marked append-only must be opened for appending.
384 */
385
386 return (0);
387}
388
389/*
390 * Close called.
391 *
392 * Update the times on the inode.
393 */
394int
395ntfs_close(void *v)
396{
397#if NTFS_DEBUG
398 struct vop_close_args *ap = v;
399 struct vnode *vp = ap->a_vp;
400 struct ntnode *ip = VTONT(vp)((((struct fnode *)((vp)->v_data)))->f_ip);
401
402 printf("ntfs_close: %d\n",ip->i_number);
403#endif
404
405 return (0);
406}
407
408int
409ntfs_readdir(void *v)
410{
411 struct vop_readdir_args *ap = v;
412 struct vnode *vp = ap->a_vp;
413 struct fnode *fp = VTOF(vp)((struct fnode *)((vp)->v_data));
414 struct ntnode *ip = FTONT(fp)((fp)->f_ip);
415 struct uio *uio = ap->a_uio;
416 struct ntfsmount *ntmp = ip->i_mp;
417 int i, error = 0;
418 u_int32_t faked = 0, num;
419 struct dirent cde;
420 off_t off;
421
422 DPRINTF("ntfs_readdir %u off: %lld resid: %zu\n", ip->i_number,
423 uio->uio_offset, uio->uio_resid);
424
425 off = uio->uio_offset;
Value stored to 'off' is never read
426 memset(&cde, 0, sizeof(cde))__builtin_memset((&cde), (0), (sizeof(cde)));
427
428 /* Simulate . in every dir except ROOT */
429 if (ip->i_number != NTFS_ROOTINO5 && uio->uio_offset == 0) {
430 cde.d_fileno = ip->i_number;
431 cde.d_reclen = sizeof(struct dirent);
432 cde.d_type = DT_DIR4;
433 cde.d_namlen = 1;
434 cde.d_off = sizeof(struct dirent);
435 cde.d_name[0] = '.';
436 cde.d_name[1] = '\0';
437 error = uiomove(&cde, sizeof(struct dirent), uio);
438 if (error)
439 goto out;
440 }
441
442 /* Simulate .. in every dir including ROOT */
443 if (uio->uio_offset < 2 * sizeof(struct dirent)) {
444 cde.d_fileno = NTFS_ROOTINO5; /* XXX */
445 cde.d_reclen = sizeof(struct dirent);
446 cde.d_type = DT_DIR4;
447 cde.d_namlen = 2;
448 cde.d_off = 2 * sizeof(struct dirent);
449 cde.d_name[0] = '.';
450 cde.d_name[1] = '.';
451 cde.d_name[2] = '\0';
452 error = uiomove(&cde, sizeof(struct dirent), uio);
453 if (error)
454 goto out;
455 }
456
457 faked = (ip->i_number == NTFS_ROOTINO5) ? 1 : 2;
458 num = uio->uio_offset / sizeof(struct dirent) - faked;
459
460 while (uio->uio_resid >= sizeof(struct dirent)) {
461 struct attr_indexentry *iep;
462 char *fname;
463 size_t remains;
464 int sz;
465
466 error = ntfs_ntreaddir(ntmp, fp, num, &iep, uio->uio_procp);
467 if (error)
468 goto out;
469
470 if (NULL((void *)0) == iep)
471 break;
472
473 for(; !(iep->ie_flag & NTFS_IEFLAG_LAST0x00000002) && (uio->uio_resid >= sizeof(struct dirent));
474 iep = NTFS_NEXTREC(iep, struct attr_indexentry *)((struct attr_indexentry *)(((caddr_t) iep) + (iep)->reclen
))
)
475 {
476 if(!ntfs_isnamepermitted(ntmp,iep))
477 continue;
478
479 remains = sizeof(cde.d_name) - 1;
480 fname = cde.d_name;
481 for(i=0; i<iep->ie_fnamelen; i++) {
482 sz = (*ntmp->ntm_wput)(fname, remains,
483 iep->ie_fname[i]);
484 fname += sz;
485 remains -= sz;
486 }
487 *fname = '\0';
488 DPRINTF("ntfs_readdir: elem: %u, fname:[%s] type: %u, "
489 "flag: %u, ",
490 num, cde.d_name, iep->ie_fnametype, iep->ie_flag);
491 cde.d_namlen = fname - (char *) cde.d_name;
492 cde.d_fileno = iep->ie_number;
493 cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR0x10000000LL) ? DT_DIR4 : DT_REG8;
494 cde.d_reclen = sizeof(struct dirent);
495 cde.d_off = uio->uio_offset + sizeof(struct dirent);
496 DPRINTF("%s\n", cde.d_type == DT_DIR ? "dir" : "reg");
497
498 error = uiomove(&cde, sizeof(struct dirent), uio);
499 if (error)
500 goto out;
501 num++;
502 }
503 }
504
505 DPRINTF("ntfs_readdir: %u entries (%lld bytes) read\n",
506 num, uio->uio_offset - off);
507 DPRINTF("ntfs_readdir: off: %lld resid: %zu\n",
508 uio->uio_offset, uio->uio_resid);
509
510/*
511 if (ap->a_eofflag)
512 *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
513*/
514out:
515 if (fp->f_dirblbuf != NULL((void *)0)) {
516 free(fp->f_dirblbuf, M_NTFSDIR131, 0);
517 fp->f_dirblbuf = NULL((void *)0);
518 }
519 return (error);
520}
521
522int
523ntfs_lookup(void *v)
524{
525 struct vop_lookup_args *ap = v;
526 struct vnode *dvp = ap->a_dvp;
527 struct ntnode *dip = VTONT(dvp)((((struct fnode *)((dvp)->v_data)))->f_ip);
528 struct ntfsmount *ntmp = dip->i_mp;
529 struct componentname *cnp = ap->a_cnp;
530 struct ucred *cred = cnp->cn_cred;
531 int error;
532 int lockparent = cnp->cn_flags & LOCKPARENT0x0008;
533#if NTFS_DEBUG
534 int wantparent = cnp->cn_flags & (LOCKPARENT0x0008|WANTPARENT0x0010);
535#endif
536 DPRINTF("ntfs_lookup: \"%.*s\" (%ld bytes) in %u, lp: %d, wp: %d \n",
537 (unsigned int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
538 dip->i_number, lockparent, wantparent);
539
540 error = VOP_ACCESS(dvp, VEXEC00100, cred, cnp->cn_proc);
541 if(error)
542 return (error);
543
544 if ((cnp->cn_flags & ISLASTCN0x008000) &&
545 (cnp->cn_nameiop == DELETE2 || cnp->cn_nameiop == RENAME3))
546 return (EROFS30);
547
548 /*
549 * We now have a segment name to search for, and a directory
550 * to search.
551 *
552 * Before tediously performing a linear scan of the directory,
553 * check the name cache to see if the directory/name pair
554 * we are looking for is known already.
555 */
556 if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0)
557 return (error);
558
559 if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
560 DPRINTF("ntfs_lookup: faking . directory in %u\n",
561 dip->i_number);
562
563 vref(dvp);
564 *ap->a_vpp = dvp;
565 error = 0;
566 } else if (cnp->cn_flags & ISDOTDOT0x002000) {
567 struct ntvattr *vap;
568
569 DPRINTF("ntfs_lookup: faking .. directory in %u\n",
570 dip->i_number);
571
572 VOP_UNLOCK(dvp);
573 cnp->cn_flags |= PDIRUNLOCK0x200000;
574
575 error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME0x30, NULL((void *)0), 0, &vap);
576 if(error)
577 return (error);
578
579 DPRINTF("ntfs_lookup: parentdir: %u\n",
580 vap->va_a_name->n_pnumber);
581 error = VFS_VGET(ntmp->ntm_mountp,(*(ntmp->ntm_mountp)->mnt_op->vfs_vget)(ntmp->ntm_mountp
, vap->va_d.name->n_pnumber, ap->a_vpp)
582 vap->va_a_name->n_pnumber,ap->a_vpp)(*(ntmp->ntm_mountp)->mnt_op->vfs_vget)(ntmp->ntm_mountp
, vap->va_d.name->n_pnumber, ap->a_vpp)
;
583 ntfs_ntvattrrele(vap);
584 if (error) {
585 if (vn_lock(dvp, LK_EXCLUSIVE0x0001UL | LK_RETRY0x2000UL) == 0)
586 cnp->cn_flags &= ~PDIRUNLOCK0x200000;
587 return (error);
588 }
589
590 if (lockparent && (cnp->cn_flags & ISLASTCN0x008000)) {
591 error = vn_lock(dvp, LK_EXCLUSIVE0x0001UL);
592 if (error) {
593 vput( *(ap->a_vpp) );
594 return (error);
595 }
596 cnp->cn_flags &= ~PDIRUNLOCK0x200000;
597 }
598 } else {
599 error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
600 if (error) {
601 DPRINTF("ntfs_ntlookupfile: returned %d\n", error);
602 return (error);
603 }
604
605 DPRINTF("ntfs_lookup: found ino: %u\n",
606 VTONT(*ap->a_vpp)->i_number);
607
608 if(!lockparent || (cnp->cn_flags & ISLASTCN0x008000) == 0) {
609 VOP_UNLOCK(dvp);
610 cnp->cn_flags |= PDIRUNLOCK0x200000;
611 }
612 }
613
614 if (cnp->cn_flags & MAKEENTRY0x004000)
615 cache_enter(dvp, *ap->a_vpp, cnp);
616
617 return (error);
618}
619
620/*
621 * Flush the blocks of a file to disk.
622 *
623 * This function is worthless for vnodes that represent directories. Maybe we
624 * could just do a sync if they try an fsync on a directory file.
625 */
626int
627ntfs_fsync(void *v)
628{
629 return (0);
630}
631
632/*
633 * Return POSIX pathconf information applicable to NTFS filesystem
634 */
635int
636ntfs_pathconf(void *v)
637{
638 struct vop_pathconf_args *ap = v;
639 int error = 0;
640
641 switch (ap->a_name) {
642 case _PC_LINK_MAX1:
643 *ap->a_retval = 1;
644 break;
645 case _PC_NAME_MAX4:
646 *ap->a_retval = NTFS_MAXFILENAME255;
647 break;
648 case _PC_CHOWN_RESTRICTED7:
649 *ap->a_retval = 1;
650 break;
651 case _PC_NO_TRUNC8:
652 *ap->a_retval = 0;
653 break;
654 default:
655 error = EINVAL22;
656 break;
657 }
658
659 return (error);
660}
661
662/*
663 * Global vfs data structures
664 */
665const struct vops ntfs_vops = {
666 .vop_getattr = ntfs_getattr,
667 .vop_inactive = ntfs_inactive,
668 .vop_reclaim = ntfs_reclaim,
669 .vop_print = ntfs_print,
670 .vop_pathconf = ntfs_pathconf,
671 .vop_lock = nullop,
672 .vop_unlock = nullop,
673 .vop_islocked = nullop,
674 .vop_lookup = ntfs_lookup,
675 .vop_access = ntfs_access,
676 .vop_close = ntfs_close,
677 .vop_open = ntfs_open,
678 .vop_readdir = ntfs_readdir,
679 .vop_fsync = ntfs_fsync,
680 .vop_bmap = ntfs_bmap,
681 .vop_strategy = ntfs_strategy,
682 .vop_bwrite = vop_generic_bwrite,
683 .vop_read = ntfs_read,
684};