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.

230 lines
4.5 KiB

  1. /*
  2. FUSE: Filesystem in Userspace
  3. Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
  4. This program can be distributed under the terms of the GNU GPL.
  5. See the file COPYING.
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <errno.h>
  12. static char *progname;
  13. static char *xstrdup(const char *s)
  14. {
  15. char *t = strdup(s);
  16. if (!t) {
  17. fprintf(stderr, "%s: failed to allocate memory\n", progname);
  18. exit(1);
  19. }
  20. return t;
  21. }
  22. static void *xrealloc(void *oldptr, size_t size)
  23. {
  24. void *ptr = realloc(oldptr, size);
  25. if (!ptr) {
  26. fprintf(stderr, "%s: failed to allocate memory\n", progname);
  27. exit(1);
  28. }
  29. return ptr;
  30. }
  31. static void add_arg(char **cmdp, const char *opt)
  32. {
  33. size_t optlen = strlen(opt);
  34. size_t cmdlen = *cmdp ? strlen(*cmdp) : 0;
  35. char *cmd = xrealloc(*cmdp, cmdlen + optlen * 4 + 4);
  36. char *s;
  37. s = cmd + cmdlen;
  38. if (*cmdp)
  39. *s++ = ' ';
  40. *s++ = '\'';
  41. for (; *opt; opt++) {
  42. if (*opt == '\'') {
  43. *s++ = '\'';
  44. *s++ = '\\';
  45. *s++ = '\'';
  46. *s++ = '\'';
  47. } else
  48. *s++ = *opt;
  49. }
  50. *s++ = '\'';
  51. *s = '\0';
  52. *cmdp = cmd;
  53. }
  54. static char *add_option(const char *opt, char *options)
  55. {
  56. int oldlen = options ? strlen(options) : 0;
  57. options = xrealloc(options, oldlen + 1 + strlen(opt) + 1);
  58. if (!oldlen)
  59. strcpy(options, opt);
  60. else {
  61. strcat(options, ",");
  62. strcat(options, opt);
  63. }
  64. return options;
  65. }
  66. int main(int argc, char *argv[])
  67. {
  68. char *type = NULL;
  69. char *source;
  70. const char *mountpoint;
  71. char *basename;
  72. char *options = NULL;
  73. char *command = NULL;
  74. char *setuid = NULL;
  75. int i;
  76. int dev = 1;
  77. int suid = 1;
  78. progname = argv[0];
  79. basename = strrchr(argv[0], '/');
  80. if (basename)
  81. basename++;
  82. else
  83. basename = argv[0];
  84. if (strncmp(basename, "mount.fuse.", 11) == 0)
  85. type = basename + 11;
  86. if (strncmp(basename, "mount.fuseblk.", 14) == 0)
  87. type = basename + 14;
  88. if (type && !type[0])
  89. type = NULL;
  90. if (argc < 3) {
  91. fprintf(stderr,
  92. "usage: %s %s destination [-t type] [-o opt[,opts...]]\n",
  93. progname, type ? "source" : "type#[source]");
  94. exit(1);
  95. }
  96. source = argv[1];
  97. if (!source[0])
  98. source = NULL;
  99. mountpoint = argv[2];
  100. for (i = 3; i < argc; i++) {
  101. if (strcmp(argv[i], "-v") == 0) {
  102. continue;
  103. } else if (strcmp(argv[i], "-t") == 0) {
  104. i++;
  105. if (i == argc) {
  106. fprintf(stderr,
  107. "%s: missing argument to option '-t'\n",
  108. progname);
  109. exit(1);
  110. }
  111. type = argv[i];
  112. if (strncmp(type, "fuse.", 5) == 0)
  113. type += 5;
  114. else if (strncmp(type, "fuseblk.", 8) == 0)
  115. type += 8;
  116. if (!type[0]) {
  117. fprintf(stderr,
  118. "%s: empty type given as argument to option '-t'\n",
  119. progname);
  120. exit(1);
  121. }
  122. } else if (strcmp(argv[i], "-o") == 0) {
  123. char *opts;
  124. char *opt;
  125. i++;
  126. if (i == argc)
  127. break;
  128. opts = xstrdup(argv[i]);
  129. opt = strtok(opts, ",");
  130. while (opt) {
  131. int j;
  132. int ignore = 0;
  133. const char *ignore_opts[] = { "",
  134. "user",
  135. "nouser",
  136. "users",
  137. "auto",
  138. "noauto",
  139. "_netdev",
  140. NULL};
  141. if (strncmp(opt, "setuid=", 7) == 0) {
  142. setuid = xstrdup(opt + 7);
  143. ignore = 1;
  144. }
  145. for (j = 0; ignore_opts[j]; j++)
  146. if (strcmp(opt, ignore_opts[j]) == 0)
  147. ignore = 1;
  148. if (!ignore) {
  149. if (strcmp(opt, "nodev") == 0)
  150. dev = 0;
  151. else if (strcmp(opt, "nosuid") == 0)
  152. suid = 0;
  153. options = add_option(opt, options);
  154. }
  155. opt = strtok(NULL, ",");
  156. }
  157. }
  158. }
  159. if (dev)
  160. options = add_option("dev", options);
  161. if (suid)
  162. options = add_option("suid", options);
  163. if (!type) {
  164. if (source) {
  165. type = xstrdup(source);
  166. source = strchr(type, '#');
  167. if (source)
  168. *source++ = '\0';
  169. if (!type[0]) {
  170. fprintf(stderr, "%s: empty filesystem type\n",
  171. progname);
  172. exit(1);
  173. }
  174. } else {
  175. fprintf(stderr, "%s: empty source\n", progname);
  176. exit(1);
  177. }
  178. }
  179. add_arg(&command, type);
  180. if (source)
  181. add_arg(&command, source);
  182. add_arg(&command, mountpoint);
  183. if (options) {
  184. add_arg(&command, "-o");
  185. add_arg(&command, options);
  186. }
  187. if (setuid && setuid[0]) {
  188. char *sucommand = command;
  189. command = NULL;
  190. add_arg(&command, "su");
  191. add_arg(&command, "-");
  192. add_arg(&command, setuid);
  193. add_arg(&command, "-c");
  194. add_arg(&command, sucommand);
  195. } else if (!getenv("HOME")) {
  196. /* Hack to make filesystems work in the boot environment */
  197. setenv("HOME", "/root", 0);
  198. }
  199. execl("/bin/sh", "/bin/sh", "-c", command, NULL);
  200. fprintf(stderr, "%s: failed to execute /bin/sh: %s\n", progname,
  201. strerror(errno));
  202. return 1;
  203. }