This source file includes following definitions.
- cachedfile_compare
- sfs_vfmake
- sfs_redirect
- sfs_open
- sfs_stat
- sfs_lstat
- sfs_chmod
- sfs_chown
- sfs_utime
- sfs_readlink
- sfs_getid
- sfs_free
- sfs_fill_names
- sfs_nothingisopen
- sfs_getlocalcopy
- sfs_ungetlocalcopy
- sfs_init
- sfs_done
- sfs_which
- vfs_init_sfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <config.h>
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <unistd.h>
44 #include <stdio.h>
45 #include <string.h>
46
47 #include "lib/global.h"
48 #include "lib/util.h"
49 #include "lib/widget.h"
50
51 #include "src/execute.h"
52
53 #include "lib/vfs/vfs.h"
54 #include "lib/vfs/utilvfs.h"
55 #include "lib/vfs/xdirentry.h"
56 #include "src/vfs/local/local.h"
57 #include "lib/vfs/gc.h"
58
59 #include "sfs.h"
60
61
62
63
64
65 #define MAXFS 32
66
67 typedef enum
68 {
69 F_NONE = 0x0,
70 F_1 = 0x1,
71 F_2 = 0x2,
72 F_NOLOCALCOPY = 0x4,
73 F_FULLMATCH = 0x8
74 } sfs_flags_t;
75
76 #define COPY_CHAR \
77 if ((size_t) (t - pad) > sizeof (pad)) \
78 { \
79 g_free (pqname); \
80 return (-1); \
81 } \
82 else \
83 *t++ = *s_iter;
84
85 #define COPY_STRING(a) \
86 if ((t - pad) + strlen (a) > sizeof (pad)) \
87 { \
88 g_free (pqname); \
89 return (-1); \
90 } \
91 else \
92 { \
93 strcpy (t, a); \
94 t += strlen (a); \
95 }
96
97
98
99 typedef struct cachedfile
100 {
101 char *name;
102 char *cache;
103 } cachedfile;
104
105
106
107 static GSList *head = NULL;
108
109 static struct vfs_s_subclass sfs_subclass;
110 static struct vfs_class *vfs_sfs_ops = VFS_CLASS (&sfs_subclass);
111
112 static int sfs_no = 0;
113 static struct
114 {
115 char *prefix;
116 char *command;
117 sfs_flags_t flags;
118 } sfs_info[MAXFS];
119
120
121
122 static int
123 cachedfile_compare (const void *a, const void *b)
124 {
125 const cachedfile *cf = (const cachedfile *) a;
126 const char *name = (const char *) b;
127
128 return strcmp (name, cf->name);
129 }
130
131
132
133 static int
134 sfs_vfmake (const vfs_path_t * vpath, vfs_path_t * cache_vpath)
135 {
136 int w;
137 char pad[10240];
138 char *s_iter, *t = pad;
139 gboolean was_percent = FALSE;
140 vfs_path_t *pname;
141 char *pqname;
142 const vfs_path_element_t *path_element;
143
144 path_element = vfs_path_get_by_index (vpath, -1);
145 pname = vfs_path_clone (vpath);
146 vfs_path_remove_element_by_index (pname, -1);
147
148 w = path_element->class->which (path_element->class, path_element->vfs_prefix);
149 if (w == -1)
150 vfs_die ("This cannot happen... Hopefully.\n");
151
152 if ((sfs_info[w].flags & F_1) == 0
153 && strcmp (vfs_path_get_last_path_str (pname), PATH_SEP_STR) != 0)
154 {
155 vfs_path_free (pname);
156 return (-1);
157 }
158
159
160 if ((sfs_info[w].flags & F_NOLOCALCOPY) != 0)
161 pqname = name_quote (vfs_path_as_str (pname), FALSE);
162 else
163 {
164 vfs_path_t *s;
165
166 s = mc_getlocalcopy (pname);
167 if (s == NULL)
168 {
169 vfs_path_free (pname);
170 return (-1);
171 }
172
173 pqname = name_quote (vfs_path_get_last_path_str (s), FALSE);
174 vfs_path_free (s);
175 }
176
177 vfs_path_free (pname);
178
179 for (s_iter = sfs_info[w].command; *s_iter != '\0'; s_iter++)
180 {
181 if (was_percent)
182 {
183 const char *ptr = NULL;
184
185 was_percent = FALSE;
186
187 switch (*s_iter)
188 {
189 case '1':
190 ptr = pqname;
191 break;
192 case '2':
193 ptr = path_element->path;
194 break;
195 case '3':
196 ptr = vfs_path_get_by_index (cache_vpath, -1)->path;
197 break;
198 case '%':
199 COPY_CHAR;
200 continue;
201 default:
202 break;
203 }
204
205 if (ptr != NULL)
206 {
207 COPY_STRING (ptr);
208 }
209 }
210 else if (*s_iter == '%')
211 was_percent = TRUE;
212 else
213 {
214 COPY_CHAR;
215 }
216 }
217
218 g_free (pqname);
219 open_error_pipe ();
220 if (my_system (EXECUTE_AS_SHELL, "/bin/sh", pad))
221 {
222 close_error_pipe (D_ERROR, NULL);
223 return (-1);
224 }
225
226 close_error_pipe (D_NORMAL, NULL);
227 return 0;
228 }
229
230
231
232 static const char *
233 sfs_redirect (const vfs_path_t * vpath)
234 {
235 GSList *cur;
236 cachedfile *cf;
237 vfs_path_t *cache_vpath;
238 int handle;
239 const vfs_path_element_t *path_element;
240
241 path_element = vfs_path_get_by_index (vpath, -1);
242 cur = g_slist_find_custom (head, vfs_path_as_str (vpath), cachedfile_compare);
243
244 if (cur != NULL)
245 {
246 cf = (cachedfile *) cur->data;
247 vfs_stamp (vfs_sfs_ops, cf);
248 return cf->cache;
249 }
250
251 handle = vfs_mkstemps (&cache_vpath, "sfs", path_element->path);
252
253 if (handle == -1)
254 return "/SOMEONE_PLAYING_DIRTY_TMP_TRICKS_ON_US";
255
256 close (handle);
257
258 if (sfs_vfmake (vpath, cache_vpath) == 0)
259 {
260 cf = g_new (cachedfile, 1);
261 cf->name = g_strdup (vfs_path_as_str (vpath));
262 cf->cache = g_strdup (vfs_path_as_str (cache_vpath));
263 head = g_slist_prepend (head, cf);
264 vfs_path_free (cache_vpath);
265
266 vfs_stamp_create (vfs_sfs_ops, (cachedfile *) head->data);
267 return cf->cache;
268 }
269
270 mc_unlink (cache_vpath);
271 vfs_path_free (cache_vpath);
272 return "/I_MUST_NOT_EXIST";
273 }
274
275
276
277 static void *
278 sfs_open (const vfs_path_t * vpath , int flags,
279 mode_t mode)
280 {
281 int *info;
282 int fd;
283
284 fd = open (sfs_redirect (vpath), NO_LINEAR (flags), mode);
285 if (fd == -1)
286 return NULL;
287
288 info = g_new (int, 1);
289 *info = fd;
290
291 return info;
292 }
293
294
295
296 static int
297 sfs_stat (const vfs_path_t * vpath, struct stat *buf)
298 {
299 return stat (sfs_redirect (vpath), buf);
300 }
301
302
303
304 static int
305 sfs_lstat (const vfs_path_t * vpath, struct stat *buf)
306 {
307 #ifndef HAVE_STATLSTAT
308 return lstat (sfs_redirect (vpath), buf);
309 #else
310 return statlstat (sfs_redirect (vpath), buf);
311 #endif
312 }
313
314
315
316 static int
317 sfs_chmod (const vfs_path_t * vpath, mode_t mode)
318 {
319 return chmod (sfs_redirect (vpath), mode);
320 }
321
322
323
324 static int
325 sfs_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
326 {
327 return chown (sfs_redirect (vpath), owner, group);
328 }
329
330
331
332 static int
333 sfs_utime (const vfs_path_t * vpath, mc_timesbuf_t * times)
334 {
335 #ifdef HAVE_UTIMENSAT
336 return utimensat (AT_FDCWD, sfs_redirect (vpath), *times, 0);
337 #else
338 return utime (sfs_redirect (vpath), times);
339 #endif
340 }
341
342
343
344 static int
345 sfs_readlink (const vfs_path_t * vpath, char *buf, size_t size)
346 {
347 return readlink (sfs_redirect (vpath), buf, size);
348 }
349
350
351
352 static vfsid
353 sfs_getid (const vfs_path_t * vpath)
354 {
355 GSList *cur;
356
357 cur = g_slist_find_custom (head, vfs_path_as_str (vpath), cachedfile_compare);
358
359 return (vfsid) (cur != NULL ? cur->data : NULL);
360 }
361
362
363
364 static void
365 sfs_free (vfsid id)
366 {
367 struct cachedfile *which;
368 GSList *cur;
369
370 which = (struct cachedfile *) id;
371 cur = g_slist_find (head, which);
372 if (cur == NULL)
373 vfs_die ("Free of thing which is unknown to me\n");
374
375 which = (struct cachedfile *) cur->data;
376 unlink (which->cache);
377 g_free (which->cache);
378 g_free (which->name);
379 g_free (which);
380
381 head = g_slist_delete_link (head, cur);
382 }
383
384
385
386 static void
387 sfs_fill_names (struct vfs_class *me, fill_names_f func)
388 {
389 GSList *cur;
390
391 (void) me;
392
393 for (cur = head; cur != NULL; cur = g_slist_next (cur))
394 func (((cachedfile *) cur->data)->name);
395 }
396
397
398
399 static gboolean
400 sfs_nothingisopen (vfsid id)
401 {
402
403
404 (void) id;
405 return TRUE;
406 }
407
408
409
410 static vfs_path_t *
411 sfs_getlocalcopy (const vfs_path_t * vpath)
412 {
413 return vfs_path_from_str (sfs_redirect (vpath));
414 }
415
416
417
418 static int
419 sfs_ungetlocalcopy (const vfs_path_t * vpath, const vfs_path_t * local, gboolean has_changed)
420 {
421 (void) vpath;
422 (void) local;
423 (void) has_changed;
424 return 0;
425 }
426
427
428
429 static int
430 sfs_init (struct vfs_class *me)
431 {
432 char *mc_sfsini;
433 FILE *cfg;
434 char key[256];
435
436 (void) me;
437
438 mc_sfsini = g_build_filename (mc_global.sysconfig_dir, "sfs.ini", (char *) NULL);
439 cfg = fopen (mc_sfsini, "r");
440
441 if (cfg == NULL)
442 {
443 fprintf (stderr, _("%s: Warning: file %s not found\n"), "sfs_init()", mc_sfsini);
444 g_free (mc_sfsini);
445 return 0;
446 }
447 g_free (mc_sfsini);
448
449 sfs_no = 0;
450 while (sfs_no < MAXFS && fgets (key, sizeof (key), cfg) != NULL)
451 {
452 char *c, *semi = NULL;
453 sfs_flags_t flags = F_NONE;
454
455 if (*key == '#' || *key == '\n')
456 continue;
457
458 for (c = key; *c != '\0'; c++)
459 if (*c == ':' || IS_PATH_SEP (*c))
460 {
461 semi = c;
462 if (IS_PATH_SEP (*c))
463 {
464 *c = '\0';
465 flags |= F_FULLMATCH;
466 }
467 break;
468 }
469
470 if (semi == NULL)
471 {
472 invalid_line:
473 fprintf (stderr, _("Warning: Invalid line in %s:\n%s\n"), "sfs.ini", key);
474 continue;
475 }
476
477 for (c = semi + 1; *c != '\0' && !whitespace (*c); c++)
478 switch (*c)
479 {
480 case '1':
481 flags |= F_1;
482 break;
483 case '2':
484 flags |= F_2;
485 break;
486 case 'R':
487 flags |= F_NOLOCALCOPY;
488 break;
489 default:
490 fprintf (stderr, _("Warning: Invalid flag %c in %s:\n%s\n"), *c, "sfs.ini", key);
491 }
492
493 if (*c == '\0')
494 goto invalid_line;
495
496 c++;
497 *(semi + 1) = '\0';
498 semi = strchr (c, '\n');
499 if (semi != NULL)
500 *semi = '\0';
501
502 sfs_info[sfs_no].prefix = g_strdup (key);
503 sfs_info[sfs_no].command = g_strdup (c);
504 sfs_info[sfs_no].flags = flags;
505 sfs_no++;
506 }
507 fclose (cfg);
508
509 return 1;
510 }
511
512
513
514 static void
515 sfs_done (struct vfs_class *me)
516 {
517 int i;
518
519 (void) me;
520
521 for (i = 0; i < sfs_no; i++)
522 {
523 MC_PTR_FREE (sfs_info[i].prefix);
524 MC_PTR_FREE (sfs_info[i].command);
525 }
526 sfs_no = 0;
527 }
528
529
530
531 static int
532 sfs_which (struct vfs_class *me, const char *path)
533 {
534 int i;
535
536 (void) me;
537
538 for (i = 0; i < sfs_no; i++)
539 if ((sfs_info[i].flags & F_FULLMATCH) != 0)
540 {
541 if (strcmp (path, sfs_info[i].prefix) == 0)
542 return i;
543 }
544 else if (strncmp (path, sfs_info[i].prefix, strlen (sfs_info[i].prefix)) == 0)
545 return i;
546
547 return (-1);
548 }
549
550
551
552
553
554 void
555 vfs_init_sfs (void)
556 {
557
558 memset (&sfs_subclass, 0, sizeof (sfs_subclass));
559
560 vfs_init_class (vfs_sfs_ops, "sfs", VFSF_UNKNOWN, NULL);
561 vfs_sfs_ops->init = sfs_init;
562 vfs_sfs_ops->done = sfs_done;
563 vfs_sfs_ops->fill_names = sfs_fill_names;
564 vfs_sfs_ops->which = sfs_which;
565 vfs_sfs_ops->open = sfs_open;
566 vfs_sfs_ops->close = local_close;
567 vfs_sfs_ops->read = local_read;
568 vfs_sfs_ops->stat = sfs_stat;
569 vfs_sfs_ops->lstat = sfs_lstat;
570 vfs_sfs_ops->fstat = local_fstat;
571 vfs_sfs_ops->chmod = sfs_chmod;
572 vfs_sfs_ops->chown = sfs_chown;
573 vfs_sfs_ops->utime = sfs_utime;
574 vfs_sfs_ops->readlink = sfs_readlink;
575 vfs_sfs_ops->ferrno = local_errno;
576 vfs_sfs_ops->lseek = local_lseek;
577 vfs_sfs_ops->getid = sfs_getid;
578 vfs_sfs_ops->nothingisopen = sfs_nothingisopen;
579 vfs_sfs_ops->free = sfs_free;
580 vfs_sfs_ops->getlocalcopy = sfs_getlocalcopy;
581 vfs_sfs_ops->ungetlocalcopy = sfs_ungetlocalcopy;
582 vfs_register_class (vfs_sfs_ops);
583 }
584
585