You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1297 lines
27 KiB

  1. /*
  2. ISC License
  3. Copyright (c) 2021, Antonio SJ Musumeci <trapexit@spawn.link>
  4. Permission to use, copy, modify, and/or distribute this software for any
  5. purpose with or without fee is hereby granted, provided that the above
  6. copyright notice and this permission notice appear in all copies.
  7. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. */
  15. #ifndef _GNU_SOURCE
  16. #define _GNU_SOURCE
  17. #endif
  18. #include "fuse_kernel.h"
  19. #include <errno.h>
  20. #include <fcntl.h>
  21. #include <inttypes.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. static FILE *g_OUTPUT = NULL;
  25. #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
  26. static
  27. int
  28. debug_set_output_null()
  29. {
  30. g_OUTPUT = stderr;
  31. setvbuf(g_OUTPUT,NULL,_IOLBF,0);
  32. return 0;
  33. }
  34. static
  35. int
  36. debug_set_output_filepath(const char *filepath_)
  37. {
  38. FILE *tmp;
  39. tmp = fopen(filepath_,"a");
  40. if(tmp == NULL)
  41. return -errno;
  42. g_OUTPUT = tmp;
  43. setvbuf(g_OUTPUT,NULL,_IOLBF,0);
  44. return 0;
  45. }
  46. int
  47. debug_set_output(const char *filepath_)
  48. {
  49. if(filepath_ == NULL)
  50. return debug_set_output_null();
  51. return debug_set_output_filepath(filepath_);
  52. }
  53. static
  54. __attribute__((constructor))
  55. void
  56. debug_constructor(void)
  57. {
  58. debug_set_output(NULL);
  59. }
  60. static
  61. const
  62. char*
  63. open_accmode_to_str(const int flags_)
  64. {
  65. switch(flags_ & O_ACCMODE)
  66. {
  67. case O_RDWR:
  68. return "O_RDWR";
  69. case O_RDONLY:
  70. return "O_RDONLY";
  71. case O_WRONLY:
  72. return "O_WRONLY";
  73. }
  74. return "";
  75. }
  76. #define FUSE_WRITE_FLAG_CASE(X) case FUSE_WRITE_##X: return #X
  77. static
  78. const
  79. char*
  80. fuse_write_flag_to_str(const uint32_t offset_)
  81. {
  82. switch(1 << offset_)
  83. {
  84. FUSE_WRITE_FLAG_CASE(CACHE);
  85. FUSE_WRITE_FLAG_CASE(LOCKOWNER);
  86. FUSE_WRITE_FLAG_CASE(KILL_PRIV);
  87. }
  88. return NULL;
  89. }
  90. #undef FUSE_WRITE_FLAG_CASE
  91. #define OPEN_FLAG_CASE(X) case X: return #X
  92. static
  93. const
  94. char*
  95. open_flag_to_str(const uint64_t offset_)
  96. {
  97. switch(1 << offset_)
  98. {
  99. OPEN_FLAG_CASE(O_APPEND);
  100. OPEN_FLAG_CASE(O_ASYNC);
  101. OPEN_FLAG_CASE(O_CLOEXEC);
  102. OPEN_FLAG_CASE(O_CREAT);
  103. OPEN_FLAG_CASE(O_DIRECT);
  104. OPEN_FLAG_CASE(O_DIRECTORY);
  105. #ifdef O_DSYNC
  106. OPEN_FLAG_CASE(O_DSYNC);
  107. #endif
  108. OPEN_FLAG_CASE(O_EXCL);
  109. #ifdef O_LARGEFILE
  110. OPEN_FLAG_CASE(O_LARGEFILE);
  111. #endif
  112. #ifdef O_NOATIME
  113. OPEN_FLAG_CASE(O_NOATIME);
  114. #endif
  115. OPEN_FLAG_CASE(O_NOCTTY);
  116. OPEN_FLAG_CASE(O_NOFOLLOW);
  117. OPEN_FLAG_CASE(O_NONBLOCK);
  118. #ifdef O_PATH
  119. OPEN_FLAG_CASE(O_PATH);
  120. #endif
  121. OPEN_FLAG_CASE(O_SYNC);
  122. #ifdef O_TMPFILE
  123. OPEN_FLAG_CASE(O_TMPFILE);
  124. #endif
  125. OPEN_FLAG_CASE(O_TRUNC);
  126. }
  127. return NULL;
  128. }
  129. #undef OPEN_FLAG_CASE
  130. #define FUSE_INIT_FLAG_CASE(X) case FUSE_##X: return #X
  131. static
  132. const
  133. char*
  134. fuse_flag_to_str(const uint64_t offset_)
  135. {
  136. switch(1ULL << offset_)
  137. {
  138. FUSE_INIT_FLAG_CASE(ASYNC_READ);
  139. FUSE_INIT_FLAG_CASE(POSIX_LOCKS);
  140. FUSE_INIT_FLAG_CASE(FILE_OPS);
  141. FUSE_INIT_FLAG_CASE(ATOMIC_O_TRUNC);
  142. FUSE_INIT_FLAG_CASE(EXPORT_SUPPORT);
  143. FUSE_INIT_FLAG_CASE(BIG_WRITES);
  144. FUSE_INIT_FLAG_CASE(DONT_MASK);
  145. FUSE_INIT_FLAG_CASE(SPLICE_WRITE);
  146. FUSE_INIT_FLAG_CASE(SPLICE_MOVE);
  147. FUSE_INIT_FLAG_CASE(SPLICE_READ);
  148. FUSE_INIT_FLAG_CASE(FLOCK_LOCKS);
  149. FUSE_INIT_FLAG_CASE(HAS_IOCTL_DIR);
  150. FUSE_INIT_FLAG_CASE(AUTO_INVAL_DATA);
  151. FUSE_INIT_FLAG_CASE(DO_READDIRPLUS);
  152. FUSE_INIT_FLAG_CASE(READDIRPLUS_AUTO);
  153. FUSE_INIT_FLAG_CASE(ASYNC_DIO);
  154. FUSE_INIT_FLAG_CASE(WRITEBACK_CACHE);
  155. FUSE_INIT_FLAG_CASE(NO_OPEN_SUPPORT);
  156. FUSE_INIT_FLAG_CASE(PARALLEL_DIROPS);
  157. FUSE_INIT_FLAG_CASE(HANDLE_KILLPRIV);
  158. FUSE_INIT_FLAG_CASE(POSIX_ACL);
  159. FUSE_INIT_FLAG_CASE(ABORT_ERROR);
  160. FUSE_INIT_FLAG_CASE(MAX_PAGES);
  161. FUSE_INIT_FLAG_CASE(CACHE_SYMLINKS);
  162. FUSE_INIT_FLAG_CASE(NO_OPENDIR_SUPPORT);
  163. FUSE_INIT_FLAG_CASE(EXPLICIT_INVAL_DATA);
  164. FUSE_INIT_FLAG_CASE(MAP_ALIGNMENT);
  165. FUSE_INIT_FLAG_CASE(SUBMOUNTS);
  166. FUSE_INIT_FLAG_CASE(HANDLE_KILLPRIV_V2);
  167. FUSE_INIT_FLAG_CASE(SETXATTR_EXT);
  168. FUSE_INIT_FLAG_CASE(INIT_EXT);
  169. FUSE_INIT_FLAG_CASE(INIT_RESERVED);
  170. FUSE_INIT_FLAG_CASE(SECURITY_CTX);
  171. FUSE_INIT_FLAG_CASE(HAS_INODE_DAX);
  172. FUSE_INIT_FLAG_CASE(CREATE_SUPP_GROUP);
  173. FUSE_INIT_FLAG_CASE(HAS_EXPIRE_ONLY);
  174. FUSE_INIT_FLAG_CASE(DIRECT_IO_ALLOW_MMAP);
  175. }
  176. return NULL;
  177. }
  178. #undef FUSE_INIT_FLAG_CASE
  179. static
  180. void
  181. debug_open_flags(const uint32_t flags_)
  182. {
  183. fprintf(stderr,"%s, ",open_accmode_to_str(flags_));
  184. for(size_t i = 0; i < (sizeof(flags_) * 8); i++)
  185. {
  186. const char *str;
  187. if(!(flags_ & (1 << i)))
  188. continue;
  189. str = open_flag_to_str(i);
  190. if(str == NULL)
  191. continue;
  192. fprintf(stderr,"%s, ",str);
  193. }
  194. }
  195. #define FOPEN_FLAG_CASE(X) case FOPEN_##X: return #X
  196. static
  197. const
  198. char*
  199. fuse_fopen_flag_to_str(const uint32_t offset_)
  200. {
  201. switch(1 << offset_)
  202. {
  203. FOPEN_FLAG_CASE(DIRECT_IO);
  204. FOPEN_FLAG_CASE(KEEP_CACHE);
  205. FOPEN_FLAG_CASE(NONSEEKABLE);
  206. FOPEN_FLAG_CASE(CACHE_DIR);
  207. FOPEN_FLAG_CASE(STREAM);
  208. }
  209. return NULL;
  210. }
  211. #undef FOPEN_FLAG_CASE
  212. void
  213. debug_fuse_open_out(const struct fuse_open_out *arg_)
  214. {
  215. fprintf(stderr,
  216. "fuse_open_out:"
  217. " fh=0x%" PRIx64 ";"
  218. " open_flags=0x%X (",
  219. arg_->fh,
  220. arg_->open_flags);
  221. for(size_t i = 0; i < (sizeof(arg_->open_flags) * 8); i++)
  222. {
  223. const char *str;
  224. if(!(arg_->open_flags & (1 << i)))
  225. continue;
  226. str = fuse_fopen_flag_to_str(i);
  227. if(str == NULL)
  228. continue;
  229. fprintf(stderr,"%s,",str);
  230. }
  231. fprintf(stderr,");\n");
  232. }
  233. static
  234. void
  235. debug_fuse_lookup(const void *arg_)
  236. {
  237. const char *name = (const char*)arg_;
  238. fprintf(g_OUTPUT,
  239. "fuse_lookup:"
  240. " name=%s;"
  241. "\n"
  242. ,
  243. name);
  244. }
  245. static
  246. void
  247. debug_fuse_getattr_in(const void *arg_)
  248. {
  249. const struct fuse_getattr_in *arg = (const fuse_getattr_in*)arg_;
  250. fprintf(g_OUTPUT,
  251. "fuse_getattr_in:"
  252. " getattr_flags=0x%08X;"
  253. " fh=0x%" PRIx64 ";\n",
  254. arg->getattr_flags,
  255. arg->fh);
  256. }
  257. static
  258. void
  259. debug_fuse_setattr_in(const void *arg_)
  260. {
  261. const struct fuse_setattr_in *arg = (const fuse_setattr_in*)arg_;
  262. fprintf(g_OUTPUT,
  263. "fuse_setattr_in:"
  264. " valid=%u;"
  265. " fh=0x%" PRIx64 ";"
  266. " size=%zu;"
  267. " lock_owner=%zu;"
  268. " atime=%zu;"
  269. " atimensec=%u;"
  270. " mtime=%zu;"
  271. " mtimensec=%u;"
  272. " ctime=%zu;"
  273. " ctimensec=%u;"
  274. " mode=%o;"
  275. " uid=%u;"
  276. " gid=%u;"
  277. "\n"
  278. ,
  279. arg->valid,
  280. arg->fh,
  281. arg->size,
  282. arg->lock_owner,
  283. arg->atime,
  284. arg->atimensec,
  285. arg->mtime,
  286. arg->mtimensec,
  287. arg->ctime,
  288. arg->ctimensec,
  289. arg->mode,
  290. arg->uid,
  291. arg->gid);
  292. }
  293. static
  294. void
  295. debug_fuse_access_in(const void *arg_)
  296. {
  297. const struct fuse_access_in *arg = (const fuse_access_in*)arg_;
  298. fprintf(g_OUTPUT,
  299. "fuse_access_in:"
  300. " mask=0x%08X;"
  301. "\n"
  302. ,
  303. arg->mask);
  304. }
  305. static
  306. void
  307. debug_fuse_mknod_in(const void *arg_)
  308. {
  309. const struct fuse_mknod_in *arg = (const fuse_mknod_in*)arg_;
  310. fprintf(g_OUTPUT,
  311. "fuse_mknod_in:"
  312. " mode=%o;"
  313. " rdev=0x%08X;"
  314. " umask=%o;"
  315. "\n"
  316. ,
  317. arg->mode,
  318. arg->rdev,
  319. arg->umask);
  320. }
  321. static
  322. void
  323. debug_fuse_mkdir_in(const void *arg_)
  324. {
  325. const struct fuse_mkdir_in *arg = (const fuse_mkdir_in*)arg_;
  326. fprintf(g_OUTPUT,
  327. "fuse_mkdir_in:"
  328. " mode=%o;"
  329. " umask=%o;"
  330. " name=%s;"
  331. "\n"
  332. ,
  333. arg->mode,
  334. arg->umask,
  335. PARAM(arg));
  336. }
  337. static
  338. void
  339. debug_fuse_unlink(const void *arg_)
  340. {
  341. const char *name = (const char*)arg_;
  342. fprintf(g_OUTPUT,
  343. "fuse_unlink:"
  344. " name=%s;"
  345. "\n"
  346. ,
  347. name);
  348. }
  349. static
  350. void
  351. debug_fuse_rmdir(const void *arg_)
  352. {
  353. const char *name = (const char*)arg_;
  354. fprintf(g_OUTPUT,
  355. "fuse_mkdir:"
  356. " name=%s;"
  357. "\n"
  358. ,
  359. name);
  360. }
  361. static
  362. void
  363. debug_fuse_symlink(const void *arg_)
  364. {
  365. const char *name;
  366. const char *linkname;
  367. name = (const char*)arg_;
  368. linkname = (name + (strlen(name) + 1));
  369. fprintf(g_OUTPUT,
  370. "fuse_mkdir:"
  371. " linkname=%s;"
  372. " name=%s;"
  373. "\n"
  374. ,
  375. linkname,
  376. name);
  377. }
  378. static
  379. void
  380. debug_fuse_rename_in(const void *arg_)
  381. {
  382. const char *oldname;
  383. const char *newname;
  384. const struct fuse_rename_in *arg = (const fuse_rename_in*)arg_;
  385. oldname = PARAM(arg);
  386. newname = (oldname + strlen(oldname) + 1);
  387. fprintf(g_OUTPUT,
  388. "fuse_rename_in:"
  389. " oldname=%s;"
  390. " newdir=%zu;"
  391. " newname=%s;"
  392. "\n"
  393. ,
  394. oldname,
  395. arg->newdir,
  396. newname);
  397. }
  398. static
  399. void
  400. debug_fuse_link_in(const void *arg_)
  401. {
  402. const char *name;
  403. const struct fuse_link_in *arg = (const fuse_link_in*)arg_;
  404. name = PARAM(arg);
  405. fprintf(g_OUTPUT,
  406. "fuse_link_in:"
  407. " oldnodeid=%zu;"
  408. " name=%s;"
  409. "\n"
  410. ,
  411. arg->oldnodeid,
  412. name);
  413. }
  414. static
  415. void
  416. debug_fuse_create_in(const void *arg_)
  417. {
  418. const char *name;
  419. const struct fuse_create_in *arg = (const fuse_create_in*)arg_;
  420. name = PARAM(arg);
  421. fprintf(g_OUTPUT,
  422. "fuse_create_in:"
  423. " mode=%o;"
  424. " umask=%o;"
  425. " name=%s;"
  426. " flags=0x%X (",
  427. arg->mode,
  428. arg->umask,
  429. name,
  430. arg->flags);
  431. debug_open_flags(arg->flags);
  432. fprintf(g_OUTPUT,");\n");
  433. }
  434. static
  435. void
  436. debug_fuse_open_in(const void *arg_)
  437. {
  438. const struct fuse_open_in *arg = (const fuse_open_in*)arg_;
  439. fprintf(g_OUTPUT,
  440. "fuse_open_in:"
  441. " flags=0x%08X (",
  442. arg->flags);
  443. debug_open_flags(arg->flags);
  444. fprintf(g_OUTPUT,");\n");
  445. }
  446. static
  447. void
  448. debug_fuse_read_in(const void *arg_)
  449. {
  450. const struct fuse_read_in *arg = (const fuse_read_in*)arg_;
  451. fprintf(g_OUTPUT,
  452. "fuse_read_in:"
  453. " fh=0x%" PRIx64 ";"
  454. " offset=%zu;"
  455. " size=%u;"
  456. " read_flags=%X;"
  457. " lock_owner=0x%" PRIx64 ";"
  458. " flags=0x%X ("
  459. ,
  460. arg->fh,
  461. arg->offset,
  462. arg->size,
  463. arg->read_flags,
  464. arg->lock_owner,
  465. arg->flags);
  466. debug_open_flags(arg->flags);
  467. fprintf(g_OUTPUT,");\n");
  468. }
  469. static
  470. void
  471. debug_fuse_write_in(const void *arg_)
  472. {
  473. const struct fuse_write_in *arg = (const fuse_write_in*)arg_;
  474. fprintf(g_OUTPUT,
  475. "fuse_write_in:"
  476. " fh=0x%" PRIx64 ";"
  477. " offset=%zu;"
  478. " size=%u;"
  479. " lock_owner=0x%" PRIx64 ";"
  480. " flags=0x%X ("
  481. ,
  482. arg->fh,
  483. arg->offset,
  484. arg->size,
  485. arg->lock_owner,
  486. arg->flags);
  487. debug_open_flags(arg->flags);
  488. fprintf(g_OUTPUT,
  489. "); write_flags=0x%X (",
  490. arg->write_flags);
  491. for(size_t i = 0; i < (sizeof(arg->write_flags) * 8); i++)
  492. {
  493. const char *str;
  494. if(!(arg->write_flags & (1 << i)))
  495. continue;
  496. str = fuse_write_flag_to_str(i);
  497. if(str == NULL)
  498. continue;
  499. fprintf(g_OUTPUT,"%s,",str);
  500. }
  501. fprintf(g_OUTPUT,");\n");
  502. }
  503. static
  504. void
  505. debug_fuse_flush_in(const void *arg_)
  506. {
  507. const struct fuse_flush_in *arg = (const fuse_flush_in*)arg_;
  508. fprintf(g_OUTPUT,
  509. "fuse_flush_in:"
  510. " fh=0x%" PRIx64 ";"
  511. " lock_owner=0x%" PRIx64 ";"
  512. "\n"
  513. ,
  514. arg->fh,
  515. arg->lock_owner);
  516. }
  517. static
  518. void
  519. debug_fuse_release_in(const void *arg_)
  520. {
  521. const struct fuse_release_in *arg = (const fuse_release_in*)arg_;
  522. fprintf(g_OUTPUT,
  523. "fuse_release_in:"
  524. " fh=0x%" PRIx64 ";"
  525. " release_flags=0x%X;"
  526. " lock_owner=0x%" PRIx64 ";"
  527. " flags=0x%X ("
  528. ,
  529. arg->fh,
  530. arg->release_flags,
  531. arg->lock_owner,
  532. arg->flags);
  533. debug_open_flags(arg->flags);
  534. fprintf(g_OUTPUT,");\n");
  535. }
  536. static
  537. void
  538. debug_fuse_fsync_in(const void *arg_)
  539. {
  540. const struct fuse_fsync_in *arg = (const fuse_fsync_in*)arg_;
  541. fprintf(g_OUTPUT,
  542. "fuse_fsync_in:"
  543. " fh=0x%" PRIx64 ";"
  544. " fsync_flags=0x%X;"
  545. "\n"
  546. ,
  547. arg->fh,
  548. arg->fsync_flags);
  549. }
  550. static
  551. void
  552. debug_fuse_setxattr_in(const void *arg_)
  553. {
  554. const char *name;
  555. const char *value;
  556. const struct fuse_setxattr_in *arg = (const fuse_setxattr_in*)arg_;
  557. name = PARAM(arg);
  558. value = (name + strlen(name) + 1);
  559. fprintf(g_OUTPUT,
  560. "fuse_setxattr_in:"
  561. " size=%u;"
  562. " flags=0x%X;"
  563. " name=%s;"
  564. " value=%s;"
  565. "\n"
  566. ,
  567. arg->size,
  568. arg->flags,
  569. name,
  570. value);
  571. }
  572. static
  573. void
  574. debug_fuse_getxattr_in(const void *arg_)
  575. {
  576. const char *name;
  577. const struct fuse_getxattr_in *arg = (const fuse_getxattr_in*)arg_;
  578. name = PARAM(arg);
  579. fprintf(g_OUTPUT,
  580. "fuse_getxattr_in:"
  581. " size=%u;"
  582. " name=%s;"
  583. "\n"
  584. ,
  585. arg->size,
  586. name);
  587. }
  588. static
  589. void
  590. debug_fuse_listxattr(const void *arg_)
  591. {
  592. const struct fuse_getxattr_in *arg = (const fuse_getxattr_in*)arg_;
  593. fprintf(g_OUTPUT,
  594. "fuse_listxattr:"
  595. " size=%u;"
  596. "\n"
  597. ,
  598. arg->size);
  599. }
  600. static
  601. void
  602. debug_fuse_removexattr(const void *arg_)
  603. {
  604. const char *name = (const char*)arg_;
  605. fprintf(g_OUTPUT,
  606. "fuse_removexattr:"
  607. " name=%s;"
  608. "\n"
  609. ,
  610. name);
  611. }
  612. static
  613. void
  614. debug_fuse_fallocate_in(const void *arg_)
  615. {
  616. const struct fuse_fallocate_in *arg = (const fuse_fallocate_in*)arg_;
  617. fprintf(g_OUTPUT,
  618. "fuse_fallocate_in:"
  619. " fh=0x%" PRIx64 ";"
  620. " offset=%zu;"
  621. " length=%zu;"
  622. " mode=%o;"
  623. "\n"
  624. ,
  625. arg->fh,
  626. arg->offset,
  627. arg->length,
  628. arg->mode);
  629. }
  630. void
  631. debug_fuse_init_in(const struct fuse_init_in *arg_)
  632. {
  633. uint64_t flags;
  634. flags = (((uint64_t)arg_->flags) | ((uint64_t)arg_->flags2) << 32);
  635. fprintf(g_OUTPUT,
  636. "FUSE_INIT_IN: "
  637. " major=%u;"
  638. " minor=%u;"
  639. " max_readahead=%u;"
  640. " flags=0x%016lx (",
  641. arg_->major,
  642. arg_->minor,
  643. arg_->max_readahead,
  644. flags);
  645. for(uint64_t i = 0; i < (sizeof(flags)*8); i++)
  646. {
  647. const char *str;
  648. if(!(flags & (1ULL << i)))
  649. continue;
  650. str = fuse_flag_to_str(i);
  651. if(str == NULL)
  652. continue;
  653. fprintf(g_OUTPUT,"%s, ",str);
  654. }
  655. fprintf(g_OUTPUT,")\n");
  656. }
  657. void
  658. debug_fuse_init_out(const uint64_t unique_,
  659. const struct fuse_init_out *arg_,
  660. const uint64_t argsize_)
  661. {
  662. uint64_t flags;
  663. const struct fuse_init_out *arg = arg_;
  664. flags = (((uint64_t)arg->flags) | ((uint64_t)arg->flags2) << 32);
  665. fprintf(g_OUTPUT,
  666. /* "unique=0x%016" PRIx64 ";" */
  667. /* " opcode=RESPONSE;" */
  668. /* " error=0 (Success);" */
  669. /* " len=%" PRIu64 "; || " */
  670. "FUSE_INIT_OUT:"
  671. " major=%u;"
  672. " minor=%u;"
  673. " max_readahead=%u;"
  674. " flags=0x%016lx ("
  675. ,
  676. /* unique_, */
  677. /* sizeof(struct fuse_out_header) + argsize_, */
  678. arg->major,
  679. arg->minor,
  680. arg->max_readahead,
  681. flags);
  682. for(uint64_t i = 0; i < (sizeof(flags)*8); i++)
  683. {
  684. const char *str;
  685. if(!(flags & (1ULL << i)))
  686. continue;
  687. str = fuse_flag_to_str(i);
  688. if(str == NULL)
  689. continue;
  690. fprintf(g_OUTPUT,"%s, ",str);
  691. }
  692. fprintf(g_OUTPUT,
  693. "); max_background=%u;"
  694. " congestion_threshold=%u;"
  695. " max_write=%u;"
  696. " time_gran=%u;"
  697. " max_pages=%u;"
  698. " map_alignment=%u;"
  699. "\n",
  700. arg->max_background,
  701. arg->congestion_threshold,
  702. arg->max_write,
  703. arg->time_gran,
  704. arg->max_pages,
  705. arg->map_alignment);
  706. }
  707. static
  708. void
  709. debug_fuse_attr(const struct fuse_attr *attr_)
  710. {
  711. fprintf(g_OUTPUT,
  712. "attr:"
  713. " ino=0x%016" PRIx64 ";"
  714. " size=%" PRIu64 ";"
  715. " blocks=%" PRIu64 ";"
  716. " atime=%" PRIu64 ";"
  717. " atimensec=%u;"
  718. " mtime=%" PRIu64 ";"
  719. " mtimensec=%u;"
  720. " ctime=%" PRIu64 ";"
  721. " ctimesec=%u;"
  722. " mode=%o;"
  723. " nlink=%u;"
  724. " uid=%u;"
  725. " gid=%u;"
  726. " rdev=%u;"
  727. " blksize=%u;"
  728. ,
  729. attr_->ino,
  730. attr_->size,
  731. attr_->blocks,
  732. attr_->atime,
  733. attr_->atimensec,
  734. attr_->mtime,
  735. attr_->mtimensec,
  736. attr_->ctime,
  737. attr_->ctimensec,
  738. attr_->mode,
  739. attr_->nlink,
  740. attr_->uid,
  741. attr_->gid,
  742. attr_->rdev,
  743. attr_->blksize);
  744. }
  745. static
  746. void
  747. debug_fuse_entry(const struct fuse_entry_out *entry_)
  748. {
  749. fprintf(g_OUTPUT,
  750. " fuse_entry_out:"
  751. " nodeid=0x%016" PRIx64 ";"
  752. " generation=0x%016" PRIx64 ";"
  753. " entry_valid=%" PRIu64 ";"
  754. " entry_valid_nsec=%u;"
  755. " attr_valid=%" PRIu64 ";"
  756. " attr_valid_nsec=%u;"
  757. " ",
  758. entry_->nodeid,
  759. entry_->generation,
  760. entry_->entry_valid,
  761. entry_->entry_valid_nsec,
  762. entry_->attr_valid,
  763. entry_->attr_valid_nsec);
  764. debug_fuse_attr(&entry_->attr);
  765. }
  766. void
  767. debug_fuse_entry_out(const uint64_t unique_,
  768. const struct fuse_entry_out *arg_,
  769. const uint64_t argsize_)
  770. {
  771. fprintf(g_OUTPUT,
  772. "unique=0x%016" PRIx64 ";"
  773. " opcode=RESPONSE;"
  774. " error=0 (Success);"
  775. " len=%" PRIu64 "; || "
  776. ,
  777. unique_,
  778. sizeof(struct fuse_out_header) + argsize_);
  779. debug_fuse_entry(arg_);
  780. }
  781. void
  782. debug_fuse_attr_out(const uint64_t unique_,
  783. const struct fuse_attr_out *arg_,
  784. const uint64_t argsize_)
  785. {
  786. fprintf(g_OUTPUT,
  787. "unique=0x%016" PRIx64 ";"
  788. " opcode=RESPONSE;"
  789. " error=0 (Success);"
  790. " len=%" PRIu64 "; || "
  791. "fuse_attr_out:"
  792. " attr_valid=%zu;"
  793. " attr_valid_nsec=%u;"
  794. " ino=%zu;"
  795. " size=%zu;"
  796. " blocks=%zu;"
  797. " atime=%zu;"
  798. " atimensec=%u;"
  799. " mtime=%zu;"
  800. " mtimensec=%u;"
  801. " ctime=%zu;"
  802. " ctimensec=%u;"
  803. " mode=%o;"
  804. " nlink=%u;"
  805. " uid=%u;"
  806. " gid=%u;"
  807. " rdev=%u;"
  808. " blksize=%u;"
  809. "\n",
  810. unique_,
  811. sizeof(struct fuse_out_header) + argsize_,
  812. arg_->attr_valid,
  813. arg_->attr_valid_nsec,
  814. arg_->attr.ino,
  815. arg_->attr.size,
  816. arg_->attr.blocks,
  817. arg_->attr.atime,
  818. arg_->attr.atimensec,
  819. arg_->attr.mtime,
  820. arg_->attr.mtimensec,
  821. arg_->attr.ctime,
  822. arg_->attr.ctimensec,
  823. arg_->attr.mode,
  824. arg_->attr.nlink,
  825. arg_->attr.uid,
  826. arg_->attr.gid,
  827. arg_->attr.rdev,
  828. arg_->attr.blksize);
  829. }
  830. static
  831. void
  832. debug_fuse_interrupt_in(const void *arg_)
  833. {
  834. const struct fuse_interrupt_in *arg = (const fuse_interrupt_in*)arg_;
  835. fprintf(g_OUTPUT,
  836. "fuse_interrupt_in:"
  837. " unique=0x%016" PRIx64 ";"
  838. "\n"
  839. ,
  840. arg->unique);
  841. }
  842. static
  843. const
  844. char*
  845. opcode_name(enum fuse_opcode op_)
  846. {
  847. static const char *names[] =
  848. {
  849. "INVALID",
  850. "LOOKUP",
  851. "FORGET",
  852. "GETATTR",
  853. "SETATTR",
  854. "READLINK",
  855. "SYMLINK",
  856. "MKNOD",
  857. "MKDIR",
  858. "UNLINK",
  859. "RMDIR",
  860. "RENAME",
  861. "LINK",
  862. "OPEN",
  863. "READ",
  864. "WRITE",
  865. "STATFS",
  866. "RELEASE",
  867. "FSYNC",
  868. "SETXATTR",
  869. "GETXATTR",
  870. "LISTXATTR",
  871. "REMOVEXATTR",
  872. "FLUSH",
  873. "INIT",
  874. "OPENDIR",
  875. "READDIR",
  876. "RELEASEDIR",
  877. "FSYNCDIR",
  878. "GETLK",
  879. "SETLK",
  880. "SETLKW",
  881. "ACCESS",
  882. "CREATE",
  883. "INTERRUPT",
  884. "BMAP",
  885. "DESTROY",
  886. "IOCTL",
  887. "POLL",
  888. "NOTIFY_REPLY",
  889. "BATCH_FORGET",
  890. "FALLOCATE",
  891. "READDIRPLUS",
  892. "RENAME2",
  893. "LSEEK",
  894. "COPY_FILE_RANGE",
  895. "SETUPMAPPING",
  896. "REMOVEMAPPING"
  897. };
  898. if(op_ >= (sizeof(names) / sizeof(names[0])))
  899. return "::UNKNOWN::";
  900. return names[op_];
  901. }
  902. void
  903. debug_fuse_in_header(const struct fuse_in_header *hdr_)
  904. {
  905. const void *arg = &hdr_[1];
  906. fprintf(stderr,
  907. "unique=0x%016" PRIx64 ";"
  908. " opcode=%s (%u);"
  909. " nodeid=%zu;"
  910. " uid=%u;"
  911. " gid=%u;"
  912. " pid=%u; || ",
  913. hdr_->unique,
  914. opcode_name((fuse_opcode)hdr_->opcode),
  915. hdr_->opcode,
  916. hdr_->nodeid,
  917. hdr_->uid,
  918. hdr_->gid,
  919. hdr_->pid);
  920. switch(hdr_->opcode)
  921. {
  922. case FUSE_LOOKUP:
  923. debug_fuse_lookup(arg);
  924. break;
  925. case FUSE_INIT:
  926. debug_fuse_init_in((const fuse_init_in*)arg);
  927. break;
  928. case FUSE_GETATTR:
  929. debug_fuse_getattr_in(arg);
  930. break;
  931. case FUSE_SETATTR:
  932. debug_fuse_setattr_in(arg);
  933. break;
  934. case FUSE_ACCESS:
  935. debug_fuse_access_in(arg);
  936. break;
  937. case FUSE_MKNOD:
  938. debug_fuse_mknod_in(arg);
  939. break;
  940. case FUSE_MKDIR:
  941. debug_fuse_mkdir_in(arg);
  942. break;
  943. case FUSE_UNLINK:
  944. debug_fuse_unlink(arg);
  945. break;
  946. case FUSE_RMDIR:
  947. debug_fuse_rmdir(arg);
  948. break;
  949. case FUSE_SYMLINK:
  950. debug_fuse_symlink(arg);
  951. break;
  952. case FUSE_RENAME:
  953. debug_fuse_rename_in(arg);
  954. break;
  955. case FUSE_LINK:
  956. debug_fuse_link_in(arg);
  957. break;
  958. case FUSE_CREATE:
  959. debug_fuse_create_in(arg);
  960. break;
  961. case FUSE_OPEN:
  962. debug_fuse_open_in(arg);
  963. break;
  964. case FUSE_OPENDIR:
  965. debug_fuse_open_in(arg);
  966. break;
  967. case FUSE_READ:
  968. debug_fuse_read_in(arg);
  969. break;
  970. case FUSE_READDIR:
  971. debug_fuse_read_in(arg);
  972. break;
  973. case FUSE_READDIRPLUS:
  974. debug_fuse_read_in(arg);
  975. break;
  976. case FUSE_WRITE:
  977. debug_fuse_write_in(arg);
  978. break;
  979. case FUSE_RELEASE:
  980. debug_fuse_release_in(arg);
  981. break;
  982. case FUSE_RELEASEDIR:
  983. debug_fuse_release_in(arg);
  984. break;
  985. case FUSE_FSYNCDIR:
  986. debug_fuse_fsync_in(arg);
  987. break;
  988. case FUSE_GETXATTR:
  989. debug_fuse_getxattr_in(arg);
  990. break;
  991. case FUSE_LISTXATTR:
  992. debug_fuse_listxattr(arg);
  993. break;
  994. case FUSE_SETXATTR:
  995. debug_fuse_setxattr_in(arg);
  996. break;
  997. case FUSE_REMOVEXATTR:
  998. debug_fuse_removexattr(arg);
  999. break;
  1000. case FUSE_FALLOCATE:
  1001. debug_fuse_fallocate_in(arg);
  1002. break;
  1003. case FUSE_FLUSH:
  1004. debug_fuse_flush_in(arg);
  1005. break;
  1006. case FUSE_INTERRUPT:
  1007. debug_fuse_interrupt_in(arg);
  1008. break;
  1009. default:
  1010. fprintf(g_OUTPUT,"FIXME\n");
  1011. break;
  1012. }
  1013. }
  1014. void
  1015. debug_fuse_out_header(const struct fuse_out_header *hdr_)
  1016. {
  1017. fprintf(g_OUTPUT,
  1018. "unique=0x%016" PRIx64 ";"
  1019. " opcode=RESPONSE;"
  1020. " error=%d (%s);"
  1021. " len=%" PRIu64 ";"
  1022. ,
  1023. hdr_->unique,
  1024. hdr_->error,
  1025. strerror(-hdr_->error),
  1026. sizeof(struct fuse_out_header));
  1027. }
  1028. void
  1029. debug_fuse_entry_open_out(const uint64_t unique_,
  1030. const struct fuse_entry_out *entry_,
  1031. const struct fuse_open_out *open_)
  1032. {
  1033. fprintf(g_OUTPUT,
  1034. "unique=0x%016" PRIx64 ";"
  1035. " opcode=RESPONSE;"
  1036. " error=0 (Success);"
  1037. " len=%" PRIu64 "; || "
  1038. ,
  1039. unique_,
  1040. sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out));
  1041. debug_fuse_entry(entry_);
  1042. }
  1043. void
  1044. debug_fuse_readlink(const uint64_t unique_,
  1045. const char *linkname_)
  1046. {
  1047. fprintf(g_OUTPUT,
  1048. "unique=0x%016" PRIx64 ";"
  1049. " opcode=RESPONSE;"
  1050. " error=0 (Success);"
  1051. " len=%" PRIu64 "; || "
  1052. "readlink: linkname=%s"
  1053. "\n"
  1054. ,
  1055. unique_,
  1056. (sizeof(struct fuse_out_header) + strlen(linkname_)),
  1057. linkname_);
  1058. }
  1059. void
  1060. debug_fuse_write_out(const uint64_t unique_,
  1061. const struct fuse_write_out *arg_)
  1062. {
  1063. fprintf(g_OUTPUT,
  1064. "unique=0x%016" PRIx64 ";"
  1065. " opcode=RESPONSE;"
  1066. " error=0 (Success);"
  1067. " len=%" PRIu64 "; || "
  1068. " fuse_write_out:"
  1069. " size=%u"
  1070. "\n"
  1071. ,
  1072. unique_,
  1073. sizeof(struct fuse_write_out),
  1074. arg_->size);
  1075. }
  1076. void
  1077. debug_fuse_statfs_out(const uint64_t unique_,
  1078. const struct fuse_statfs_out *arg_)
  1079. {
  1080. fprintf(g_OUTPUT,
  1081. "unique=0x%016" PRIx64 ";"
  1082. " opcode=RESPONSE;"
  1083. " error=0 (Success);"
  1084. " len=%" PRIu64 "; || "
  1085. " fuse_statfs_out:"
  1086. " blocks=%" PRIu64 ";"
  1087. " bfree=%" PRIu64 ";"
  1088. " bavail=%" PRIu64 ";"
  1089. " files=%" PRIu64 ";"
  1090. " ffree=%" PRIu64 ";"
  1091. " bsize=%u;"
  1092. " namelen=%u;"
  1093. " frsize=%u;"
  1094. "\n"
  1095. ,
  1096. unique_,
  1097. sizeof(struct fuse_statfs_out),
  1098. arg_->st.blocks,
  1099. arg_->st.bfree,
  1100. arg_->st.bavail,
  1101. arg_->st.files,
  1102. arg_->st.ffree,
  1103. arg_->st.bsize,
  1104. arg_->st.namelen,
  1105. arg_->st.frsize);
  1106. }
  1107. void
  1108. debug_fuse_getxattr_out(const uint64_t unique_,
  1109. const struct fuse_getxattr_out *arg_)
  1110. {
  1111. fprintf(g_OUTPUT,
  1112. "unique=0x%016" PRIx64 ";"
  1113. " opcode=RESPONSE;"
  1114. " error=0 (Success);"
  1115. " len=%" PRIu64 "; || "
  1116. " fuse_getxattr_out:"
  1117. " size=%u;"
  1118. "\n"
  1119. ,
  1120. unique_,
  1121. sizeof(struct fuse_out_header) + sizeof(struct fuse_getxattr_out),
  1122. arg_->size);
  1123. }
  1124. void
  1125. debug_fuse_lk_out(const uint64_t unique_,
  1126. const struct fuse_lk_out *arg_)
  1127. {
  1128. fprintf(g_OUTPUT,
  1129. "unique=0x%016" PRIx64 ";"
  1130. " opcode=RESPONSE;"
  1131. " error=0 (Success);"
  1132. " len=%" PRIu64 "; || "
  1133. " fuse_file_lock:"
  1134. " start=%" PRIu64 ";"
  1135. " end=%" PRIu64 ";"
  1136. " type=%u;"
  1137. " pid=%u;"
  1138. "\n"
  1139. ,
  1140. unique_,
  1141. sizeof(struct fuse_out_header) + sizeof(struct fuse_lk_out),
  1142. arg_->lk.start,
  1143. arg_->lk.end,
  1144. arg_->lk.type,
  1145. arg_->lk.pid);
  1146. }
  1147. void
  1148. debug_fuse_bmap_out(const uint64_t unique_,
  1149. const struct fuse_bmap_out *arg_)
  1150. {
  1151. fprintf(g_OUTPUT,
  1152. "unique=0x%016" PRIx64 ";"
  1153. " opcode=RESPONSE;"
  1154. " error=0 (Success);"
  1155. " len=%" PRIu64 "; || "
  1156. " fuse_bmap_out:"
  1157. " block=%" PRIu64 ";"
  1158. "\n"
  1159. ,
  1160. unique_,
  1161. sizeof(struct fuse_out_header) + sizeof(struct fuse_bmap_out),
  1162. arg_->block);
  1163. }