Browse Source

BIG changes: tar now uses brand-new direntry.c. Hope it does not hurt
too much.

Pavel Machek 26 years ago
parent
commit
37e364fe67
10 changed files with 1036 additions and 889 deletions
  1. 34 0
      vfs/ChangeLog
  2. 639 0
      vfs/direntry.c
  3. 153 0
      vfs/direntry.h
  4. 4 8
      vfs/extfs.c
  5. 3 1
      vfs/fish.c
  6. 17 42
      vfs/ftpfs.c
  7. 4 6
      vfs/mcfs.c
  8. 6 4
      vfs/sfs.c
  9. 2 0
      vfs/shared_tar_ext.c
  10. 174 828
      vfs/tar.c

+ 34 - 0
vfs/ChangeLog

@@ -1,3 +1,37 @@
+Thu Oct 22 22:24:44 1998  Pavel Machek  <pavel@bug.ucw.cz>
+
+	* README: added. If you are using emacs or hacking libvfs, please
+ 	read this one.
+
+	* direntry.{c,h}: new library created, so that same entry/inode
+ 	code does not have to be copied in every handler
+
+	* tar.c: converted to use direntry.c library
+
+	* ftpfs.c: small updates to make code look nicer
+	
+Mon Oct 19 19:40:58 1998  Pavel Machek  <pavel@bug.ucw.cz>
+
+	* vfs.h (&more): killed ERRNOR() from vfs.h and put it into files
+ 	which actually need it.
+
+	* extfs.c: extfs_current_dir killed - it was unneccessary.
+
+	* mcfs.c (mcfs_get_path): It is possible for path not to begin
+ 	with /#mc:, for example if user does /etc/#mc:. (It is not
+ 	correct, of course). Return error, but do not vfs_die().
+
+Sun Oct 18 23:48:00 1998  Pavel Machek  <pavel@bug.ucw.cz>
+
+	* lib/mc.ext.in: cpio support fixed. It was broken since time we
+ 	started to do #ext syntax.
+
+Sat Oct 17 20:43:20 1998  Pavel Machek  <pavel@bug.ucw.cz>
+
+	* vfs.c (mc_open): die() if open is unsupported. If filesytem does
+ 	not support open, it is probably stupid typo, so we want bug to be
+ 	fixed.
+
 Thu Oct 22 20:30:28 1998  Norbert Warmuth  <nwarmuth@privat.circular.de>
 
 	* ftpfs.c (resolve_symlink, retrieve_dir): Don't timeout and

+ 639 - 0
vfs/direntry.c

@@ -0,0 +1,639 @@
+/* Directory cache support -- so that you do not have copy of this in
+ * each and every filesystem.
+ *
+ * Written at 1998 by Pavel Machek <pavel@ucw.cz>, distribute under LGPL.
+ *
+ * Based on tar.c from midnight and archives.[ch] from avfs by Miklos
+ * Szeredi (mszeredi@inf.bme.hu) */
+
+#include "direntry.h"
+
+#define CALL(x) if (MEDATA->x) MEDATA->x
+
+vfs_s_inode *vfs_s_new_inode (vfs *me, struct stat *initstat)
+{
+    vfs_s_inode *ino;
+
+    ino = xmalloc(sizeof (vfs_s_inode), "Dcache inode");
+    if (!ino) return NULL;
+
+    ino->linkname = ino->localname = NULL;
+    ino->subdir = NULL;
+    if (initstat)
+        ino->st = *initstat;
+    ino->st.st_nlink = 0;
+
+    CALL(init_inode) (me, ino);
+
+    return ino;
+}
+
+vfs_s_entry *vfs_s_new_entry (vfs *me, char *name, vfs_s_inode *inode)
+{
+    vfs_s_entry *entry;
+
+    entry = (struct vfs_s_entry *) xmalloc (sizeof (struct vfs_s_entry), "Dcache entry");
+
+    entry->name = strdup (name);
+    entry->dir = NULL;
+    entry->next = NULL;
+    entry->prevp = NULL;
+    entry->ino = inode;
+    CALL(init_entry) (me, entry);
+
+    return entry;
+}
+
+void vfs_s_free_entry (vfs *me, vfs_s_entry *ent)
+{
+    *ent->prevp = ent->next;
+    if (ent->next) ent->next->prevp = ent->prevp;
+
+    printf( "Freeing : %s\n", ent->name);
+    free(ent->name);
+    ent->name = NULL;
+    if(ent->ino->st.st_nlink == 1) {
+	CALL(free_inode) (me, ent->ino);
+	ifree(ent->ino->linkname);
+	ifree(ent->ino->localname);
+	ifree(ent->ino);
+	ent->ino = NULL;
+    } else ent->ino->st.st_nlink--;
+
+    free(ent);
+}
+
+void vfs_s_free_tree (vfs *me, vfs_s_inode *dir, vfs_s_inode *parentdir)
+{
+    vfs_s_entry *ent;
+
+    while(dir->subdir) {
+	ent = dir->subdir;
+	if(ent->ino != dir && ent->ino != parentdir) vfs_s_free_tree(me, ent->ino, dir);
+	vfs_s_free_entry(me, ent);
+    }
+}
+
+void vfs_s_insert_entry (vfs *me, vfs_s_inode *dir, vfs_s_entry *ent)
+{
+    vfs_s_entry **ep;
+
+    for(ep = &dir->subdir; *ep != NULL; ep = &((*ep)->next));
+    ent->prevp = ep;
+    ent->next = NULL;
+    ent->dir = dir;
+    *ep = ent;
+
+    ent->ino->st.st_nlink++;
+}
+
+struct stat *vfs_s_default_stat (vfs *me, mode_t mode)
+{
+    static struct stat st;
+    int myumask;
+
+    myumask = umask (022);
+    umask (myumask);
+    mode &= ~myumask;
+
+    st.st_mode = mode;
+    st.st_ino = MEDATA->inode_counter++;
+    st.st_dev = MEDATA->rdev;
+    st.st_rdev = 0;
+    st.st_uid = getuid ();
+    st.st_gid = getgid ();
+    st.st_size = 0;
+    st.st_mtime = st.st_atime = st.st_ctime = time (NULL);
+    st.st_nlink = 1;
+
+    return &st;
+}
+
+void vfs_s_add_dots (vfs *me, vfs_s_inode *dir, vfs_s_inode *parent)
+{
+    struct vfs_s_entry *dot, *dotdot;
+
+    if (!parent)
+        parent = dir;
+    dot = vfs_s_new_entry (me, ".", dir);
+    dot->ino = dir;
+    dotdot = vfs_s_new_entry (me, "..", parent);
+    dot->ino = parent;
+    vfs_s_insert_entry(me, dir, dot);
+    vfs_s_insert_entry(me, dir, dotdot);
+    dir->st.st_nlink += 2;
+}
+
+struct vfs_s_entry *vfs_s_generate_entry (vfs *me, char *name, struct vfs_s_inode *parent, mode_t mode)
+{
+    struct vfs_s_inode *inode;
+    struct vfs_s_entry *entry;
+    struct stat *st;
+
+    st = vfs_s_default_stat (me, mode);
+    inode = vfs_s_new_inode (me, st);
+    if (S_ISDIR (mode))
+        vfs_s_add_dots (me, inode, parent);
+
+    entry = vfs_s_new_entry (me, name, inode);
+
+    return entry;
+}
+
+/* We were asked to create entries automagically
+ */
+vfs_s_entry *vfs_s_automake(vfs *me, vfs_s_inode *dir, char *path, int flags)
+{
+    struct vfs_s_entry *res;
+    char *sep = strchr( path, DIR_SEP_CHAR );
+    if (sep) *sep = 0;
+    res = vfs_s_generate_entry(me, path, dir, flags & FL_MKDIR ? (0777 | S_IFDIR) : 0777 );
+    if (sep) *sep = DIR_SEP_CHAR;
+    return res;
+}
+
+/* Follow > 0: follow links, serves as loop protect,
+ *       == -1: do not follow links
+ */
+vfs_s_entry *vfs_s_find_entry(vfs *me, vfs_s_inode *root, char *path, int follow, int flags)
+{
+    unsigned int pseg;
+    vfs_s_entry* ent = NULL;
+    int found;
+
+    while(1) {
+	for(pseg = 0; path[pseg] == DIR_SEP_CHAR; pseg++);
+	if(!path[pseg]) return ent;
+	path += pseg;
+
+	for(pseg = 0; path[pseg] && path[pseg] != DIR_SEP_CHAR; pseg++);
+
+	found = 0;
+	for(ent = root->subdir; ent != NULL; ent = ent->next)
+	    if(strlen(ent->name) == pseg && strncmp(ent->name, path, pseg) == 0)
+		/* FOUND! */
+		break;
+
+	if (!ent && (flags & (FL_MKFILE | FL_MKDIR)))
+	    ent = vfs_s_automake(me, root, path+pseg, flags);
+	if (!ent) ERRNOR (ENOENT, NULL);
+	path += pseg;
+	if (!vfs_s_resolve_symlink(me, ent, follow)) return NULL;
+	root = ent->ino;
+    }
+}
+
+vfs_s_inode *vfs_s_find_inode(vfs *me, vfs_s_inode *root, char *path, int follow, int flags)
+{
+    vfs_s_entry *ent;
+    if (!path || !path[0])
+	return root;
+    ent = vfs_s_find_entry(me, root, path, follow, flags);
+    if (!ent)
+	return NULL;
+    return ent->ino;
+}
+
+vfs_s_inode *vfs_s_find_root(vfs *me, vfs_s_entry *entry)
+{
+    vfs_die("Implement me");
+    return NULL;
+}
+
+vfs_s_entry *vfs_s_resolve_symlink (vfs *me, vfs_s_entry *entry, int follow)
+{
+    vfs_s_inode *dir;
+    if (follow == -1)
+	return entry;
+    if (follow == 0)
+	ERRNOR (ELOOP, NULL);
+    if (!entry)
+	ERRNOR (ENOENT, NULL);
+    if (!S_ISLNK(entry->ino->st.st_mode))
+	return entry;
+
+    /* We have to handle "/" by ourself; "." and ".." have
+       corresponding entries, so there's no problem with them. */
+    if (*entry->ino->linkname == '/') dir = vfs_s_find_root(me, entry); 
+    else dir = entry->dir;
+    return vfs_s_find_entry (me, dir, entry->ino->linkname, follow-1, 0);
+}
+
+/* Ook, these were functions around direcory entries / inodes */
+/* -------------------------------- superblock games -------------------------- */
+
+vfs_s_super *vfs_s_new_super (vfs *me)
+{
+    vfs_s_super *super;
+
+    super = xmalloc( sizeof( struct vfs_s_super ), "Direntry: superblock" );
+    super->root = NULL;
+    super->name = NULL;
+    super->fd_usage = 0;
+    super->me = me;
+
+    super->next = MEDATA->supers;
+    super->prevp = &MEDATA->supers;
+
+    if (MEDATA->supers != NULL) MEDATA->supers->prevp = &super->next;
+    MEDATA->supers = super;
+    return super;
+} 
+
+void vfs_s_free_super (vfs *me, vfs_s_super *super)
+{
+    if (super->root)
+	vfs_s_free_tree (me, super->root, NULL);
+
+    *super->prevp = super->next;
+    if (super->next) super->next->prevp = super->prevp;
+
+    CALL(free_archive) (me, super);
+    free(super);
+}
+
+/* ========================================================================= */
+
+static void vfs_s_stamp_me (vfs *me, struct vfs_s_super *psup, char *fs_name)
+{
+    struct vfs_stamping *parent;
+    vfs *v;
+ 
+    v = vfs_type (fs_name);
+    if (v == &vfs_local_ops) {
+	parent = NULL;
+    } else {
+	parent = xmalloc (sizeof (struct vfs_stamping), "vfs stamping");
+	parent->v = v;
+	parent->next = 0;
+	parent->id = (*v->getid) (v, fs_name, &(parent->parent));
+    }
+    vfs_add_noncurrent_stamps (&vfs_tarfs_ops, (vfsid) psup, parent);
+    vfs_rm_parents (parent);
+}
+
+char *vfs_s_get_path_mangle (vfs *me, char *inname, struct vfs_s_super **archive, int flags)
+{
+    char *local, *op, *archive_name;
+    int result = -1;
+    struct vfs_s_super *psup;
+    void *cookie;
+    
+    archive_name = inname;
+    vfs_split( inname, &local, &op );
+    if (!local)
+        local = "";
+
+    if (! (cookie = MEDATA->archive_check (me, archive_name, op)))
+	return NULL;
+
+    for (psup = MEDATA->supers; psup != NULL; psup = psup->next) {
+	int i; /* 0 == other, 1 == same, return it, 2 == other but stop scanning */
+	if ((i = MEDATA->archive_same (me, psup, archive_name, cookie))) {
+	    if (i==1) goto return_success;
+	    else break;
+	}
+    }
+
+    if (flags & FL_NO_OPEN) ERRNOR (EIO, NULL);
+
+    psup = vfs_s_new_super (me);
+    result = MEDATA->open_archive (me, psup, archive_name, op);
+    if (result == -1) {
+	vfs_s_free_super (me, psup);
+	ERRNOR (EIO, NULL);
+    }
+
+    vfs_s_stamp_me (me, psup, archive_name);
+
+return_success:
+    *archive = psup;
+    return local;
+}
+
+char *vfs_s_get_path (vfs *me, char *inname, struct vfs_s_super **archive, int flags)
+{
+    char *buf = strdup( inname );
+    char *res = vfs_s_get_path_mangle( me, buf, archive, flags );
+    char *res2 = NULL;
+    if (res)
+        res2 = strdup(res);
+    free(buf);
+    return res2;
+}
+
+/* Support of archives */
+/* ========================== readdir & friends ========================================= */
+
+vfs_s_inode *vfs_s_inode_from_path (vfs *me, char *name, int flags)
+{
+    struct vfs_s_super *super;
+    char *q;
+    struct vfs_s_inode *ino;
+
+    if (!(q = vfs_s_get_path_mangle (me, name, &super, 0))) 
+	return NULL;
+
+    ino = vfs_s_find_inode (me, super->root, q, flags & FL_FOLLOW ? FOLLOW : NO_FOLLOW, FL_NONE);
+    if (ino) return ino;
+
+    if ((flags & FL_DIR) && MEDATA->load_dir) {
+	MEDATA->load_dir (me, super, q);
+	ino = vfs_s_find_inode (me, super->root, q, flags & FL_FOLLOW ? FOLLOW : NO_FOLLOW, FL_NONE);
+    }
+
+    return ino;
+}
+
+void * vfs_s_opendir (vfs *me, char *dirname)
+{
+    struct vfs_s_inode *ino;
+    struct vfs_s_entry **info;
+
+    ino = vfs_s_inode_from_path (me, dirname, FL_DIR | FL_FOLLOW);
+    if (!ino) return NULL;
+    if (!S_ISDIR (ino->st.st_mode)) ERRNOR (ENOTDIR, NULL);
+
+    info = (struct vfs_s_entry **) xmalloc (2*sizeof (struct vfs_s_entry *), "Dentry opendir");
+    info[0] = ino->subdir;
+    info[1] = ino->subdir;
+
+    return info;
+}
+
+void * vfs_s_readdir (void *data)
+{
+    static struct {
+	struct dirent dir; 
+#ifdef NEED_EXTRA_DIRENT_BUFFER
+	char extra_buffer [MC_MAXPATHLEN];
+#endif
+    } dir;
+
+    struct vfs_s_entry **info = (struct vfs_s_entry **) data;
+
+    if (!*info)
+    	return NULL;
+
+    strcpy (&(dir.dir.d_name [0]), (*info)->name);
+    
+#ifndef DIRENT_LENGTH_COMPUTED
+    dir.d_namlen = strlen (dir.dir.d_name);
+#endif
+    *info = (*info)->next;
+    
+    return (void *)&dir;
+}
+
+int vfs_s_telldir (void *data)
+{
+    struct vfs_s_entry **info = (struct vfs_s_entry **) data;
+    struct vfs_s_entry *cur;
+    int num = 0;
+
+    cur = info[1];
+    while (cur!=NULL) {
+        if (cur == info[0]) return num;
+	num++;
+	cur = cur->next;
+    }
+    return -1;
+}
+
+void vfs_s_seekdir (void *data, int offset)
+{
+    struct vfs_s_entry **info = (struct vfs_s_entry **) data;
+    int i;
+    info[0] = info[1];
+    for (i=0; i<offset; i++)
+        vfs_s_readdir( data );
+}
+
+int vfs_s_closedir (void *data)
+{
+    free (data);
+    return 0;
+}
+
+int vfs_s_chdir (vfs *me, char *path)
+{
+    void *data;
+    if (!(data = vfs_s_opendir( me, path )))
+	return -1;
+    vfs_s_closedir(data);
+    return 0;
+}
+
+/* =========================== stat and friends ============================== */
+
+static int vfs_s_internal_stat (vfs *me, char *path, struct stat *buf, int flag)
+{
+    struct vfs_s_inode *ino;
+
+    if (!(ino = vfs_s_inode_from_path( me, path, flag ))) return -1;
+    *buf = ino->st;
+    return 0;
+}
+
+int vfs_s_stat (vfs *me, char *path, struct stat *buf)
+{
+    return vfs_s_internal_stat (me, path, buf, FL_FOLLOW);
+}
+
+int vfs_s_lstat (vfs *me, char *path, struct stat *buf)
+{
+    return vfs_s_internal_stat (me, path, buf, FL_NONE);
+}
+
+int vfs_s_fstat (void *fh, struct stat *buf)
+{
+    *buf = FH->ino->st;
+    return 0;
+}
+
+int vfs_s_readlink (vfs *me, char *path, char *buf, int size)
+{
+    struct vfs_s_inode *ino;
+
+    ino = vfs_s_inode_from_path(me, path, 0);
+    if (!ino) return -1;
+
+    if (!S_ISLNK (ino->st.st_mode)) ERRNOR (EINVAL, -1);
+    strncpy (buf, ino->linkname, size);
+    *(buf+size-1) = 0;
+    return strlen(buf);
+}
+
+void *vfs_s_open (vfs *me, char *file, int flags, int mode)
+{
+    struct vfs_s_fh *fh;
+    vfs_s_super *super;
+    char *q;
+    struct vfs_s_inode *ino;
+
+    if ((q = vfs_s_get_path_mangle (me, file, &super, 0)) == NULL)
+	return NULL;
+    if (!(ino = vfs_s_find_inode (me, super->root, q, FOLLOW, FL_NONE)))
+    	return NULL;
+    if (S_ISDIR (ino->st.st_mode)) ERRNOR (EISDIR, NULL);
+    if ((flags & O_ACCMODE) != O_RDONLY) ERRNOR (EROFS, NULL);
+    
+    fh = (struct vfs_s_fh *) xmalloc (sizeof (struct vfs_s_fh), "Direntry: filehandle");
+    fh->super = super;
+    fh->pos = 0;
+    fh->ino = ino;
+    fh->handle = -1;
+    if (MEDATA->fh_open)
+	if (MEDATA->fh_open (me, fh)) {
+	    free(fh);
+	    return NULL;
+	}
+
+     /* i.e. we had no open files and now we have one */
+    vfs_rmstamp (&vfs_tarfs_ops, (vfsid) super, 1);
+    super->fd_usage++;
+    return fh;
+}
+
+int vfs_s_lseek (void *fh, off_t offset, int whence)
+{
+    off_t size = FH->ino->st.st_size;
+    switch (whence) {
+    	case SEEK_CUR:
+    	    offset += FH->pos; break;
+    	case SEEK_END:
+    	    offset += size; break;
+    }
+    if (offset < 0)
+    	FH->pos = 0;
+    else if (offset < size)
+    	FH->pos = offset;
+    else
+    	FH->pos = size;
+    return FH->pos;
+}
+
+int vfs_s_close (void *fh)
+{
+    vfs *me = FH->super->me;
+
+    FH->super->fd_usage--;
+    if (!FH->super->fd_usage) {
+        struct vfs_stamping *parent;
+        vfs *v;
+        
+	v = vfs_type (FH->super->name);
+	if (v == &vfs_local_ops) {
+	    parent = NULL;
+	} else {
+	    parent = xmalloc (sizeof (struct vfs_stamping), "vfs stamping");
+	    parent->v = v;
+	    parent->next = 0;
+	    parent->id = (*v->getid) (v, FH->super->name, &(parent->parent));
+	}
+        vfs_add_noncurrent_stamps (&vfs_tarfs_ops, (vfsid) (FH->super), parent);
+	vfs_rm_parents (parent);
+    }
+    CALL(fh_close) (me, fh);
+    if (FH->handle)
+	mc_close(FH->handle);
+	
+    free (fh);
+    return 0;
+}
+
+/* ------------------------------- mc support ---------------------------- */
+
+void vfs_s_fill_names (vfs *me, void (*func)(char *))
+{
+    struct vfs_s_super *a = MEDATA->supers;
+    char *name;
+    
+    while (a){
+	name = copy_strings ( a->name, "#", me->prefix, "/",
+			      /* a->current_dir->name, */ 0);
+	(*func)(name);
+	free (name);
+	a = a->next;
+    }
+}
+
+int
+vfs_s_ferrno(vfs *me)
+{
+    return me->verrno;
+}
+
+void
+vfs_s_dump(vfs *me, char *prefix, vfs_s_inode *ino)
+{
+    printf( "%s %s %d ", prefix, S_ISDIR(ino->st.st_mode) ? "DIR" : "FILE", ino->st.st_mode );
+    if (!ino->subdir) printf ("FILE\n");
+    else
+    {
+	struct vfs_s_entry *ent;
+	ent = ino->subdir;
+	while(ent) {
+	    char *s;
+	    s = copy_strings(prefix, "/", ent->name, NULL );
+	    if (ent->name[0] == '.')
+		printf("%s IGNORED\n", s);
+	    else
+		vfs_s_dump(me, s, ent->ino);
+	    free(s);
+	    ent = ent->next;
+	}
+    }
+}
+
+char *vfs_s_getlocalcopy (vfs *me, char *path)
+{
+    struct vfs_s_inode *ino;
+    char buf[MC_MAXPATHLEN];
+
+    strcpy( buf, path );
+    ino = vfs_s_inode_from_path (me, path, FL_FOLLOW | FL_NONE);
+
+    if (!ino->localname)
+	ino->localname = mc_def_getlocalcopy (me, buf);
+    return ino->localname;
+}
+
+/* ----------------------------- Stamping support ----------------------------- */
+
+vfsid vfs_s_getid (vfs *me, char *path, struct vfs_stamping **parent)
+{
+    vfs_s_super *archive;
+    vfs *v;
+    char *p;
+    vfsid id;
+    struct vfs_stamping *par;
+
+    *parent = NULL;
+    if (!(p = vfs_s_get_path (me, path, &archive, FL_NO_OPEN)))
+	return (vfsid) -1;
+    free(p);
+    v = vfs_type (archive->name);
+    id = (*v->getid) (v, archive->name, &par);
+    if (id != (vfsid)-1) {
+        *parent = xmalloc (sizeof (struct vfs_stamping), "vfs stamping");
+        (*parent)->v = v;
+        (*parent)->id = id;
+        (*parent)->parent = par;
+        (*parent)->next = NULL;
+    }
+    return (vfsid) archive;    
+}
+
+int vfs_s_nothingisopen (vfsid id)
+{
+    if (((vfs_s_super *)id)->fd_usage <= 0)
+    	return 1;
+    else
+    	return 0;
+}
+
+void vfs_s_free (vfsid id)
+{
+    vfs_s_free_super (((vfs_s_super *)id)->me, (vfs_s_super *)id);
+}

