rgpgfs.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include <errno.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. // posix
  6. #include <dirent.h>
  7. #include <sys/stat.h>
  8. #include <sys/types.h>
  9. #include <unistd.h>
  10. // http://libfuse.github.io/doxygen/globals.html
  11. #define FUSE_USE_VERSION 31
  12. #include <fuse.h>
  13. #define FUSE_PATH_BUF_LEN 256
  14. static char cache_dir[] = "/tmp/rgpgfs-cache-XXXXXX";
  15. static const size_t CACHE_PATH_BUF_LEN = sizeof(cache_dir) + FUSE_PATH_BUF_LEN;
  16. static int rgpgfs_mkdirs(char *path) {
  17. char *delimiter = strrchr(path, '/');
  18. if (delimiter == NULL) {
  19. errno = ENOTSUP;
  20. return 1;
  21. }
  22. *delimiter = '\0';
  23. struct stat statbuf;
  24. if (lstat(path, &statbuf) && (rgpgfs_mkdirs(path) || mkdir(path, S_IRWXU))) {
  25. *delimiter = '/';
  26. return 1;
  27. }
  28. *delimiter = '/';
  29. return 0;
  30. }
  31. static int rgpgfs_encrypt(const char *source_path, char *cache_path) {
  32. size_t source_path_len = strnlen(source_path, FUSE_PATH_BUF_LEN);
  33. if (source_path_len >= FUSE_PATH_BUF_LEN) {
  34. errno = ENAMETOOLONG;
  35. perror("rgpgfs_encrypt");
  36. return 1;
  37. }
  38. strcpy(cache_path, cache_dir);
  39. strcat(cache_path, source_path);
  40. if (rgpgfs_mkdirs(cache_path)) {
  41. perror("rgpgfs_encrypt: failed to create dirs");
  42. return 1;
  43. }
  44. FILE *cache_file = fopen(cache_path, "w");
  45. if (cache_file == NULL) {
  46. perror("rgpgfs_encrypt: failed to open cache file");
  47. return 1;
  48. }
  49. fprintf(cache_file, "path: %s\n", cache_path);
  50. fclose(cache_file);
  51. return 0;
  52. }
  53. static int rgpgfs_getattr(const char *path, struct stat *statbuf,
  54. struct fuse_file_info *fi) {
  55. int res = lstat(path, statbuf);
  56. // printf("rgpgfs_getattr(%s, ...) = %d\n", path, res);
  57. if (res == -1)
  58. return -errno;
  59. return 0;
  60. }
  61. static int rgpgfs_access(const char *path, int mask) {
  62. int res = access(path, mask);
  63. // printf("rgpgfs_access(%s, %d) = %d\n", path, mask, res);
  64. if (res == -1)
  65. return -errno;
  66. return 0;
  67. }
  68. static int rgpgfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
  69. off_t offset, struct fuse_file_info *fi,
  70. enum fuse_readdir_flags flags) {
  71. DIR *dirp = opendir(path);
  72. if (dirp == NULL)
  73. return -errno;
  74. struct dirent *entp;
  75. while ((entp = readdir(dirp)) != NULL) {
  76. struct stat statbf;
  77. memset(&statbf, 0, sizeof(statbf));
  78. statbf.st_ino = entp->d_ino;
  79. statbf.st_mode = entp->d_type << 12;
  80. if (filler(buf, entp->d_name, &statbf, 0, 0))
  81. break;
  82. }
  83. closedir(dirp);
  84. return 0;
  85. }
  86. static int rgpgfs_open(const char *source_path, struct fuse_file_info *fi) {
  87. char cache_path[CACHE_PATH_BUF_LEN];
  88. if (rgpgfs_encrypt(source_path, cache_path))
  89. return -errno;
  90. int res = open(cache_path, fi->flags);
  91. if (res == -1)
  92. return -errno;
  93. fi->fh = res;
  94. return 0;
  95. }
  96. static int rgpgfs_read(const char *path, char *buf, size_t count, off_t offset,
  97. struct fuse_file_info *fi) {
  98. if (fi == NULL) {
  99. return ENOTSUP;
  100. }
  101. ssize_t bytes_num = pread(fi->fh, buf, count, offset);
  102. if (bytes_num == -1)
  103. return -errno;
  104. return bytes_num;
  105. }
  106. static int rgpgfs_release(const char *path, struct fuse_file_info *fi) {
  107. close(fi->fh);
  108. return 0;
  109. }
  110. static struct fuse_operations rgpgfs_fuse_operations = {
  111. .getattr = rgpgfs_getattr,
  112. .open = rgpgfs_open,
  113. .read = rgpgfs_read,
  114. .release = rgpgfs_release,
  115. .readdir = rgpgfs_readdir,
  116. .access = rgpgfs_access,
  117. };
  118. int main(int argc, char *argv[]) {
  119. if (mkdtemp(cache_dir) == NULL) {
  120. return 1;
  121. }
  122. printf("cache: %s\n", cache_dir);
  123. // TODO rm -r cache_dir (see man nftw)
  124. return fuse_main(argc, argv, &rgpgfs_fuse_operations, NULL);
  125. }