Misc. fixes
authorEric Biggers <ebiggers3@gmail.com>
Sun, 21 Apr 2013 21:57:30 +0000 (16:57 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 21 Apr 2013 21:57:30 +0000 (16:57 -0500)
14 files changed:
src/dentry.c
src/extract_image.c
src/hardlink.c
src/lookup_table.c
src/lookup_table.h
src/mount_image.c
src/ntfs-apply.c
src/ntfs-capture.c
src/resource.c
src/sha1.h
src/wim.c
src/wimlib_internal.h
src/win32.c
src/write.c

index b0ebf64..5b19f6f 100644 (file)
@@ -589,9 +589,6 @@ print_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
        if (ret)
                return ret;
        tprintf(T("%"TS"\n"), dentry->_full_path);
-       FREE(dentry->_full_path);
-       dentry->_full_path = NULL;
-       dentry->full_path_nbytes = 0;
        return 0;
 }
 
@@ -1211,6 +1208,29 @@ inode_set_unix_data(struct wim_inode *inode, uid_t uid, gid_t gid, mode_t mode,
 }
 #endif /* !__WIN32__ */
 
+static void
+replace_forbidden_characters(utf16lechar *name)
+{
+       utf16lechar *p;
+
+       for (p = name; *p; p++) {
+       #ifdef __WIN32__
+               if (wcschr(L"<>:\"/\\|?*", (wchar_t)*p))
+       #else
+               if (*p == '/') {
+       #endif
+                       if (name) {
+                               WARNING("File, directory, or stream name \"%"WS"\"\n"
+                                       "          contains forbidden characters; "
+                                       "replacing them with Unicode codepoint U+001A",
+                                       name);
+                               name = NULL;
+                       }
+                       *p = 0x1a;
+               }
+       }
+}
+
 /*
  * Reads the alternate data stream entries of a WIM dentry.
  *
@@ -1338,6 +1358,7 @@ read_ads_entries(const u8 *p, struct wim_inode *inode, u64 remaining_size)
                        get_bytes(p, cur_entry->stream_name_nbytes,
                                  cur_entry->stream_name);
                        cur_entry->stream_name[cur_entry->stream_name_nbytes / 2] = 0;
+                       replace_forbidden_characters(cur_entry->stream_name);
                }
                /* It's expected that the size of every ADS entry is a multiple
                 * of 8.  However, to be safe, I'm allowing the possibility of
@@ -1511,6 +1532,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                        WARNING("File name in WIM dentry \"%"WS"\" is not "
                                "null-terminated!", file_name);
                }
+               replace_forbidden_characters(file_name);
        }
 
        /* Align the calculated size */
@@ -1561,6 +1583,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                        WARNING("Short name in WIM dentry \"%"WS"\" is not "
                                "null-terminated!", file_name);
                }
+               replace_forbidden_characters(short_name);
        }
 
        /*
index 8941b0e..fffdcfd 100644 (file)
@@ -898,7 +898,7 @@ out:
        return ret;
 }
 
-static const tchar *filename_forbidden_chars =
+static const tchar * const filename_forbidden_chars =
 T(
 #ifdef __WIN32__
 "<>:\"/\\|?*"
index b2d3309..f806c7f 100644 (file)
@@ -159,11 +159,6 @@ inode_ref_streams(struct wim_inode *inode)
        }
 }
 
-void
-inode_add_link(struct wim_inode *inode, struct wim_dentry *dentry)
-{
-}
-
 /* Given a directory entry with the name @name for the file with the inode
  * number @ino and device number @devno, create a new WIM dentry with an
  * associated inode, where the inode is shared if an inode with the same @ino
index f22bfaf..c6b45fe 100644 (file)
@@ -865,6 +865,34 @@ inode_stream_lte(const struct wim_inode *inode, unsigned stream_idx,
                return inode_stream_lte_unresolved(inode, stream_idx, table);
 }
 
+struct wim_lookup_table_entry *
+inode_unnamed_lte_resolved(const struct wim_inode *inode)
+{
+       wimlib_assert(inode->i_resolved);
+       for (unsigned i = 0; i <= inode->i_num_ads; i++) {
+               if (inode_stream_name_nbytes(inode, i) == 0 &&
+                   !is_zero_hash(inode_stream_hash_resolved(inode, i)))
+               {
+                       return inode_stream_lte_resolved(inode, i);
+               }
+       }
+       return NULL;
+}
+
+struct wim_lookup_table_entry *
+inode_unnamed_lte_unresolved(const struct wim_inode *inode,
+                            const struct wim_lookup_table *table)
+{
+       wimlib_assert(!inode->i_resolved);
+       for (unsigned i = 0; i <= inode->i_num_ads; i++) {
+               if (inode_stream_name_nbytes(inode, i) == 0 &&
+                   !is_zero_hash(inode_stream_hash_unresolved(inode, i)))
+               {
+                       return inode_stream_lte_unresolved(inode, i, table);
+               }
+       }
+       return NULL;
+}
 
 /* Return the lookup table entry for the unnamed data stream of an inode, or
  * NULL if there is none.
index 2a6bf89..d9d8959 100644 (file)
@@ -63,11 +63,9 @@ enum resource_location {
         * WIM file will be pointed to by the @wim member. */
        RESOURCE_IN_WIM,
 
