Author: jkim
Date: Mon Feb 20 18:49:11 2012
New Revision: 231942
URL: http://svn.freebsd.org/changeset/base/231942

Log:
  MFC:  r230795
  
  Allow contents of multiple directories to be merged to the current image.

Modified:
  stable/9/usr.sbin/makefs/cd9660.c
  stable/9/usr.sbin/makefs/cd9660.h
  stable/9/usr.sbin/makefs/cd9660/cd9660_write.c
  stable/9/usr.sbin/makefs/ffs.c
  stable/9/usr.sbin/makefs/makefs.8
  stable/9/usr.sbin/makefs/makefs.c
  stable/9/usr.sbin/makefs/makefs.h
  stable/9/usr.sbin/makefs/walk.c
Directory Properties:
  stable/9/usr.sbin/makefs/   (props changed)

Modified: stable/9/usr.sbin/makefs/cd9660.c
==============================================================================
--- stable/9/usr.sbin/makefs/cd9660.c   Mon Feb 20 17:09:52 2012        
(r231941)
+++ stable/9/usr.sbin/makefs/cd9660.c   Mon Feb 20 18:49:11 2012        
(r231942)
@@ -472,8 +472,6 @@ cd9660_makefs(const char *image, const c
                return;
        }
 
-       diskStructure.rootFilesystemPath = dir;
-
        if (diskStructure.verbose_level > 0)
                printf("cd9660_makefs: image %s directory %s root %p\n",
                    image, dir, root);
@@ -1584,24 +1582,15 @@ cd9660_generate_path_table(void)
 }
 
 void
-cd9660_compute_full_filename(cd9660node *node, char *buf, int level)
+cd9660_compute_full_filename(cd9660node *node, char *buf)
 {
-       cd9660node *parent;
-
-       parent = (node->rr_real_parent == NULL ?
-                 node->parent : node->rr_real_parent);
-       if (parent != NULL) {
-               cd9660_compute_full_filename(parent, buf, level + 1);
-               strcat(buf, node->node->name);
-       } else {
-               /* We are at the root */
-               strcat(buf, diskStructure.rootFilesystemPath);
-               if (buf[strlen(buf) - 1] == '/')
-                       buf[strlen(buf) - 1] = '\0';
-       }
+       int len;
 
-       if (level != 0)
-               strcat(buf, "/");
+       len = CD9660MAXPATH + 1;
+       len = snprintf(buf, len, "%s/%s/%s", node->node->root,
+           node->node->path, node->node->name);
+       if (len > CD9660MAXPATH)
+               errx(1, "Pathname too long.");
 }
 
 /* NEW filename conversion method */

Modified: stable/9/usr.sbin/makefs/cd9660.h
==============================================================================
--- stable/9/usr.sbin/makefs/cd9660.h   Mon Feb 20 17:09:52 2012        
(r231941)
+++ stable/9/usr.sbin/makefs/cd9660.h   Mon Feb 20 18:49:11 2012        
(r231942)
@@ -244,8 +244,6 @@ typedef struct _iso9660_disk {
 
        cd9660node *rootNode;
 
-       const char *rootFilesystemPath;
-
        /* Important sector numbers here */
        /* primaryDescriptor.type_l_path_table*/
        int64_t primaryBigEndianTableSector;
@@ -345,7 +343,7 @@ int cd9660_setup_boot_volume_descriptor(
 int    cd9660_write_image(const char *image);
 int    cd9660_copy_file(FILE *, off_t, const char *);
 
-void   cd9660_compute_full_filename(cd9660node *, char *, int);
+void   cd9660_compute_full_filename(cd9660node *, char *);
 int    cd9660_compute_record_size(cd9660node *);
 
 /* Debugging functions */

Modified: stable/9/usr.sbin/makefs/cd9660/cd9660_write.c
==============================================================================
--- stable/9/usr.sbin/makefs/cd9660/cd9660_write.c      Mon Feb 20 17:09:52 
2012        (r231941)
+++ stable/9/usr.sbin/makefs/cd9660/cd9660_write.c      Mon Feb 20 18:49:11 
2012        (r231942)
@@ -296,7 +296,7 @@ cd9660_write_file(FILE *fd, cd9660node *
                        inode->flags |= FI_WRITTEN;
                        if (writenode->node->contents == NULL)
                                cd9660_compute_full_filename(writenode,
-                                   temp_file_name, 0);
+                                   temp_file_name);
                        ret = cd9660_copy_file(fd, writenode->fileDataSector,
                            (writenode->node->contents != NULL) ?
                            writenode->node->contents : temp_file_name);

Modified: stable/9/usr.sbin/makefs/ffs.c
==============================================================================
--- stable/9/usr.sbin/makefs/ffs.c      Mon Feb 20 17:09:52 2012        
(r231941)
+++ stable/9/usr.sbin/makefs/ffs.c      Mon Feb 20 18:49:11 2012        
(r231942)
@@ -780,8 +780,8 @@ ffs_populate_dir(const char *dir, fsnode
                cur->inode->flags |= FI_WRITTEN;
 
                if (cur->contents == NULL) {
-                       if (snprintf(path, sizeof(path), "%s/%s", dir,
-                           cur->name) >= sizeof(path))
+                       if (snprintf(path, sizeof(path), "%s/%s/%s", cur->root,
+                           cur->path, cur->name) >= (int)sizeof(path))
                                errx(1, "Pathname too long.");
                }
 

Modified: stable/9/usr.sbin/makefs/makefs.8
==============================================================================
--- stable/9/usr.sbin/makefs/makefs.8   Mon Feb 20 17:09:52 2012        
(r231941)
+++ stable/9/usr.sbin/makefs/makefs.8   Mon Feb 20 18:49:11 2012        
(r231942)
@@ -35,7 +35,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 10, 2009
+.Dd January 30, 2012
 .Dt MAKEFS 8
 .Os
 .Sh NAME
@@ -58,6 +58,7 @@
 .Op Fl t Ar fs-type
 .Ar image-file
 .Ar directory | manifest
+.Op Ar extra-directory ...
 .Sh DESCRIPTION
 The utility
 .Nm
@@ -67,6 +68,15 @@ from the directory tree
 .Ar directory
 or from the mtree manifest
 .Ar manifest .
+If optional directory tree
+.Ar extra-directory
+is passed, then the directory tree of each argument will be merged
+into the
+.Ar directory
+or
+.Ar manifest
+first before creating
+.Ar image-file .
 No special devices or privileges are required to perform this task.
 .Pp
 The options are as follows:

Modified: stable/9/usr.sbin/makefs/makefs.c
==============================================================================
--- stable/9/usr.sbin/makefs/makefs.c   Mon Feb 20 17:09:52 2012        
(r231941)
+++ stable/9/usr.sbin/makefs/makefs.c   Mon Feb 20 18:49:11 2012        
(r231942)
@@ -87,7 +87,7 @@ main(int argc, char *argv[])
        fstype_t        *fstype;
        fsinfo_t         fsoptions;
        fsnode          *root;
-       int              ch, len;
+       int              ch, i, len;
        char            *subtree;
        char            *specfile;
 
@@ -241,7 +241,7 @@ main(int argc, char *argv[])
        argc -= optind;
        argv += optind;
 
-       if (argc != 2)
+       if (argc < 2)
                usage();
 
        /* -x must be accompanied by -F */
@@ -260,7 +260,7 @@ main(int argc, char *argv[])
        case S_IFDIR:           /* walk the tree */
                subtree = argv[1];
                TIMER_START(start);
-               root = walk_dir(subtree, NULL);
+               root = walk_dir(subtree, ".", NULL, NULL);
                TIMER_RESULTS(start, "walk_dir");
                break;
        case S_IFREG:           /* read the manifest file */
@@ -274,6 +274,17 @@ main(int argc, char *argv[])
                /* NOTREACHED */
        }
 
+       /* append extra directory */
+       for (i = 2; i < argc; i++) {
+               if (stat(argv[i], &sb) == -1)
+                       err(1, "Can't stat `%s'", argv[i]);
+               if (!S_ISDIR(sb.st_mode))
+                       errx(1, "%s: not a directory", argv[i]);
+               TIMER_START(start);
+               root = walk_dir(argv[i], ".", NULL, root);
+               TIMER_RESULTS(start, "walk_dir2");
+       }
+
        if (specfile) {         /* apply a specfile */
                TIMER_START(start);
                apply_specfile(specfile, subtree, root, fsoptions.onlyspec);
@@ -282,7 +293,7 @@ main(int argc, char *argv[])
 
        if (debug & DEBUG_DUMP_FSNODES) {
                printf("\nparent: %s\n", subtree);
-               dump_fsnodes(".", root);
+               dump_fsnodes(root);
                putchar('\n');
        }
 
@@ -336,7 +347,7 @@ usage(void)
 "usage: %s [-t fs-type] [-o fs-options] [-d debug-mask] [-B endian]\n"
 "\t[-S sector-size] [-M minimum-size] [-m maximum-size] [-s image-size]\n"
 "\t[-b free-blocks] [-f free-files] [-F mtree-specfile] [-x]\n"
-"\t[-N userdb-dir] image-file directory | manifest\n",
+"\t[-N userdb-dir] image-file directory | manifest [extra-directory ...]\n",
            prog);
        exit(1);
 }

Modified: stable/9/usr.sbin/makefs/makefs.h
==============================================================================
--- stable/9/usr.sbin/makefs/makefs.h   Mon Feb 20 17:09:52 2012        
(r231941)
+++ stable/9/usr.sbin/makefs/makefs.h   Mon Feb 20 18:49:11 2012        
(r231942)
@@ -94,6 +94,8 @@ typedef struct _fsnode {
        fsinode         *inode;         /* actual inode data */
        char            *symlink;       /* symlink target */
        char            *contents;      /* file to provide contents */
+       const char      *root;          /* root path */
+       char            *path;          /* directory name */
        char            *name;          /* file name */
        int             flags;          /* misc flags */
 } fsnode;
@@ -147,11 +149,11 @@ typedef struct {
 
 
 void           apply_specfile(const char *, const char *, fsnode *, int);
-void           dump_fsnodes(const char *, fsnode *);
+void           dump_fsnodes(fsnode *);
 const char *   inode_type(mode_t);
 fsnode *       read_mtree(const char *, fsnode *);
 int            set_option(option_t *, const char *, const char *);
-fsnode *       walk_dir(const char *, fsnode *);
+fsnode *       walk_dir(const char *, const char *, fsnode *, fsnode *);
 void           free_fsnodes(fsnode *);
 
 void           ffs_prep_opts(fsinfo_t *);

Modified: stable/9/usr.sbin/makefs/walk.c
==============================================================================
--- stable/9/usr.sbin/makefs/walk.c     Mon Feb 20 17:09:52 2012        
(r231941)
+++ stable/9/usr.sbin/makefs/walk.c     Mon Feb 20 18:49:11 2012        
(r231942)
@@ -57,40 +57,70 @@ __FBSDID("$FreeBSD$");
 
 static void     apply_specdir(const char *, NODE *, fsnode *, int);
 static void     apply_specentry(const char *, NODE *, fsnode *);
-static fsnode  *create_fsnode(const char *, struct stat *);
+static fsnode  *create_fsnode(const char *, const char *, const char *,
+                              struct stat *);
 static fsinode *link_check(fsinode *);
 
 
 /*
  * walk_dir --
- *     build a tree of fsnodes from `dir', with a parent fsnode of `parent'
- *     (which may be NULL for the root of the tree).
+ *     build a tree of fsnodes from `root' and `dir', with a parent
+ *     fsnode of `parent' (which may be NULL for the root of the tree).
+ *     append the tree to a fsnode of `join' if it is not NULL.
  *     each "level" is a directory, with the "." entry guaranteed to be
  *     at the start of the list, and without ".." entries.
  */
 fsnode *
-walk_dir(const char *dir, fsnode *parent)
+walk_dir(const char *root, const char *dir, fsnode *parent, fsnode *join)
 {
-       fsnode          *first, *cur, *prev;
+       fsnode          *first, *cur, *prev, *last;
        DIR             *dirp;
        struct dirent   *dent;
        char            path[MAXPATHLEN + 1];
        struct stat     stbuf;
+       char            *name, *rp;
+       int             dot, len;
 
+       assert(root != NULL);
        assert(dir != NULL);
 
+       len = snprintf(path, sizeof(path), "%s/%s", root, dir);
+       if (len >= (int)sizeof(path))
+               errx(1, "Pathname too long.");
        if (debug & DEBUG_WALK_DIR)
-               printf("walk_dir: %s %p\n", dir, parent);
-       if ((dirp = opendir(dir)) == NULL)
-               err(1, "Can't opendir `%s'", dir);
-       first = prev = NULL;
+               printf("walk_dir: %s %p\n", path, parent);
+       if ((dirp = opendir(path)) == NULL)
+               err(1, "Can't opendir `%s'", path);
+       rp = path + strlen(root) + 1;
+       if (join != NULL) {
+               first = cur = join;
+               while (cur->next != NULL)
+                       cur = cur->next;
+               prev = cur;
+       } else
+               first = prev = NULL;
+       last = prev;
        while ((dent = readdir(dirp)) != NULL) {
-               if (strcmp(dent->d_name, "..") == 0)
-                       continue;
+               name = dent->d_name;
+               dot = 0;
+               if (name[0] == '.')
+                       switch (name[1]) {
+                       case '\0':      /* "." */
+                               if (join != NULL)
+                                       continue;
+                               dot = 1;
+                               break;
+                       case '.':       /* ".." */
+                               if (name[2] == '\0')
+                                       continue;
+                               /* FALLTHROUGH */
+                       default:
+                               dot = 0;
+                       }
                if (debug & DEBUG_WALK_DIR_NODE)
-                       printf("scanning %s/%s\n", dir, dent->d_name);
-               if (snprintf(path, sizeof(path), "%s/%s", dir, dent->d_name)
-                   >= sizeof(path))
+                       printf("scanning %s/%s/%s\n", root, dir, name);
+               if (snprintf(path + len, sizeof(path) - len, "/%s", name) >=
+                   (int)sizeof(path) - len)
                        errx(1, "Pathname too long.");
                if (lstat(path, &stbuf) == -1)
                        err(1, "Can't lstat `%s'", path);
@@ -102,22 +132,51 @@ walk_dir(const char *dir, fsnode *parent
                }
 #endif
 
-               cur = create_fsnode(dent->d_name, &stbuf);
+               if (join != NULL) {
+                       cur = join->next;
+                       for (;;) {
+                               if (cur == NULL || strcmp(cur->name, name) == 0)
+                                       break;
+                               if (cur == last) {
+                                       cur = NULL;
+                                       break;
+                               }
+                               cur = cur->next;
+                       }
+                       if (cur != NULL) {
+                               if (S_ISDIR(cur->type) &&
+                                   S_ISDIR(stbuf.st_mode)) {
+                                       if (debug & DEBUG_WALK_DIR_NODE)
+                                               printf("merging %s with %p\n",
+                                                   path, cur->child);
+                                       cur->child = walk_dir(root, rp, cur,
+                                           cur->child);
+                                       continue;
+                               }
+                               errx(1, "Can't merge %s `%s' with existing %s",
+                                   inode_type(stbuf.st_mode), path,
+                                   inode_type(cur->type));
+                       }
+               }
+
+               cur = create_fsnode(root, dir, name, &stbuf);
                cur->parent = parent;
-               if (strcmp(dent->d_name, ".") == 0) {
+               if (dot) {
                                /* ensure "." is at the start of the list */
                        cur->next = first;
                        first = cur;
                        if (! prev)
                                prev = cur;
+                       cur->first = first;
                } else {                        /* not "." */
                        if (prev)
                                prev->next = cur;
                        prev = cur;
                        if (!first)
                                first = cur;
+                       cur->first = first;
                        if (S_ISDIR(cur->type)) {
-                               cur->child = walk_dir(path, cur);
+                               cur->child = walk_dir(root, rp, cur, NULL);
                                continue;
                        }
                }
@@ -147,22 +206,27 @@ walk_dir(const char *dir, fsnode *parent
                                err(1, "Memory allocation error");
                }
        }
-       for (cur = first; cur != NULL; cur = cur->next)
-               cur->first = first;
+       assert(first != NULL);
+       if (join == NULL)
+               for (cur = first->next; cur != NULL; cur = cur->next)
+                       cur->first = first;
        if (closedir(dirp) == -1)
-               err(1, "Can't closedir `%s'", dir);
+               err(1, "Can't closedir `%s/%s'", root, dir);
        return (first);
 }
 
 static fsnode *
-create_fsnode(const char *name, struct stat *stbuf)
+create_fsnode(const char *root, const char *path, const char *name,
+    struct stat *stbuf)
 {
        fsnode *cur;
 
        if ((cur = calloc(1, sizeof(fsnode))) == NULL ||
+           (cur->path = strdup(path)) == NULL ||
            (cur->name = strdup(name)) == NULL ||
            (cur->inode = calloc(1, sizeof(fsinode))) == NULL)
                err(1, "Memory allocation error");
+       cur->root = root;
        cur->type = stbuf->st_mode & S_IFMT;
        cur->inode->nlink = 1;
        cur->inode->st = *stbuf;
@@ -211,6 +275,7 @@ free_fsnodes(fsnode *node)
                        free(cur->inode);
                if (cur->symlink)
                        free(cur->symlink);
+               free(cur->path);
                free(cur->name);
                free(cur);
        }
@@ -388,14 +453,16 @@ apply_specdir(const char *dir, NODE *spe
                        stbuf.st_mtimensec = stbuf.st_atimensec =
                            stbuf.st_ctimensec = start_time.tv_nsec;
 #endif
-                       curfsnode = create_fsnode(curnode->name, &stbuf);
+                       curfsnode = create_fsnode(".", ".", curnode->name,
+                           &stbuf);
                        curfsnode->parent = dirnode->parent;
                        curfsnode->first = dirnode;
                        curfsnode->next = dirnode->next;
                        dirnode->next = curfsnode;
                        if (curfsnode->type == S_IFDIR) {
                                        /* for dirs, make "." entry as well */
-                               curfsnode->child = create_fsnode(".", &stbuf);
+                               curfsnode->child = create_fsnode(".", ".", ".",
+                                   &stbuf);
                                curfsnode->child->parent = curfsnode;
                                curfsnode->child->first = curfsnode->child;
                        }
@@ -503,19 +570,18 @@ apply_specentry(const char *dir, NODE *s
 
 /*
  * dump_fsnodes --
- *     dump the fsnodes from `cur', based in the directory `dir'
+ *     dump the fsnodes from `cur'
  */
 void
-dump_fsnodes(const char *dir, fsnode *root)
+dump_fsnodes(fsnode *root)
 {
        fsnode  *cur;
        char    path[MAXPATHLEN + 1];
 
-       assert (dir != NULL);
-       printf("dump_fsnodes: %s %p\n", dir, root);
+       printf("dump_fsnodes: %s %p\n", root->path, root);
        for (cur = root; cur != NULL; cur = cur->next) {
-               if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
-                   >= sizeof(path))
+               if (snprintf(path, sizeof(path), "%s/%s", cur->path,
+                   cur->name) >= (int)sizeof(path))
                        errx(1, "Pathname too long.");
 
                if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
@@ -534,10 +600,10 @@ dump_fsnodes(const char *dir, fsnode *ro
 
                if (cur->child) {
                        assert (cur->type == S_IFDIR);
-                       dump_fsnodes(path, cur->child);
+                       dump_fsnodes(cur->child);
                }
        }
-       printf("dump_fsnodes: finished %s\n", dir);
+       printf("dump_fsnodes: finished %s/%s\n", root->path, root->name);
 }
 
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to