Whamcloud - gitweb
debian: add support for DEB_BUILD_OPTIONS=parallel=N
[tools/e2fsprogs.git] / misc / create_inode.c
index c6a79c3..e2676a0 100644 (file)
@@ -39,6 +39,8 @@
 #include "create_inode.h"
 #include "support/nls-enable.h"
 
+#include "create_inode_libarchive.h"
+
 /* 64KiB is the minimum blksize to best minimize system call overhead. */
 #define COPY_FILE_BUFLEN       65536
 
@@ -69,7 +71,7 @@ static int ext2_file_type(unsigned int mode)
 }
 
 /* Link an inode number to a directory */
-static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
+errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
                          ext2_ino_t ino, const char *name)
 {
        struct ext2_inode       inode;
@@ -107,9 +109,16 @@ static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
        return retval;
 }
 
+static time_t clamped_time(ext2_filsys fs, time_t t)
+{
+       if ((fs->flags2 & EXT2_FLAG2_USE_FAKE_TIME) && t > fs->now)
+               return fs->now;
+       return t;
+}
+
 /* Set the uid, gid, mode and time for the inode */
-static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino,
-                                struct stat *st)
+errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino,
+                                const struct stat *st)
 {
        errcode_t               retval;
        struct ext2_inode       inode;
@@ -125,9 +134,9 @@ static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino,
        inode.i_gid = st->st_gid;
        ext2fs_set_i_gid_high(inode, st->st_gid >> 16);
        inode.i_mode = (LINUX_S_IFMT & inode.i_mode) | (~S_IFMT & st->st_mode);
-       inode.i_atime = st->st_atime;
-       inode.i_mtime = st->st_mtime;
-       inode.i_ctime = st->st_ctime;
+       ext2fs_inode_xtime_set(&inode, i_atime, clamped_time(fs, st->st_atime));
+       ext2fs_inode_xtime_set(&inode, i_ctime, clamped_time(fs, st->st_ctime));
+       ext2fs_inode_xtime_set(&inode, i_mtime, clamped_time(fs, st->st_mtime));
 
        retval = ext2fs_write_inode(fs, ino, &inode);
        if (retval)
@@ -150,6 +159,8 @@ static errcode_t set_inode_xattr(ext2_filsys fs, ext2_ino_t ino,
 
        size = llistxattr(filename, NULL, 0);
        if (size == -1) {
+               if (errno == ENOTSUP)
+                       return 0;
                retval = errno;
                com_err(__func__, retval, _("while listing attributes of \"%s\""),
                        filename);
@@ -234,7 +245,6 @@ static errcode_t set_inode_xattr(ext2_filsys fs, ext2_ino_t ino,
                retval = retval ? retval : close_retval;
        }
        return retval;
-       return 0;
 }
 #else /* HAVE_LLISTXATTR */
 static errcode_t set_inode_xattr(ext2_filsys fs EXT2FS_ATTR((unused)),
@@ -255,6 +265,7 @@ errcode_t do_mknod_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name,
        struct ext2_inode       inode;
        unsigned long           devmajor, devminor, mode;
        int                     filetype;
+       time_t                  now;
 
        switch(st_mode & S_IFMT) {
        case S_IFCHR:
@@ -308,8 +319,10 @@ errcode_t do_mknod_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name,
        ext2fs_inode_alloc_stats2(fs, ino, +1, 0);
        memset(&inode, 0, sizeof(inode));
        inode.i_mode = mode;
-       inode.i_atime = inode.i_ctime = inode.i_mtime =
-               fs->now ? fs->now : time(0);
+       now = fs->now ? fs->now : time(0);
+       ext2fs_inode_xtime_set(&inode, i_atime, now);
+       ext2fs_inode_xtime_set(&inode, i_ctime, now);
+       ext2fs_inode_xtime_set(&inode, i_mtime, now);
 
        if (filetype != S_IFIFO) {
                devmajor = major(st_rdev);
@@ -630,6 +643,7 @@ errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src,
        errcode_t       retval;
        struct ext2_inode inode;
        char            *cp;
+       time_t          now;
 
        fd = ext2fs_open_file(src, O_RDONLY, 0);
        if (fd < 0) {
@@ -650,7 +664,7 @@ errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src,
                if (retval) {
                        com_err(dest, retval, _("while looking up \"%s\""),
                                dest);
-                       return retval;
+                       goto out;
                }
                dest = cp+1;
        } else
@@ -683,8 +697,10 @@ errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src,
        ext2fs_inode_alloc_stats2(fs, newfile, +1, 0);
        memset(&inode, 0, sizeof(inode));
        inode.i_mode = (statbuf.st_mode & ~S_IFMT) | LINUX_S_IFREG;
-       inode.i_atime = inode.i_ctime = inode.i_mtime =
-               fs->now ? fs->now : time(0);
+       now = fs->now ? fs->now : time(0);
+       ext2fs_inode_xtime_set(&inode, i_atime, now);
+       ext2fs_inode_xtime_set(&inode, i_ctime, now);
+       ext2fs_inode_xtime_set(&inode, i_mtime, now);
        inode.i_links_count = 1;
        retval = ext2fs_inode_size_set(fs, &inode, statbuf.st_size);
        if (retval)
@@ -719,12 +735,6 @@ out:
        return retval;
 }
 
-struct file_info {
-       char *path;
-       size_t path_len;
-       size_t path_max_len;
-};
-
 static errcode_t path_append(struct file_info *target, const char *file)
 {
        if (strlen(file) + target->path_len + 1 > target->path_max_len) {
@@ -764,37 +774,33 @@ static int scandir(const char *dir_name, struct dirent ***name_list,
                        size_t new_list_size = temp_list_size + 32;
                        struct dirent **new_list = (struct dirent**)realloc(
                                temp_list, new_list_size * sizeof(struct dirent*));
-                       if (new_list == NULL) {
-                               goto out;
-                       }
+                       if (new_list == NULL)
+                               goto out_err;
                        temp_list_size = new_list_size;
                        temp_list = new_list;
                }
                // add the copy of dirent to the list
                temp_list[num_dent] = (struct dirent*)malloc((dent->d_reclen + 3) & ~3);
+               if (!temp_list[num_dent])
+                       goto out_err;
                memcpy(temp_list[num_dent], dent, dent->d_reclen);
                num_dent++;
        }
+       closedir(dir);
 
        if (compar != NULL) {
                qsort(temp_list, num_dent, sizeof(struct dirent*),
                      (int (*)(const void*, const void*))compar);
        }
-
-        // release the temp list
        *name_list = temp_list;
-       temp_list = NULL;
+       return num_dent;
 
-out:
-       if (temp_list != NULL) {
-               while (num_dent > 0) {
-                       free(temp_list[--num_dent]);
-               }
-               free(temp_list);
-               num_dent = -1;
-       }
+out_err:
        closedir(dir);
-       return num_dent;
+       while (num_dent > 0)
+               free(temp_list[--num_dent]);
+       free(temp_list);
+       return -1;
 }
 
 static int alphasort(const struct dirent **a, const struct dirent **b) {
@@ -812,11 +818,9 @@ static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
        const char      *name;
        struct dirent   **dent;
        struct stat     st;
-       char            *ln_target = NULL;
        unsigned int    save_inode;
        ext2_ino_t      ino;
        errcode_t       retval = 0;
-       int             read_cnt;
        int             hdlink;
        size_t          cur_dir_path_len;
        int             i, num_dents;
@@ -899,7 +903,10 @@ static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
                                goto out;
                        }
                        break;
-               case S_IFLNK:
+               case S_IFLNK: {
+                       char *ln_target;
+                       int read_cnt;
+
                        ln_target = malloc(st.st_size + 1);
                        if (ln_target == NULL) {
                                com_err(__func__, retval,
@@ -934,7 +941,8 @@ static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
                                goto out;
                        }
                        break;
-#endif
+               }
+#endif /* !_WIN32 */
                case S_IFREG:
                        retval = do_write_internal(fs, parent_ino, name, name,
                                                   root);
@@ -1045,7 +1053,7 @@ out:
 }
 
 errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino,
-                      const char *source_dir, ext2_ino_t root,
+                      const char *source, ext2_ino_t root,
                       struct fs_ops_callbacks *fs_callbacks)
 {
        struct file_info file_info;
@@ -1070,14 +1078,35 @@ errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino,
        file_info.path_max_len = 255;
        file_info.path = calloc(file_info.path_max_len, 1);
 
-       retval = set_inode_xattr(fs, root, source_dir);
+       /* interpret input as tarball either if it's "-" (stdin) or if it's
+        * a regular file (or a symlink pointing to a regular file)
+        */
+       if (strcmp(source, "-") == 0) {
+               retval = __populate_fs_from_tar(fs, parent_ino, NULL, root, &hdlinks,
+                                          &file_info, fs_callbacks);
+               goto out;
+       }
+
+       struct stat st;
+       if (stat(source, &st)) {
+               retval = errno;
+               com_err(__func__, retval, _("while calling stat"));
+               return retval;
+       }
+       if (S_ISREG(st.st_mode)) {
+               retval = __populate_fs_from_tar(fs, parent_ino, source, root, &hdlinks,
+                                          &file_info, fs_callbacks);
+               goto out;
+       }
+
+       retval = set_inode_xattr(fs, root, source);
        if (retval) {
                com_err(__func__, retval,
                        _("while copying xattrs on root directory"));
                goto out;
        }
 
-       retval = __populate_fs(fs, parent_ino, source_dir, root, &hdlinks,
+       retval = __populate_fs(fs, parent_ino, source, root, &hdlinks,
                               &file_info, fs_callbacks);
 
 out:
@@ -1087,7 +1116,7 @@ out:
 }
 
 errcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
-                     const char *source_dir, ext2_ino_t root)
+                     const char *source, ext2_ino_t root)
 {
-       return populate_fs2(fs, parent_ino, source_dir, root, NULL);
+       return populate_fs2(fs, parent_ino, source, root, NULL);
 }