-       /* The stream resource is located in an external file.  The name of the
-        * file will be provided by @file_on_disk member.  In addition, if
-        * @file_on_disk_fp is not NULL, it will be an open FILE * to the file.
-        * */
 #ifndef __WIN32__
+       /* The stream resource is located in an external file.  The name of the
+        * file will be provided by @file_on_disk member. */
        RESOURCE_IN_FILE_ON_DISK,
 #endif
 
@@ -143,9 +141,10 @@ struct wim_lookup_table_entry {
        /* 1 if this stream is a unique size (only set while writing streams). */
        u8 unique_size : 1;
 
-       /* 1 if this stream had a SHA1-message digest calculated for it yet? */
+       /* 1 if this stream has not had a SHA1 message digest calculated for it
+        * yet */
        u8 unhashed : 1;
-       
+
        u8 deferred : 1;
 
        u8 no_progress : 1;
@@ -222,10 +221,10 @@ struct wim_lookup_table_entry {
        union {
                /* When a WIM file is written, @output_resource_entry is filled
                 * in with the resource entry for the output WIM.  This will not
-                * necessarily be the same as the @resource_entry since: - The
-                * stream may have a different offset in the new WIM - The
-                * stream may have a different compressed size in the new WIM if
-                * the compression type changed
+                * necessarily be the same as the @resource_entry since:
+                * - The stream may have a different offset in the new WIM
+                * - The stream may have a different compressed size in the new
+                *   WIM if the compression type changed
                 */
                struct resource_entry output_resource_entry;
 
@@ -464,34 +463,12 @@ inode_stream_name_nbytes(const struct wim_inode *inode, unsigned stream_idx)
                return inode->i_ads_entries[stream_idx - 1].stream_name_nbytes;
 }
 
-static inline struct wim_lookup_table_entry *
-inode_unnamed_lte_resolved(const struct wim_inode *inode)
-{
-       wimlib_assert(inode->i_resolved);
-       for (unsigned i = 0; i <= inode->i_num_ads; i++) {
-               if (inode_stream_name_nbytes(inode, i) == 0 &&
-                   !is_zero_hash(inode_stream_hash_resolved(inode, i)))
-               {
-                       return inode_stream_lte_resolved(inode, i);
-               }
-       }
-       return NULL;
-}
+extern struct wim_lookup_table_entry *
+inode_unnamed_lte_resolved(const struct wim_inode *inode);
 
-static inline struct wim_lookup_table_entry *
+extern struct wim_lookup_table_entry *
 inode_unnamed_lte_unresolved(const struct wim_inode *inode,
-                            const struct wim_lookup_table *table)
-{
-       wimlib_assert(!inode->i_resolved);
-       for (unsigned i = 0; i <= inode->i_num_ads; i++) {
-               if (inode_stream_name_nbytes(inode, i) == 0 &&
-                   !is_zero_hash(inode_stream_hash_unresolved(inode, i)))
-               {
-                       return inode_stream_lte_unresolved(inode, i, table);
-               }
-       }
-       return NULL;
-}
+                            const struct wim_lookup_table *table);
 
 extern struct wim_lookup_table_entry *
 inode_unnamed_lte(const struct wim_inode *inode, const struct wim_lookup_table *table);
index a83c6ba..7856201 100644 (file)
@@ -160,6 +160,54 @@ flags_writable(int open_flags)
        return open_flags & (O_RDWR | O_WRONLY);
 }
 
