From: Eric Biggers Date: Thu, 22 Nov 2012 19:58:41 +0000 (-0600) Subject: Various changes/fixes X-Git-Tag: v1.2.0~6 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=c79590300def03992af2062d97afebade0fc4fdf Various changes/fixes --- diff --git a/src/extract.c b/src/extract.c index a3942cf7..8e809608 100644 --- a/src/extract.c +++ b/src/extract.c @@ -433,12 +433,8 @@ static void calculate_bytes_to_extract(struct list_head *stream_list, total_bytes += wim_resource_size(lte); } } else { - list_for_each_entry(inode, <e->inode_list, - lte_inode_list) - { - num_streams++; - total_bytes += wim_resource_size(lte); - } + num_streams += lte->out_refcnt; + total_bytes += lte->out_refcnt * wim_resource_size(lte); } } progress->extract.num_streams = num_streams; @@ -449,8 +445,7 @@ static void calculate_bytes_to_extract(struct list_head *stream_list, static void maybe_add_stream_for_extraction(struct lookup_table_entry *lte, struct list_head *stream_list) { - if (lte->out_refcnt == 0) { - lte->out_refcnt = 1; + if (++lte->out_refcnt == 1) { INIT_LIST_HEAD(<e->inode_list); list_add_tail(<e->staging_list, stream_list); } @@ -474,7 +469,7 @@ static void inode_find_streams_for_extraction(struct inode *inode, if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) { for (unsigned i = 0; i < inode->num_ads; i++) { if (inode->ads_entries[i].stream_name_len != 0) { - lte = inode_stream_lte_resolved(inode, i + 1); + lte = inode->ads_entries[i].lte; if (lte) { maybe_add_stream_for_extraction(lte, stream_list); @@ -523,8 +518,8 @@ static const struct apply_operations normal_apply_operations = { #ifdef WITH_NTFS_3G static const struct apply_operations ntfs_apply_operations = { - .apply_dentry = wim_apply_dentry_ntfs, - .apply_dentry_timestamps = wim_apply_dentry_timestamps, + .apply_dentry = apply_dentry_ntfs, + .apply_dentry_timestamps = apply_dentry_timestamps_ntfs, }; #endif @@ -539,8 +534,17 @@ static int apply_stream_list(struct list_head *stream_list, struct inode *inode; struct dentry *dentry; int ret = 0; + + /* This complicated loop is actually just looping through the dentries + * (as for_dentry_in_tree() does), but the outer loop is actually over + * the distinct streams to be extracted so that sequential reading of + * the WIM can be implemented. */ + + /* For each distinct stream to be extracted */ list_for_each_entry(lte, stream_list, staging_list) { + /* For each inode that contains the stream */ list_for_each_entry(inode, <e->inode_list, lte_inode_list) { + /* For each dentry that points to the inode */ inode_for_each_dentry(dentry, inode) { ret = ops->apply_dentry(dentry, args); if (ret != 0) @@ -589,13 +593,8 @@ static int extract_single_image(WIMStruct *w, int image, ERROR_WITH_ERRNO("Failed to mount NTFS volume `%s'", target); return WIMLIB_ERR_NTFS_3G; } - } -#endif - -#ifdef WITH_NTFS_3G - if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) ops = &ntfs_apply_operations; - else + } else #endif ops = &normal_apply_operations; @@ -604,10 +603,9 @@ static int extract_single_image(WIMStruct *w, int image, goto out; inode_list = &w->image_metadata[image - 1].inode_list; - find_streams_for_extraction(inode_list, - &stream_list, - w->lookup_table, - extract_flags); + + find_streams_for_extraction(inode_list, &stream_list, + w->lookup_table, extract_flags); calculate_bytes_to_extract(&stream_list, extract_flags, &args.progress); @@ -630,7 +628,6 @@ static int extract_single_image(WIMStruct *w, int image, &args.progress); } - args.extract_flags |= WIMLIB_EXTRACT_FLAG_NO_STREAMS; ret = for_dentry_in_tree(wim_root_dentry(w), ops->apply_dentry, &args); args.extract_flags &= ~WIMLIB_EXTRACT_FLAG_NO_STREAMS; @@ -730,8 +727,8 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image, if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) { #ifdef WITH_NTFS_3G if ((extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK))) { - ERROR("Cannot specify symlink or hardlink flags when applying "); - ERROR("directly to a NTFS volume"); + ERROR("Cannot specify symlink or hardlink flags when applying\n" + " directly to a NTFS volume"); return WIMLIB_ERR_INVALID_PARAM; } if (image == WIMLIB_ALL_IMAGES) { diff --git a/src/mount.c b/src/mount.c index b0d256e2..0122d848 100644 --- a/src/mount.c +++ b/src/mount.c @@ -2018,8 +2018,8 @@ WIMLIBAPI int wimlib_mount_image(WIMStruct *wim, int image, const char *dir, /* Mark dentry tree as modified if read-write mount. */ if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) { - imd->modified = true; - imd->has_been_mounted_rw = true; + imd->modified = 1; + imd->has_been_mounted_rw = 1; } /* Resolve all the lookup table entries of the dentry tree */ diff --git a/src/ntfs-apply.c b/src/ntfs-apply.c index 7522ec89..1113a832 100644 --- a/src/ntfs-apply.c +++ b/src/ntfs-apply.c @@ -161,10 +161,10 @@ static int write_ntfs_data_streams(ntfs_inode *ni, const struct dentry *dentry, * * Return 0 on success, nonzero on failure. */ -static int wim_apply_hardlink_ntfs(const struct dentry *from_dentry, - const struct inode *inode, - ntfs_inode *dir_ni, - ntfs_inode **to_ni_ret) +static int apply_hardlink_ntfs(const struct dentry *from_dentry, + const struct inode *inode, + ntfs_inode *dir_ni, + ntfs_inode **to_ni_ret) { int ret; char *p; @@ -313,8 +313,8 @@ static int apply_reparse_data(ntfs_inode *ni, const struct dentry *dentry, return 0; } -static int do_wim_apply_dentry_ntfs(struct dentry *dentry, ntfs_inode *dir_ni, - struct apply_args *args); +static int do_apply_dentry_ntfs(struct dentry *dentry, ntfs_inode *dir_ni, + struct apply_args *args); /* * If @dentry is part of a hard link group, search for hard-linked dentries in @@ -355,8 +355,8 @@ static int preapply_dentry_with_dos_name(struct dentry *dentry, DEBUG("pre-applying DOS name `%s'", dentry_with_dos_name->full_path_utf8); - ret = do_wim_apply_dentry_ntfs(dentry_with_dos_name, - *dir_ni_p, args); + ret = do_apply_dentry_ntfs(dentry_with_dos_name, + *dir_ni_p, args); if (ret != 0) return ret; p = dentry->full_path_utf8 + dentry->full_path_utf8_len; @@ -387,8 +387,8 @@ static int preapply_dentry_with_dos_name(struct dentry *dentry, * * @return: 0 on success; nonzero on failure. */ -static int do_wim_apply_dentry_ntfs(struct dentry *dentry, ntfs_inode *dir_ni, - struct apply_args *args) +static int do_apply_dentry_ntfs(struct dentry *dentry, ntfs_inode *dir_ni, + struct apply_args *args) { int ret = 0; mode_t type; @@ -417,8 +417,8 @@ static int do_wim_apply_dentry_ntfs(struct dentry *dentry, ntfs_inode *dir_ni, * group. We can make a hard link instead of extracting * the file data. */ if (inode->extracted_file) { - ret = wim_apply_hardlink_ntfs(dentry, inode, - dir_ni, &ni); + ret = apply_hardlink_ntfs(dentry, inode, + dir_ni, &ni); is_hardlink = true; if (ret) goto out_close_dir_ni; @@ -559,9 +559,8 @@ out_close_dir_ni: return ret; } -static int wim_apply_root_dentry_ntfs(const struct dentry *dentry, - ntfs_volume *vol, - const WIMStruct *w) +static int apply_root_dentry_ntfs(const struct dentry *dentry, + ntfs_volume *vol, const WIMStruct *w) { ntfs_inode *ni; int ret = 0; @@ -582,7 +581,7 @@ static int wim_apply_root_dentry_ntfs(const struct dentry *dentry, } /* Applies a WIM dentry to the NTFS volume */ -int wim_apply_dentry_ntfs(struct dentry *dentry, void *arg) +int apply_dentry_ntfs(struct dentry *dentry, void *arg) { struct apply_args *args = arg; ntfs_volume *vol = args->vol; @@ -600,7 +599,6 @@ int wim_apply_dentry_ntfs(struct dentry *dentry, void *arg) if (inode_unnamed_lte_resolved(dentry->d_inode)) return 0; - DEBUG("Applying dentry `%s' to NTFS", dentry->full_path_utf8); if ((extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) && @@ -612,7 +610,7 @@ int wim_apply_dentry_ntfs(struct dentry *dentry, void *arg) } if (dentry_is_root(dentry)) - return wim_apply_root_dentry_ntfs(dentry, vol, w); + return apply_root_dentry_ntfs(dentry, vol, w); p = dentry->full_path_utf8 + dentry->full_path_utf8_len; do { @@ -630,10 +628,10 @@ int wim_apply_dentry_ntfs(struct dentry *dentry, void *arg) dir_name); return WIMLIB_ERR_NTFS_3G; } - return do_wim_apply_dentry_ntfs(dentry, dir_ni, arg); + return do_apply_dentry_ntfs(dentry, dir_ni, arg); } -int wim_apply_dentry_timestamps(struct dentry *dentry, void *arg) +int apply_dentry_timestamps_ntfs(struct dentry *dentry, void *arg) { struct apply_args *args = arg; ntfs_volume *vol = args->vol; diff --git a/src/split.c b/src/split.c index 091fa3fe..649a9bf2 100644 --- a/src/split.c +++ b/src/split.c @@ -245,6 +245,7 @@ WIMLIBAPI int wimlib_split(WIMStruct *w, const char *swm_name, } } out: + close_wim_writable(w); memcpy(&w->hdr, &hdr_save, sizeof(struct wim_header)); return ret; } diff --git a/src/wim.c b/src/wim.c index 44653f19..cd024b18 100644 --- a/src/wim.c +++ b/src/wim.c @@ -225,6 +225,7 @@ int select_wim_image(WIMStruct *w, int image) destroy_image_metadata(imd, NULL); imd->root_dentry = NULL; imd->security_data = NULL; + INIT_HLIST_HEAD(&imd->inode_list); } } @@ -419,21 +420,6 @@ WIMLIBAPI int wimlib_get_boot_idx(const WIMStruct *w) return w->hdr.boot_idx; } -/* Opens a WIM readable */ -static int open_wim_readable(WIMStruct *w, const char *path) -{ - if (w->fp != NULL) - fclose(w->fp); - wimlib_assert(path != NULL); - w->fp = fopen(path, "rb"); - if (!w->fp) { - ERROR_WITH_ERRNO("Failed to open `%s' for reading", - path); - return WIMLIB_ERR_OPEN; - } - return 0; -} - /* * Begins the reading of a WIM file; opens the file and reads its header and * lookup table, and optionally checks the integrity. @@ -446,10 +432,22 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags, DEBUG("Reading the WIM file `%s'", in_wim_path); - ret = open_wim_readable(w, in_wim_path); - if (ret != 0) - goto out; + w->fp = fopen(in_wim_path, "rb"); + if (!w->fp) { + ERROR_WITH_ERRNO("Failed to open `%s' for reading", + in_wim_path); + return WIMLIB_ERR_OPEN; + } + /* The absolute path to the WIM is requested so that wimlib_overwrite() + * still works even if the process changes its working directory. This + * actually happens if a WIM is mounted read-write, since the FUSE + * thread changes directory to "/", and it needs to be able to find the + * WIM file again. + * + * This will break if the full path to the WIM changes in the + * intervening time... + */ w->filename = realpath(in_wim_path, NULL); if (!w->filename) { ERROR_WITH_ERRNO("Failed to resolve WIM filename"); @@ -597,7 +595,8 @@ WIMLIBAPI int wimlib_open_wim(const char *wim_file, int open_flags, WIMStruct *w; int ret; - DEBUG("wim_file = `%s', open_flags = %#x", wim_file, open_flags); + if (!wim_file || !w_ret) + return WIMLIB_ERR_INVALID_PARAM; w = new_wim_struct(); if (!w) { ERROR("Failed to allocate memory for WIMStruct"); diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index 9b8c6b72..840348d4 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -250,7 +250,6 @@ struct image_metadata { * the case, the memory for the filesystem is not freed when switching * to a different WIM image. */ u8 modified : 1; - u8 has_been_mounted_rw : 1; }; @@ -457,8 +456,8 @@ struct apply_args { wimlib_progress_func_t progress_func; }; -extern int wim_apply_dentry_ntfs(struct dentry *dentry, void *arg); -extern int wim_apply_dentry_timestamps(struct dentry *dentry, void *arg); +extern int apply_dentry_ntfs(struct dentry *dentry, void *arg); +extern int apply_dentry_timestamps_ntfs(struct dentry *dentry, void *arg); /* ntfs-capture.c */ extern int build_dentry_tree_ntfs(struct dentry **root_p, @@ -541,6 +540,7 @@ extern int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *)); /* write.c */ extern int begin_write(WIMStruct *w, const char *path, int write_flags); +extern void close_wim_writable(WIMStruct *w); extern int finish_write(WIMStruct *w, int image, int write_flags, wimlib_progress_func_t progress_func); diff --git a/src/write.c b/src/write.c index 5b586cee..061f0e7b 100644 --- a/src/write.c +++ b/src/write.c @@ -1529,7 +1529,6 @@ static int open_wim_writable(WIMStruct *w, const char *path, bool trunc, bool readable) { const char *mode; - int ret = 0; if (trunc) if (readable) mode = "w+b"; @@ -1538,26 +1537,18 @@ static int open_wim_writable(WIMStruct *w, const char *path, else mode = "r+b"; - DEBUG("Opening `%s' read-write", path); wimlib_assert(w->out_fp == NULL); - wimlib_assert(path != NULL); w->out_fp = fopen(path, mode); - if (!w->out_fp) { + if (w->out_fp) { + return 0; + } else { ERROR_WITH_ERRNO("Failed to open `%s' for writing", path); return WIMLIB_ERR_OPEN; } - if (trunc) { - ret = lock_wim(w->out_fp, path); - if (ret != 0) { - fclose(w->out_fp); - w->out_fp = NULL; - } - } - return ret; } -static void close_wim_writable(WIMStruct *w) +void close_wim_writable(WIMStruct *w) { if (w->out_fp) { if (fclose(w->out_fp) != 0) { @@ -1572,12 +1563,8 @@ static void close_wim_writable(WIMStruct *w) int begin_write(WIMStruct *w, const char *path, int write_flags) { int ret; - bool need_readable = false; - bool trunc = true; - if (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) - need_readable = true; - - ret = open_wim_writable(w, path, trunc, need_readable); + ret = open_wim_writable(w, path, true, + (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) != 0); if (ret != 0) return ret; /* Write dummy header. It will be overwritten later. */ @@ -1751,10 +1738,6 @@ static int overwrite_wim_inplace(WIMStruct *w, int write_flags, INIT_LIST_HEAD(&stream_list); for (int i = modified_image_idx; i < w->hdr.image_count; i++) { DEBUG("Identifiying streams in image %d", i + 1); - wimlib_assert(w->image_metadata[i].modified); - wimlib_assert(!w->image_metadata[i].has_been_mounted_rw); - wimlib_assert(w->image_metadata[i].root_dentry != NULL); - wimlib_assert(w->image_metadata[i].metadata_lte != NULL); w->private = &stream_list; for_dentry_in_tree(w->image_metadata[i].root_dentry, dentry_find_streams_to_write, w); @@ -1773,7 +1756,6 @@ static int overwrite_wim_inplace(WIMStruct *w, int write_flags, if (modified_image_idx == w->hdr.image_count && !w->deletion_occurred) { /* If no images have been modified and no images have been * deleted, a new lookup table does not need to be written. */ - wimlib_assert(list_empty(&stream_list)); old_wim_end = w->hdr.lookup_table_res_entry.offset + w->hdr.lookup_table_res_entry.size; write_flags |= WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE | @@ -1789,9 +1771,17 @@ static int overwrite_wim_inplace(WIMStruct *w, int write_flags, if (ret != 0) return ret; + ret = lock_wim(w->out_fp, w->filename); + if (ret != 0) { + fclose(w->out_fp); + w->out_fp = NULL; + return ret; + } + if (fseeko(w->out_fp, old_wim_end, SEEK_SET) != 0) { ERROR_WITH_ERRNO("Can't seek to end of WIM"); - return WIMLIB_ERR_WRITE; + ret = WIMLIB_ERR_WRITE; + goto out_ftruncate; } if (!list_empty(&stream_list)) { @@ -1851,12 +1841,6 @@ static int overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags, goto err; } - /* Close the original WIM file that was opened for reading. */ - if (w->fp != NULL) { - fclose(w->fp); - w->fp = NULL; - } - DEBUG("Renaming `%s' to `%s'", tmpfile, w->filename); /* Rename the new file to the old file .*/ @@ -1874,12 +1858,20 @@ static int overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags, progress_func(WIMLIB_PROGRESS_MSG_RENAME, &progress); } + /* Close the original WIM file that was opened for reading. */ + if (w->fp != NULL) { + fclose(w->fp); + w->fp = NULL; + } + /* Re-open the WIM read-only. */ w->fp = fopen(w->filename, "rb"); if (w->fp == NULL) { ret = WIMLIB_ERR_REOPEN; WARNING("Failed to re-open `%s' read-only: %s", w->filename, strerror(errno)); + FREE(w->filename); + w->filename = NULL; } return ret; err: