fuse_mnt.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * fusectl test file-system
  4. * Creates a simple FUSE filesystem with a single read-write file (/test)
  5. */
  6. #define FUSE_USE_VERSION 26
  7. #include <fuse.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <fcntl.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  15. static char *content;
  16. static size_t content_size = 0;
  17. static const char test_path[] = "/test";
  18. static int test_getattr(const char *path, struct stat *st)
  19. {
  20. memset(st, 0, sizeof(*st));
  21. if (!strcmp(path, "/")) {
  22. st->st_mode = S_IFDIR | 0755;
  23. st->st_nlink = 2;
  24. return 0;
  25. }
  26. if (!strcmp(path, test_path)) {
  27. st->st_mode = S_IFREG | 0664;
  28. st->st_nlink = 1;
  29. st->st_size = content_size;
  30. return 0;
  31. }
  32. return -ENOENT;
  33. }
  34. static int test_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
  35. off_t offset, struct fuse_file_info *fi)
  36. {
  37. if (strcmp(path, "/"))
  38. return -ENOENT;
  39. filler(buf, ".", NULL, 0);
  40. filler(buf, "..", NULL, 0);
  41. filler(buf, test_path + 1, NULL, 0);
  42. return 0;
  43. }
  44. static int test_open(const char *path, struct fuse_file_info *fi)
  45. {
  46. if (strcmp(path, test_path))
  47. return -ENOENT;
  48. return 0;
  49. }
  50. static int test_read(const char *path, char *buf, size_t size, off_t offset,
  51. struct fuse_file_info *fi)
  52. {
  53. if (strcmp(path, test_path) != 0)
  54. return -ENOENT;
  55. if (!content || content_size == 0)
  56. return 0;
  57. if (offset >= content_size)
  58. return 0;
  59. if (offset + size > content_size)
  60. size = content_size - offset;
  61. memcpy(buf, content + offset, size);
  62. return size;
  63. }
  64. static int test_write(const char *path, const char *buf, size_t size,
  65. off_t offset, struct fuse_file_info *fi)
  66. {
  67. size_t new_size;
  68. if (strcmp(path, test_path) != 0)
  69. return -ENOENT;
  70. if(offset > content_size)
  71. return -EINVAL;
  72. new_size = MAX(offset + size, content_size);
  73. if (new_size > content_size)
  74. content = realloc(content, new_size);
  75. content_size = new_size;
  76. if (!content)
  77. return -ENOMEM;
  78. memcpy(content + offset, buf, size);
  79. return size;
  80. }
  81. static int test_truncate(const char *path, off_t size)
  82. {
  83. if (strcmp(path, test_path) != 0)
  84. return -ENOENT;
  85. if (size == 0) {
  86. free(content);
  87. content = NULL;
  88. content_size = 0;
  89. return 0;
  90. }
  91. content = realloc(content, size);
  92. if (!content)
  93. return -ENOMEM;
  94. if (size > content_size)
  95. memset(content + content_size, 0, size - content_size);
  96. content_size = size;
  97. return 0;
  98. }
  99. static struct fuse_operations memfd_ops = {
  100. .getattr = test_getattr,
  101. .readdir = test_readdir,
  102. .open = test_open,
  103. .read = test_read,
  104. .write = test_write,
  105. .truncate = test_truncate,
  106. };
  107. int main(int argc, char *argv[])
  108. {
  109. return fuse_main(argc, argv, &memfd_ops, NULL);
  110. }