X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Funix_capture.c;h=c0aa195066e5ea3f6acf767821e2ba8e1f4551dd;hp=906920a86144dc9549b58975e694691d6c8563ee;hb=07e37b8d03fb6cd8bd5905905dd52807774204cd;hpb=f5d26d6005ba759762bec8c7cd45a738e577a8a7 diff --git a/src/unix_capture.c b/src/unix_capture.c index 906920a8..c0aa1950 100644 --- a/src/unix_capture.c +++ b/src/unix_capture.c @@ -45,7 +45,7 @@ static int unix_capture_regular_file(const char *path, u64 size, struct wim_inode *inode, - struct wim_lookup_table *lookup_table) + struct list_head *unhashed_streams) { inode->i_attributes = FILE_ATTRIBUTE_NORMAL; @@ -64,8 +64,8 @@ unix_capture_regular_file(const char *path, } lte->file_on_disk = file_on_disk; lte->resource_location = RESOURCE_IN_FILE_ON_DISK; - lte->resource_entry.original_size = size; - lookup_table_insert_unhashed(lookup_table, lte, inode, 0); + lte->size = size; + add_unhashed_stream(lte, inode, 0, unhashed_streams); inode->i_lte = lte; } return 0; @@ -128,6 +128,7 @@ unix_capture_directory(struct wim_dentry *dir_dentry, if (child) dentry_add_child(dir_dentry, child); } + path[path_len] = '\0'; closedir(dir); return ret; } @@ -162,14 +163,17 @@ unix_capture_symlink(struct wim_dentry **root_p, dest = capture_fixup_absolute_symlink(dest, params->capture_root_ino, params->capture_root_dev); - if (!dest) { - WARNING("Ignoring out of tree absolute symlink " - "\"%s\" -> \"%s\"\n" - " (Use --norpfix to capture " - "absolute symlinks as-is)", - path, deref_name_buf); + if (dest == NULL) { + /* RPFIX (reparse point fixup) mode: Ignore + * absolute symbolic link that points out of the + * tree to be captured. */ free_dentry(*root_p); *root_p = NULL; + params->progress.scan.cur_path = path; + params->progress.scan.symlink_target = deref_name_buf; + do_capture_progress(params, + WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK, + NULL); return 0; } inode->i_not_rpfixed = 0; @@ -201,62 +205,60 @@ unix_build_dentry_tree_recursive(struct wim_dentry **root_ret, struct add_image_params *params) { struct wim_dentry *root = NULL; - int ret = 0; - struct wim_inode *inode; - - if (exclude_path(path, path_len, params->config, true)) { - if ((params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE) - && params->progress_func) - { - union wimlib_progress_info info; - info.scan.cur_path = path; - info.scan.excluded = true; - params->progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY, &info); - } - goto out; - } + int ret; + struct wim_inode *inode = NULL; + struct stat stbuf; - if ((params->add_flags & WIMLIB_ADD_FLAG_VERBOSE) - && params->progress_func) + if (exclude_path(path + params->capture_root_nchars, + path_len - params->capture_root_nchars, + params->config)) { - union wimlib_progress_info info; - info.scan.cur_path = path; - info.scan.excluded = false; - params->progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY, &info); + ret = 0; + goto out_progress; } - struct stat stbuf; - int (*stat_fn)(const char *restrict, struct stat *restrict); if ((params->add_flags & WIMLIB_ADD_FLAG_DEREFERENCE) || (params->add_flags & WIMLIB_ADD_FLAG_ROOT)) - stat_fn = stat; + ret = stat(path, &stbuf); else - stat_fn = lstat; + ret = lstat(path, &stbuf); - ret = (*stat_fn)(path, &stbuf); if (ret) { - ERROR_WITH_ERRNO("Failed to stat `%s'", path); + ERROR_WITH_ERRNO("Failed to stat \"%s\"", path); ret = WIMLIB_ERR_STAT; goto out; } - if (!S_ISREG(stbuf.st_mode) && !S_ISDIR(stbuf.st_mode) - && !S_ISLNK(stbuf.st_mode)) { - ERROR("`%s' is not a regular file, directory, or symbolic link.", - path); - ret = WIMLIB_ERR_SPECIAL_FILE; + + if (!S_ISREG(stbuf.st_mode) && + !S_ISDIR(stbuf.st_mode) && + !S_ISLNK(stbuf.st_mode)) + { + if (params->add_flags & WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE) + { + ERROR("Can't archive unsupported file \"%s\"", path); + ret = WIMLIB_ERR_UNSUPPORTED_FILE; + goto out; + } + params->progress.scan.cur_path = path; + do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL); + ret = 0; goto out; } - ret = inode_table_new_dentry(¶ms->inode_table, + ret = inode_table_new_dentry(params->inode_table, path_basename_with_len(path, path_len), - stbuf.st_ino, stbuf.st_dev, false, &root); + stbuf.st_ino, stbuf.st_dev, + S_ISDIR(stbuf.st_mode), &root); if (ret) goto out; inode = root->d_inode; - if (inode->i_nlink > 1) /* Already captured this inode? */ - goto out; + if (inode->i_nlink > 1) { + /* Already captured this inode? */ + ret = 0; + goto out_progress; + } #ifdef HAVE_STAT_NANOSECOND_PRECISION inode->i_creation_time = timespec_to_wim_timestamp(stbuf.st_mtim); @@ -280,23 +282,36 @@ unix_build_dentry_tree_recursive(struct wim_dentry **root_ret, params->add_flags &= ~WIMLIB_ADD_FLAG_ROOT; if (S_ISREG(stbuf.st_mode)) ret = unix_capture_regular_file(path, stbuf.st_size, - inode, params->lookup_table); + inode, params->unhashed_streams); else if (S_ISDIR(stbuf.st_mode)) ret = unix_capture_directory(root, path, path_len, params); - else + else { ret = unix_capture_symlink(&root, path, inode, params); -out: - if (ret == 0) - *root_ret = root; + if (root == NULL) + goto out; + } + + if (ret) + goto out; + +out_progress: + params->progress.scan.cur_path = path; + if (root == NULL) + do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL); else + do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode); +out: + if (ret) free_dentry_tree(root, params->lookup_table); + else + *root_ret = root; return ret; } /* * unix_build_dentry_tree(): - * Builds a tree of WIM dentries from an on-disk directory tree (UNIX - * version; no NTFS-specific data is captured). + * Builds a tree of WIM dentries from an on-disk directory tree (UNIX + * version; no NTFS-specific data is captured). * * @root_ret: Place to return a pointer to the root of the dentry tree. Only * modified if successful. Set to NULL if the file or directory was @@ -330,13 +345,6 @@ unix_build_dentry_tree(struct wim_dentry **root_ret, return WIMLIB_ERR_STAT; } - if ((params->add_flags & WIMLIB_ADD_FLAG_ROOT) && - !S_ISDIR(root_stbuf.st_mode)) - { - ERROR("Root of capture \"%s\" is not a directory", - root_disk_path); - return WIMLIB_ERR_NOTDIR; - } params->capture_root_ino = root_stbuf.st_ino; params->capture_root_dev = root_stbuf.st_dev; } @@ -347,11 +355,13 @@ unix_build_dentry_tree(struct wim_dentry **root_ret, if (path_len >= path_bufsz) return WIMLIB_ERR_INVALID_PARAM; - path_buf = MALLOC(path_bufsz); + path_buf = MALLOC(path_bufsz); if (!path_buf) return WIMLIB_ERR_NOMEM; memcpy(path_buf, root_disk_path, path_len + 1); + params->capture_root_nchars = path_len; + ret = unix_build_dentry_tree_recursive(root_ret, path_buf, path_len, params); FREE(path_buf);