sfs.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*
  2. * Single File fileSystem
  3. *
  4. * Copyright 1998 Pavel Machek, distribute under GPL
  5. *
  6. * This defines whole class of filesystems which contain single file
  7. * inside. It is somehow similar to extfs, except that extfs makes
  8. * whole virtual trees and we do only single virtual files.
  9. *
  10. * If you want to gunzip something, you should open it with #ugz
  11. * suffix, DON'T try to gunzip it yourself.
  12. *
  13. * Namespace: exports vfs_sfs_ops */
  14. #include <config.h>
  15. #include <errno.h>
  16. #include <sys/types.h>
  17. #include <unistd.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "utilvfs.h"
  21. #include "vfs.h"
  22. #include "local.h"
  23. #include "../src/execute.h"
  24. struct cachedfile {
  25. char *name, *cache;
  26. struct cachedfile *next;
  27. };
  28. static struct cachedfile *head;
  29. #define MAXFS 32
  30. static int sfs_no = 0;
  31. static char *sfs_prefix[ MAXFS ];
  32. static char *sfs_command[ MAXFS ];
  33. static int sfs_flags[ MAXFS ];
  34. #define F_1 1
  35. #define F_2 2
  36. #define F_NOLOCALCOPY 4
  37. #define F_FULLMATCH 8
  38. static int uptodate (char *name, char *cache)
  39. {
  40. return 1;
  41. }
  42. static int vfmake (vfs *me, char *name, char *cache)
  43. {
  44. char *inpath, *op;
  45. int w;
  46. char pad [10240];
  47. char *s, *t = pad;
  48. int was_percent = 0;
  49. vfs_split (name, &inpath, &op);
  50. if ((w = (*me->which) (me, op)) == -1)
  51. vfs_die ("This cannot happen... Hopefully.\n");
  52. if ((sfs_flags[w] & F_1) || (!strcmp (name, "/"))) ; else return -1;
  53. /* if ((sfs_flags[w] & F_2) || (!inpath) || (!*inpath)); else return -1; */
  54. if (!(sfs_flags[w] & F_NOLOCALCOPY)) {
  55. s = mc_getlocalcopy (name);
  56. if (!s)
  57. return -1;
  58. name = name_quote (s, 0);
  59. g_free (s);
  60. } else
  61. name = name_quote (name, 0);
  62. #define COPY_CHAR if (t-pad>sizeof(pad)) { g_free (name); return -1; } else *t++ = *s;
  63. #define COPY_STRING(a) if ((t-pad)+strlen(a)>sizeof(pad)) { g_free (name); return -1; } else { strcpy (t, a); t+= strlen(a); }
  64. for (s = sfs_command[w]; *s; s++) {
  65. if (was_percent) {
  66. char *ptr = NULL;
  67. was_percent = 0;
  68. switch (*s) {
  69. case '1': ptr = name; break;
  70. case '2': ptr = op + strlen (sfs_prefix[w]); break;
  71. case '3': ptr = cache; break;
  72. case '%': COPY_CHAR; continue;
  73. }
  74. COPY_STRING (ptr);
  75. } else {
  76. if (*s == '%')
  77. was_percent = 1;
  78. else
  79. COPY_CHAR;
  80. }
  81. }
  82. g_free (name);
  83. open_error_pipe ();
  84. if (my_system (EXECUTE_AS_SHELL, "/bin/sh", pad)) {
  85. close_error_pipe (1, NULL);
  86. return -1;
  87. }
  88. close_error_pipe (0, NULL);
  89. return 0; /* OK */
  90. }
  91. static char *
  92. redirect (vfs *me, char *name)
  93. {
  94. struct cachedfile *cur = head;
  95. char *cache;
  96. int handle;
  97. while (cur) {
  98. /* FIXME: when not uptodate, we might want to kill cache
  99. * file immediately, not to wait until timeout. */
  100. if ((!strcmp (name, cur->name))
  101. && (uptodate (cur->name, cur->cache))) {
  102. vfs_stamp (&vfs_sfs_ops, cur);
  103. return cur->cache;
  104. }
  105. cur = cur->next;
  106. }
  107. handle = mc_mkstemps (&cache, "sfs", NULL);
  108. if (handle == -1) {
  109. return "/SOMEONE_PLAYING_DIRTY_TMP_TRICKS_ON_US";
  110. }
  111. close (handle);
  112. if (!vfmake (me, name, cache)) {
  113. cur = g_new (struct cachedfile, 1);
  114. cur->name = g_strdup (name);
  115. cur->cache = cache;
  116. cur->next = head;
  117. head = cur;
  118. vfs_add_noncurrent_stamps (&vfs_sfs_ops, (vfsid) head, NULL);
  119. vfs_rm_parents (NULL);
  120. return cache;
  121. }
  122. unlink (cache);
  123. g_free (cache);
  124. return "/I_MUST_NOT_EXIST";
  125. }
  126. static void *
  127. sfs_open (vfs *me, char *path, int flags, int mode)
  128. {
  129. int *sfs_info;
  130. int fd;
  131. path = redirect (me, path);
  132. fd = open (path, NO_LINEAR(flags), mode);
  133. if (fd == -1)
  134. return 0;
  135. sfs_info = g_new (int, 1);
  136. *sfs_info = fd;
  137. return sfs_info;
  138. }
  139. static int sfs_stat (vfs *me, char *path, struct stat *buf)
  140. {
  141. path = redirect (me, path);
  142. return stat (path, buf);
  143. }
  144. static int sfs_lstat (vfs *me, char *path, struct stat *buf)
  145. {
  146. path = redirect (me, path);
  147. #ifndef HAVE_STATLSTAT
  148. return lstat (path, buf);
  149. #else
  150. return statlstat (path, buf);
  151. #endif
  152. }
  153. static int sfs_chmod (vfs *me, char *path, int mode)
  154. {
  155. path = redirect (me, path);
  156. return chmod (path, mode);
  157. }
  158. static int sfs_chown (vfs *me, char *path, int owner, int group)
  159. {
  160. path = redirect (me, path);
  161. return chown (path, owner, group);
  162. }
  163. static int sfs_utime (vfs *me, char *path, struct utimbuf *times)
  164. {
  165. path = redirect (me, path);
  166. return utime (path, times);
  167. }
  168. static int sfs_readlink (vfs *me, char *path, char *buf, int size)
  169. {
  170. path = redirect (me, path);
  171. return readlink (path, buf, size);
  172. }
  173. static vfsid
  174. sfs_getid (vfs *me, char *path, struct vfs_stamping **parent)
  175. { /* FIXME: what should I do? */
  176. vfs *v;
  177. vfsid id;
  178. struct vfs_stamping *par;
  179. struct cachedfile *cur = head;
  180. while (cur) {
  181. if (!strcmp (path, cur->name))
  182. break;
  183. cur = cur->next;
  184. }
  185. *parent = NULL;
  186. if (!cur)
  187. return (vfsid) (-1);
  188. {
  189. char *path2 = g_strdup (path);
  190. /* Strip suffix which led to this being sfs */
  191. v = vfs_split (path2, NULL, NULL);
  192. /* ... and learn whoever was the parent system */
  193. v = vfs_split (path2, NULL, NULL);
  194. id = (*v->getid) (v, path2, &par);
  195. g_free (path2);
  196. }
  197. if (id != (vfsid) - 1) {
  198. *parent = g_new (struct vfs_stamping, 1);
  199. (*parent)->v = v;
  200. (*parent)->id = id;
  201. (*parent)->parent = par;
  202. (*parent)->next = NULL;
  203. }
  204. return (vfsid) cur;
  205. }
  206. static void sfs_free (vfsid id)
  207. {
  208. struct cachedfile *which = (struct cachedfile *) id;
  209. struct cachedfile *cur, *prev;
  210. for (cur = head, prev = 0; cur && cur != which; prev = cur, cur = cur->next)
  211. ;
  212. if (!cur)
  213. vfs_die( "Free of thing which is unknown to me\n" );
  214. unlink (cur->cache);
  215. if (prev)
  216. prev->next = cur->next;
  217. else
  218. head = cur->next;
  219. g_free (cur->cache);
  220. g_free (cur->name);
  221. g_free (cur);
  222. }
  223. static void sfs_fill_names (vfs *me, void (*func)(char *))
  224. {
  225. struct cachedfile *cur = head;
  226. while (cur){
  227. (*func)(cur->name);
  228. cur = cur->next;
  229. }
  230. }
  231. static int sfs_nothingisopen (vfsid id)
  232. {
  233. /* FIXME: Investigate whether have to guard this like in
  234. the other VFSs (see fd_usage in extfs) -- Norbert */
  235. return 1;
  236. }
  237. static char *sfs_getlocalcopy (vfs *me, char *path)
  238. {
  239. path = redirect (me, path);
  240. return g_strdup (path);
  241. }
  242. static int sfs_ungetlocalcopy (vfs *me, char *path, char *local, int has_changed)
  243. {
  244. g_free(local);
  245. return 0;
  246. }
  247. static int sfs_init (vfs *me)
  248. {
  249. char *mc_sfsini;
  250. FILE *cfg;
  251. mc_sfsini = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR "sfs.ini");
  252. cfg = fopen (mc_sfsini, "r");
  253. if (!cfg){
  254. fprintf (stderr, _("Warning: file %s not found\n"), mc_sfsini);
  255. g_free (mc_sfsini);
  256. return 0;
  257. }
  258. g_free (mc_sfsini);
  259. sfs_no = 0;
  260. while (sfs_no < MAXFS){
  261. char key[256];
  262. char *c, *semi = NULL, flags = 0;
  263. if (!fgets (key, sizeof (key), cfg))
  264. break;
  265. if (*key == '#')
  266. continue;
  267. for (c = key; *c; c++)
  268. if ((*c == ':') || (*c == '/')){
  269. semi = c;
  270. if (*c == '/'){
  271. *c = 0;
  272. flags |= F_FULLMATCH;
  273. }
  274. break;
  275. }
  276. if (!semi){
  277. fprintf (stderr, _("Warning: Invalid line in %s:\n%s\n"),
  278. "sfs.ini", key);
  279. continue;
  280. }
  281. c = semi + 1;
  282. while ((*c != ' ') && (*c != '\t')) {
  283. switch (*c) {
  284. case '1': flags |= F_1; break;
  285. case '2': flags |= F_2; break;
  286. case 'R': flags |= F_NOLOCALCOPY; break;
  287. default:
  288. fprintf (stderr, _("Warning: Invalid flag %c in %s:\n%s\n"),
  289. *c, "sfs.ini", key);
  290. }
  291. c++;
  292. }
  293. c++;
  294. *(semi+1) = 0;
  295. if ((semi = strchr (c, '\n')))
  296. *semi = 0;
  297. sfs_prefix [sfs_no] = g_strdup (key);
  298. sfs_command [sfs_no] = g_strdup (c);
  299. sfs_flags [sfs_no] = flags;
  300. sfs_no++;
  301. }
  302. fclose (cfg);
  303. return 1;
  304. }
  305. static void
  306. sfs_done (vfs *me)
  307. {
  308. int i;
  309. for (i = 0; i < sfs_no; i++){
  310. g_free (sfs_prefix [i]);
  311. g_free (sfs_command [i]);
  312. sfs_prefix [i] = sfs_command [i] = NULL;
  313. }
  314. sfs_no = 0;
  315. }
  316. static int
  317. sfs_which (vfs *me, char *path)
  318. {
  319. int i;
  320. for (i = 0; i < sfs_no; i++)
  321. if (sfs_flags [i] & F_FULLMATCH) {
  322. if (!strcmp (path, sfs_prefix [i]))
  323. return i;
  324. } else
  325. if (!strncmp (path, sfs_prefix [i], strlen (sfs_prefix [i])))
  326. return i;
  327. return -1;
  328. }
  329. vfs vfs_sfs_ops = {
  330. NULL, /* This is place of next pointer */
  331. "sfs",
  332. F_EXEC, /* flags */
  333. NULL, /* prefix */
  334. NULL, /* data */
  335. 0, /* errno */
  336. sfs_init,
  337. sfs_done,
  338. sfs_fill_names,
  339. sfs_which,
  340. sfs_open,
  341. local_close,
  342. local_read,
  343. NULL,
  344. NULL,
  345. NULL,
  346. NULL,
  347. NULL,
  348. NULL,
  349. sfs_stat,
  350. sfs_lstat,
  351. local_fstat,
  352. sfs_chmod,
  353. sfs_chown,
  354. sfs_utime,
  355. sfs_readlink,
  356. NULL,
  357. NULL,
  358. NULL,
  359. NULL,
  360. NULL,
  361. local_errno,
  362. local_lseek,
  363. NULL,
  364. sfs_getid,
  365. sfs_nothingisopen,
  366. sfs_free,
  367. sfs_getlocalcopy,
  368. sfs_ungetlocalcopy,
  369. NULL,
  370. NULL,
  371. NULL,
  372. NULL
  373. #ifdef HAVE_MMAP
  374. ,local_mmap,
  375. local_munmap
  376. #endif
  377. };