+ 153 - 0
vfs/direntry.h

@@ -0,0 +1,153 @@
+#ifndef DIRENTRY_H
+#define DIRENTRY_H
+
+#include <config.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "../src/fs.h"
+#include "../src/util.h"
+#include "../src/mem.h"
+#include "../src/mad.h"
+#include "vfs.h"
+
+
+#define FOLLOW 15
+#define NO_FOLLOW -1
+
+/* For vfs_s_find_entry */
+#define FL_NONE 0
+#define FL_MKDIR 1
+#define FL_MKFILE 2
+
+/* For open_super */
+#define FL_NO_OPEN 1
+
+/* For vfs_s_entry_from_path */
+#define FL_FOLLOW 1
+#define FL_DIR 2
+
+typedef struct vfs_s_entry {
+    struct vfs_s_entry **prevp, *next;
+    struct vfs_s_inode *dir;	/* Directory we are in - FIXME: is this needed? */
+    char *name;			/* Name of this entry */
+    struct vfs_s_inode *ino;	/* ... and its inode */
+} vfs_s_entry;
+
+typedef struct vfs_s_inode {
+    struct vfs_s_entry *subdir;
+    struct stat st;		/* Parameters of this inode */
+    char *linkname;		/* Symlink's contents */
+    char *localname;		/* filename of local file, if we have one */
+
+    union {
+	struct {
+	    long data_offset;
+	} tar;
+    } u;
+} vfs_s_inode;
+
+typedef struct vfs_s_super {
+    struct vfs_s_super **prevp, *next;
+    vfs *me;
+    vfs_s_inode *root;
+    char *name;		/* My name, whatever it means */
+    int fd_usage;	/* Usage count of this superblock */
+
+    union {
+	struct {
+	    int fd;
+	    struct stat tarstat;
+	} tar;
+    } u;
+} vfs_s_super;
+
+typedef struct vfs_s_fh {
+    struct vfs_s_super *super;	/* Is this field needed? */
+    struct vfs_s_inode *ino;
+    long pos;			/* This is for module's use */
+    int handle;	/* This is for module's use, but if != -1, will be mc_close()d */
+} vfs_s_fh;
+
+struct vfs_s_data {
+    struct vfs_s_super *supers;
+    int inode_counter;
+    dev_t rdev;
+
+    int (*init_inode) (vfs *me, vfs_s_inode *ino);
+    void (*free_inode) (vfs *me, vfs_s_inode *ino);
+    int (*init_entry) (vfs *me, vfs_s_entry *entry);
+
+    void* (*archive_check) (vfs *me, char *name, char *op);
+    int (*archive_same) (vfs *me, vfs_s_super *psup, char *archive_name, void *cookie);
+    int (*open_archive) (vfs *me, vfs_s_super *psup, char *archive_name, char *op);
+    void (*free_archive) (vfs *me, vfs_s_super *psup);
+
+    int (*load_dir) (vfs *me, vfs_s_super *super, char *q);
+
+    int (*fh_open) (vfs *me, vfs_s_fh *fh);
+    int (*fh_close) (vfs *me, vfs_s_fh *fh);
+};
+
+/* entries and inodes */
+vfs_s_inode *vfs_s_new_inode (vfs *me, struct stat *initstat);
+vfs_s_entry *vfs_s_new_entry (vfs *me, char *name, vfs_s_inode *inode);
+void vfs_s_free_entry (vfs *me, vfs_s_entry *ent);
+void vfs_s_free_tree (vfs *me, vfs_s_inode *dir, vfs_s_inode *parentdir);
+void vfs_s_insert_entry (vfs *me, vfs_s_inode *dir, vfs_s_entry *ent);
+struct stat *vfs_s_default_stat (vfs *me, mode_t mode);
+void vfs_s_add_dots (vfs *me, vfs_s_inode *dir, vfs_s_inode *parent);
+struct vfs_s_entry *vfs_s_generate_entry (vfs *me, char *name, struct vfs_s_inode *parent, mode_t mode);
+vfs_s_entry *vfs_s_automake(vfs *me, vfs_s_inode *dir, char *path, int flags);
+vfs_s_entry *vfs_s_find_entry(vfs *me, vfs_s_inode *root, char *path, int follow, int flags);
+vfs_s_inode *vfs_s_find_inode(vfs *me, vfs_s_inode *root, char *path, int follow, int flags);
+vfs_s_inode *vfs_s_find_root(vfs *me, vfs_s_entry *entry);
+struct vfs_s_entry *vfs_s_resolve_symlink (vfs *me, struct vfs_s_entry *entry, int follow);
+/* superblock games */
+vfs_s_super *vfs_s_new_super (vfs *me);
+void vfs_s_free_super (vfs *me, vfs_s_super *super); 
+/* outside interface */
+char *vfs_s_get_path_mangle (vfs *me, char *inname, struct vfs_s_super **archive, int flags);
+char *vfs_s_get_path (vfs *me, char *inname, struct vfs_s_super **archive, int flags);
+/* readdir & friends */
+vfs_s_inode *vfs_s_inode_from_path (vfs *me, char *name, int flags);
+void * vfs_s_opendir (vfs *me, char *dirname);
+void * vfs_s_readdir (void *data);
+int vfs_s_telldir (void *data);
+void vfs_s_seekdir (void *data, int offset);
+int vfs_s_closedir (void *data);
+int vfs_s_chdir (vfs *me, char *path);
+/* stat & friends */
+int vfs_s_stat (vfs *me, char *path, struct stat *buf);
+int vfs_s_lstat (vfs *me, char *path, struct stat *buf);
+int vfs_s_fstat (void *fh, struct stat *buf);
+int vfs_s_readlink (vfs *me, char *path, char *buf, int size);
+void *vfs_s_open (vfs *me, char *file, int flags, int mode);
+int vfs_s_lseek (void *fh, off_t offset, int whence);
+int vfs_s_close (void *fh);
+/* mc support */
+void vfs_s_fill_names (vfs *me, void (*func)(char *));
+int vfs_s_ferrno(vfs *me);
+void vfs_s_dump(vfs *me, char *prefix, vfs_s_inode *ino);
+char *vfs_s_getlocalcopy (vfs *me, char *path);
+/* stamping support */
+vfsid vfs_s_getid (vfs *me, char *path, struct vfs_stamping **parent);
+int vfs_s_nothingisopen (vfsid id);
+void vfs_s_free (vfsid id);
+
+/* If non-null, FREE */
+#define ifree(ptr) do { if (ptr) free(ptr); } while (0)
+
+#define MEDATA ((struct vfs_s_data *) me->data)
+#define ERRNOR(a, b) do { me->verrno = a; return b; } while (0)
+#define FH ((struct vfs_s_fh *) fh)
+
+#endif

