Blob Blame History Raw
commit 698385bdd0bfb485bcc42a634f86a8cd0ffae564
Author: Andrew Borodin <aborodin@vmail.ru>
Date:   Wed Nov 18 16:26:24 2009 +0300

    Ticket #1732: cpio VFS skips empty directories in the root of archive
    
    Initial step: some optimization and type accuracy.
    
    Signed-off-by: Andrew Borodin <aborodin@vmail.ru>

diff --git a/vfs/cpio.c b/vfs/cpio.c
index 5eeef95..8c24573 100644
--- a/vfs/cpio.c
+++ b/vfs/cpio.c
@@ -103,7 +103,6 @@ struct defer_inode {
 static int cpio_position;
 
 static int cpio_find_head(struct vfs_class *me, struct vfs_s_super *super);
-static int cpio_create_entry(struct vfs_class *me, struct vfs_s_super *super, struct stat *, char *name);
 static ssize_t cpio_read_bin_head(struct vfs_class *me, struct vfs_s_super *super);
 static ssize_t cpio_read_oldc_head(struct vfs_class *me, struct vfs_s_super *super);
 static ssize_t cpio_read_crc_head(struct vfs_class *me, struct vfs_s_super *super);
@@ -234,8 +233,8 @@ static int cpio_find_head(struct vfs_class *me, struct vfs_s_super *super)
 {
     char buf[256];
     int ptr = 0;
-    int top;
-    int tmp;
+    ssize_t top;
+    ssize_t tmp;
 
     top = mc_read (super->u.arch.fd, buf, 256);
     if (top > 0)
@@ -271,6 +270,140 @@ static int cpio_find_head(struct vfs_class *me, struct vfs_s_super *super)
 #undef RETURN
 #undef SEEKBACK
 
+static int
+cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super,
+		   struct stat *st, char *name)
+{
+    struct vfs_s_inode *inode = NULL;
+    struct vfs_s_inode *root = super->root;
+    struct vfs_s_entry *entry = NULL;
+    char *tn;
+
+    switch (st->st_mode & S_IFMT) {	/* For case of HP/UX archives */
+    case S_IFCHR:
+    case S_IFBLK:
+#ifdef S_IFSOCK
+    case S_IFSOCK:
+#endif
+#ifdef S_IFIFO
+    case S_IFIFO:
+#endif
+#ifdef S_IFNAM
+    case S_IFNAM:
+#endif
+	if ((st->st_size != 0) && (st->st_rdev == 0x0001)) {
+	    /* FIXME: representation of major/minor differs between */
+	    /* different operating systems. */
+	    st->st_rdev = (unsigned) st->st_size;
+	    st->st_size = 0;
+	}
+	break;
+    default:
+	break;
+    }
+
+    if ((st->st_nlink > 1)
+	     && ((super->u.arch.type == CPIO_NEWC)
+		    || (super->u.arch.type == CPIO_CRC))) {	/* For case of hardlinked files */
+	struct defer_inode i, *l;
+	i.inumber = st->st_ino;
+	i.device = st->st_dev;
+	i.inode = NULL;
+
+	l = cpio_defer_find (super->u.arch.deferred, &i);
+	if (l != NULL) {
+	    inode = l->inode;
+	    if (inode->st.st_size != 0 && st->st_size != 0
+		    && (inode->st.st_size != st->st_size)) {
+		message (D_ERROR, MSG_ERROR,
+			_("Inconsistent hardlinks of\n%s\nin cpio archive\n%s"),
+			name, super->name);
+		inode = NULL;
+	    } else if (inode->st.st_size == 0)
+		inode->st.st_size = st->st_size;
+	}
+    }
+
+    /* remove trailing slashes */
+    for (tn = name + strlen (name) - 1; tn >= name && *tn == PATH_SEP; tn--)
+	*tn = '\0';
+
+    tn = strrchr (name, PATH_SEP);
+    if (tn == NULL)
+	tn = name;
+    else {
+	*tn = '\0';
+	root = vfs_s_find_inode (me, super, name, LINK_FOLLOW, FL_MKDIR);
+	*tn = PATH_SEP;
+	tn++;
+    }
+
+    entry = MEDATA->find_entry (me, root, tn, LINK_FOLLOW, FL_NONE);	/* In case entry is already there */
+
+    if (entry != NULL) {
+	/* This shouldn't happen! (well, it can happen if there is a record for a 
+	   file and than a record for a directory it is in; cpio would die with
+	   'No such file or directory' is such case) */
+
+	if (!S_ISDIR (entry->ino->st.st_mode)) {
+	    /* This can be considered archive inconsistency */
+	    message (D_ERROR, MSG_ERROR,
+		     _("%s contains duplicate entries! Skipping!"),
+		     super->name);
+	} else {
+	    entry->ino->st.st_mode = st->st_mode;
+	    entry->ino->st.st_uid = st->st_uid;
+	    entry->ino->st.st_gid = st->st_gid;
+	    entry->ino->st.st_atime = st->st_atime;
+	    entry->ino->st.st_mtime = st->st_mtime;
+	    entry->ino->st.st_ctime = st->st_ctime;
+	}
+
+	g_free (name);
+    } else {			/* !entry */
+	if (inode == NULL) {
+	    inode = vfs_s_new_inode (me, super, st);
+	    if ((st->st_nlink > 0)
+		     && ((super->u.arch.type == CPIO_NEWC)
+			    || (super->u.arch.type == CPIO_CRC))) {
+		/* For case of hardlinked files */
+		struct defer_inode *i;
+		i = g_new (struct defer_inode, 1);
+		i->inumber = st->st_ino;
+		i->device = st->st_dev;
+		i->inode = inode;
+		i->next = super->u.arch.deferred;
+		super->u.arch.deferred = i;
+	    }
+	}
+
+	if (st->st_size != 0)
+	    inode->data_offset = CPIO_POS (super);
+
+	entry = vfs_s_new_entry (me, tn, inode);
+	vfs_s_insert_entry (me, root, entry);
+
+	g_free (name);
+
+	if (!S_ISLNK (st->st_mode))
+	    CPIO_SEEK_CUR (super, st->st_size);
+	else {
+	    inode->linkname = g_malloc (st->st_size + 1);
+
+	    if (mc_read (super->u.arch.fd, inode->linkname, st->st_size) < st->st_size) {
+		inode->linkname[0] = '\0';
+		return STATUS_EOF;
+	    }
+
+	    inode->linkname[st->st_size] = '\0';	/* Linkname stored without terminating \0 !!! */
+	    CPIO_POS (super) += st->st_size;
+	    cpio_skip_padding (super);
+	}
+    }				/* !entry */
+
+    return STATUS_OK;
+}
+
 #define HEAD_LENGTH (26)
 static ssize_t cpio_read_bin_head(struct vfs_class *me, struct vfs_s_super *super)
 {
@@ -278,7 +411,7 @@ static ssize_t cpio_read_bin_head(struct vfs_class *me, struct vfs_s_super *supe
 	struct old_cpio_header buf;
 	short shorts[HEAD_LENGTH >> 1];
     } u;
-    int len;
+    ssize_t len;
     char *name;
     struct stat st;
 
@@ -333,7 +466,7 @@ static ssize_t cpio_read_oldc_head(struct vfs_class *me, struct vfs_s_super *sup
 	struct stat st;
 	char buf[HEAD_LENGTH + 1];
     } u;
-    int len;
+    ssize_t len;
     char *name;
 
     if (mc_read (super->u.arch.fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
@@ -385,25 +518,28 @@ static ssize_t cpio_read_oldc_head(struct vfs_class *me, struct vfs_s_super *sup
 #undef HEAD_LENGTH
 
 #define HEAD_LENGTH (110)
-static ssize_t cpio_read_crc_head(struct vfs_class *me, struct vfs_s_super *super)
+static ssize_t
+cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
 {
     struct new_cpio_header hd;
     union {
 	struct stat st;
 	char buf[HEAD_LENGTH + 1];
     } u;
-    int len;
+    ssize_t len;
     char *name;
 
     if (mc_read (super->u.arch.fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
 	return STATUS_EOF;
+
     CPIO_POS (super) += HEAD_LENGTH;
-    u.buf[HEAD_LENGTH] = 0;
+    u.buf[HEAD_LENGTH] = '\0';
 
     if (sscanf (u.buf, "%6ho%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
 	      &hd.c_magic, &hd.c_ino, &hd.c_mode, &hd.c_uid, &hd.c_gid,
 	      &hd.c_nlink,  &hd.c_mtime, &hd.c_filesize,
-	      (unsigned long *)&hd.c_dev, (unsigned long *)&hd.c_devmin, (unsigned long *)&hd.c_rdev, (unsigned long *)&hd.c_rdevmin,
+	      (unsigned long *)&hd.c_dev, (unsigned long *)&hd.c_devmin,
+	      (unsigned long *)&hd.c_rdev, (unsigned long *)&hd.c_rdevmin,
 	      &hd.c_namesize, &hd.c_chksum) < 14) {
 	message (D_ERROR, MSG_ERROR, _("Corrupted cpio header encountered in\n%s"),
 		   super->name);
@@ -421,8 +557,9 @@ static ssize_t cpio_read_crc_head(struct vfs_class *me, struct vfs_s_super *supe
     }
 
     name = g_malloc(hd.c_namesize);
-    if((len = mc_read (super->u.arch.fd, name, hd.c_namesize)) == -1 ||
-       (unsigned long) len < hd.c_namesize) {
+    len = mc_read (super->u.arch.fd, name, hd.c_namesize);
+
+    if ((len == -1) || ((unsigned long) len < hd.c_namesize)) {
 	g_free (name);
 	return STATUS_EOF;
     }
@@ -430,7 +567,7 @@ static ssize_t cpio_read_crc_head(struct vfs_class *me, struct vfs_s_super *supe
     CPIO_POS(super) += len;
     cpio_skip_padding(super);
 
-    if(!strcmp("TRAILER!!!", name)) { /* We got to the last record */
+    if (strcmp ("TRAILER!!!", name) == 0) { /* We got to the last record */
 	g_free(name);
 	return STATUS_TRAIL;
     }
@@ -448,128 +585,6 @@ static ssize_t cpio_read_crc_head(struct vfs_class *me, struct vfs_s_super *supe
     return cpio_create_entry (me, super, &u.st, name);
 }
 
-static int
-cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super,
-		   struct stat *st, char *name)
-{
-    struct vfs_s_inode *inode = NULL;
-    struct vfs_s_inode *root = super->root;
-    struct vfs_s_entry *entry = NULL;
-    char *tn;
-
-    switch (st->st_mode & S_IFMT) {	/* For case of HP/UX archives */
-    case S_IFCHR:
-    case S_IFBLK:
-#ifdef S_IFSOCK
-    case S_IFSOCK:
-#endif
-#ifdef S_IFIFO
-    case S_IFIFO:
-#endif
-#ifdef S_IFNAM
-    case S_IFNAM:
-#endif
-	if ((st->st_size != 0) && (st->st_rdev == 0x0001)) {
-	    /* FIXME: representation of major/minor differs between */
-	    /* different operating systems. */
-	    st->st_rdev = (unsigned) st->st_size;
-	    st->st_size = 0;
-	}
-	break;
-    default:
-	break;
-    }
-
-    if ((st->st_nlink > 1) && (super->u.arch.type == CPIO_NEWC || super->u.arch.type == CPIO_CRC)) {	/* For case of hardlinked files */
-	struct defer_inode i, *l;
-	i.inumber = st->st_ino;
-	i.device = st->st_dev;
-	i.inode = NULL;
-	if ((l = cpio_defer_find (super->u.arch.deferred, &i)) != NULL) {
-	    inode = l->inode;
-	    if (inode->st.st_size && st->st_size
-		&& (inode->st.st_size != st->st_size)) {
-		message (D_ERROR, MSG_ERROR,
-			 _
-			 ("Inconsistent hardlinks of\n%s\nin cpio archive\n%s"),
-			 name, super->name);
-		inode = NULL;
-	    } else if (!inode->st.st_size)
-		inode->st.st_size = st->st_size;
-	}
-    }
-
-    for (tn = name + strlen (name) - 1; tn >= name && *tn == PATH_SEP; tn--)
-	*tn = 0;
-    if ((tn = strrchr (name, PATH_SEP))) {
-	*tn = 0;
-	root = vfs_s_find_inode (me, super, name, LINK_FOLLOW, FL_MKDIR);
-	*tn = PATH_SEP;
-	tn++;
-    } else
-	tn = name;
-
-    entry = MEDATA->find_entry (me, root, tn, LINK_FOLLOW, FL_NONE);	/* In case entry is already there */
-
-    if (entry) {		/* This shouldn't happen! (well, it can happen if there is a record for a 
-				   file and than a record for a directory it is in; cpio would die with
-				   'No such file or directory' is such case) */
-
-	if (!S_ISDIR (entry->ino->st.st_mode)) {	/* This can be considered archive inconsistency */
-	    message (D_ERROR, MSG_ERROR,
-		     _("%s contains duplicate entries! Skipping!"),
-		     super->name);
-	} else {
-	    entry->ino->st.st_mode = st->st_mode;
-	    entry->ino->st.st_uid = st->st_uid;
-	    entry->ino->st.st_gid = st->st_gid;
-	    entry->ino->st.st_atime = st->st_atime;
-	    entry->ino->st.st_mtime = st->st_mtime;
-	    entry->ino->st.st_ctime = st->st_ctime;
-	}
-
-    } else {			/* !entry */
-
-	if (!inode) {
-	    inode = vfs_s_new_inode (me, super, st);
-	    if ((st->st_nlink > 0) && (super->u.arch.type == CPIO_NEWC || super->u.arch.type == CPIO_CRC)) {	/* For case of hardlinked files */
-		struct defer_inode *i;
-		i = g_new (struct defer_inode, 1);
-		i->inumber = st->st_ino;
-		i->device = st->st_dev;
-		i->inode = inode;
-		i->next = super->u.arch.deferred;
-		super->u.arch.deferred = i;
-	    }
-	}
-
-	if (st->st_size)
-	    inode->data_offset = CPIO_POS (super);
-
-	entry = vfs_s_new_entry (me, tn, inode);
-	vfs_s_insert_entry (me, root, entry);
-
-	if (S_ISLNK (st->st_mode)) {
-	    inode->linkname = g_malloc (st->st_size + 1);
-	    if (mc_read (super->u.arch.fd, inode->linkname, st->st_size)
-		< st->st_size) {
-		inode->linkname[0] = 0;
-		g_free (name);
-		return STATUS_EOF;
-	    }
-	    inode->linkname[st->st_size] = 0;	/* Linkname stored without terminating \0 !!! */
-	    CPIO_POS (super) += st->st_size;
-	    cpio_skip_padding (super);
-	} else {
-	    CPIO_SEEK_CUR (super, st->st_size);
-	}
-
-    }				/* !entry */
-
-    g_free (name);
-    return STATUS_OK;
-}
-
 /* Need to CPIO_SEEK_CUR to skip the file at the end of add entry!!!! */
 
 static int
diff --git a/vfs/direntry.c b/vfs/direntry.c
index f7a8bfb..80b0b12 100644
--- a/vfs/direntry.c
+++ b/vfs/direntry.c
@@ -400,12 +400,12 @@ vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super,
 		  const char *path, int follow, int flags)
 {
     struct vfs_s_entry *ent;
-    if (!(MEDATA->flags & VFS_S_REMOTE) && (!*path))
+
+    if (((MEDATA->flags & VFS_S_REMOTE) == 0) && (*path == '\0'))
 	return super->root;
+
     ent = (MEDATA->find_entry) (me, super->root, path, follow, flags);
-    if (!ent)
-	return NULL;
-    return ent->ino;
+    return (ent != NULL) ? ent->ino : NULL;
 }
 
 /* Ook, these were functions around directory entries / inodes */
@@ -488,9 +488,8 @@ vfs_s_get_path_mangle (struct vfs_class *me, char *inname,
 
     for (super = MEDATA->supers; super != NULL; super = super->next) {
 	/* 0 == other, 1 == same, return it, 2 == other but stop scanning */
-	int i;
-	if ((i =
-	     MEDATA->archive_same (me, super, archive_name, op, cookie))) {
+	int i = MEDATA->archive_same (me, super, archive_name, op, cookie);
+	if (i != 0) {
 	    if (i == 1)
 		goto return_success;
 	    else
diff --git a/vfs/vfs.c b/vfs/vfs.c
index 7c1de54..f8eb7a1 100644
--- a/vfs/vfs.c
+++ b/vfs/vfs.c
@@ -1124,7 +1124,8 @@ static char *
 mc_def_getlocalcopy (const char *filename)
 {
     char *tmp;
-    int fdin, fdout, i;
+    int fdin, fdout;
+    ssize_t i;
     char buffer[8192];
     struct stat mystat;
 
commit f84917a188f6f88cdc0d0d0067beefc13d42f40a
Author: Andrew Borodin <aborodin@vmail.ru>
Date:   Thu Nov 19 10:51:21 2009 +0300

    Fixed skip of empty directories in the root of cpio archive.
    
    Signed-off-by: Andrew Borodin <aborodin@vmail.ru>

diff --git a/vfs/cpio.c b/vfs/cpio.c
index 8c24573..0af9cda 100644
--- a/vfs/cpio.c
+++ b/vfs/cpio.c
@@ -331,7 +331,10 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super,
     tn = strrchr (name, PATH_SEP);
     if (tn == NULL)
 	tn = name;
-    else {
+    else if (tn == name + 1) {
+	/* started with "./" -- directory in the root of archive */
+	tn++;
+    } else {
 	*tn = '\0';
 	root = vfs_s_find_inode (me, super, name, LINK_FOLLOW, FL_MKDIR);
 	*tn = PATH_SEP;
@@ -341,7 +344,7 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super,
     entry = MEDATA->find_entry (me, root, tn, LINK_FOLLOW, FL_NONE);	/* In case entry is already there */
 
     if (entry != NULL) {
-	/* This shouldn't happen! (well, it can happen if there is a record for a 
+	/* This shouldn't happen! (well, it can happen if there is a record for a
 	   file and than a record for a directory it is in; cpio would die with
 	   'No such file or directory' is such case) */