1 /* Directory cache support -- so that you do not have copy of this in
2 * each and every filesystem.
4 * Written at 1998 by Pavel Machek <pavel@ucw.cz>, distribute under LGPL.
8 * Very loosely based on tar.c from midnight and archives.[ch] from
9 * avfs by Miklos Szeredi (mszeredi@inf.bme.hu)
11 * Unfortunately, I was unable to keep all filesystems
12 * uniform. tar-like filesystems use tree structure where each
13 * directory has pointers to its subdirectories. We can do this
14 * because we have full information about our archive.
16 * At ftp-like filesystems, situation is a little bit different. When
17 * you cd /usr/src/linux/drivers/char, you do _not_ want /usr,
18 * /usr/src, /usr/src/linux and /usr/src/linux/drivers to be
19 * listed. That means that we do not have complete information, and if
20 * /usr is symlink to /4, we will not know. Also we have to time out
21 * entries and things would get messy with tree-like approach. So we
22 * do different trick: root directory is completely special and
23 * completely fake, it contains entries such as 'usr', 'usr/src', ...,
24 * and we'll try to use custom find_entry function.
26 * Paths here do _not_ begin with '/', so root directory of
27 * archive/site is simply "". Beware. */
32 #include "xdirentry.h"
33 #include "../src/tty.h"
35 #define CALL(x) if (MEDATA->x) MEDATA->x
37 static volatile int total_inodes
= 0, total_entries
= 0;
40 vfs_s_new_inode (vfs
*me
, vfs_s_super
*super
, struct stat
*initstat
)
44 ino
= g_new0 (vfs_s_inode
, 1);
52 ino
->st
.st_ino
= MEDATA
->inode_counter
++;
53 ino
->st
.st_dev
= MEDATA
->rdev
;
58 CALL (init_inode
) (me
, ino
);
64 vfs_s_new_entry (vfs
*me
, char *name
, vfs_s_inode
*inode
)
68 entry
= g_new0 (struct vfs_s_entry
, 1);
72 entry
->name
= g_strdup (name
);
75 entry
->ino
->ent
= entry
;
76 CALL (init_entry
) (me
, entry
);
82 vfs_s_free_inode (vfs
*me
, vfs_s_inode
*ino
)
85 vfs_die ("Don't pass NULL to me");
87 /* ==0 can happen if freshly created entry is deleted */
88 if (ino
->st
.st_nlink
<= 1){
90 vfs_s_free_entry (me
, ino
->subdir
);
93 CALL (free_inode
) (me
, ino
);
94 g_free (ino
->linkname
);
96 unlink (ino
->localname
);
97 g_free(ino
->localname
);
100 ino
->super
->ino_usage
--;
102 } else ino
->st
.st_nlink
--;
106 vfs_s_free_entry (vfs
*me
, vfs_s_entry
*ent
)
109 if (ent
->prevp
){ /* It is possible that we are deleting freshly created entry */
110 *ent
->prevp
= ent
->next
;
112 ent
->next
->prevp
= ent
->prevp
;
116 is_dot
= (!strcmp (ent
->name
, ".")) || (!strcmp (ent
->name
, ".."));
121 if (!is_dot
&& ent
->ino
){
122 ent
->ino
->ent
= NULL
;
123 vfs_s_free_inode (me
, ent
->ino
);
132 vfs_s_insert_entry (vfs
*me
, vfs_s_inode
*dir
, vfs_s_entry
*ent
)
136 for (ep
= &dir
->subdir
; *ep
!= NULL
; ep
= &((*ep
)->next
))
143 ent
->ino
->st
.st_nlink
++;
147 vfs_s_default_stat (vfs
*me
, mode_t mode
)
149 static struct stat st
;
152 myumask
= umask (022);
160 st
.st_uid
= getuid ();
161 st
.st_gid
= getgid ();
163 st
.st_mtime
= st
.st_atime
= st
.st_ctime
= time (NULL
);
169 vfs_s_add_dots (vfs
*me
, vfs_s_inode
*dir
, vfs_s_inode
*parent
)
171 struct vfs_s_entry
*dot
, *dotdot
;
175 dot
= vfs_s_new_entry (me
, ".", dir
);
176 dotdot
= vfs_s_new_entry (me
, "..", parent
);
177 vfs_s_insert_entry (me
, dir
, dot
);
178 vfs_s_insert_entry (me
, dir
, dotdot
);
180 parent
->st
.st_nlink
--; /* We do not count "." and ".." into nlinks */
184 vfs_s_generate_entry (vfs
*me
, char *name
, struct vfs_s_inode
*parent
, mode_t mode
)
186 struct vfs_s_inode
*inode
;
189 st
= vfs_s_default_stat (me
, mode
);
190 inode
= vfs_s_new_inode (me
, parent
->super
, st
);
192 vfs_s_add_dots (me
, inode
, parent
);
194 return vfs_s_new_entry (me
, name
, inode
);
197 /* We were asked to create entries automagically */
199 vfs_s_automake (vfs
*me
, vfs_s_inode
*dir
, char *path
, int flags
)
201 struct vfs_s_entry
*res
;
202 char *sep
= strchr (path
, PATH_SEP
);
206 res
= vfs_s_generate_entry (me
, path
, dir
, flags
& FL_MKDIR
? (0777 | S_IFDIR
) : 0777);
207 vfs_s_insert_entry (me
, dir
, res
);
216 * Follow > 0: follow links, serves as loop protect,
217 * == -1: do not follow links
220 vfs_s_find_entry_tree (vfs
*me
, vfs_s_inode
*root
, char *path
, int follow
, int flags
)
223 vfs_s_entry
*ent
= NULL
;
224 char p
[MC_MAXPATHLEN
] = "";
229 while (*path
== PATH_SEP
) /* Strip leading '/' */
235 for (pseg
= 0; path
[pseg
] && path
[pseg
] != PATH_SEP
; pseg
++)
238 strcat (p
, PATH_SEP_STR
);
239 strncpy (p
+ (t
= strlen (p
)), path
, pseg
);
242 for (ent
= root
->subdir
; ent
!= NULL
; ent
= ent
->next
)
243 if (strlen (ent
->name
) == pseg
&& (!strncmp (ent
->name
, path
, pseg
)))
247 if (!ent
&& (flags
& (FL_MKFILE
| FL_MKDIR
)))
248 ent
= vfs_s_automake (me
, root
, path
, flags
);
249 if (!ent
) ERRNOR (ENOENT
, NULL
);
251 /* here we must follow leading directories always; only the actual file is optional */
252 if (!(ent
= vfs_s_resolve_symlink (me
, ent
, p
, strchr (path
, PATH_SEP
) ? LINK_FOLLOW
: follow
)))
261 split_dir_name (vfs
*me
, char *path
, char **dir
, char **name
, char **save
)
264 s
= strrchr (path
, PATH_SEP
);
278 vfs_s_find_entry_linear (vfs
*me
, vfs_s_inode
*root
, char *path
, int follow
, int flags
)
280 vfs_s_entry
* ent
= NULL
;
282 if (root
->super
->root
!= root
)
283 vfs_die ("We have to use _real_ root. Always. Sorry." );
285 canonicalize_pathname (path
);
287 if (!(flags
& FL_DIR
)){
288 char *dirname
, *name
, *save
;
290 split_dir_name (me
, path
, &dirname
, &name
, &save
);
291 ino
= vfs_s_find_inode (me
, root
, dirname
, follow
, flags
| FL_DIR
);
294 return vfs_s_find_entry_tree (me
, ino
, name
, follow
, flags
);
297 for (ent
= root
->subdir
; ent
!= NULL
; ent
= ent
->next
)
298 if (!strcmp (ent
->name
, path
))
301 if (ent
&& (! (MEDATA
->dir_uptodate
) (me
, ent
->ino
))){
303 print_vfs_message (_("Dir cache expired for %s"), path
);
305 vfs_s_free_entry (me
, ent
);
312 ino
= vfs_s_new_inode (me
, root
->super
, vfs_s_default_stat (me
, S_IFDIR
| 0755));
313 ent
= vfs_s_new_entry (me
, path
, ino
);
314 if ((MEDATA
->dir_load
) (me
, ino
, path
) == -1){
315 vfs_s_free_entry (me
, ent
);
318 vfs_s_insert_entry (me
, root
, ent
);
320 for (ent
= root
->subdir
; ent
!= NULL
; ent
= ent
->next
)
321 if (!strcmp (ent
->name
, path
))
325 vfs_die ("find_linear: success but directory is not there\n");
328 if (!vfs_s_resolve_symlink (me
, ent
, follow
)) return NULL
;
334 vfs_s_find_inode (vfs
*me
, vfs_s_inode
*root
, char *path
, int follow
, int flags
)
337 if ((MEDATA
->find_entry
== vfs_s_find_entry_tree
) && (!*path
))
339 ent
= (MEDATA
->find_entry
)(me
, root
, path
, follow
, flags
);
345 /* Ouch - vfs_s_resolve symlink does not work for filesystems like ftp & fish:
346 you may not lookup with some other root! */
348 vfs_s_resolve_symlink (vfs
*me
, vfs_s_entry
*entry
, char *path
, int follow
)
350 char buf
[MC_MAXPATHLEN
], *linkname
;
352 if (follow
== LINK_NO_FOLLOW
)
355 ERRNOR (ELOOP
, NULL
);
357 ERRNOR (ENOENT
, NULL
);
358 if (!S_ISLNK (entry
->ino
->st
.st_mode
))
361 linkname
= entry
->ino
->linkname
;
363 if (linkname
== NULL
)
364 ERRNOR (EFAULT
, NULL
);
366 if (MEDATA
->find_entry
== vfs_s_find_entry_linear
) {
367 if (*linkname
== PATH_SEP
)
368 return (MEDATA
->find_entry
) (me
, entry
->dir
->super
->root
, linkname
, follow
- 1, 0);
369 else { /* FIXME: this does not work */
370 char *fullpath
= vfs_s_fullpath(me
, entry
->dir
);
371 snprintf(buf
, sizeof (buf
), "%s/%s", fullpath
, linkname
);
373 return (MEDATA
->find_entry
) (me
, entry
->dir
->super
->root
, buf
, follow
- 1, 0);
377 /* Convert absolute paths to relative ones */
378 if (*linkname
== PATH_SEP
) {
380 for (p
= path
, q
= entry
->ino
->linkname
; *p
== *q
; p
++, q
++);
381 while (*(--q
) != PATH_SEP
);
384 p
= strchr (p
, PATH_SEP
);
390 strcat (buf
, PATH_SEP_STR
);
395 return (MEDATA
->find_entry
) (me
, entry
->dir
, linkname
, follow
- 1, 0);
398 /* Ook, these were functions around directory entries / inodes */
399 /* -------------------------------- superblock games -------------------------- */
402 vfs_s_new_super (vfs
*me
)
406 super
= g_new0 (struct vfs_s_super
, 1);
412 vfs_s_insert_super (vfs
*me
, vfs_s_super
*super
)
414 super
->next
= MEDATA
->supers
;
415 super
->prevp
= &MEDATA
->supers
;
417 if (MEDATA
->supers
!= NULL
)
418 MEDATA
->supers
->prevp
= &super
->next
;
419 MEDATA
->supers
= super
;
423 vfs_s_free_super (vfs
*me
, vfs_s_super
*super
)
426 vfs_s_free_inode (me
, super
->root
);
431 /* FIXME: We currently leak small ammount of memory, sometimes. Fix it if you can. */
432 if (super
->ino_usage
)
433 message_1s1d (1, " Direntry warning ",
434 "Super ino_usage is %d, memory leak",
437 if (super
->want_stale
)
438 message_1s (1, " Direntry warning ", "Super has want_stale set");
442 *super
->prevp
= super
->next
;
444 super
->next
->prevp
= super
->prevp
;
447 CALL (free_archive
) (me
, super
);
448 g_free (super
->name
);
453 /* ------------------------------------------------------------------------= */
456 vfs_s_stamp_me (vfs
*me
, struct vfs_s_super
*psup
, char *fs_name
)
458 struct vfs_stamping
*parent
;
461 v
= vfs_type (fs_name
);
462 if (v
== &vfs_local_ops
){
465 parent
= g_new (struct vfs_stamping
, 1);
468 parent
->id
= (*v
->getid
) (v
, fs_name
, &(parent
->parent
));
470 vfs_add_noncurrent_stamps (me
, (vfsid
) psup
, parent
);
471 vfs_rm_parents (parent
);
475 vfs_s_get_path_mangle (vfs
*me
, char *inname
, struct vfs_s_super
**archive
, int flags
)
477 char *local
, *op
, *archive_name
;
479 struct vfs_s_super
*super
;
482 archive_name
= inname
;
483 vfs_split (inname
, &local
, &op
);
487 if (MEDATA
->archive_check
)
488 if (! (cookie
= MEDATA
->archive_check (me
, archive_name
, op
)))
491 for (super
= MEDATA
->supers
; super
!= NULL
; super
= super
->next
){
492 int i
; /* 0 == other, 1 == same, return it, 2 == other but stop scanning */
493 if ((i
= MEDATA
->archive_same (me
, super
, archive_name
, op
, cookie
))){
494 if (i
==1) goto return_success
;
499 if (flags
& FL_NO_OPEN
)
502 super
= vfs_s_new_super (me
);
503 result
= MEDATA
->open_archive (me
, super
, archive_name
, op
);
505 vfs_s_free_super (me
, super
);
509 vfs_die ("You have to fill name\n");
511 vfs_die ("You have to fill root inode\n");
513 vfs_s_insert_super (me
, super
);
514 vfs_s_stamp_me (me
, super
, archive_name
);
522 vfs_s_get_path (vfs
*me
, char *inname
, struct vfs_s_super
**archive
, int flags
)
524 char *buf
= g_strdup( inname
);
525 char *res
= vfs_s_get_path_mangle (me
, buf
, archive
, flags
);
533 vfs_s_invalidate (vfs
*me
, vfs_s_super
*super
)
535 if (!super
->want_stale
){
536 vfs_s_free_inode (me
, super
->root
);
537 super
->root
= vfs_s_new_inode (me
, super
, vfs_s_default_stat (me
, S_IFDIR
| 0755));
542 vfs_s_fullpath (vfs
*me
, vfs_s_inode
*ino
)
544 /* For now, usable only on filesystems with _linear structure */
545 if (MEDATA
->find_entry
!= vfs_s_find_entry_linear
)
546 vfs_die ("Implement me!");
547 if (!ino
->ent
) /* That must be directory... */
548 ERRNOR (EAGAIN
, NULL
);
550 if ((!ino
->ent
->dir
) || (!ino
->ent
->dir
->ent
)) /* It must be directory */
551 return g_strdup (ino
->ent
->name
);
553 return g_strconcat (ino
->ent
->dir
->ent
->name
, PATH_SEP_STR
,
554 ino
->ent
->name
, NULL
);
557 /* Support of archives */
558 /* ------------------------ readdir & friends ----------------------------- */
560 vfs_s_super
*vfs_s_super_from_path (vfs
*me
, char *name
)
562 struct vfs_s_super
*super
;
564 if (!vfs_s_get_path_mangle (me
, name
, &super
, 0))
570 vfs_s_inode_from_path (vfs
*me
, char *name
, int flags
)
572 struct vfs_s_super
*super
;
573 struct vfs_s_inode
*ino
;
576 if (!(q
= vfs_s_get_path_mangle (me
, name
, &super
, 0)))
579 ino
= vfs_s_find_inode (me
, super
->root
, q
, flags
& FL_FOLLOW
? LINK_FOLLOW
: LINK_NO_FOLLOW
, flags
& ~FL_FOLLOW
);
581 /* We are asking about / directory of ftp server: assume it exists */
582 ino
= vfs_s_find_inode (me
, super
->root
, q
, flags
& FL_FOLLOW
? LINK_FOLLOW
: LINK_NO_FOLLOW
, FL_DIR
| (flags
& ~FL_FOLLOW
));
592 vfs_s_opendir (vfs
*me
, char *dirname
)
594 struct vfs_s_inode
*dir
;
595 struct dirhandle
*info
;
597 dir
= vfs_s_inode_from_path (me
, dirname
, FL_DIR
| FL_FOLLOW
);
600 if (!S_ISDIR (dir
->st
.st_mode
))
601 ERRNOR (ENOTDIR
, NULL
);
605 if (!dir
->subdir
) /* This can actually happen if we allow empty directories */
606 ERRNOR (EAGAIN
, NULL
);
608 info
= g_new (struct dirhandle
, 1);
609 info
->cur
= dir
->subdir
;
616 vfs_s_readdir(void *data
)
618 static union vfs_dirent dir
;
619 struct dirhandle
*info
= (struct dirhandle
*) data
;
624 if (info
->cur
->name
) {
625 strncpy(dir
.dent
.d_name
, info
->cur
->name
, MC_MAXPATHLEN
);
626 dir
.dent
.d_name
[MC_MAXPATHLEN
] = 0;
628 vfs_die("Null in structure-can not happen");
631 compute_namelen(&dir
.dent
);
632 info
->cur
= info
->cur
->next
;
634 return (void *) &dir
;
638 vfs_s_telldir (void *data
)
640 struct dirhandle
*info
= (struct dirhandle
*) data
;
641 struct vfs_s_entry
*cur
;
644 cur
= info
->dir
->subdir
;
646 if (cur
== info
->cur
)
655 vfs_s_seekdir (void *data
, int offset
)
657 struct dirhandle
*info
= (struct dirhandle
*) data
;
659 info
->cur
= info
->dir
->subdir
;
660 for (i
=0; i
<offset
; i
++)
661 vfs_s_readdir (data
);
665 vfs_s_closedir (void *data
)
667 struct dirhandle
*info
= (struct dirhandle
*) data
;
668 struct vfs_s_inode
*dir
= info
->dir
;
670 vfs_s_free_inode (dir
->super
->me
, dir
);
676 vfs_s_chdir (vfs
*me
, char *path
)
679 if (!(data
= vfs_s_opendir (me
, path
)))
681 vfs_s_closedir (data
);
685 /* --------------------------- stat and friends ---------------------------- */
688 vfs_s_internal_stat (vfs
*me
, char *path
, struct stat
*buf
, int flag
)
690 struct vfs_s_inode
*ino
;
692 if (!(ino
= vfs_s_inode_from_path (me
, path
, flag
)))
699 vfs_s_stat (vfs
*me
, char *path
, struct stat
*buf
)
701 return vfs_s_internal_stat (me
, path
, buf
, FL_FOLLOW
);
705 vfs_s_lstat (vfs
*me
, char *path
, struct stat
*buf
)
707 return vfs_s_internal_stat (me
, path
, buf
, FL_NONE
);
711 vfs_s_fstat (void *fh
, struct stat
*buf
)
718 vfs_s_readlink (vfs
*me
, char *path
, char *buf
, int size
)
720 struct vfs_s_inode
*ino
;
722 ino
= vfs_s_inode_from_path (me
, path
, 0);
726 if (!S_ISLNK (ino
->st
.st_mode
))
729 if (ino
->linkname
== NULL
)
732 strncpy (buf
, ino
->linkname
, size
);
738 vfs_s_open (vfs
*me
, char *file
, int flags
, int mode
)
744 struct vfs_s_inode
*ino
;
746 if ((q
= vfs_s_get_path_mangle (me
, file
, &super
, 0)) == NULL
)
748 ino
= vfs_s_find_inode (me
, super
->root
, q
, LINK_FOLLOW
, FL_NONE
);
749 if (ino
&& ((flags
& (O_CREAT
| O_EXCL
)) == (O_CREAT
| O_EXCL
)))
750 ERRNOR (EEXIST
, NULL
);
752 char *dirname
, *name
, *save
;
756 if (!(flags
& O_CREAT
))
759 split_dir_name (me
, q
, &dirname
, &name
, &save
);
760 /* FIXME: if vfs_s_find_inode returns NULL, this will do rather bad
762 dir
= vfs_s_find_inode (me
, super
->root
, dirname
, LINK_FOLLOW
, FL_DIR
);
765 ent
= vfs_s_generate_entry (me
, name
, dir
, 0755);
767 vfs_s_insert_entry (me
, dir
, ent
);
768 tmp_handle
= mc_mkstemps (&ino
->localname
, me
->name
, NULL
);
769 if (tmp_handle
== -1)
775 if (S_ISDIR (ino
->st
.st_mode
))
776 ERRNOR (EISDIR
, NULL
);
778 fh
= g_new (struct vfs_s_fh
, 1);
782 fh
->changed
= was_changed
;
785 if (IS_LINEAR(flags
)) {
786 if (MEDATA
->linear_start
) {
787 print_vfs_message (_("Starting linear transfer..."));
788 if (!MEDATA
->linear_start (me
, fh
, 0)){
793 } else if ((MEDATA
->fh_open
) && (MEDATA
->fh_open (me
, fh
, flags
, mode
))){
798 if (fh
->ino
->localname
){
799 fh
->handle
= open (fh
->ino
->localname
, NO_LINEAR(flags
), mode
);
800 if (fh
->handle
== -1){
802 ERRNOR (errno
, NULL
);
806 /* i.e. we had no open files and now we have one */
807 vfs_rmstamp (me
, (vfsid
) super
, 1);
809 fh
->ino
->st
.st_nlink
++;
814 vfs_s_read (void *fh
, char *buffer
, int count
)
817 vfs
*me
= FH_SUPER
->me
;
819 if (FH
->linear
== LS_LINEAR_CLOSED
)
820 vfs_die ("linear_start() did not set linear_state!");
822 if (FH
->linear
== LS_LINEAR_OPEN
)
823 return MEDATA
->linear_read (me
, FH
, buffer
, count
);
825 if (FH
->handle
!= -1){
826 n
= read (FH
->handle
, buffer
, count
);
831 vfs_die ("vfs_s_read: This should not happen\n");
836 vfs_s_write (void *fh
, char *buffer
, int count
)
839 vfs
*me
= FH_SUPER
->me
;
842 vfs_die ("no writing to linear files, please");
845 if (FH
->handle
!= -1){
846 n
= write (FH
->handle
, buffer
, count
);
851 vfs_die ("vfs_s_write: This should not happen\n");
856 vfs_s_lseek (void *fh
, off_t offset
, int whence
)
858 off_t size
= FH
->ino
->st
.st_size
;
860 if (FH
->handle
!= -1){ /* If we have local file opened, we want to work with it */
861 int retval
= lseek (FH
->handle
, offset
, whence
);
863 FH
->ino
->super
->me
->verrno
= errno
;
869 offset
+= FH
->pos
; break;
871 offset
+= size
; break;
875 else if (offset
< size
)
883 vfs_s_close (void *fh
)
886 vfs
*me
= FH_SUPER
->me
;
888 FH_SUPER
->fd_usage
--;
889 if (!FH_SUPER
->fd_usage
){
890 struct vfs_stamping
*parent
;
893 v
= vfs_type (FH_SUPER
->name
);
894 if (v
== &vfs_local_ops
){
897 parent
= g_new (struct vfs_stamping
, 1);
900 parent
->id
= (*v
->getid
) (v
, FH_SUPER
->name
, &(parent
->parent
));
902 vfs_add_noncurrent_stamps (me
, (vfsid
) (FH_SUPER
), parent
);
903 vfs_rm_parents (parent
);
905 if (FH
->linear
== LS_LINEAR_OPEN
)
906 MEDATA
->linear_close (me
, fh
);
907 if (MEDATA
->fh_close
)
908 res
= MEDATA
->fh_close (me
, fh
);
909 if (FH
->changed
&& MEDATA
->file_store
){
910 char *s
= vfs_s_fullpath (me
, FH
->ino
);
914 res
= MEDATA
->file_store (me
, fh
, s
, FH
->ino
->localname
);
917 vfs_s_invalidate (me
, FH_SUPER
);
919 if (FH
->handle
!= -1)
922 vfs_s_free_inode (me
, FH
->ino
);
928 vfs_s_retrieve_file(vfs
*me
, struct vfs_s_inode
*ino
)
930 /* If you want reget, you'll have to open file with O_LINEAR */
934 off_t stat_size
= ino
->st
.st_size
;
937 memset(&fh
, 0, sizeof(fh
));
942 handle
= mc_mkstemps (&ino
->localname
, me
->name
, NULL
);
948 if (!MEDATA
->linear_start (me
, &fh
, 0))
951 /* Clear the interrupt status */
953 while ((n
= MEDATA
->linear_read (me
, &fh
, buffer
, sizeof(buffer
)))) {
959 vfs_print_stats (me
->name
, _("Getting file"), ino
->ent
->name
, total
, stat_size
);
961 if (write(handle
, buffer
, n
) < 0) {
966 MEDATA
->linear_close (me
, &fh
);
971 MEDATA
->linear_close (me
, &fh
);
973 disable_interrupt_key();
975 unlink(ino
->localname
);
977 g_free(ino
->localname
);
978 ino
->localname
= NULL
;
982 /* ------------------------------- mc support ---------------------------- */
985 vfs_s_fill_names (vfs
*me
, void (*func
)(char *))
987 struct vfs_s_super
*a
= MEDATA
->supers
;
991 name
= g_strconcat ( a
->name
, "#", me
->prefix
, "/", /* a->current_dir->name, */ NULL
);
999 vfs_s_ferrno (vfs
*me
)
1005 vfs_s_dump (vfs
*me
, char *prefix
, vfs_s_inode
*ino
)
1007 printf ("%s %s %d ", prefix
, S_ISDIR (ino
->st
.st_mode
) ? "DIR" : "FILE", ino
->st
.st_mode
);
1012 struct vfs_s_entry
*ent
;
1013 for (ent
= ino
->subdir
; ent
; ent
= ent
->next
){
1014 char *s
= g_strconcat (prefix
, "/", ent
->name
, NULL
);
1015 if (ent
->name
[0] == '.')
1016 printf ("%s IGNORED\n", s
);
1018 vfs_s_dump (me
, s
, ent
->ino
);
1025 vfs_s_getlocalcopy (vfs
*me
, char *path
)
1027 struct vfs_s_inode
*ino
;
1028 char buf
[MC_MAXPATHLEN
];
1030 strncpy (buf
, path
, MC_MAXPATHLEN
);
1031 ino
= vfs_s_inode_from_path (me
, path
, FL_FOLLOW
| FL_NONE
);
1033 if (!ino
->localname
)
1034 ino
->localname
= mc_def_getlocalcopy (me
, buf
);
1035 /* FIXME: fd_usage++ missing */
1036 return g_strdup (ino
->localname
);
1040 vfs_s_setctl (vfs
*me
, char *path
, int ctlop
, char *arg
)
1042 vfs_s_inode
*ino
= vfs_s_inode_from_path (me
, path
, 0);
1046 case MCCTL_WANT_STALE_DATA
:
1047 ino
->super
->want_stale
= 1;
1049 case MCCTL_NO_STALE_DATA
:
1050 ino
->super
->want_stale
= 0;
1051 vfs_s_invalidate(me
, ino
->super
);
1053 #if 0 /* FIXME: We should implement these */
1054 case MCCTL_REMOVELOCALCOPY
:
1055 return remove_temp_file (path
);
1056 case MCCTL_FORGET_ABOUT
:
1065 /* ----------------------------- Stamping support -------------------------- */
1068 vfs_s_getid (vfs
*me
, char *path
, struct vfs_stamping
**parent
)
1070 vfs_s_super
*archive
;
1074 struct vfs_stamping
*par
;
1077 if (!(p
= vfs_s_get_path (me
, path
, &archive
, FL_NO_OPEN
)))
1080 v
= vfs_type (archive
->name
);
1081 id
= (*v
->getid
) (v
, archive
->name
, &par
);
1082 if (id
!= (vfsid
)-1){
1083 *parent
= g_new (struct vfs_stamping
, 1);
1086 (*parent
)->parent
= par
;
1087 (*parent
)->next
= NULL
;
1089 return (vfsid
) archive
;
1093 vfs_s_nothingisopen (vfsid id
)
1095 /* Our data structures should survive free of superblock at any time */
1100 vfs_s_free (vfsid id
)
1102 vfs_s_free_super (((vfs_s_super
*)id
)->me
, (vfs_s_super
*)id
);
1105 /* ----------- Utility functions for networked filesystems -------------- */
1109 vfs_s_select_on_two (int fd1
, int fd2
)
1112 struct timeval timeout
;
1114 int maxfd
= (fd1
> fd2
? fd1
: fd2
) + 1;
1117 timeout
.tv_usec
= 0;
1121 v
= select (maxfd
, &set
, 0, 0, &timeout
);
1124 if (FD_ISSET (fd1
, &set
))
1126 if (FD_ISSET (fd2
, &set
))
1132 vfs_s_get_line (vfs
*me
, int sock
, char *buf
, int buf_len
, char term
)
1134 FILE *logfile
= MEDATA
->logfile
;
1138 for (i
= 0; i
< buf_len
- 1; i
++, buf
++){
1139 if (read (sock
, buf
, sizeof(char)) <= 0)
1142 fwrite (buf
, 1, 1, logfile
);
1151 /* Line is too long - terminate buffer and discard the rest of line */
1153 while ((status
= read (sock
, &c
, sizeof (c
))) > 0){
1155 fwrite (&c
, 1, 1, logfile
);
1165 vfs_s_get_line_interruptible (vfs
*me
, char *buffer
, int size
, int fd
)
1170 enable_interrupt_key ();
1171 for (i
= 0; i
< size
-1; i
++){
1172 n
= read (fd
, buffer
+i
, 1);
1173 disable_interrupt_key ();
1174 if (n
== -1 && errno
== EINTR
){
1182 if (buffer
[i
] == '\n'){
1187 buffer
[size
-1] = 0;
1190 #endif /* USE_NETCODE */