+ 4 - 8
vfs/extfs.c

@@ -47,6 +47,8 @@
 #include "vfs.h"
 #include "extfs.h"
 
+#define ERRNOR(x,y) do { my_errno = x; return y; } while(0)
+
 static struct entry *
 find_entry (struct entry *dir, char *name, int make_dirs, int make_file);
 static int extfs_which (vfs *me, char *path);
@@ -54,8 +56,6 @@ static int extfs_which (vfs *me, char *path);
 static struct archive *first_archive = NULL;
 static int my_errno = 0;
 static struct stat hstat;		/* Stat struct corresponding */
-static char *current_file_name, *current_link_name;
-static char *extfs_current_dir;
 
 #define MAXEXTFS 32
 static char *extfs_prefixes [MAXEXTFS];
@@ -267,6 +267,8 @@ static int read_archive (int fstype, char *name, struct archive **pparc)
     FILE *extfsd;
     char *buffer;
     struct archive *current_archive;
+    char *current_file_name, *current_link_name;
+
 
     if ((extfsd = open_archive (fstype, name, &current_archive)) == NULL) {
         message_3s (1, MSG_ERROR, _("Couldn't open %s archive\n%s"), 
@@ -752,9 +754,6 @@ static int extfs_chdir (vfs *me, char *path)
         entry->inode->archive->name, "#", extfs_prefixes [entry->inode->archive->fstype], 
 	"/", q, NULL);
     my_errno = 0;
-    if (extfs_current_dir)
-	free (extfs_current_dir);
-    extfs_current_dir = res;
     return 0;
 }
 
