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.

211 lines
3.8 KiB

  1. /*
  2. FUSE fioc: FUSE ioctl example
  3. Copyright (C) 2008 SUSE Linux Products GmbH
  4. Copyright (C) 2008 Tejun Heo <teheo@suse.de>
  5. This program can be distributed under the terms of the GNU GPL.
  6. See the file COPYING.
  7. gcc -Wall fioc.c `pkg-config fuse --cflags --libs` -o fioc
  8. */
  9. #define FUSE_USE_VERSION 26
  10. #include <fuse.h>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include <time.h>
  16. #include <errno.h>
  17. #include "fioc.h"
  18. #define FIOC_NAME "fioc"
  19. enum {
  20. FIOC_NONE,
  21. FIOC_ROOT,
  22. FIOC_FILE,
  23. };
  24. static void *fioc_buf;
  25. static size_t fioc_size;
  26. static int fioc_resize(size_t new_size)
  27. {
  28. void *new_buf;
  29. if (new_size == fioc_size)
  30. return 0;
  31. new_buf = realloc(fioc_buf, new_size);
  32. if (!new_buf && new_size)
  33. return -ENOMEM;
  34. if (new_size > fioc_size)
  35. memset(new_buf + fioc_size, 0, new_size - fioc_size);
  36. fioc_buf = new_buf;
  37. fioc_size = new_size;
  38. return 0;
  39. }
  40. static int fioc_expand(size_t new_size)
  41. {
  42. if (new_size > fioc_size)
  43. return fioc_resize(new_size);
  44. return 0;
  45. }
  46. static int fioc_file_type(const char *path)
  47. {
  48. if (strcmp(path, "/") == 0)
  49. return FIOC_ROOT;
  50. if (strcmp(path, "/" FIOC_NAME) == 0)
  51. return FIOC_FILE;
  52. return FIOC_NONE;
  53. }
  54. static int fioc_getattr(const char *path, struct stat *stbuf)
  55. {
  56. stbuf->st_uid = getuid();
  57. stbuf->st_gid = getgid();
  58. stbuf->st_atime = stbuf->st_mtime = time(NULL);
  59. switch (fioc_file_type(path)) {
  60. case FIOC_ROOT:
  61. stbuf->st_mode = S_IFDIR | 0755;
  62. stbuf->st_nlink = 2;
  63. break;
  64. case FIOC_FILE:
  65. stbuf->st_mode = S_IFREG | 0644;
  66. stbuf->st_nlink = 1;
  67. stbuf->st_size = fioc_size;
  68. break;
  69. case FIOC_NONE:
  70. return -ENOENT;
  71. }
  72. return 0;
  73. }
  74. static int fioc_open(const char *path, struct fuse_file_info *fi)
  75. {
  76. (void) fi;
  77. if (fioc_file_type(path) != FIOC_NONE)
  78. return 0;
  79. return -ENOENT;
  80. }
  81. static int fioc_do_read(char *buf, size_t size, off_t offset)
  82. {
  83. if (offset >= fioc_size)
  84. return 0;
  85. if (size > fioc_size - offset)
  86. size = fioc_size - offset;
  87. memcpy(buf, fioc_buf + offset, size);
  88. return size;
  89. }
  90. static int fioc_read(const char *path, char *buf, size_t size,
  91. off_t offset, struct fuse_file_info *fi)
  92. {
  93. (void) fi;
  94. if (fioc_file_type(path) != FIOC_FILE)
  95. return -EINVAL;
  96. return fioc_do_read(buf, size, offset);
  97. }
  98. static int fioc_do_write(const char *buf, size_t size, off_t offset)
  99. {
  100. if (fioc_expand(offset + size))
  101. return -ENOMEM;
  102. memcpy(fioc_buf + offset, buf, size);
  103. return size;
  104. }
  105. static int fioc_write(const char *path, const char *buf, size_t size,
  106. off_t offset, struct fuse_file_info *fi)
  107. {
  108. (void) fi;
  109. if (fioc_file_type(path) != FIOC_FILE)
  110. return -EINVAL;
  111. return fioc_do_write(buf, size, offset);
  112. }
  113. static int fioc_truncate(const char *path, off_t size)
  114. {
  115. if (fioc_file_type(path) != FIOC_FILE)
  116. return -EINVAL;
  117. return fioc_resize(size);
  118. }
  119. static int fioc_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
  120. off_t offset, struct fuse_file_info *fi)
  121. {
  122. (void) fi;
  123. (void) offset;
  124. if (fioc_file_type(path) != FIOC_ROOT)
  125. return -ENOENT;
  126. filler(buf, ".", NULL, 0);
  127. filler(buf, "..", NULL, 0);
  128. filler(buf, FIOC_NAME, NULL, 0);
  129. return 0;
  130. }
  131. static int fioc_ioctl(const char *path, int cmd, void *arg,
  132. struct fuse_file_info *fi, unsigned int flags, void *data)
  133. {
  134. (void) arg;
  135. (void) fi;
  136. (void) flags;
  137. if (fioc_file_type(path) != FIOC_FILE)
  138. return -EINVAL;
  139. if (flags & FUSE_IOCTL_COMPAT)
  140. return -ENOSYS;
  141. switch (cmd) {
  142. case FIOC_GET_SIZE:
  143. *(size_t *)data = fioc_size;
  144. return 0;
  145. case FIOC_SET_SIZE:
  146. fioc_resize(*(size_t *)data);
  147. return 0;
  148. }
  149. return -EINVAL;
  150. }
  151. static struct fuse_operations fioc_oper = {
  152. .getattr = fioc_getattr,
  153. .readdir = fioc_readdir,
  154. .truncate = fioc_truncate,
  155. .open = fioc_open,
  156. .read = fioc_read,
  157. .write = fioc_write,
  158. .ioctl = fioc_ioctl,
  159. };
  160. int main(int argc, char *argv[])
  161. {
  162. return fuse_main(argc, argv, &fioc_oper, NULL);
  163. }