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