@@ -950,9 +949,6 @@ static void extfs_done (vfs *me)
     for (i = 0; i < extfs_no; i++ )
 	free (extfs_prefixes [i]);
     extfs_no = 0;
-    if (extfs_current_dir)
-	free (extfs_current_dir);
-    extfs_current_dir = 0;
 }
 
 static int extfs_setctl (vfs *me, char *path, int ctlop, char *arg)

+ 3 - 1
vfs/fish.c

@@ -75,6 +75,8 @@
 #    define MAXHOSTNAMELEN 64
 #endif
 
+#define ERRNOR(x,y) do { my_errno = x; return y; } while(0)
+
 /*
  * Reply codes.
  */
@@ -582,7 +584,7 @@ store_file(struct direntry *fe)
 
     fstat(local_handle, &s);
 
-    /* Use this as stor: ( dd block ; dd malyblock ) | ( cat > file; cat > /dev/null ) */
+    /* Use this as stor: ( dd block ; dd smallblock ) | ( cat > file; cat > /dev/null ) */
 
     print_vfs_message("FISH: store: sending command..." );
     if (command (fe->bucket, WAIT_REPLY, 

+ 17 - 42
vfs/ftpfs.c

@@ -92,6 +92,7 @@
 #    define MAXHOSTNAMELEN 64
 #endif
 
+#define ERRNOR(x,y) do { my_errno = x; return y; } while(0)
 #define UPLOAD_ZERO_LENGTH_FILE
 
 static int my_errno;
@@ -369,38 +370,17 @@ login_server (struct connection *bucket, char *netrcpass)
 #if defined(HSC_PROXY)
 	if (qproxy(bucket)) {
 	    print_vfs_message("ftpfs: sending proxy login name");
-	    if (command (bucket, 1, "USER %s", proxyname) == CONTINUE) {
-		print_vfs_message("ftpfs: sending proxy user password");
-		if (command (bucket, 1, "PASS %s", proxypass) == COMPLETE)
-		    {
-			print_vfs_message("ftpfs: proxy authentication succeeded");
-			if (command (bucket, 1, "SITE %s", qhost(bucket)+1) ==
-			    COMPLETE) {
-			    print_vfs_message("ftpfs: connected to %s", qhost(bucket)+1);
-			}
-			else {
-			    bucket->failed_on_login = 1;
-			    /* my_errno = E; */
-			    if (proxypass)
-				wipe_password (proxypass);
-    			    wipe_password (pass);
-			    free (proxyname);
-			    free (name);
-			    return 0;
-			}
-		    }
-		else {
-		    bucket->failed_on_login = 1;
-		    /* my_errno = E; */
-		    if (proxypass)
-			wipe_password (proxypass);
-		    wipe_password (pass);
-		    free (proxyname);
-		    free (name);
-		    return 0;
-		}
-	    }
-	    else {
+	    if (command (bucket, 1, "USER %s", proxyname) != CONTINUE)
+		goto proxyfail;
+	    print_vfs_message("ftpfs: sending proxy user password");
+	    if (command (bucket, 1, "PASS %s", proxypass) != COMPLETE)
+		goto proxyfail;
+	    print_vfs_message("ftpfs: proxy authentication succeeded");
+	    if (command (bucket, 1, "SITE %s", qhost(bucket)+1) != COMPLETE)
+		goto proxyfail;
+	    print_vfs_message("ftpfs: connected to %s", qhost(bucket)+1);
+	    if (0) {
+	    proxyfail:
 		bucket->failed_on_login = 1;
 		/* my_errno = E; */
 		if (proxypass)
@@ -408,7 +388,7 @@ login_server (struct connection *bucket, char *netrcpass)
 		wipe_password (pass);
 		free (proxyname);
 		free (name);
-		return 0;
+		ERRNOR (EPERM, 0);
 	    }
 	    if (proxypass)
 		wipe_password (proxypass);
@@ -437,19 +417,14 @@ login_server (struct connection *bucket, char *netrcpass)
 		wipe_password (bucket->password);
 	    bucket->password = 0;
 	    
-	    /* This matches the end of the code below, just to make it
-	     * obvious to the optimizer
-	     */
-	    wipe_password (pass);
-	    free (name);
-	    return 0;
+	    goto login_fail;
 	}
     }
     print_vfs_message ("ftpfs: Login incorrect for user %s ", quser(bucket));
-    my_errno = EPERM;
+login_fail:
     wipe_password (pass);
     free (name);
-    return 0;
+    ERRNOR (EPERM, 0);
 }
 
 #ifdef HAVE_SETSOCKOPT
@@ -1487,7 +1462,7 @@ ftpfs_init_passwd(void)
 	return;
 
     if ((passwd_info = getpwuid (geteuid ())) == NULL)
-	p = "guest";
+	p = "unknown";
     else
 	p = passwd_info->pw_name;
     gethostname(hostname, sizeof(hostname));

+ 4 - 6
vfs/mcfs.c

@@ -363,9 +363,8 @@ static char *mcfs_get_path (mcfs_connection **mc, char *path)
     int    port;
 
     /* An absolute path name, try to determine connection socket */
-    if (strncmp (path, "/#mc:", 5)) {
-        vfs_die( "Mcfs: this should not happen.\n" );
-    }
+    if (strncmp (path, "/#mc:", 5))
+        return NULL;
     path += 5;
 
     /* Port = 0 means that open_tcp_link will try to contact the
@@ -1078,9 +1077,8 @@ my_forget (char *path)
     char *host, *user, *pass, *p;
     int  port, i, vers;
 
-    if (strncmp (path, "/#mc:", 5)) {
-        vfs_die( "Mcfs: this should not happen.\n" );
-    }
+    if (strncmp (path, "/#mc:", 5))
+        return NULL;
     path += 5;
     if (path[0] == '/' && path[1] == '/')
 	path += 2;

+ 6 - 4
vfs/sfs.c

@@ -7,8 +7,10 @@
  * inside. It is somehow similar to extfs, except that extfs makes
  * whole virtual trees and we do only single virtual files. 
  *
- * Namespace: exports vfs_sfs_ops, shell (FIXME)
- */
+ * If you want to gunzip something, you should open it with #ugz
+ * suffix, DON'T try to gunzip it yourself.
+ *
+ * Namespace: exports vfs_sfs_ops, shell (FIXME) */
 
 #include <config.h>
 #include <errno.h>
@@ -97,7 +99,6 @@ static int vfmake( vfs *me, char *name, char *cache )
     return 0; /* OK */
 }
 
