File: | ntfs/ntfs_vnops.c |
Warning: | line 425, column 2 Value stored to 'off' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
59 | int ntfs_read(void *); |
60 | int ntfs_getattr(void *); |
61 | int ntfs_inactive(void *); |
62 | int ntfs_print(void *); |
63 | int ntfs_reclaim(void *); |
64 | int ntfs_strategy(void *); |
65 | int ntfs_access(void *v); |
66 | int ntfs_open(void *v); |
67 | int ntfs_close(void *); |
68 | int ntfs_readdir(void *); |
69 | int ntfs_lookup(void *); |
70 | int ntfs_bmap(void *); |
71 | int ntfs_fsync(void *); |
72 | int ntfs_pathconf(void *); |
73 | |
74 | int 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 | */ |
79 | int |
80 | ntfs_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 | |
94 | int |
95 | ntfs_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 | |
132 | int |
133 | ntfs_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 | */ |
177 | int |
178 | ntfs_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 | */ |
204 | int |
205 | ntfs_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 | |
234 | int |
235 | ntfs_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 | */ |
250 | int |
251 | ntfs_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 | |
301 | int |
302 | ntfs_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 | */ |
371 | int |
372 | ntfs_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 | */ |
394 | int |
395 | ntfs_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 | |
408 | int |
409 | ntfs_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 | */ |
514 | out: |
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 | |
522 | int |
523 | ntfs_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 | */ |
626 | int |
627 | ntfs_fsync(void *v) |
628 | { |
629 | return (0); |
630 | } |
631 | |
632 | /* |
633 | * Return POSIX pathconf information applicable to NTFS filesystem |
634 | */ |
635 | int |
636 | ntfs_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 | */ |
665 | const 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 | }; |