X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fmodify.c;h=681624c6054488629e62e3c750fe8e1a07a4f10a;hb=8396da8b23c2c66cf7f8752f2c487cdc6c40516e;hp=141f2dd8aac45cb0de271803cb2a6d71a4258f8e;hpb=1dde5fb0d809f2f5e032e4d5241d1cb15ff3eb65;p=wimlib diff --git a/src/modify.c b/src/modify.c index 141f2dd8..681624c6 100644 --- a/src/modify.c +++ b/src/modify.c @@ -41,7 +41,7 @@ #include /** Private flag: Used to mark that we currently adding the root directory of - * the WIM. */ + * the WIM image. */ #define WIMLIB_ADD_IMAGE_FLAG_ROOT 0x80000000 void destroy_image_metadata(struct image_metadata *imd,struct lookup_table *lt) @@ -85,6 +85,7 @@ static int build_dentry_tree(struct dentry **root_ret, const char *root_disk_pat int ret = 0; int (*stat_fn)(const char *restrict, struct stat *restrict); struct dentry *root; + const char *filename; if (exclude_path(root_disk_path, config, true)) { if (add_flags & WIMLIB_ADD_IMAGE_FLAG_VERBOSE) @@ -117,11 +118,17 @@ static int build_dentry_tree(struct dentry **root_ret, const char *root_disk_pat } if (!S_ISREG(root_stbuf.st_mode) && !S_ISDIR(root_stbuf.st_mode) && !S_ISLNK(root_stbuf.st_mode)) { - ERROR("`%s' is not a regular file, directory, or symbolic link."); + ERROR("`%s' is not a regular file, directory, or symbolic link.", + root_disk_path); return WIMLIB_ERR_SPECIAL_FILE; } - root = new_dentry(path_basename(root_disk_path)); + if (add_flags & WIMLIB_ADD_IMAGE_FLAG_ROOT) + filename = ""; + else + filename = path_basename(root_disk_path); + + root = new_dentry(filename); if (!root) return WIMLIB_ERR_NOMEM; @@ -166,7 +173,6 @@ static int build_dentry_tree(struct dentry **root_ret, const char *root_disk_pat closedir(dir); } else if (dentry_is_symlink(root)) { /* Archiving a symbolic link */ - size_t symlink_buf_len; char deref_name_buf[4096]; ssize_t deref_name_len; @@ -186,6 +192,10 @@ static int build_dentry_tree(struct dentry **root_ret, const char *root_disk_pat struct lookup_table_entry *lte; u8 hash[SHA1_HASH_SIZE]; + /* Empty files do not have to have a lookup table entry. */ + if (root_stbuf.st_size == 0) + goto out; + /* For each regular file, we must check to see if the file is in * the lookup table already; if it is, we increment its refcnt; * otherwise, we create a new lookup table entry and insert it. @@ -219,6 +229,7 @@ static int build_dentry_tree(struct dentry **root_ret, const char *root_disk_pat } root->lte = lte; } +out: *root_ret = root; return ret; } @@ -281,6 +292,7 @@ static int add_lte_to_dest_wim(struct dentry *dentry, void *arg) * * @w: The WIMStruct for the WIM file. * @root_dentry: The root of the directory tree for the image. + * @sd: The security data for the image. */ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry, struct wim_security_data *sd) @@ -308,7 +320,7 @@ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry, lgt = new_link_group_table(9001); if (!lgt) - goto out_free_security_data; + goto out_free_metadata_lte; metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA; random_hash(metadata_lte->hash); @@ -328,8 +340,6 @@ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry, /* Change the current image to the new one. */ return wimlib_select_image(w, w->hdr.image_count); -out_free_security_data: - FREE(sd); out_free_metadata_lte: FREE(metadata_lte); out_free_imd: @@ -513,6 +523,7 @@ enum pattern_type { ALIGNMENT_LIST, }; +/* Default capture configuration file when none is specified. */ static const char *default_config = "[ExclusionList]\n" "\\$ntfs.log\n" @@ -560,6 +571,8 @@ static int pattern_list_add_pattern(struct pattern_list *list, return 0; } +/* Parses the contents of the image capture configuration file and fills in a + * `struct capture_config'. */ static int init_capture_config(const char *_config_str, size_t config_len, const char *_prefix, struct capture_config *config) { @@ -568,7 +581,6 @@ static int init_capture_config(const char *_config_str, size_t config_len, char *p; char *eol; char *next_p; - size_t next_bytes_remaining; size_t bytes_remaining; enum pattern_type type = NONE; int ret; @@ -622,6 +634,7 @@ static int init_capture_config(const char *_config_str, size_t config_len, if (eol - p > 2 && isalpha(*p) && *(p + 1) == ':') p += 2; + ret = 0; if (strcmp(p, "[ExclusionList]") == 0) type = EXCLUSION_LIST; else if (strcmp(p, "[ExclusionException]") == 0) @@ -630,7 +643,11 @@ static int init_capture_config(const char *_config_str, size_t config_len, type = COMPRESSION_EXCLUSION_LIST; else if (strcmp(p, "[AlignmentList]") == 0) type = ALIGNMENT_LIST; - else switch (type) { + else if (p[0] == '[' && strrchr(p, ']')) { + ERROR("Unknown capture configuration section `%s'", p); + ret = WIMLIB_ERR_INVALID_CAPTURE_CONFIG; + goto out_destroy; + } else switch (type) { case EXCLUSION_LIST: DEBUG("Adding pattern \"%s\" to exclusion list", p); ret = pattern_list_add_pattern(&config->exclusion_list, p); @@ -709,6 +726,15 @@ static void print_capture_config(const struct capture_config *config) } } +/* Return true if the image capture configuration file indicates we should + * exclude the filename @path from capture. + * + * If @exclude_prefix is %true, the part of the path up and including the name + * of the directory being captured is not included in the path for matching + * purposes. This allows, for example, a pattern like /hiberfil.sys to match a + * file /mnt/windows7/hiberfil.sys if we are capturing the /mnt/windows7 + * directory. + */ bool exclude_path(const char *path, const struct capture_config *config, bool exclude_prefix) { @@ -726,6 +752,18 @@ bool exclude_path(const char *path, const struct capture_config *config, +/* + * Adds an image to the WIM, delegating the capture of the dentry tree and + * security data to the function @capture_tree passed as a parameter. + * Currently, @capture_tree may be build_dentry_tree() for capturing a "regular" + * directory tree on disk, or build_dentry_tree_ntfs() for capturing a WIM image + * directory from a NTFS volume using libntfs-3g. + * + * The @capture_tree function is also expected to create lookup table entries + * for all the file streams it captures and insert them into @lookup_table, + * being careful to look for identical entries that already exist and simply + * increment the reference count for them rather than duplicating the entry. + */ int do_add_image(WIMStruct *w, const char *dir, const char *name, const char *config_str, size_t config_len, int flags, @@ -737,19 +775,19 @@ int do_add_image(WIMStruct *w, const char *dir, const char *name, void *extra_arg) { struct dentry *root_dentry = NULL; - struct image_metadata *imd; struct wim_security_data *sd; struct capture_config config; + struct link_group_table *lgt; int ret; - DEBUG("Adding dentry tree from dir `%s'.", dir); + DEBUG("Adding dentry tree from directory or NTFS volume `%s'.", dir); if (!name || !*name) { ERROR("Must specify a non-empty string for the image name"); return WIMLIB_ERR_INVALID_PARAM; } if (!dir) { - ERROR("Must specify the name of a directory"); + ERROR("Must specify the name of a directory or NTFS volume"); return WIMLIB_ERR_INVALID_PARAM; } @@ -798,13 +836,20 @@ int do_add_image(WIMStruct *w, const char *dir, const char *name, if (ret != 0) goto out_free_dentry_tree; + lgt = w->image_metadata[w->hdr.image_count - 1].lgt; DEBUG("Inserting dentries into hard link group table"); - ret = for_dentry_in_tree(root_dentry, link_group_table_insert, - w->image_metadata[w->hdr.image_count - 1].lgt); + ret = for_dentry_in_tree(root_dentry, link_group_table_insert, lgt); + if (ret != 0) goto out_destroy_imd; - DEBUG("Assigning hard link groups"); - assign_link_groups(w->image_metadata[w->hdr.image_count - 1].lgt); + + DEBUG("Cleanup up the hard link groups"); + ret = fix_link_groups(lgt); + if (ret != 0) + goto out_destroy_imd; + + DEBUG("Assigning hard link group IDs"); + assign_link_group_ids(w->image_metadata[w->hdr.image_count - 1].lgt); if (flags & WIMLIB_ADD_IMAGE_FLAG_BOOT) wimlib_set_boot_idx(w, w->hdr.image_count); @@ -821,7 +866,6 @@ out_destroy_imd: return ret; out_free_dentry_tree: free_dentry_tree(root_dentry, w->lookup_table); -out_free_sd: free_security_data(sd); out_destroy_config: destroy_capture_config(&config);