-#define CUR (*cur)
 static char *redirect( vfs *me, char *name )
 {
     struct cachedfile *cur = head;
@@ -131,7 +132,6 @@ static char *redirect( vfs *me, char *name )
 	return cache;
     } else {
         free(xname);
-	fprintf( stderr, "vfmake failed\n" );
     }
     return "/I_MUST_NOT_EXIST";
 }
@@ -194,6 +194,7 @@ static int sfs_readlink (vfs *me, char *path, char *buf, int size)
     return readlink (path, buf, size);
 }
 
+#define CUR (*cur)
 static vfsid sfs_getid (vfs *me, char *path, struct vfs_stamping **parent)
 {	/* FIXME: what should I do? */
     vfs *v;
@@ -234,6 +235,7 @@ static void sfs_free (vfsid id)
     struct cachedfile *which = (struct cachedfile *) id;
     struct cachedfile **cur = &head;
 
+    message_1s(1, "%s", "Freeing sfs file" );
     unlink( CUR->cache );
     while (CUR) {
         if (CUR == which)

+ 2 - 0
vfs/shared_tar_ext.c

@@ -2,6 +2,8 @@
  * Large portions of tar.c & extfs.c were nearly same. I killed this 
  * redundancy, so code is maintainable, again.
  *
+ * Actually, tar no longer uses this code :-).
+ *
  * 1998 Pavel Machek
  *
  * Namespace: no pollution.

File diff suppressed because it is too large
+ 174 - 828
vfs/tar.c


Some files were not shown because too many files changed in this diff