+/* Like pread(), but keep trying until everything has been read or we know for
+ * sure that there was an error. */
+static ssize_t
+full_pread(int fd, void *buf, size_t count, off_t offset)
+{
+       ssize_t bytes_remaining = count;
+       ssize_t bytes_read;
+
+       while (bytes_remaining > 0) {
+               bytes_read = pread(fd, buf, bytes_remaining, offset);
+               if (bytes_read <= 0) {
+                       if (bytes_read < 0) {
+                               if (errno == EINTR)
+                                       continue;
+                       } else {
+                               errno = EIO;
+                       }
+                       break;
+               }
+               bytes_remaining -= bytes_read;
+               buf += bytes_read;
+               offset += bytes_read;
+       }
+       return count - bytes_remaining;
+}
+
+/* Like pwrite(), but keep trying until everything has been written or we know
+ * for sure that there was an error. */
+static ssize_t
+full_pwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+       ssize_t bytes_remaining = count;
+       ssize_t bytes_written;
+
+       while (bytes_remaining > 0) {
+               bytes_written = pwrite(fd, buf, bytes_remaining, offset);
+               if (bytes_written < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       break;
+               }
+               bytes_remaining -= bytes_written;
+               buf += bytes_written;
+               offset += bytes_written;
+       }
+       return count - bytes_remaining;
+}
+
 /*
  * Allocate a file descriptor for a stream.
  *
@@ -649,6 +697,7 @@ extract_resource_to_staging_dir(struct wim_inode *inode,
 
        lookup_table_insert_unhashed(ctx->wim->lookup_table, new_lte,
                                     inode, stream_id);
+       *retrieve_lte_pointer(new_lte) = new_lte;
        *lte = new_lte;
        return 0;
 out_revert_fd_changes:
@@ -804,7 +853,6 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags,
        image_for_each_unhashed_stream_safe(lte, tmp, imd) {
                wimlib_assert(lte->unhashed);
                if (wim_resource_size(lte) == 0) {
-                       print_lookup_table_entry(lte, stderr);
                        struct wim_lookup_table_entry **back_ptr;
                        back_ptr = retrieve_lte_pointer(lte);
                        *back_ptr = NULL;
@@ -1493,13 +1541,6 @@ execute_fusermount(const char *dir)
        return 0;
 }
 
-#if 0
-static int wimfs_access(const char *path, int mask)
-{
-       return -ENOSYS;
-}
-#endif
-
 static int
 wimfs_chmod(const char *path, mode_t mask)
 {
@@ -1561,17 +1602,6 @@ wimfs_destroy(void *p)
        }
 }
 
-#if 0
-static int wimfs_fallocate(const char *path, int mode,
-                          off_t offset, off_t len, struct fuse_file_info *fi)
-{
-       struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
-       wimlib_assert(fd->staging_fd != -1);
-       return fallocate(fd->staging_fd, mode, offset, len);
-}
-
-#endif
-
 static int
 wimfs_fgetattr(const char *path, struct stat *stbuf,
               struct fuse_file_info *fi)
@@ -1809,7 +1839,7 @@ wimfs_open(const char *path, struct fuse_file_info *fi)
 
        ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx),
                              &dentry, &lte, &stream_idx);
-       if (ret != 0)
+       if (ret)
                return ret;
 
        inode = dentry->d_inode;
@@ -1834,15 +1864,14 @@ wimfs_open(const char *path, struct fuse_file_info *fi)
                u64 size = (lte) ? wim_resource_size(lte) : 0;
                ret = extract_resource_to_staging_dir(inode, stream_id,
                                                      &lte, size, ctx);
-               if (ret != 0)
+               if (ret)
                        return ret;
                *back_ptr = lte;
        }
-       print_lookup_table_entry(lte, stderr);
 
        ret = alloc_wimfs_fd(inode, stream_id, lte, &fd,
                             wimfs_ctx_readonly(ctx));
-       if (ret != 0)
+       if (ret)
                return ret;
 
        if (lte && lte->resource_location == RESOURCE_IN_STAGING_FILE) {
@@ -1892,26 +1921,33 @@ wimfs_read(const char *path, char *buf, size_t size,
        if (!fd)
                return -EBADF;
 
-       if (!fd->f_lte) /* Empty stream with no lookup table entry */
+       if (size == 0)
                return 0;
 
-       res_size = wim_resource_size(fd->f_lte);
+       if (fd->f_lte)
+               res_size = wim_resource_size(fd->f_lte);
+       else
+               res_size = 0;
+
        if (offset > res_size)
                return -EOVERFLOW;
-       size = min(size, INT_MAX);
+
        size = min(size, res_size - offset);
+       if (size == 0)
+               return 0;
 
        switch (fd->f_lte->resource_location) {
        case RESOURCE_IN_STAGING_FILE:
-               ret = pread(fd->staging_fd, buf, size, offset);
-               if (ret < 0)
+               ret = full_pread(fd->staging_fd, buf, size, offset);
+               if (ret != size)
                        ret = -errno;
                break;
        case RESOURCE_IN_WIM:
                if (read_partial_wim_resource_into_buf(fd->f_lte, size,
                                                       offset, buf, true))
                        ret = -errno;
-               ret = size;
+               else
+                       ret = size;
                break;
        case RESOURCE_IN_ATTACHED_BUFFER:
                memcpy(buf, fd->f_lte->attached_buffer + offset, size);
@@ -2216,13 +2252,19 @@ wimfs_truncate(const char *path, off_t size)
        } else {
                /* File in WIM.  Extract it to the staging directory, but only
                 * the first @size bytes of it. */
+               struct wim_lookup_table_entry **back_ptr;
+
                inode = dentry->d_inode;
-               if (stream_idx == 0)
+               if (stream_idx == 0) {
                        stream_id = 0;
-               else
+                       back_ptr = &inode->i_lte;
+               } else {
                        stream_id = inode->i_ads_entries[stream_idx - 1].stream_id;
+                       back_ptr = &inode->i_ads_entries[stream_idx - 1].lte;
+               }
                ret = extract_resource_to_staging_dir(inode, stream_id,
                                                      &lte, size, ctx);
+               *back_ptr = lte;
        }
        return ret;
 }
