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