/core/10.5/fusefs/fuse_internal.h

http://macfuse.googlecode.com/ · C Header · 897 lines · 655 code · 164 blank · 78 comment · 81 complexity · 0ae5ecf12e6cd27f7bfa596de5b3a4a4 MD5 · raw file

  1. /*
  2. * Copyright (C) 2006-2008 Google. All Rights Reserved.
  3. * Amit Singh <singh@>
  4. */
  5. #ifndef _FUSE_INTERNAL_H_
  6. #define _FUSE_INTERNAL_H_
  7. #include <kern/clock.h>
  8. #include <sys/types.h>
  9. #include <sys/kauth.h>
  10. #include <sys/kernel_types.h>
  11. #include <sys/mount.h>
  12. #include <sys/stat.h>
  13. #include <sys/ubc.h>
  14. #include <sys/uio.h>
  15. #include <sys/vnode.h>
  16. #include <sys/xattr.h>
  17. #include <fuse_ioctl.h>
  18. #include "fuse_ipc.h"
  19. #include "fuse_kludges.h"
  20. #include "fuse_locking.h"
  21. #include "fuse_node.h"
  22. #if M_MACFUSE_ENABLE_KUNC
  23. #include <UserNotification/KUNCUserNotifications.h>
  24. #else
  25. enum {
  26. kKUNCDefaultResponse = 0,
  27. kKUNCAlternateResponse = 1,
  28. kKUNCOtherResponse = 2,
  29. kKUNCCancelResponse = 3
  30. };
  31. #endif
  32. struct fuse_attr;
  33. struct fuse_data;
  34. struct fuse_dispatcher;
  35. struct fuse_filehandle;
  36. struct fuse_iov;
  37. struct fuse_ticket;
  38. /* time */
  39. #define fuse_timespec_add(vvp, uvp) \
  40. do { \
  41. (vvp)->tv_sec += (uvp)->tv_sec; \
  42. (vvp)->tv_nsec += (uvp)->tv_nsec; \
  43. if ((vvp)->tv_nsec >= 1000000000) { \
  44. (vvp)->tv_sec++; \
  45. (vvp)->tv_nsec -= 1000000000; \
  46. } \
  47. } while (0)
  48. #define fuse_timespec_cmp(tvp, uvp, cmp) \
  49. (((tvp)->tv_sec == (uvp)->tv_sec) ? \
  50. ((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \
  51. ((tvp)->tv_sec cmp (uvp)->tv_sec))
  52. /* miscellaneous */
  53. #if M_MACFUSE_ENABLE_UNSUPPORTED
  54. extern const char *vnode_getname(vnode_t vp);
  55. extern void vnode_putname(const char *name);
  56. #endif /* M_MACFUSE_ENABLE_UNSUPPORTED */
  57. static __inline__
  58. int
  59. fuse_match_cred(kauth_cred_t daemoncred, kauth_cred_t requestcred)
  60. {
  61. if ((daemoncred->cr_uid == requestcred->cr_uid) &&
  62. (daemoncred->cr_uid == requestcred->cr_ruid) &&
  63. // THINK_ABOUT_THIS_LATER
  64. // (daemoncred->cr_uid == requestcred->cr_svuid) &&
  65. (daemoncred->cr_groups[0] == requestcred->cr_groups[0]) &&
  66. (daemoncred->cr_groups[0] == requestcred->cr_rgid) &&
  67. (daemoncred->cr_groups[0] == requestcred->cr_svgid)) {
  68. return 0;
  69. }
  70. return EPERM;
  71. }
  72. static __inline__
  73. int
  74. fuse_vfs_context_issuser(vfs_context_t context)
  75. {
  76. return (vfs_context_ucred(context)->cr_uid == 0);
  77. }
  78. static __inline__
  79. int
  80. fuse_isautocache_mp(mount_t mp)
  81. {
  82. return (fuse_get_mpdata(mp)->dataflags & FSESS_AUTO_CACHE);
  83. }
  84. #define fuse_isdeadfs_nop(vp) 0
  85. static __inline__
  86. int
  87. fuse_isdeadfs_mp(mount_t mp)
  88. {
  89. return (fuse_get_mpdata(mp)->dataflags & FSESS_DEAD);
  90. }
  91. static __inline__
  92. int
  93. fuse_isdeadfs(vnode_t vp)
  94. {
  95. if (VTOFUD(vp)->flag & FN_REVOKED) {
  96. return 1;
  97. }
  98. return fuse_isdeadfs_mp(vnode_mount(vp));
  99. }
  100. static __inline__
  101. int
  102. fuse_isdeadfs_fs(vnode_t vp)
  103. {
  104. return fuse_isdeadfs_mp(vnode_mount(vp));
  105. }
  106. static __inline__
  107. int
  108. fuse_isdirectio(vnode_t vp)
  109. {
  110. /* Try global first. */
  111. if (fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_DIRECT_IO) {
  112. return 1;
  113. }
  114. return (VTOFUD(vp)->flag & FN_DIRECT_IO);
  115. }
  116. static __inline__
  117. int
  118. fuse_isdirectio_mp(mount_t mp)
  119. {
  120. return (fuse_get_mpdata(mp)->dataflags & FSESS_DIRECT_IO);
  121. }
  122. static __inline__
  123. int
  124. fuse_isnoattrcache(vnode_t vp)
  125. {
  126. /* Try global first. */
  127. if (fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_NO_ATTRCACHE) {
  128. return 1;
  129. }
  130. return 0;
  131. }
  132. static __inline__
  133. int
  134. fuse_isnoattrcache_mp(mount_t mp)
  135. {
  136. return (fuse_get_mpdata(mp)->dataflags & FSESS_NO_ATTRCACHE);
  137. }
  138. static __inline__
  139. int
  140. fuse_isnoreadahead(vnode_t vp)
  141. {
  142. /* Try global first. */
  143. if (fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_NO_READAHEAD) {
  144. return 1;
  145. }
  146. /* In our model, direct_io implies no readahead. */
  147. return fuse_isdirectio(vp);
  148. }
  149. static __inline__
  150. int
  151. fuse_isnosynconclose(vnode_t vp)
  152. {
  153. if (fuse_isdirectio(vp)) {
  154. return 0;
  155. }
  156. return (fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_NO_SYNCONCLOSE);
  157. }
  158. static __inline__
  159. int
  160. fuse_isnosyncwrites_mp(mount_t mp)
  161. {
  162. /* direct_io implies we won't have nosyncwrites. */
  163. if (fuse_isdirectio_mp(mp)) {
  164. return 0;
  165. }
  166. return (fuse_get_mpdata(mp)->dataflags & FSESS_NO_SYNCWRITES);
  167. }
  168. static __inline__
  169. void
  170. fuse_setnosyncwrites_mp(mount_t mp)
  171. {
  172. vfs_clearflags(mp, MNT_SYNCHRONOUS);
  173. vfs_setflags(mp, MNT_ASYNC);
  174. fuse_get_mpdata(mp)->dataflags |= FSESS_NO_SYNCWRITES;
  175. }
  176. static __inline__
  177. void
  178. fuse_clearnosyncwrites_mp(mount_t mp)
  179. {
  180. if (!vfs_issynchronous(mp)) {
  181. vfs_clearflags(mp, MNT_ASYNC);
  182. vfs_setflags(mp, MNT_SYNCHRONOUS);
  183. fuse_get_mpdata(mp)->dataflags &= ~FSESS_NO_SYNCWRITES;
  184. }
  185. }
  186. static __inline__
  187. int
  188. fuse_isnoubc(vnode_t vp)
  189. {
  190. /* Try global first. */
  191. if (fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_NO_UBC) {
  192. return 1;
  193. }
  194. /* In our model, direct_io implies no UBC. */
  195. return fuse_isdirectio(vp);
  196. }
  197. static __inline__
  198. int
  199. fuse_isnoubc_mp(mount_t mp)
  200. {
  201. return (fuse_get_mpdata(mp)->dataflags & FSESS_NO_UBC);
  202. }
  203. static __inline__
  204. int
  205. fuse_isnegativevncache_mp(mount_t mp)
  206. {
  207. return (fuse_get_mpdata(mp)->dataflags & FSESS_NEGATIVE_VNCACHE);
  208. }
  209. static __inline__
  210. int
  211. fuse_isnovncache(vnode_t vp)
  212. {
  213. /* Try global first. */
  214. if (fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_NO_VNCACHE) {
  215. return 1;
  216. }
  217. /* In our model, direct_io implies no vncache for this vnode. */
  218. return fuse_isdirectio(vp);
  219. }
  220. static __inline__
  221. int
  222. fuse_isnovncache_mp(mount_t mp)
  223. {
  224. return (fuse_get_mpdata(mp)->dataflags & FSESS_NO_VNCACHE);
  225. }
  226. static __inline__
  227. int
  228. fuse_isextendedsecurity(vnode_t vp)
  229. {
  230. return (fuse_get_mpdata(vnode_mount(vp))->dataflags & \
  231. FSESS_EXTENDED_SECURITY);
  232. }
  233. static __inline__
  234. int
  235. fuse_isextendedsecurity_mp(mount_t mp)
  236. {
  237. return (fuse_get_mpdata(mp)->dataflags & FSESS_EXTENDED_SECURITY);
  238. }
  239. static __inline__
  240. int
  241. fuse_isdefaultpermissions(vnode_t vp)
  242. {
  243. return (fuse_get_mpdata(vnode_mount(vp))->dataflags & \
  244. FSESS_DEFAULT_PERMISSIONS);
  245. }
  246. static __inline__
  247. int
  248. fuse_isdefaultpermissions_mp(mount_t mp)
  249. {
  250. return (fuse_get_mpdata(mp)->dataflags & FSESS_DEFAULT_PERMISSIONS);
  251. }
  252. static __inline__
  253. int
  254. fuse_isdeferpermissions(vnode_t vp)
  255. {
  256. return (fuse_get_mpdata(vnode_mount(vp))->dataflags & \
  257. FSESS_DEFER_PERMISSIONS);
  258. }
  259. static __inline__
  260. int
  261. fuse_isdeferpermissions_mp(mount_t mp)
  262. {
  263. return (fuse_get_mpdata(mp)->dataflags & FSESS_DEFER_PERMISSIONS);
  264. }
  265. static __inline__
  266. int
  267. fuse_isxtimes(vnode_t vp)
  268. {
  269. return (fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_XTIMES);
  270. }
  271. static __inline__
  272. int
  273. fuse_isxtimes_mp(mount_t mp)
  274. {
  275. return (fuse_get_mpdata(mp)->dataflags & FSESS_XTIMES);
  276. }
  277. static __inline__
  278. int
  279. fuse_issparse_mp(mount_t mp)
  280. {
  281. return (fuse_get_mpdata(mp)->dataflags & FSESS_SPARSE);
  282. }
  283. static __inline__
  284. uint32_t
  285. fuse_round_powerof2(uint32_t size)
  286. {
  287. uint32_t result = 512;
  288. size = size & 0x7FFFFFFFU; /* clip at 2G */
  289. while (result < size) {
  290. result <<= 1;
  291. }
  292. return result;
  293. }
  294. static __inline__
  295. uint32_t
  296. fuse_round_size(uint32_t size, uint32_t b_min, uint32_t b_max)
  297. {
  298. uint32_t candidate = fuse_round_powerof2(size);
  299. /* We assume that b_min and b_max will already be powers of 2. */
  300. if (candidate < b_min) {
  301. candidate = b_min;
  302. }
  303. if (candidate > b_max) {
  304. candidate = b_max;
  305. }
  306. return candidate;
  307. }
  308. static __inline__
  309. int
  310. fuse_skip_apple_double_mp(mount_t mp, char *nameptr, long namelen)
  311. {
  312. #define DS_STORE ".DS_Store"
  313. int ismpoption = fuse_get_mpdata(mp)->dataflags & FSESS_NO_APPLEDOUBLE;
  314. if (ismpoption && nameptr) {
  315. /* This _will_ allow just "._", that is, a namelen of 2. */
  316. if (namelen > 2) {
  317. if ((namelen == ((sizeof(DS_STORE)/sizeof(char)) - 1)) &&
  318. (bcmp(nameptr, DS_STORE, sizeof(DS_STORE)) == 0)) {
  319. return 1;
  320. } else if (nameptr[0] == '.' && nameptr[1] == '_') {
  321. return 1;
  322. }
  323. }
  324. }
  325. return 0;
  326. }
  327. static __inline__
  328. int
  329. fuse_blanket_deny(vnode_t vp, vfs_context_t context)
  330. {
  331. mount_t mp = vnode_mount(vp);
  332. struct fuse_data *data = fuse_get_mpdata(mp);
  333. int issuser = fuse_vfs_context_issuser(context);
  334. int isvroot = vnode_isvroot(vp);
  335. /* if allow_other is set */
  336. if (data->dataflags & FSESS_ALLOW_OTHER) {
  337. return 0;
  338. }
  339. /* if allow_root is set */
  340. if (issuser && (data->dataflags & FSESS_ALLOW_ROOT)) {
  341. return 0;
  342. }
  343. /* if this is the user who mounted the fs */
  344. if (fuse_match_cred(data->daemoncred, vfs_context_ucred(context)) == 0) {
  345. return 0;
  346. }
  347. if (!(data->dataflags & FSESS_INITED) && isvroot && issuser) {
  348. return 0;
  349. }
  350. if (fuse_isdeadfs(vp) && isvroot) {
  351. return 0;
  352. }
  353. /* If kernel itself, allow. */
  354. if (vfs_context_pid(context) == 0) {
  355. return 0;
  356. }
  357. return 1;
  358. }
  359. #define CHECK_BLANKET_DENIAL(vp, context, err) \
  360. { \
  361. if (fuse_blanket_deny(vp, context)) { \
  362. return err; \
  363. } \
  364. }
  365. /* access */
  366. /* FN_ACCESS_NOOP is in fuse_node.h */
  367. #define FACCESS_VA_VALID 0x00000001
  368. #define FACCESS_DO_ACCESS 0x00000002
  369. #define FACCESS_NOCHECKSPY 0x00000004
  370. #define FACCESS_FROM_VNOP 0x00000008
  371. struct fuse_access_param {
  372. uid_t xuid;
  373. gid_t xgid;
  374. uint32_t facc_flags;
  375. };
  376. int
  377. fuse_internal_access(vnode_t vp,
  378. int action,
  379. vfs_context_t context,
  380. struct fuse_access_param *facp);
  381. /* attributes */
  382. int
  383. fuse_internal_loadxtimes(vnode_t vp, struct vnode_attr *out_vap,
  384. vfs_context_t context);
  385. int
  386. fuse_internal_attr_vat2fsai(mount_t mp,
  387. vnode_t vp,
  388. struct vnode_attr *vap,
  389. struct fuse_setattr_in *fsai,
  390. uint64_t *newsize);
  391. static __inline__
  392. void
  393. fuse_internal_attr_fat2vat(vnode_t vp,
  394. struct fuse_attr *fat,
  395. struct vnode_attr *vap)
  396. {
  397. struct timespec t;
  398. mount_t mp = vnode_mount(vp);
  399. struct fuse_data *data = fuse_get_mpdata(mp);
  400. struct fuse_vnode_data *fvdat = VTOFUD(vp);
  401. VATTR_INIT(vap);
  402. VATTR_RETURN(vap, va_fsid, vfs_statfs(mp)->f_fsid.val[0]);
  403. VATTR_RETURN(vap, va_fileid, fat->ino);
  404. VATTR_RETURN(vap, va_linkid, fat->ino);
  405. /*
  406. * If we have asynchronous writes enabled, our local in-kernel size
  407. * takes precedence over what the daemon thinks.
  408. */
  409. /* ATTR_FUDGE_CASE */
  410. if (!vfs_issynchronous(mp)) {
  411. fat->size = fvdat->filesize;
  412. }
  413. VATTR_RETURN(vap, va_data_size, fat->size);
  414. /*
  415. * The kernel will compute the following for us if we leave them
  416. * untouched (and have sane values in statvfs):
  417. *
  418. * va_total_size
  419. * va_data_alloc
  420. * va_total_alloc
  421. */
  422. if (fuse_issparse_mp(mp)) {
  423. VATTR_RETURN(vap, va_data_alloc, fat->blocks);
  424. }
  425. t.tv_sec = (typeof(t.tv_sec))fat->atime; /* XXX: truncation */
  426. t.tv_nsec = fat->atimensec;
  427. VATTR_RETURN(vap, va_access_time, t);
  428. t.tv_sec = (typeof(t.tv_sec))fat->ctime; /* XXX: truncation */
  429. t.tv_nsec = fat->ctimensec;
  430. VATTR_RETURN(vap, va_change_time, t);
  431. t.tv_sec = (typeof(t.tv_sec))fat->mtime; /* XXX: truncation */
  432. t.tv_nsec = fat->mtimensec;
  433. VATTR_RETURN(vap, va_modify_time, t);
  434. t.tv_sec = (typeof(t.tv_sec))fat->crtime; /* XXX: truncation */
  435. t.tv_nsec = fat->crtimensec;
  436. VATTR_RETURN(vap, va_create_time, t);
  437. VATTR_RETURN(vap, va_mode, fat->mode & ~S_IFMT);
  438. VATTR_RETURN(vap, va_nlink, fat->nlink);
  439. VATTR_RETURN(vap, va_uid, fat->uid);
  440. VATTR_RETURN(vap, va_gid, fat->gid);
  441. VATTR_RETURN(vap, va_rdev, fat->rdev);
  442. /*
  443. * If the file in question has ACLs, we record that knowledge here:
  444. *
  445. * VTOFUD(vp)->flag |= FN_HAS_ACL;
  446. */
  447. VATTR_RETURN(vap, va_type, IFTOVT(fat->mode));
  448. VATTR_RETURN(vap, va_iosize, data->iosize);
  449. VATTR_RETURN(vap, va_flags, fat->flags);
  450. }
  451. static __inline__
  452. void
  453. fuse_internal_attr_loadvap(vnode_t vp, struct vnode_attr *out_vap,
  454. vfs_context_t context)
  455. {
  456. mount_t mp = vnode_mount(vp);
  457. struct vnode_attr *in_vap = VTOVA(vp);
  458. struct fuse_vnode_data *fvdat = VTOFUD(vp);
  459. int purged = 0;
  460. long hint = 0;
  461. if (in_vap == out_vap) {
  462. return;
  463. }
  464. VATTR_RETURN(out_vap, va_fsid, in_vap->va_fsid);
  465. VATTR_RETURN(out_vap, va_fileid, in_vap->va_fileid);
  466. VATTR_RETURN(out_vap, va_linkid, in_vap->va_linkid);
  467. VATTR_RETURN(out_vap, va_gen,
  468. (typeof(out_vap->va_gen))fvdat->generation); /* XXX: truncation */
  469. if (!vnode_isvroot(vp)) {
  470. /*
  471. * If we do return va_parentid for our root vnode, things get
  472. * a bit too interesting for the Finder.
  473. */
  474. VATTR_RETURN(out_vap, va_parentid, fvdat->parent_nodeid);
  475. }
  476. /*
  477. * If we have asynchronous writes enabled, our local in-kernel size
  478. * takes precedence over what the daemon thinks.
  479. */
  480. /* ATTR_FUDGE_CASE */
  481. if (!vfs_issynchronous(mp)) {
  482. /* Bring in_vap up to date if need be. */
  483. VATTR_RETURN(in_vap, va_data_size, fvdat->filesize);
  484. } else {
  485. /* The size might have changed remotely. */
  486. if (fvdat->filesize != (off_t)in_vap->va_data_size) {
  487. hint |= NOTE_WRITE;
  488. /* Remote size overrides what we have. */
  489. (void)ubc_msync(vp, (off_t)0, fvdat->filesize, (off_t*)0,
  490. UBC_PUSHALL | UBC_INVALIDATE | UBC_SYNC);
  491. purged = 1;
  492. if (fvdat->filesize > (off_t)in_vap->va_data_size) {
  493. hint |= NOTE_EXTEND;
  494. }
  495. fvdat->filesize = in_vap->va_data_size;
  496. ubc_setsize(vp, fvdat->filesize);
  497. }
  498. }
  499. VATTR_RETURN(out_vap, va_data_size, in_vap->va_data_size);
  500. if (fuse_issparse_mp(mp)) {
  501. VATTR_RETURN(out_vap, va_data_alloc, in_vap->va_data_alloc);
  502. }
  503. VATTR_RETURN(out_vap, va_mode, in_vap->va_mode);
  504. VATTR_RETURN(out_vap, va_nlink, in_vap->va_nlink);
  505. VATTR_RETURN(out_vap, va_uid, in_vap->va_uid);
  506. VATTR_RETURN(out_vap, va_gid, in_vap->va_gid);
  507. VATTR_RETURN(out_vap, va_rdev, in_vap->va_rdev);
  508. VATTR_RETURN(out_vap, va_type, in_vap->va_type);
  509. VATTR_RETURN(out_vap, va_iosize, in_vap->va_iosize);
  510. VATTR_RETURN(out_vap, va_flags, in_vap->va_flags);
  511. VATTR_RETURN(out_vap, va_access_time, in_vap->va_access_time);
  512. VATTR_RETURN(out_vap, va_change_time, in_vap->va_change_time);
  513. VATTR_RETURN(out_vap, va_modify_time, in_vap->va_modify_time);
  514. /*
  515. * When __DARWIN_64_BIT_INO_T is not enabled, the User library
  516. * will set va_create_time to -1. In that case, we will have
  517. * to ask for it separately, if necessary.
  518. */
  519. if (in_vap->va_create_time.tv_sec != (int64_t)-1) {
  520. VATTR_RETURN(out_vap, va_create_time, in_vap->va_create_time);
  521. }
  522. if ((fvdat->modify_time.tv_sec != in_vap->va_modify_time.tv_sec) ||
  523. (fvdat->modify_time.tv_nsec != in_vap->va_modify_time.tv_nsec)) {
  524. fvdat->modify_time.tv_sec = in_vap->va_modify_time.tv_sec;
  525. fvdat->modify_time.tv_nsec = in_vap->va_modify_time.tv_nsec;
  526. hint |= NOTE_ATTRIB;
  527. if (fuse_isautocache_mp(mp) && !purged) {
  528. (void)ubc_msync(vp, (off_t)0, fvdat->filesize, (off_t*)0,
  529. UBC_PUSHALL | UBC_INVALIDATE | UBC_SYNC);
  530. }
  531. }
  532. if (VATTR_IS_ACTIVE(out_vap, va_backup_time) ||
  533. (VATTR_IS_ACTIVE(out_vap, va_create_time) &&
  534. !VATTR_IS_SUPPORTED(out_vap, va_create_time))) {
  535. (void)fuse_internal_loadxtimes(vp, out_vap, context);
  536. }
  537. if (hint) {
  538. FUSE_KNOTE(vp, hint);
  539. }
  540. }
  541. #define cache_attrs(vp, fuse_out) do { \
  542. struct timespec uptsp_ ## __func__; \
  543. \
  544. /* XXX: truncation; user space sends us a 64-bit tv_sec */ \
  545. VTOFUD(vp)->attr_valid.tv_sec = (time_t)(fuse_out)->attr_valid; \
  546. VTOFUD(vp)->attr_valid.tv_nsec = (fuse_out)->attr_valid_nsec; \
  547. nanouptime(&uptsp_ ## __func__); \
  548. \
  549. fuse_timespec_add(&VTOFUD(vp)->attr_valid, &uptsp_ ## __func__); \
  550. \
  551. fuse_internal_attr_fat2vat(vp, &(fuse_out)->attr, VTOVA(vp)); \
  552. } while (0)
  553. #if M_MACFUSE_ENABLE_EXCHANGE
  554. /* exchange */
  555. int
  556. fuse_internal_exchange(vnode_t fvp,
  557. const char *fname,
  558. size_t flen,
  559. vnode_t tvp,
  560. const char *tname,
  561. size_t tlen,
  562. int options,
  563. vfs_context_t context);
  564. #endif /* M_MACFUSE_ENABLE_EXCHANGE */
  565. /* fsync */
  566. int
  567. fuse_internal_fsync(vnode_t vp,
  568. vfs_context_t context,
  569. struct fuse_filehandle *fufh,
  570. void *param,
  571. fuse_op_waitfor_t waitfor);
  572. int
  573. fuse_internal_fsync_callback(struct fuse_ticket *ftick, uio_t uio);
  574. /* ioctl */
  575. int
  576. fuse_internal_ioctl_avfi(vnode_t vp,
  577. vfs_context_t context,
  578. struct fuse_avfi_ioctl *avfi);
  579. /* readdir */
  580. struct pseudo_dirent {
  581. uint32_t d_namlen;
  582. };
  583. int
  584. fuse_internal_readdir(vnode_t vp,
  585. uio_t uio,
  586. vfs_context_t context,
  587. struct fuse_filehandle *fufh,
  588. struct fuse_iov *cookediov,
  589. int *numdirent);
  590. int
  591. fuse_internal_readdir_processdata(vnode_t vp,
  592. uio_t uio,
  593. size_t reqsize,
  594. void *buf,
  595. size_t bufsize,
  596. struct fuse_iov *cookediov,
  597. int *numdirent);
  598. /* remove */
  599. int
  600. fuse_internal_remove(vnode_t dvp,
  601. vnode_t vp,
  602. struct componentname *cnp,
  603. enum fuse_opcode op,
  604. vfs_context_t context);
  605. /* rename */
  606. int
  607. fuse_internal_rename(vnode_t fdvp,
  608. vnode_t fvp,
  609. struct componentname *fcnp,
  610. vnode_t tdvp,
  611. vnode_t tvp,
  612. struct componentname *tcnp,
  613. vfs_context_t context);
  614. /* revoke */
  615. int
  616. fuse_internal_revoke(vnode_t vp, int flags, vfs_context_t context, int how);
  617. void
  618. fuse_internal_vnode_disappear(vnode_t vp, vfs_context_t context, int how);
  619. /* strategy */
  620. int
  621. fuse_internal_strategy(vnode_t vp, buf_t bp);
  622. errno_t
  623. fuse_internal_strategy_buf(struct vnop_strategy_args *ap);
  624. /* xattr */
  625. static __inline__
  626. int
  627. fuse_skip_apple_xattr_mp(mount_t mp, const char *name)
  628. {
  629. int ismpoption = fuse_get_mpdata(mp)->dataflags & FSESS_NO_APPLEXATTR;
  630. if (ismpoption && name) {
  631. #define COM_APPLE_ "com.apple."
  632. if (bcmp(name, COM_APPLE_, sizeof(COM_APPLE_) - 1) == 0) {
  633. return 1;
  634. }
  635. }
  636. return 0;
  637. }
  638. /* entity creation */
  639. static __inline__
  640. int
  641. fuse_internal_checkentry(struct fuse_entry_out *feo, enum vtype vtype)
  642. {
  643. if (vtype != IFTOVT(feo->attr.mode)) {
  644. return EINVAL;
  645. }
  646. if (feo->nodeid == FUSE_NULL_ID) {
  647. return EINVAL;
  648. }
  649. if (feo->nodeid == FUSE_ROOT_ID) {
  650. return EINVAL;
  651. }
  652. return 0;
  653. }
  654. int
  655. fuse_internal_newentry(vnode_t dvp,
  656. vnode_t *vpp,
  657. struct componentname *cnp,
  658. enum fuse_opcode op,
  659. void *buf,
  660. size_t bufsize,
  661. enum vtype vtype,
  662. vfs_context_t context);
  663. void
  664. fuse_internal_newentry_makerequest(mount_t mp,
  665. uint64_t dnid,
  666. struct componentname *cnp,
  667. enum fuse_opcode op,
  668. void *buf,
  669. size_t bufsize,
  670. struct fuse_dispatcher *fdip,
  671. vfs_context_t context);
  672. int
  673. fuse_internal_newentry_core(vnode_t dvp,
  674. vnode_t *vpp,
  675. struct componentname *cnp,
  676. enum vtype vtyp,
  677. struct fuse_dispatcher *fdip,
  678. vfs_context_t context);
  679. /* entity destruction */
  680. int
  681. fuse_internal_forget_callback(struct fuse_ticket *ftick, uio_t uio);
  682. void
  683. fuse_internal_forget_send(mount_t mp,
  684. vfs_context_t context,
  685. uint64_t nodeid,
  686. uint64_t nlookup,
  687. struct fuse_dispatcher *fdip);
  688. void
  689. fuse_internal_interrupt_send(struct fuse_ticket *ftick);
  690. enum {
  691. REVOKE_NONE = 0,
  692. REVOKE_SOFT = 1,
  693. REVOKE_HARD = 2,
  694. };
  695. /* fuse start/stop */
  696. int fuse_internal_init_synchronous(struct fuse_ticket *ftick);
  697. int fuse_internal_send_init(struct fuse_data *data, vfs_context_t context);
  698. /* other */
  699. static __inline__
  700. int
  701. fuse_implemented(struct fuse_data *data, uint64_t which)
  702. {
  703. int result;
  704. /* FUSE_DATA_LOCK_SHARED(data); */
  705. result = (int)!(data->noimplflags & which);
  706. /* FUSE_DATA_UNLOCK_SHARED(data); */
  707. return result;
  708. }
  709. static __inline__
  710. void
  711. fuse_clear_implemented(struct fuse_data *data, uint64_t which)
  712. {
  713. /* FUSE_DATA_LOCK_EXCLUSIVE(data); */
  714. data->noimplflags |= which;
  715. /* FUSE_DATA_UNLOCK_EXCLUSIVE(data); */
  716. }
  717. static __inline__
  718. int
  719. fuse_set_implemented_custom(struct fuse_data *data, uint64_t flags)
  720. {
  721. if (!data) {
  722. return EINVAL;
  723. }
  724. FUSE_DATA_LOCK_EXCLUSIVE(data);
  725. data->noimplflags = flags;
  726. FUSE_DATA_UNLOCK_EXCLUSIVE(data);
  727. return 0;
  728. }
  729. void
  730. fuse_internal_print_vnodes(mount_t mp);
  731. void
  732. fuse_preflight_log(vnode_t vp, fufh_type_t fufh_type, int err, char *message);
  733. #endif /* _FUSE_INTERNAL_H_ */