@@ -2321,8 +2363,8 @@ wimfs_write(const char *path, const char *buf, size_t size,
        wimlib_assert(fd->f_inode != NULL);
 
        /* Write the data. */
-       ret = pwrite(fd->staging_fd, buf, size, offset);
-       if (ret == -1)
+       ret = full_pwrite(fd->staging_fd, buf, size, offset);
+       if (ret != size)
                return -errno;
 
        /* Update file size */
@@ -2339,15 +2381,9 @@ wimfs_write(const char *path, const char *buf, size_t size,
 }
 
 static struct fuse_operations wimfs_operations = {
-#if 0
-       .access      = wimfs_access,
-#endif
        .chmod       = wimfs_chmod,
        .chown       = wimfs_chown,
        .destroy     = wimfs_destroy,
-#if 0
-       .fallocate   = wimfs_fallocate,
-#endif
        .fgetattr    = wimfs_fgetattr,
        .ftruncate   = wimfs_ftruncate,
        .getattr     = wimfs_getattr,
index 1e3ec48..b9f6bf2 100644 (file)
@@ -102,13 +102,19 @@ write_ntfs_data_streams(ntfs_inode *ni, struct wim_dentry *dentry,
        const struct wim_inode *inode = dentry->d_inode;
        struct wim_lookup_table_entry *lte;
 
+       lte = inode->i_lte;
+
+       /* For directories, skip unnamed streams; just extract alternate data
+        * streams. */
+       if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
+               goto cont;
+
        DEBUG("Writing %u NTFS data stream%s for `%s'",
              inode->i_num_ads + 1,
              (inode->i_num_ads == 0 ? "" : "s"),
              dentry->_full_path);
 
-       lte = inode->i_lte;
-       while (1) {
+       for (;;) {
                if (stream_name_nbytes) {
                        /* Skip special UNIX data entries (see documentation for
                         * WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA) */
@@ -121,7 +127,7 @@ write_ntfs_data_streams(ntfs_inode *ni, struct wim_dentry *dentry,
                        /* Create an empty named stream. */
                        ret = ntfs_attr_add(ni, AT_DATA, stream_name,
                                            stream_name_nbytes / 2, NULL, 0);
-                       if (ret != 0) {
+                       if (ret) {
                                ERROR_WITH_ERRNO("Failed to create named data "
                                                 "stream for extracted file "
                                                 "`%s'",
@@ -151,7 +157,7 @@ write_ntfs_data_streams(ntfs_inode *ni, struct wim_dentry *dentry,
                         * length, so the NTFS attribute should be resized to
                         * this length before starting to extract the data. */
                        ret = ntfs_attr_truncate_solid(na, wim_resource_size(lte));
-                       if (ret != 0) {
+                       if (ret) {
                                ntfs_attr_close(na);
                                break;
                        }
@@ -161,7 +167,7 @@ write_ntfs_data_streams(ntfs_inode *ni, struct wim_dentry *dentry,
 
                        /* Close the attribute */
                        ntfs_attr_close(na);
-                       if (ret != 0)
+                       if (ret)
                                break;
 
                        /* Record the number of bytes of uncompressed data that
@@ -304,13 +310,12 @@ apply_file_attributes_and_security_data(ntfs_inode *ni,
                                         ni, dir_ni,
                                         (const char*)&attributes_le32,
                                         sizeof(u32), 0);
-       if (ret != 0) {
+       if (ret) {
                ERROR("Failed to set NTFS file attributes on `%s'",
                      dentry->_full_path);
-               return WIMLIB_ERR_NTFS_3G;
-       }
-       if (inode->i_security_id != -1 &&
-           !(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS))
+               ret = WIMLIB_ERR_NTFS_3G;
+       } else if (inode->i_security_id != -1 &&
+                  !(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS))
        {
                const char *desc;
                const struct wim_security_data *sd;
@@ -325,13 +330,13 @@ apply_file_attributes_and_security_data(ntfs_inode *ni,
                                                 ni, dir_ni, desc,
                                                 sd->sizes[inode->i_security_id], 0);
 
-               if (ret != 0) {
+               if (ret) {
                        ERROR_WITH_ERRNO("Failed to set security data on `%s'",
                                        dentry->_full_path);
-                       return WIMLIB_ERR_NTFS_3G;
+                       ret = WIMLIB_ERR_NTFS_3G;
                }
        }
-       return 0;
+       return ret;
 }
 
 /*
@@ -343,7 +348,7 @@ apply_reparse_data(ntfs_inode *ni, struct wim_dentry *dentry,
                   union wimlib_progress_info *progress_info)
 {
        struct wim_lookup_table_entry *lte;
-       int ret = 0;
+       int ret;
 
        lte = inode_unnamed_lte_resolved(dentry->d_inode);
 
@@ -355,7 +360,9 @@ apply_reparse_data(ntfs_inode *ni, struct wim_dentry *dentry,
                return WIMLIB_ERR_INVALID_DENTRY;
        }
 
-       if (wim_resource_size(lte) >= 0xffff) {
+       /* "Reparse point data, including the tag and optional GUID, cannot
+        * exceed 16 kilobytes." - MSDN  */
+       if (wim_resource_size(lte) > (16 * 1024 - 8)) {
                ERROR("Reparse data of `%s' is too long (%"PRIu64" bytes)",
                      dentry->_full_path, wim_resource_size(lte));
                return WIMLIB_ERR_INVALID_DENTRY;
@@ -378,9 +385,10 @@ apply_reparse_data(ntfs_inode *ni, struct wim_dentry *dentry,
                ERROR_WITH_ERRNO("Failed to set NTFS reparse data on `%s'",
                                 dentry->_full_path);
                return WIMLIB_ERR_NTFS_3G;
+       } else {
+               progress_info->extract.completed_bytes += wim_resource_size(lte);
        }
-       progress_info->extract.completed_bytes += wim_resource_size(lte);
-       return 0;
+       return ret;
 }
 
 /*
@@ -395,7 +403,7 @@ static int
 do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
                     struct apply_args *args)
 {
-       int ret = 0;
+       int ret;
        mode_t type;
        ntfs_inode *ni = NULL;
        struct wim_inode *inode = dentry->d_inode;
@@ -419,10 +427,7 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
                                 * extracted yet, so go ahead and extract the
                                 * first one. */
                                FREE(inode->i_extracted_file);
-                               const tchar *full_path = dentry->_full_path;
-
-                               if (!full_path ||
-                                   !(inode->i_extracted_file = STRDUP(full_path)))
+                               if (!(inode->i_extracted_file = STRDUP(dentry->_full_path)))
                                {
                                        ret = WIMLIB_ERR_NOMEM;
                                        goto out_close_dir_ni;
@@ -446,24 +451,22 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
                goto out_close_dir_ni;
        }
 
-       /* Write the data streams, unless this is a directory or reparse point
-        * */
-       if (!(inode->i_attributes & (FILE_ATTRIBUTE_REPARSE_POINT |
-                                  FILE_ATTRIBUTE_DIRECTORY))) {
+       /* Write the data streams, unless this is reparse point. */
+       if (!(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
                ret = write_ntfs_data_streams(ni, dentry, &args->progress);
-               if (ret != 0)
+               if (ret)
                        goto out_close_dir_ni;
        }
 
        ret = apply_file_attributes_and_security_data(ni, dir_ni, dentry,
                                                      args->w,
                                                      args->extract_flags);
-       if (ret != 0)
+       if (ret)
                goto out_close_dir_ni;
 
        if (inode->i_attributes & FILE_ATTR_REPARSE_POINT) {
                ret = apply_reparse_data(ni, dentry, &args->progress);
-               if (ret != 0)
+               if (ret)
                        goto out_close_dir_ni;
        }
 
@@ -475,7 +478,7 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
                                      dentry->short_name_nbytes,
                                      &short_name_mbs,
                                      &short_name_mbs_nbytes);
-               if (ret != 0)
+               if (ret)
                        goto out_close_dir_ni;
 
                DEBUG("Setting short (DOS) name of `%s' to %s",
@@ -484,7 +487,7 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
                ret = ntfs_set_ntfs_dos_name(ni, dir_ni, short_name_mbs,
                                             short_name_mbs_nbytes, 0);
                FREE(short_name_mbs);
-               if (ret != 0) {
+               if (ret) {
                        ERROR_WITH_ERRNO("Could not set DOS (short) name for `%s'",
                                         dentry->_full_path);
                        ret = WIMLIB_ERR_NTFS_3G;
index 2656d1d..9d501aa 100644 (file)
@@ -176,8 +176,8 @@ capture_ntfs_streams(struct wim_inode *inode,
                     ATTR_TYPES type)
 {
        ntfs_attr_search_ctx *actx;
-       struct ntfs_location *ntfs_loc = NULL;
-       int ret = 0;
+       struct ntfs_location *ntfs_loc;
+       int ret;
        struct wim_lookup_table_entry *lte;
 
        DEBUG2("Capturing NTFS data streams from `%s'", path);
@@ -199,14 +199,9 @@ capture_ntfs_streams(struct wim_inode *inode,
                u32 stream_id;
 
                if (data_size == 0) {
-                       if (errno != 0) {
-                               ERROR_WITH_ERRNO("Failed to get size of attribute of "
-                                                "`%s'", path);
-                               ret = WIMLIB_ERR_NTFS_3G;
-                               goto out_put_actx;
-                       }
                        /* Empty stream.  No lookup table entry is needed. */
                        lte = NULL;
+                       ntfs_loc = NULL;
                } else {
                        ntfs_loc = CALLOC(1, sizeof(*ntfs_loc));
                        if (!ntfs_loc)
@@ -280,7 +275,13 @@ capture_ntfs_streams(struct wim_inode *inode,
                                                     inode, stream_id);
                }
        }
-       ret = 0;
+       if (errno == ENOENT) {
+               ret = 0;
+       } else {
+               ERROR_WITH_ERRNO("Error listing NTFS attributes from `%s'",
+                                path);
+               ret = WIMLIB_ERR_NTFS_3G;
+       }
        goto out_put_actx;
 out_free_lte:
        free_lookup_table_entry(lte);
@@ -295,7 +296,7 @@ out_put_actx:
        if (ret == 0)
                DEBUG2("Successfully captured NTFS streams from `%s'", path);
        else
-               ERROR("Failed to capture NTFS streams from `%s", path);
+               ERROR("Failed to capture NTFS streams from `%s'", path);
        return ret;
 }
 
@@ -550,6 +551,7 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
        int ret;
        struct wim_dentry *root;
        struct wim_inode *inode;
+       ATTR_TYPES stream_type;
 
        if (exclude_path(path, path_len, config, false)) {
                /* Exclude a file or directory tree based on the capture
@@ -603,7 +605,7 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
        if (inode->i_nlink > 1) /* Shared inode; nothing more to do */
                goto out;
 
-       if (name_type & FILE_NAME_WIN32) /* Win32 or Win32+DOS name */
+       if (name_type & FILE_NAME_WIN32) /* Win32 or Win32+DOS name (rather than POSIX) */
                root->is_win32_name = 1;
        inode->i_creation_time    = le64_to_cpu(ni->creation_time);
        inode->i_last_write_time  = le64_to_cpu(ni->last_data_change_time);
@@ -611,14 +613,26 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
        inode->i_attributes       = le32_to_cpu(attributes);
        inode->i_resolved         = 1;
 
-       if (attributes & FILE_ATTR_REPARSE_POINT) {
-               /* Junction point, symbolic link, or other reparse point */
-               ret = capture_ntfs_streams(inode, ni, path,
-                                          path_len, lookup_table,
-                                          vol, AT_REPARSE_POINT);
-       } else if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+       if (attributes & FILE_ATTR_REPARSE_POINT)
+               stream_type = AT_REPARSE_POINT;
+       else
+               stream_type = AT_DATA;
+
+       /* Capture the file's streams; more specifically, this is supposed to:
+        *
+        * - Regular files: capture unnamed data stream and any named data
+        *   streams
+        * - Directories: capture any named data streams
+        * - Reparse points: capture reparse data only
+        */
+       ret = capture_ntfs_streams(inode, ni, path, path_len, lookup_table,
+                                  vol, stream_type);
+       if (ret)
+               goto out;
+
+       if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
 
-               /* Normal directory */
+               /* Recurse to directory children */
                s64 pos = 0;
                struct dos_name_map dos_name_map = { .rb_root = {.rb_node = NULL} };
                struct readdir_ctx ctx = {
@@ -644,14 +658,9 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
                                               &dos_name_map);
                }
                destroy_dos_name_map(&dos_name_map);
-       } else {
-               /* Normal file */
-               ret = capture_ntfs_streams(inode, ni, path,
-                                          path_len, lookup_table,
-                                          vol, AT_DATA);
+               if (ret)
+                       goto out;
        }
-       if (ret)
-               goto out;
 
        if (!(add_image_flags & WIMLIB_ADD_IMAGE_FLAG_NO_ACLS)) {
                /* Get security descriptor */
index ea62b59..8c88129 100644 (file)
@@ -812,8 +812,8 @@ extract_wim_resource(const struct wim_lookup_table_entry *lte,
                                print_lookup_table_entry(lte, stderr);
                                if (lte->resource_location == RESOURCE_IN_WIM)
                                        ERROR("The WIM file appears to be corrupt!");
-                               ret = WIMLIB_ERR_INVALID_RESOURCE_HASH;
                        #endif
+                               ret = WIMLIB_ERR_INVALID_RESOURCE_HASH;
                        }
                }
        } else {
index 7a3b312..3f500b2 100644 (file)
@@ -47,7 +47,7 @@ is_zero_hash(const u8 hash[SHA1_HASH_SIZE])
 {
        if (hash)
                for (u8 i = 0; i < SHA1_HASH_SIZE / 4; i++)
-                       if (((u32*)hash)[i])
+                       if (((const u32*)hash)[i])
                                return false;
        return true;
 }
index 9bc0255..61e910a 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -536,7 +536,7 @@ destroy_image_metadata(struct wim_image_metadata *imd,
        INIT_LIST_HEAD(&imd->inode_list);
 #ifdef WITH_NTFS_3G
        if (imd->ntfs_vol) {
-               do_ntfs_umount(imd->ntfs_vol);  
+               do_ntfs_umount(imd->ntfs_vol);
                imd->ntfs_vol = NULL;
        }
 #endif
index c66d826..34d43fd 100644 (file)
@@ -541,7 +541,6 @@ libntfs3g_global_init();
 
 /* ntfs-capture.c */
 
-/* The types of these two callbacks are intentionally the same. */
 typedef int (*consume_data_callback_t)(const void *buf, size_t len, void *ctx);
 
 extern int
index 0836aca..35026a5 100644 (file)
@@ -1329,7 +1329,7 @@ static int
 do_win32_extract_encrypted_stream(const wchar_t *path,
                                  const struct wim_lookup_table_entry *lte)
 {
-       ERROR("Extrat encryted streams not implemented");
+       ERROR("Extracting encryted streams not implemented");
        return WIMLIB_ERR_INVALID_PARAM;
 }
 
index 6956b48..311eff9 100644 (file)
 
 #include <limits.h>
 
-#if defined(__WIN32__) && !defined(INVALID_HANDLE_VALUE)
-#  define INVALID_HANDLE_VALUE ((HANDLE)(-1))
-#endif
-
 /* Chunk table that's located at the beginning of each compressed resource in
  * the WIM.  (This is not the on-disk format; the on-disk format just has an
  * array of offsets.) */
@@ -172,16 +168,18 @@ get_compress_func(int out_ctype)
  * Returns 0 on success; nonzero on failure.
  */
 static int
-write_wim_resource_chunk(const void *chunk, unsigned chunk_size,
-                        FILE *out_fp, compress_func_t compress,
-                        struct chunk_table *chunk_tab)
+write_wim_resource_chunk(const void * restrict chunk,
+                        unsigned chunk_size,
+                        FILE * restrict out_fp,
+                        compress_func_t compress,
+                        struct chunk_table * restrict chunk_tab)
 {
        const void *out_chunk;
        unsigned out_chunk_size;
        if (compress) {
-               u8 *compressed_chunk = alloca(chunk_size);
+               void *compressed_chunk = alloca(chunk_size);
 
-               out_chunk_size = compress(chunk, chunk_size, compressed_chunk);
+               out_chunk_size = (*compress)(chunk, chunk_size, compressed_chunk);
                if (out_chunk_size) {
                        /* Write compressed */
                        out_chunk = compressed_chunk;
@@ -212,8 +210,9 @@ write_wim_resource_chunk(const void *chunk, unsigned chunk_size,
  * @compressed_size_p.
  */
 static int
-finish_wim_resource_chunk_tab(struct chunk_table *chunk_tab,
-                             FILE *out_fp, u64 *compressed_size_p)
+finish_wim_resource_chunk_tab(struct chunk_table * restrict chunk_tab,
+                             FILE * restrict out_fp,
+                             u64 * restrict compressed_size_p)
 {
        size_t bytes_written;
        if (fseeko(out_fp, chunk_tab->file_offset, SEEK_SET) != 0) {
@@ -261,7 +260,8 @@ fflush_and_ftruncate(FILE *out_fp, off_t offset)
 }
 
 static int
-finalize_and_check_sha1(SHA_CTX *sha_ctx, struct wim_lookup_table_entry *lte)
+finalize_and_check_sha1(SHA_CTX * restrict sha_ctx,
+                       struct wim_lookup_table_entry * restrict lte)
 {
        u8 md[SHA1_HASH_SIZE];
        sha1_final(md, sha_ctx);
@@ -289,7 +289,8 @@ struct write_resource_ctx {
 };
 
 static int
-write_resource_cb(const void *chunk, size_t chunk_size, void *_ctx)
+write_resource_cb(const void *restrict chunk, size_t chunk_size,
+                 void *restrict _ctx)
 {
        struct write_resource_ctx *ctx = _ctx;
 
@@ -734,8 +735,11 @@ do_write_stream_list_serial(struct list_head *stream_list,
 static inline int
 write_flags_to_resource_flags(int write_flags)
 {
-       return (write_flags & WIMLIB_WRITE_FLAG_RECOMPRESS) ?
-                       WIMLIB_RESOURCE_FLAG_RECOMPRESS : 0;
+       int resource_flags = 0;
+
+       if (write_flags & WIMLIB_WRITE_FLAG_RECOMPRESS)
+               resource_flags |= WIMLIB_RESOURCE_FLAG_RECOMPRESS;
+       return resource_flags;
 }
 
 static int