This source file includes following definitions.
- extfs_super_new
- extfs_entry_new
- extfs_fill_name
- extfs_cmp_archive
- extfs_generate_entry
- extfs_find_entry_int
- extfs_find_entry
- extfs_fill_names
- extfs_free_inode
- extfs_free_archive
- extfs_skip_leading_dotslash
- extfs_add_file
- extfs_open_archive
- extfs_read_archive
- extfs_which
- extfs_open_and_read_archive
- extfs_get_path
- extfs_get_path_from_entry
- extfs_resolve_symlinks_int
- extfs_resolve_symlinks
- extfs_get_archive_name
- extfs_cmd
- extfs_run
- extfs_open
- extfs_read
- extfs_close
- extfs_errno
- extfs_opendir
- extfs_readdir
- extfs_closedir
- extfs_stat_move
- extfs_internal_stat
- extfs_stat
- extfs_lstat
- extfs_fstat
- extfs_readlink
- extfs_write
- extfs_unlink
- extfs_mkdir
- extfs_rmdir
- extfs_chdir
- extfs_lseek
- extfs_getid
- extfs_getlocalcopy
- extfs_ungetlocalcopy
- extfs_get_plugins
- extfs_init
- extfs_done
- extfs_setctl
- vfs_init_extfs
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
42 #include <stdio.h>
43 #include <ctype.h>
44 #include <string.h>
45 #include <stdlib.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <unistd.h>
49 #include <signal.h>
50 #include <errno.h>
51 #include <sys/wait.h>
52
53 #include "lib/global.h"
54 #include "lib/fileloc.h"
55 #include "lib/mcconfig.h"
56 #include "lib/util.h"
57 #include "lib/widget.h"
58
59 #include "src/execute.h"
60
61 #include "lib/vfs/vfs.h"
62 #include "lib/vfs/utilvfs.h"
63 #include "lib/vfs/xdirentry.h"
64 #include "lib/vfs/gc.h"
65
66 #include "extfs.h"
67
68
69
70
71
72 #undef ERRNOR
73 #define ERRNOR(x, y) \
74 do \
75 { \
76 my_errno = x; \
77 return y; \
78 } \
79 while (0)
80
81 #define RECORDSIZE 512
82
83 #define EXTFS_SUPER(a) ((struct extfs_super_t *) (a))
84
85
86
87 struct extfs_super_t
88 {
89 struct vfs_s_super base;
90
91 int fstype;
92 char *local_name;
93 struct stat local_stat;
94 dev_t rdev;
95 };
96
97 typedef struct
98 {
99 char *path;
100 char *prefix;
101 gboolean need_archive;
102 } extfs_plugin_info_t;
103
104
105
106 static struct vfs_s_entry *extfs_resolve_symlinks_int (struct vfs_s_entry *entry, GSList *list);
107
108
109
110 static GArray *extfs_plugins = NULL;
111
112 static gboolean errloop;
113 static gboolean notadir;
114
115 static struct vfs_s_subclass extfs_subclass;
116 static struct vfs_class *vfs_extfs_ops = VFS_CLASS (&extfs_subclass);
117
118 static int my_errno = 0;
119
120
121
122
123
124 static struct extfs_super_t *
125 extfs_super_new (struct vfs_class *me, const char *name, const vfs_path_t *local_name_vpath,
126 int fstype)
127 {
128 struct extfs_super_t *super;
129 struct vfs_s_super *vsuper;
130
131 super = g_new0 (struct extfs_super_t, 1);
132 vsuper = VFS_SUPER (super);
133
134 vsuper->me = me;
135 vsuper->name = g_strdup (name);
136
137 super->fstype = fstype;
138
139 if (local_name_vpath != NULL)
140 {
141 super->local_name = g_strdup (vfs_path_get_last_path_str (local_name_vpath));
142 mc_stat (local_name_vpath, &super->local_stat);
143 }
144
145 VFS_SUBCLASS (me)->supers = g_list_prepend (VFS_SUBCLASS (me)->supers, super);
146
147 return super;
148 }
149
150
151
152
153 static struct vfs_s_entry *
154 extfs_entry_new (struct vfs_class *me, const char *name, struct vfs_s_inode *inode)
155 {
156 struct vfs_s_entry *entry;
157
158 (void) me;
159
160 entry = g_new0 (struct vfs_s_entry, 1);
161
162 entry->name = g_strdup (name);
163 entry->ino = inode;
164
165 return entry;
166 }
167
168
169
170 static void
171 extfs_fill_name (void *data, void *user_data)
172 {
173 struct vfs_s_super *a = VFS_SUPER (data);
174 fill_names_f func = (fill_names_f) user_data;
175 extfs_plugin_info_t *info;
176 char *name;
177
178 info = &g_array_index (extfs_plugins, extfs_plugin_info_t, EXTFS_SUPER (a)->fstype);
179 name = g_strconcat (a->name != NULL ? a->name : "", PATH_SEP_STR, info->prefix,
180 VFS_PATH_URL_DELIMITER, (char *) NULL);
181 func (name);
182 g_free (name);
183 }
184
185
186
187 static gint
188 extfs_cmp_archive (const void *a, const void *b)
189 {
190 const struct vfs_s_super *ar = (const struct vfs_s_super *) a;
191 const char *archive_name = (const char *) b;
192
193 return (ar->name != NULL && strcmp (ar->name, archive_name) == 0) ? 0 : 1;
194 }
195
196
197
198 static struct vfs_s_entry *
199 extfs_generate_entry (struct extfs_super_t *archive, const char *name, struct vfs_s_inode *parent,
200 mode_t mode)
201 {
202 struct vfs_class *me = VFS_SUPER (archive)->me;
203 struct stat st;
204 mode_t myumask;
205 struct vfs_s_inode *inode;
206 struct vfs_s_entry *entry;
207
208 memset (&st, 0, sizeof (st));
209 st.st_ino = VFS_SUPER (archive)->ino_usage++;
210 st.st_dev = archive->rdev;
211 myumask = umask (022);
212 umask (myumask);
213 st.st_mode = mode & ~myumask;
214 st.st_uid = getuid ();
215 st.st_gid = getgid ();
216 st.st_mtime = time (NULL);
217 st.st_atime = st.st_mtime;
218 st.st_ctime = st.st_mtime;
219 st.st_nlink = 1;
220
221 inode = vfs_s_new_inode (me, VFS_SUPER (archive), &st);
222 entry = vfs_s_new_entry (me, name, inode);
223 if (parent != NULL)
224 vfs_s_insert_entry (me, parent, entry);
225
226 return entry;
227 }
228
229
230
231 static struct vfs_s_entry *
232 extfs_find_entry_int (struct vfs_s_inode *dir, const char *name, GSList *list, int flags)
233 {
234 struct vfs_s_entry *pent, *pdir;
235 const char *p, *name_end;
236 char *name_copy;
237 char c = PATH_SEP;
238 struct extfs_super_t *super;
239
240 if (g_path_is_absolute (name))
241 {
242
243 name = g_path_skip_root (name);
244 dir = dir->super->root;
245 }
246
247 super = EXTFS_SUPER (dir->super);
248 pent = dir->ent;
249
250 const size_t name_len = strlen (name);
251
252 name_copy = g_strndup (name, name_len);
253 p = name_copy;
254 name_end = name_copy + name_len;
255
256 while ((pent != NULL) && (c != '\0') && (*p != '\0'))
257 {
258 const char *q = strchr (p, PATH_SEP);
259 if (q == NULL)
260 q = name_end;
261
262 c = *q;
263 name_copy[q - name_copy] = '\0';
264
265 if (DIR_IS_DOTDOT (p))
266 pent = pent->dir != NULL ? pent->dir->ent : NULL;
267 else
268 {
269 GList *pl;
270
271 pent = extfs_resolve_symlinks_int (pent, list);
272 if (pent == NULL)
273 {
274 g_free (name_copy);
275 return NULL;
276 }
277
278 if (!S_ISDIR (pent->ino->st.st_mode))
279 {
280 notadir = TRUE;
281 g_free (name_copy);
282 return NULL;
283 }
284
285 pdir = pent;
286 pl = g_queue_find_custom (pent->ino->subdir, p, vfs_s_entry_compare);
287 pent = pl != NULL ? VFS_ENTRY (pl->data) : NULL;
288 if (pent != NULL && q + 1 > name_end)
289 {
290
291 notadir = !S_ISDIR (pent->ino->st.st_mode);
292 g_free (name_copy);
293 return pent;
294 }
295
296
297 if (pent == NULL && (flags & FL_MKDIR) != 0)
298 pent = extfs_generate_entry (super, p, pdir->ino, S_IFDIR | 0777);
299 if (pent == NULL && (flags & FL_MKFILE) != 0)
300 pent = extfs_generate_entry (super, p, pdir->ino, S_IFREG | 0666);
301 }
302
303
304 name_copy[q - name_copy] = c;
305 if (c != '\0')
306 p = q + 1;
307 }
308
309 g_free (name_copy);
310
311 if (pent == NULL)
312 my_errno = ENOENT;
313
314 return pent;
315 }
316
317
318
319 static struct vfs_s_entry *
320 extfs_find_entry (struct vfs_s_inode *dir, const char *name, int flags)
321 {
322 struct vfs_s_entry *res;
323
324 errloop = FALSE;
325 notadir = FALSE;
326
327 res = extfs_find_entry_int (dir, name, NULL, flags);
328 if (res == NULL)
329 {
330 if (errloop)
331 my_errno = ELOOP;
332 else if (notadir)
333 my_errno = ENOTDIR;
334 }
335 return res;
336 }
337
338
339
340 static void
341 extfs_fill_names (struct vfs_class *me, fill_names_f func)
342 {
343 g_list_foreach (VFS_SUBCLASS (me)->supers, extfs_fill_name, func);
344 }
345
346
347
348
349 static void
350 extfs_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
351 {
352 (void) me;
353
354 if (ino->localname != NULL)
355 {
356 unlink (ino->localname);
357 MC_PTR_FREE (ino->localname);
358 }
359 }
360
361
362
363 static void
364 extfs_free_archive (struct vfs_class *me, struct vfs_s_super *psup)
365 {
366 struct extfs_super_t *archive = EXTFS_SUPER (psup);
367
368 (void) me;
369
370 if (archive->local_name != NULL)
371 {
372 struct stat my;
373 vfs_path_t *local_name_vpath, *name_vpath;
374
375 local_name_vpath = vfs_path_from_str (archive->local_name);
376 name_vpath = vfs_path_from_str (psup->name);
377 mc_stat (local_name_vpath, &my);
378 mc_ungetlocalcopy (name_vpath, local_name_vpath,
379 archive->local_stat.st_mtime != my.st_mtime);
380 vfs_path_free (local_name_vpath, TRUE);
381 vfs_path_free (name_vpath, TRUE);
382 g_free (archive->local_name);
383 }
384 }
385
386
387
388 static inline char *
389 extfs_skip_leading_dotslash (char *s)
390 {
391
392
393
394
395
396
397
398
399
400 if (s[0] == '.' && s[1] == PATH_SEP)
401 s += 2;
402
403 return s;
404 }
405
406
407
408 static int
409 extfs_add_file (struct extfs_super_t *archive, const char *file_name)
410 {
411 struct vfs_s_super *super = VFS_SUPER (archive);
412 struct stat hstat;
413 char *current_file_name = NULL, *current_link_name = NULL;
414 int ret = 0;
415
416 if (vfs_parse_ls_lga (file_name, &hstat, ¤t_file_name, ¤t_link_name, NULL))
417 {
418 char *cfn = current_file_name;
419
420 if (*cfn != '\0')
421 {
422 struct vfs_s_entry *entry;
423 struct vfs_s_entry *pent = NULL;
424 struct vfs_s_inode *inode;
425 char *p, *q;
426
427 cfn = extfs_skip_leading_dotslash (cfn);
428 if (IS_PATH_SEP (*cfn))
429 cfn++;
430 p = strchr (cfn, '\0');
431 if (p != cfn && IS_PATH_SEP (p[-1]))
432 p[-1] = '\0';
433 p = strrchr (cfn, PATH_SEP);
434 if (p == NULL)
435 {
436 p = cfn;
437 q = strchr (cfn, '\0');
438 }
439 else
440 {
441 *(p++) = '\0';
442 q = cfn;
443 }
444
445 if (*q != '\0')
446 {
447 pent = extfs_find_entry (super->root, q, FL_MKDIR);
448 if (pent == NULL)
449 {
450 ret = -1;
451 goto done;
452 }
453 }
454
455 if (pent != NULL)
456 {
457 entry = extfs_entry_new (super->me, p, pent->ino);
458 entry->dir = pent->ino;
459 g_queue_push_tail (pent->ino->subdir, entry);
460 }
461 else
462 {
463 entry = extfs_entry_new (super->me, p, super->root);
464 entry->dir = super->root;
465 g_queue_push_tail (super->root->subdir, entry);
466 }
467
468 if (!S_ISLNK (hstat.st_mode) && (current_link_name != NULL))
469 {
470 pent = extfs_find_entry (super->root, current_link_name, FL_NONE);
471 if (pent == NULL)
472 {
473 ret = -1;
474 goto done;
475 }
476
477 pent->ino->st.st_nlink++;
478 entry->ino = pent->ino;
479 }
480 else
481 {
482 struct stat st;
483
484 memset (&st, 0, sizeof (st));
485 st.st_ino = super->ino_usage++;
486 st.st_nlink = 1;
487 st.st_dev = archive->rdev;
488 st.st_mode = hstat.st_mode;
489 #ifdef HAVE_STRUCT_STAT_ST_RDEV
490 st.st_rdev = hstat.st_rdev;
491 #endif
492 st.st_uid = hstat.st_uid;
493 st.st_gid = hstat.st_gid;
494 st.st_size = hstat.st_size;
495 st.st_mtime = hstat.st_mtime;
496 st.st_atime = hstat.st_atime;
497 st.st_ctime = hstat.st_ctime;
498
499 if (current_link_name == NULL && S_ISLNK (hstat.st_mode))
500 st.st_mode &= ~S_IFLNK;
501
502 inode = vfs_s_new_inode (super->me, super, &st);
503 inode->ent = entry;
504 entry->ino = inode;
505
506 if (current_link_name != NULL && S_ISLNK (hstat.st_mode))
507 {
508 inode->linkname = current_link_name;
509 current_link_name = NULL;
510 }
511 }
512 }
513
514 done:
515 g_free (current_file_name);
516 g_free (current_link_name);
517 }
518
519 return ret;
520 }
521
522
523
524 static mc_pipe_t *
525 extfs_open_archive (int fstype, const char *name, struct extfs_super_t **pparc, GError **error)
526 {
527 const extfs_plugin_info_t *info;
528 static dev_t archive_counter = 0;
529 mc_pipe_t *result = NULL;
530 mode_t mode;
531 GString *cmd;
532 struct stat mystat;
533 struct extfs_super_t *current_archive;
534 struct vfs_s_entry *root_entry;
535 GString *quoted_name = NULL;
536 vfs_path_t *local_name_vpath = NULL;
537 vfs_path_t *name_vpath;
538
539 memset (&mystat, 0, sizeof (mystat));
540
541 name_vpath = vfs_path_from_str (name);
542 info = &g_array_index (extfs_plugins, extfs_plugin_info_t, fstype);
543
544 if (info->need_archive)
545 {
546 if (mc_stat (name_vpath, &mystat) == -1)
547 {
548 mc_propagate_error (error, 0, "%s", unix_error_string (errno));
549 goto ret;
550 }
551
552 if (!vfs_file_is_local (name_vpath))
553 {
554 local_name_vpath = mc_getlocalcopy (name_vpath);
555 if (local_name_vpath == NULL)
556 goto ret;
557 }
558
559 quoted_name = name_quote (vfs_path_get_last_path_str (name_vpath), FALSE);
560 }
561
562 const char *local_last_path = vfs_path_get_last_path_str (local_name_vpath);
563
564 cmd = g_string_new (info->path);
565 g_string_append (cmd, info->prefix);
566 g_string_append (cmd, " list ");
567
568 if (local_last_path != NULL)
569 g_string_append (cmd, local_last_path);
570 else if (quoted_name != NULL)
571 {
572 mc_g_string_concat (cmd, quoted_name);
573 g_string_free (quoted_name, TRUE);
574 }
575
576 result = mc_popen (cmd->str, TRUE, TRUE, error);
577 g_string_free (cmd, TRUE);
578
579 if (result == NULL)
580 {
581 if (local_name_vpath != NULL)
582 {
583 mc_ungetlocalcopy (name_vpath, local_name_vpath, FALSE);
584 vfs_path_free (local_name_vpath, TRUE);
585 }
586 goto ret;
587 }
588
589 current_archive = extfs_super_new (vfs_extfs_ops, name, local_name_vpath, fstype);
590 current_archive->rdev = archive_counter++;
591 vfs_path_free (local_name_vpath, TRUE);
592
593 mode = mystat.st_mode & 07777;
594 if (mode & 0400)
595 mode |= 0100;
596 if (mode & 0040)
597 mode |= 0010;
598 if (mode & 0004)
599 mode |= 0001;
600 mode |= S_IFDIR;
601
602 root_entry = extfs_generate_entry (current_archive, PATH_SEP_STR, NULL, mode);
603 root_entry->ino->st.st_uid = mystat.st_uid;
604 root_entry->ino->st.st_gid = mystat.st_gid;
605 root_entry->ino->st.st_atime = mystat.st_atime;
606 root_entry->ino->st.st_ctime = mystat.st_ctime;
607 root_entry->ino->st.st_mtime = mystat.st_mtime;
608 root_entry->ino->ent = root_entry;
609 VFS_SUPER (current_archive)->root = root_entry->ino;
610
611 *pparc = current_archive;
612
613 ret:
614 vfs_path_free (name_vpath, TRUE);
615 return result;
616 }
617
618
619
620
621
622
623
624 static int
625 extfs_read_archive (mc_pipe_t *pip, struct extfs_super_t *archive, GError **error)
626 {
627 int ret = 0;
628 GString *buffer;
629 GString *err_msg = NULL;
630 GString *remain_file_name = NULL;
631
632 while (ret != -1)
633 {
634
635 pip->out.len = MC_PIPE_BUFSIZE;
636 pip->err.len = MC_PIPE_BUFSIZE;
637
638 mc_pread (pip, error);
639
640 if (*error != NULL)
641 return (-1);
642
643 if (pip->err.len > 0)
644 {
645
646 if (err_msg == NULL)
647 err_msg = g_string_new_len (pip->err.buf, pip->err.len);
648 else
649 {
650 if (err_msg->str[err_msg->len - 1] != '\n')
651 g_string_append_c (err_msg, '\n');
652 g_string_append_len (err_msg, pip->err.buf, pip->err.len);
653 }
654 }
655
656 if (pip->out.len == MC_PIPE_STREAM_EOF)
657 break;
658
659 if (pip->out.len == 0)
660 continue;
661
662 if (pip->out.len == MC_PIPE_ERROR_READ)
663 return (-1);
664
665 while (ret != -1 && (buffer = mc_pstream_get_string (&pip->out)) != NULL)
666 {
667
668
669 if (buffer->str[buffer->len - 1] == '\n')
670 {
671
672
673 g_string_truncate (buffer, buffer->len - 1);
674
675
676 if (remain_file_name != NULL)
677 {
678 g_string_append_len (remain_file_name, buffer->str, buffer->len);
679 g_string_free (buffer, TRUE);
680 buffer = remain_file_name;
681 remain_file_name = NULL;
682 }
683 }
684 else
685 {
686
687
688 if (remain_file_name == NULL)
689 remain_file_name = buffer;
690 else
691 {
692 g_string_append_len (remain_file_name, buffer->str, buffer->len);
693 g_string_free (buffer, TRUE);
694 }
695
696 continue;
697 }
698
699 ret = extfs_add_file (archive, buffer->str);
700
701 g_string_free (buffer, TRUE);
702 }
703 }
704
705 if (remain_file_name != NULL)
706 g_string_free (remain_file_name, TRUE);
707
708 if (err_msg != NULL)
709 {
710 if (*error == NULL)
711 mc_propagate_error (error, 0, "%s", err_msg->str);
712
713 g_string_free (err_msg, TRUE);
714 }
715 else if (ret == -1)
716 mc_propagate_error (error, 0, "%s", _ ("Inconsistent archive"));
717
718 return ret;
719 }
720
721
722
723 static int
724 extfs_which (struct vfs_class *me, const char *path)
725 {
726 size_t path_len;
727 size_t i;
728
729 (void) me;
730
731 path_len = strlen (path);
732
733 for (i = 0; i < extfs_plugins->len; i++)
734 {
735 extfs_plugin_info_t *info;
736
737 info = &g_array_index (extfs_plugins, extfs_plugin_info_t, i);
738
739 if ((strncmp (path, info->prefix, path_len) == 0)
740 && ((info->prefix[path_len] == '\0') || (info->prefix[path_len] == '+')))
741 return i;
742 }
743 return -1;
744 }
745
746
747
748 static int
749 extfs_open_and_read_archive (int fstype, const char *name, struct extfs_super_t **archive)
750 {
751 int result = -1;
752 struct extfs_super_t *a;
753 mc_pipe_t *pip;
754 GError *error = NULL;
755
756 pip = extfs_open_archive (fstype, name, archive, &error);
757
758 a = *archive;
759
760 if (pip == NULL)
761 {
762 const extfs_plugin_info_t *info;
763
764 info = &g_array_index (extfs_plugins, extfs_plugin_info_t, fstype);
765 if (error == NULL)
766 message (D_ERROR, MSG_ERROR, _ ("Cannot open %s archive\n%s"), info->prefix, name);
767 else
768 {
769 message (D_ERROR, MSG_ERROR, _ ("Cannot open %s archive\n%s:\n%s"), info->prefix, name,
770 error->message);
771 g_error_free (error);
772 }
773 }
774 else
775 {
776 result = extfs_read_archive (pip, a, &error);
777
778 if (result != 0)
779 VFS_SUPER (a)->me->free (VFS_SUPER (a));
780
781 if (error != NULL)
782 {
783 message (D_ERROR, MSG_ERROR, _ ("EXTFS virtual file system:\n%s"), error->message);
784 g_error_free (error);
785 }
786
787 mc_pclose (pip, NULL);
788 }
789
790 return result;
791 }
792
793
794
795
796
797 static const char *
798 extfs_get_path (const vfs_path_t *vpath, struct extfs_super_t **archive, int flags)
799 {
800 char *archive_name;
801 int result = -1;
802 GList *parc;
803 int fstype;
804 const vfs_path_element_t *path_element;
805 struct extfs_super_t *a = NULL;
806
807 path_element = vfs_path_get_by_index (vpath, -1);
808
809 fstype = extfs_which (path_element->class, path_element->vfs_prefix);
810 if (fstype == -1)
811 return NULL;
812
813 archive_name = vfs_path_to_str_elements_count (vpath, -1);
814
815
816 parc = g_list_find_custom (extfs_subclass.supers, archive_name, extfs_cmp_archive);
817 if (parc != NULL)
818 {
819 a = EXTFS_SUPER (parc->data);
820 vfs_stamp (vfs_extfs_ops, (vfsid) a);
821 g_free (archive_name);
822 }
823 else
824 {
825 if ((flags & FL_NO_OPEN) == 0)
826 result = extfs_open_and_read_archive (fstype, archive_name, &a);
827
828 g_free (archive_name);
829
830 if (result == -1)
831 {
832 path_element->class->verrno = EIO;
833 return NULL;
834 }
835 }
836
837 *archive = a;
838 return path_element->path;
839 }
840
841
842
843
844 static char *
845 extfs_get_path_from_entry (const struct vfs_s_entry *entry)
846 {
847 const struct vfs_s_entry *e;
848 GString *localpath;
849
850 localpath = g_string_new ("");
851
852 for (e = entry; e->dir != NULL; e = e->dir->ent)
853 {
854 g_string_prepend (localpath, e->name);
855 if (e->dir->ent->dir != NULL)
856 g_string_prepend_c (localpath, PATH_SEP);
857 }
858
859 return g_string_free (localpath, FALSE);
860 }
861
862
863
864 static struct vfs_s_entry *
865 extfs_resolve_symlinks_int (struct vfs_s_entry *entry, GSList *list)
866 {
867 struct vfs_s_entry *pent = NULL;
868
869 if (!S_ISLNK (entry->ino->st.st_mode))
870 return entry;
871
872 if (g_slist_find (list, entry) != NULL)
873 {
874
875 errloop = TRUE;
876 }
877 else
878 {
879 GSList *looping;
880
881 looping = g_slist_prepend (list, entry);
882 pent = extfs_find_entry_int (entry->dir, entry->ino->linkname, looping, FL_NONE);
883 looping = g_slist_delete_link (looping, looping);
884
885 if (pent == NULL)
886 my_errno = ENOENT;
887 }
888
889 return pent;
890 }
891
892
893
894 static struct vfs_s_entry *
895 extfs_resolve_symlinks (struct vfs_s_entry *entry)
896 {
897 struct vfs_s_entry *res;
898
899 errloop = FALSE;
900 notadir = FALSE;
901 res = extfs_resolve_symlinks_int (entry, NULL);
902 if (res == NULL)
903 {
904 if (errloop)
905 my_errno = ELOOP;
906 else if (notadir)
907 my_errno = ENOTDIR;
908 }
909 return res;
910 }
911
912
913
914 static char *
915 extfs_get_archive_name (const struct extfs_super_t *archive)
916 {
917 const char *archive_name;
918
919 if (archive->local_name != NULL)
920 archive_name = archive->local_name;
921 else
922 archive_name = CONST_VFS_SUPER (archive)->name;
923
924 if (archive_name == NULL || *archive_name == '\0')
925 return g_strdup ("no_archive_name");
926 else
927 {
928 char *ret_str;
929 vfs_path_t *vpath;
930 const char *path;
931
932 vpath = vfs_path_from_str (archive_name);
933 path = vfs_path_get_last_path_str (vpath);
934 ret_str = g_strdup (path);
935 vfs_path_free (vpath, TRUE);
936 return ret_str;
937 }
938 }
939
940
941
942
943 static int
944 extfs_cmd (const char *str_extfs_cmd, const struct extfs_super_t *archive,
945 const struct vfs_s_entry *entry, const char *localname)
946 {
947 char *file;
948 GString *quoted_file;
949 char *archive_name;
950 GString *quoted_archive_name;
951 const extfs_plugin_info_t *info;
952 GString *cmd;
953 int retval = 0;
954 GError *error = NULL;
955 mc_pipe_t *pip;
956
957 file = extfs_get_path_from_entry (entry);
958 quoted_file = name_quote (file, FALSE);
959 g_free (file);
960
961 if (quoted_file == NULL)
962 {
963 message (D_ERROR, MSG_ERROR, _ ("EXTFS virtual file system:\nwrong file name"));
964 return (-1);
965 }
966
967 archive_name = extfs_get_archive_name (archive);
968 quoted_archive_name = name_quote (archive_name, FALSE);
969 g_free (archive_name);
970
971 if (quoted_archive_name == NULL)
972 {
973 message (D_ERROR, MSG_ERROR, _ ("EXTFS virtual file system:\nwrong archive name"));
974 g_string_free (quoted_file, TRUE);
975 return (-1);
976 }
977
978 info = &g_array_index (extfs_plugins, extfs_plugin_info_t, archive->fstype);
979
980
981 file = extfs_skip_leading_dotslash (quoted_file->str);
982
983 cmd = g_string_new (info->path);
984 g_string_append (cmd, info->prefix);
985 g_string_append (cmd, str_extfs_cmd);
986 mc_g_string_concat (cmd, quoted_archive_name);
987 g_string_append_c (cmd, ' ');
988 g_string_append (cmd, file);
989
990 g_string_free (quoted_file, TRUE);
991 g_string_free (quoted_archive_name, TRUE);
992
993 if (localname != NULL && *localname != '\0')
994 {
995 GString *quoted_localname;
996
997 quoted_localname = name_quote (localname, FALSE);
998 g_string_append_c (cmd, ' ');
999 mc_g_string_concat (cmd, quoted_localname);
1000 g_string_free (quoted_localname, TRUE);
1001 }
1002
1003
1004 pip = mc_popen (cmd->str, FALSE, TRUE, &error);
1005 g_string_free (cmd, TRUE);
1006
1007 if (pip == NULL)
1008 {
1009 message (D_ERROR, MSG_ERROR, _ ("EXTFS virtual file system:\n%s"), error->message);
1010 g_error_free (error);
1011 return (-1);
1012 }
1013
1014 pip->err.null_term = TRUE;
1015
1016 mc_pread (pip, &error);
1017 if (error != NULL)
1018 {
1019 message (D_ERROR, MSG_ERROR, _ ("EXTFS virtual file system:\n%s"), error->message);
1020 g_error_free (error);
1021 retval = -1;
1022 }
1023 else if (pip->err.len > 0)
1024 message (D_ERROR, MSG_ERROR, _ ("EXTFS virtual file system:\n%s"), pip->err.buf);
1025
1026 mc_pclose (pip, NULL);
1027
1028 return retval;
1029 }
1030
1031
1032
1033 static void
1034 extfs_run (const vfs_path_t *vpath)
1035 {
1036 struct extfs_super_t *archive = NULL;
1037 const char *p;
1038 GString *quoted_name;
1039 char *archive_name;
1040 GString *quoted_archive_name;
1041 GString *cmd;
1042 const extfs_plugin_info_t *info;
1043
1044 p = extfs_get_path (vpath, &archive, FL_NONE);
1045 if (p == NULL)
1046 return;
1047
1048 quoted_name = name_quote (p, FALSE);
1049 archive_name = extfs_get_archive_name (archive);
1050 quoted_archive_name = name_quote (archive_name, FALSE);
1051 g_free (archive_name);
1052
1053 info = &g_array_index (extfs_plugins, extfs_plugin_info_t, archive->fstype);
1054
1055 cmd = g_string_new (info->path);
1056 g_string_append (cmd, info->prefix);
1057 g_string_append (cmd, " run ");
1058 mc_g_string_concat (cmd, quoted_archive_name);
1059 g_string_append_c (cmd, ' ');
1060 mc_g_string_concat (cmd, quoted_name);
1061
1062 g_string_free (quoted_archive_name, TRUE);
1063 g_string_free (quoted_name, TRUE);
1064
1065 shell_execute (cmd->str, 0);
1066
1067 g_string_free (cmd, TRUE);
1068 }
1069
1070
1071
1072 static void *
1073 extfs_open (const vfs_path_t *vpath, int flags, mode_t mode)
1074 {
1075 vfs_file_handler_t *extfs_info;
1076 struct extfs_super_t *archive = NULL;
1077 const char *q;
1078 struct vfs_s_entry *entry;
1079 int local_handle;
1080 gboolean created = FALSE;
1081
1082 q = extfs_get_path (vpath, &archive, FL_NONE);
1083 if (q == NULL)
1084 return NULL;
1085 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_NONE);
1086 if ((entry == NULL) && ((flags & O_CREAT) != 0))
1087 {
1088
1089 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_MKFILE);
1090 created = (entry != NULL);
1091 }
1092
1093 if (entry == NULL)
1094 return NULL;
1095 entry = extfs_resolve_symlinks (entry);
1096 if (entry == NULL)
1097 return NULL;
1098
1099 if (S_ISDIR (entry->ino->st.st_mode))
1100 ERRNOR (EISDIR, NULL);
1101
1102 if (entry->ino->localname == NULL)
1103 {
1104 vfs_path_t *local_filename_vpath;
1105 const char *local_filename;
1106
1107 local_handle = vfs_mkstemps (&local_filename_vpath, "extfs", entry->name);
1108
1109 if (local_handle == -1)
1110 return NULL;
1111 close (local_handle);
1112 local_filename = vfs_path_get_last_path_str (local_filename_vpath);
1113
1114 if (!created && ((flags & O_TRUNC) == 0)
1115 && extfs_cmd (" copyout ", archive, entry, local_filename))
1116 {
1117 unlink (local_filename);
1118 vfs_path_free (local_filename_vpath, TRUE);
1119 my_errno = EIO;
1120 return NULL;
1121 }
1122 entry->ino->localname = g_strdup (local_filename);
1123 vfs_path_free (local_filename_vpath, TRUE);
1124 }
1125
1126 local_handle = open (entry->ino->localname, NO_LINEAR (flags), mode);
1127
1128 if (local_handle == -1)
1129 {
1130
1131 flags = ~O_CREAT & (NO_LINEAR (flags) | O_TRUNC);
1132 local_handle = open (entry->ino->localname, flags, mode);
1133 }
1134
1135 if (local_handle == -1)
1136 ERRNOR (EIO, NULL);
1137
1138 extfs_info = g_new (vfs_file_handler_t, 1);
1139 vfs_s_init_fh (extfs_info, entry->ino, created);
1140 extfs_info->handle = local_handle;
1141
1142
1143 vfs_rmstamp (vfs_extfs_ops, (vfsid) archive);
1144 VFS_SUPER (archive)->fd_usage++;
1145 return extfs_info;
1146 }
1147
1148
1149
1150 static ssize_t
1151 extfs_read (void *fh, char *buffer, size_t count)
1152 {
1153 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1154
1155 return read (file->handle, buffer, count);
1156 }
1157
1158
1159
1160 static int
1161 extfs_close (void *fh)
1162 {
1163 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1164 int errno_code = 0;
1165
1166 close (file->handle);
1167 file->handle = -1;
1168
1169
1170 if (file->changed)
1171 {
1172 struct stat file_status;
1173
1174 if (extfs_cmd (" copyin ", EXTFS_SUPER (VFS_FILE_HANDLER_SUPER (fh)), file->ino->ent,
1175 file->ino->localname))
1176 errno_code = EIO;
1177
1178 if (stat (file->ino->localname, &file_status) != 0)
1179 errno_code = EIO;
1180 else
1181 file->ino->st.st_size = file_status.st_size;
1182
1183 file->ino->st.st_mtime = time (NULL);
1184 }
1185
1186 if (--VFS_FILE_HANDLER_SUPER (fh)->fd_usage == 0)
1187 vfs_stamp_create (vfs_extfs_ops, VFS_FILE_HANDLER_SUPER (fh));
1188
1189 g_free (fh);
1190 if (errno_code != 0)
1191 ERRNOR (EIO, -1);
1192 return 0;
1193 }
1194
1195
1196
1197 static int
1198 extfs_errno (struct vfs_class *me)
1199 {
1200 (void) me;
1201 return my_errno;
1202 }
1203
1204
1205
1206 static void *
1207 extfs_opendir (const vfs_path_t *vpath)
1208 {
1209 struct extfs_super_t *archive = NULL;
1210 const char *q;
1211 struct vfs_s_entry *entry;
1212 GList **info;
1213
1214 q = extfs_get_path (vpath, &archive, FL_NONE);
1215 if (q == NULL)
1216 return NULL;
1217 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_NONE);
1218 if (entry == NULL)
1219 return NULL;
1220 entry = extfs_resolve_symlinks (entry);
1221 if (entry == NULL)
1222 return NULL;
1223 if (!S_ISDIR (entry->ino->st.st_mode))
1224 ERRNOR (ENOTDIR, NULL);
1225
1226 info = g_new (GList *, 1);
1227 *info = g_queue_peek_head_link (entry->ino->subdir);
1228
1229 return info;
1230 }
1231
1232
1233
1234 static struct vfs_dirent *
1235 extfs_readdir (void *data)
1236 {
1237 struct vfs_dirent *dir;
1238 GList **info = (GList **) data;
1239
1240 if (*info == NULL)
1241 return NULL;
1242
1243 dir = vfs_dirent_init (NULL, VFS_ENTRY ((*info)->data)->name, 0, DT_UNKNOWN);
1244
1245 *info = g_list_next (*info);
1246
1247 return dir;
1248 }
1249
1250
1251
1252 static int
1253 extfs_closedir (void *data)
1254 {
1255 g_free (data);
1256 return 0;
1257 }
1258
1259
1260
1261 static void
1262 extfs_stat_move (struct stat *buf, const struct vfs_s_inode *inode)
1263 {
1264 const time_t atime = inode->st.st_atime;
1265 const time_t mtime = inode->st.st_mtime;
1266 const time_t ctime = inode->st.st_ctime;
1267
1268 *buf = inode->st;
1269
1270 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1271 buf->st_blksize = RECORDSIZE;
1272 #endif
1273
1274 vfs_adjust_stat (buf);
1275 vfs_zero_stat_times (buf);
1276
1277 buf->st_atime = atime;
1278 buf->st_mtime = mtime;
1279 buf->st_ctime = ctime;
1280 }
1281
1282
1283
1284 static int
1285 extfs_internal_stat (const vfs_path_t *vpath, struct stat *buf, gboolean resolve)
1286 {
1287 struct extfs_super_t *archive;
1288 const char *q;
1289 struct vfs_s_entry *entry;
1290 int result = -1;
1291
1292 q = extfs_get_path (vpath, &archive, FL_NONE);
1293 if (q == NULL)
1294 goto cleanup;
1295 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_NONE);
1296 if (entry == NULL)
1297 goto cleanup;
1298 if (resolve)
1299 {
1300 entry = extfs_resolve_symlinks (entry);
1301 if (entry == NULL)
1302 goto cleanup;
1303 }
1304 extfs_stat_move (buf, entry->ino);
1305 result = 0;
1306 cleanup:
1307 return result;
1308 }
1309
1310
1311
1312 static int
1313 extfs_stat (const vfs_path_t *vpath, struct stat *buf)
1314 {
1315 return extfs_internal_stat (vpath, buf, TRUE);
1316 }
1317
1318
1319
1320 static int
1321 extfs_lstat (const vfs_path_t *vpath, struct stat *buf)
1322 {
1323 return extfs_internal_stat (vpath, buf, FALSE);
1324 }
1325
1326
1327
1328 static int
1329 extfs_fstat (void *fh, struct stat *buf)
1330 {
1331 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1332
1333 extfs_stat_move (buf, file->ino);
1334 return 0;
1335 }
1336
1337
1338
1339 static int
1340 extfs_readlink (const vfs_path_t *vpath, char *buf, size_t size)
1341 {
1342 struct extfs_super_t *archive;
1343 const char *q;
1344 size_t len;
1345 struct vfs_s_entry *entry;
1346 int result = -1;
1347
1348 q = extfs_get_path (vpath, &archive, FL_NONE);
1349 if (q == NULL)
1350 goto cleanup;
1351 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_NONE);
1352 if (entry == NULL)
1353 goto cleanup;
1354 if (!S_ISLNK (entry->ino->st.st_mode))
1355 {
1356 VFS_CLASS (vfs_path_get_last_path_vfs (vpath))->verrno = EINVAL;
1357 goto cleanup;
1358 }
1359 len = strlen (entry->ino->linkname);
1360 if (size < len)
1361 len = size;
1362
1363 result = len;
1364 memcpy (buf, entry->ino->linkname, result);
1365 cleanup:
1366 return result;
1367 }
1368
1369
1370
1371 static ssize_t
1372 extfs_write (void *fh, const char *buf, size_t nbyte)
1373 {
1374 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1375
1376 file->changed = TRUE;
1377 return write (file->handle, buf, nbyte);
1378 }
1379
1380
1381
1382 static int
1383 extfs_unlink (const vfs_path_t *vpath)
1384 {
1385 struct extfs_super_t *archive;
1386 const char *q;
1387 struct vfs_s_entry *entry;
1388 int result = -1;
1389
1390 q = extfs_get_path (vpath, &archive, FL_NONE);
1391 if (q == NULL)
1392 goto cleanup;
1393 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_NONE);
1394 if (entry == NULL)
1395 goto cleanup;
1396 entry = extfs_resolve_symlinks (entry);
1397 if (entry == NULL)
1398 goto cleanup;
1399 if (S_ISDIR (entry->ino->st.st_mode))
1400 {
1401 VFS_CLASS (vfs_path_get_last_path_vfs (vpath))->verrno = EISDIR;
1402 goto cleanup;
1403 }
1404 if (extfs_cmd (" rm ", archive, entry, ""))
1405 {
1406 my_errno = EIO;
1407 goto cleanup;
1408 }
1409 vfs_s_free_entry (VFS_SUPER (archive)->me, entry);
1410 result = 0;
1411 cleanup:
1412 return result;
1413 }
1414
1415
1416
1417 static int
1418 extfs_mkdir (const vfs_path_t *vpath, mode_t mode)
1419 {
1420 struct extfs_super_t *archive;
1421 const char *q;
1422 struct vfs_s_entry *entry;
1423 int result = -1;
1424 struct vfs_class *me;
1425
1426 (void) mode;
1427
1428 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1429 q = extfs_get_path (vpath, &archive, FL_NONE);
1430 if (q == NULL)
1431 goto cleanup;
1432 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_NONE);
1433 if (entry != NULL)
1434 {
1435 me->verrno = EEXIST;
1436 goto cleanup;
1437 }
1438 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_MKDIR);
1439 if (entry == NULL)
1440 goto cleanup;
1441 entry = extfs_resolve_symlinks (entry);
1442 if (entry == NULL)
1443 goto cleanup;
1444 if (!S_ISDIR (entry->ino->st.st_mode))
1445 {
1446 me->verrno = ENOTDIR;
1447 goto cleanup;
1448 }
1449
1450 if (extfs_cmd (" mkdir ", archive, entry, ""))
1451 {
1452 my_errno = EIO;
1453 vfs_s_free_entry (VFS_SUPER (archive)->me, entry);
1454 goto cleanup;
1455 }
1456 result = 0;
1457 cleanup:
1458 return result;
1459 }
1460
1461
1462
1463 static int
1464 extfs_rmdir (const vfs_path_t *vpath)
1465 {
1466 struct extfs_super_t *archive;
1467 const char *q;
1468 struct vfs_s_entry *entry;
1469 int result = -1;
1470
1471 q = extfs_get_path (vpath, &archive, FL_NONE);
1472 if (q == NULL)
1473 goto cleanup;
1474 entry = extfs_find_entry (VFS_SUPER (archive)->root, q, FL_NONE);
1475 if (entry == NULL)
1476 goto cleanup;
1477 entry = extfs_resolve_symlinks (entry);
1478 if (entry == NULL)
1479 goto cleanup;
1480 if (!S_ISDIR (entry->ino->st.st_mode))
1481 {
1482 VFS_CLASS (vfs_path_get_last_path_vfs (vpath))->verrno = ENOTDIR;
1483 goto cleanup;
1484 }
1485
1486 if (extfs_cmd (" rmdir ", archive, entry, ""))
1487 {
1488 my_errno = EIO;
1489 goto cleanup;
1490 }
1491 vfs_s_free_entry (VFS_SUPER (archive)->me, entry);
1492 result = 0;
1493 cleanup:
1494 return result;
1495 }
1496
1497
1498
1499 static int
1500 extfs_chdir (const vfs_path_t *vpath)
1501 {
1502 void *data;
1503
1504 my_errno = ENOTDIR;
1505 data = extfs_opendir (vpath);
1506 if (data == NULL)
1507 return (-1);
1508 extfs_closedir (data);
1509 my_errno = 0;
1510 return 0;
1511 }
1512
1513
1514
1515 static off_t
1516 extfs_lseek (void *fh, off_t offset, int whence)
1517 {
1518 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1519
1520 return lseek (file->handle, offset, whence);
1521 }
1522
1523
1524
1525 static vfsid
1526 extfs_getid (const vfs_path_t *vpath)
1527 {
1528 struct extfs_super_t *archive = NULL;
1529 const char *p;
1530
1531 p = extfs_get_path (vpath, &archive, FL_NO_OPEN);
1532 return (p == NULL ? NULL : (vfsid) archive);
1533 }
1534
1535
1536
1537 static vfs_path_t *
1538 extfs_getlocalcopy (const vfs_path_t *vpath)
1539 {
1540 vfs_file_handler_t *fh;
1541 vfs_path_t *p;
1542
1543 fh = VFS_FILE_HANDLER (extfs_open (vpath, O_RDONLY, 0));
1544 if (fh == NULL)
1545 return NULL;
1546 if (fh->ino->localname == NULL)
1547 {
1548 extfs_close ((void *) fh);
1549 return NULL;
1550 }
1551 p = vfs_path_from_str (fh->ino->localname);
1552 VFS_FILE_HANDLER_SUPER (fh)->fd_usage++;
1553 extfs_close ((void *) fh);
1554 return p;
1555 }
1556
1557
1558
1559 static int
1560 extfs_ungetlocalcopy (const vfs_path_t *vpath, const vfs_path_t *local, gboolean has_changed)
1561 {
1562 vfs_file_handler_t *fh;
1563
1564 fh = VFS_FILE_HANDLER (extfs_open (vpath, O_RDONLY, 0));
1565 if (fh == NULL)
1566 return 0;
1567
1568 if (strcmp (fh->ino->localname, vfs_path_get_last_path_str (local)) == 0)
1569 {
1570 VFS_FILE_HANDLER_SUPER (fh)->fd_usage--;
1571 if (has_changed)
1572 fh->changed = TRUE;
1573 extfs_close ((void *) fh);
1574 return 0;
1575 }
1576 else
1577 {
1578
1579 extfs_close ((void *) fh);
1580 return 0;
1581 }
1582 }
1583
1584
1585
1586 static gboolean
1587 extfs_get_plugins (const char *where, gboolean silent)
1588 {
1589 char *dirname;
1590 GDir *dir;
1591 const char *filename;
1592
1593 dirname = g_build_path (PATH_SEP_STR, where, MC_EXTFS_DIR, (char *) NULL);
1594 dir = g_dir_open (dirname, 0, NULL);
1595
1596
1597
1598
1599 if (dir == NULL)
1600 {
1601 if (!silent)
1602 fprintf (stderr, _ ("Warning: cannot open %s directory\n"), dirname);
1603 g_free (dirname);
1604 return FALSE;
1605 }
1606
1607 if (extfs_plugins == NULL)
1608 extfs_plugins = g_array_sized_new (FALSE, TRUE, sizeof (extfs_plugin_info_t), 32);
1609
1610 while ((filename = g_dir_read_name (dir)) != NULL)
1611 {
1612 char fullname[MC_MAXPATHLEN];
1613 struct stat s;
1614
1615 g_snprintf (fullname, sizeof (fullname), "%s" PATH_SEP_STR "%s", dirname, filename);
1616
1617 if ((stat (fullname, &s) == 0) && S_ISREG (s.st_mode) && !S_ISDIR (s.st_mode)
1618 && is_exe (s.st_mode))
1619 {
1620 int f;
1621
1622 f = open (fullname, O_RDONLY);
1623
1624 if (f >= 0)
1625 {
1626 size_t len, i;
1627 extfs_plugin_info_t info;
1628 gboolean found = FALSE;
1629
1630 close (f);
1631
1632
1633
1634
1635 len = strlen (filename);
1636 info.need_archive = (filename[len - 1] != '+');
1637 info.path = g_strconcat (dirname, PATH_SEP_STR, (char *) NULL);
1638 info.prefix = g_strndup (filename, len);
1639
1640
1641 if (!info.need_archive)
1642 info.prefix[len - 1] = '\0';
1643
1644
1645 for (i = 0; i < extfs_plugins->len && !found; i++)
1646 {
1647 extfs_plugin_info_t *p;
1648
1649 p = &g_array_index (extfs_plugins, extfs_plugin_info_t, i);
1650
1651
1652 found =
1653 strcmp (info.path, p->path) != 0 && strcmp (info.prefix, p->prefix) == 0;
1654 }
1655
1656 if (found)
1657 {
1658 g_free (info.path);
1659 g_free (info.prefix);
1660 }
1661 else
1662 {
1663
1664 if (!info.need_archive)
1665 info.prefix[len - 1] = '+';
1666 g_array_append_val (extfs_plugins, info);
1667 }
1668 }
1669 }
1670 }
1671
1672 g_dir_close (dir);
1673 g_free (dirname);
1674
1675 return TRUE;
1676 }
1677
1678
1679
1680 static int
1681 extfs_init (struct vfs_class *me)
1682 {
1683 gboolean d1, d2;
1684
1685 (void) me;
1686
1687
1688 d1 = extfs_get_plugins (mc_config_get_data_path (), TRUE);
1689
1690 d2 = extfs_get_plugins (LIBEXECDIR, d1);
1691
1692 return (d1 || d2 ? 1 : 0);
1693 }
1694
1695
1696
1697 static void
1698 extfs_done (struct vfs_class *me)
1699 {
1700 size_t i;
1701
1702 while (VFS_SUBCLASS (me)->supers != NULL)
1703 me->free ((vfsid) VFS_SUBCLASS (me)->supers->data);
1704
1705 if (extfs_plugins == NULL)
1706 return;
1707
1708 for (i = 0; i < extfs_plugins->len; i++)
1709 {
1710 extfs_plugin_info_t *info;
1711
1712 info = &g_array_index (extfs_plugins, extfs_plugin_info_t, i);
1713 g_free (info->path);
1714 g_free (info->prefix);
1715 }
1716
1717 g_array_free (extfs_plugins, TRUE);
1718 }
1719
1720
1721
1722 static int
1723 extfs_setctl (const vfs_path_t *vpath, int ctlop, void *arg)
1724 {
1725 (void) arg;
1726
1727 if (ctlop == VFS_SETCTL_RUN)
1728 {
1729 extfs_run (vpath);
1730 return 1;
1731 }
1732 return 0;
1733 }
1734
1735
1736
1737
1738
1739 void
1740 vfs_init_extfs (void)
1741 {
1742 vfs_init_subclass (&extfs_subclass, "extfs", VFSF_UNKNOWN, NULL);
1743 vfs_extfs_ops->init = extfs_init;
1744 vfs_extfs_ops->done = extfs_done;
1745 vfs_extfs_ops->fill_names = extfs_fill_names;
1746 vfs_extfs_ops->which = extfs_which;
1747 vfs_extfs_ops->open = extfs_open;
1748 vfs_extfs_ops->close = extfs_close;
1749 vfs_extfs_ops->read = extfs_read;
1750 vfs_extfs_ops->write = extfs_write;
1751 vfs_extfs_ops->opendir = extfs_opendir;
1752 vfs_extfs_ops->readdir = extfs_readdir;
1753 vfs_extfs_ops->closedir = extfs_closedir;
1754 vfs_extfs_ops->stat = extfs_stat;
1755 vfs_extfs_ops->lstat = extfs_lstat;
1756 vfs_extfs_ops->fstat = extfs_fstat;
1757 vfs_extfs_ops->readlink = extfs_readlink;
1758 vfs_extfs_ops->unlink = extfs_unlink;
1759 vfs_extfs_ops->chdir = extfs_chdir;
1760 vfs_extfs_ops->ferrno = extfs_errno;
1761 vfs_extfs_ops->lseek = extfs_lseek;
1762 vfs_extfs_ops->getid = extfs_getid;
1763 vfs_extfs_ops->getlocalcopy = extfs_getlocalcopy;
1764 vfs_extfs_ops->ungetlocalcopy = extfs_ungetlocalcopy;
1765 vfs_extfs_ops->mkdir = extfs_mkdir;
1766 vfs_extfs_ops->rmdir = extfs_rmdir;
1767 vfs_extfs_ops->setctl = extfs_setctl;
1768 extfs_subclass.free_inode = extfs_free_inode;
1769 extfs_subclass.free_archive = extfs_free_archive;
1770 vfs_register_class (vfs_extfs_ops);
1771 }
1772
1773