ntfs_vnops.c 18 KB

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