]> wimlib.net Git - wimlib/blobdiff - src/resource.c
resource.c: Fix two comments
[wimlib] / src / resource.c
index bbf929a3b311ca1130bbcb8c6ce91c620f5d79f6..f7684b10baee9bab6fffaa109f0977e79a19d1ed 100644 (file)
@@ -37,7 +37,7 @@
 #include "wimlib/wim.h"
 
 #ifdef __WIN32__
-/* for read_win32_file_prefix(), read_win32_encrypted_file_prefix() */
+/* for read_winnt_file_prefix(), read_win32_encrypted_file_prefix() */
 #  include "wimlib/win32.h"
 #endif
 
@@ -169,9 +169,9 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec,
        struct filedes * const in_fd = &rspec->wim->in_fd;
 
        /* Determine if we're reading a pipable resource from a pipe or not.  */
-       const bool is_pipe_read = !filedes_is_seekable(in_fd);
+       const bool is_pipe_read = (rspec->is_pipable && !filedes_is_seekable(in_fd));
 
-       /* Determine if the chunk table is in an altenate format.  */
+       /* Determine if the chunk table is in an alternate format.  */
        const bool alt_chunk_table = (rspec->flags & WIM_RESHDR_FLAG_PACKED_STREAMS)
                                        && !is_pipe_read;
 
@@ -193,6 +193,7 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec,
                      "expected power-of-2 chunk size (got %"PRIu32")",
                      chunk_size);
                ret = WIMLIB_ERR_INVALID_CHUNK_SIZE;
+               errno = EINVAL;
                goto out_free_memory;
        }
 
@@ -207,8 +208,11 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec,
        } else {
                ret = wimlib_create_decompressor(ctype, chunk_size, NULL,
                                                 &decompressor);
-               if (ret)
+               if (ret) {
+                       if (ret != WIMLIB_ERR_NOMEM)
+                               errno = EINVAL;
                        goto out_free_memory;
+               }
        }
 
        const u32 chunk_order = bsr32(chunk_size);
@@ -562,6 +566,28 @@ read_error:
        goto out_free_memory;
 }
 
+static int
+fill_zeroes(u64 size, consume_data_callback_t cb, void *cb_ctx)
+{
+       if (unlikely(size)) {
+               u8 buf[min(size, BUFFER_SIZE)];
+
+               memset(buf, 0, sizeof(buf));
+
+               do {
+                       size_t len;
+                       int ret;
+
+                       len = min(size, BUFFER_SIZE);
+                       ret = cb(buf, len, cb_ctx);
+                       if (ret)
+                               return ret;
+                       size -= len;
+               } while (size);
+       }
+       return 0;
+}
+
 /* Read raw data from a file descriptor at the specified offset, feeding the
  * data it in chunks into the specified callback function.  */
 static int
@@ -654,11 +680,37 @@ read_partial_wim_resource(const struct wim_resource_spec *rspec,
                return read_compressed_wim_resource(rspec, &range, 1,
                                                    cb, cb_ctx);
        } else {
-               return read_raw_file_data(&rspec->wim->in_fd,
-                                         rspec->offset_in_wim + offset,
-                                         size,
-                                         cb,
-                                         cb_ctx);
+               /* Reading uncompressed resource.  For completeness, handle the
+                * weird case where size_in_wim < uncompressed_size.  */
+
+               u64 read_size;
+               u64 zeroes_size;
+               int ret;
+
+               if (likely(offset + size <= rspec->size_in_wim) ||
+                   rspec->is_pipable)
+               {
+                       read_size = size;
+                       zeroes_size = 0;
+               } else {
+                       if (offset >= rspec->size_in_wim) {
+                               read_size = 0;
+                               zeroes_size = size;
+                       } else {
+                               read_size = rspec->size_in_wim - offset;
+                               zeroes_size = offset + size - rspec->size_in_wim;
+                       }
+               }
+
+               ret = read_raw_file_data(&rspec->wim->in_fd,
+                                        rspec->offset_in_wim + offset,
+                                        read_size,
+                                        cb,
+                                        cb_ctx);
+               if (ret)
+                       return ret;
+
+               return fill_zeroes(zeroes_size, cb, cb_ctx);
        }
 }
 
@@ -710,7 +762,6 @@ read_wim_stream_prefix(const struct wim_lookup_table_entry *lte, u64 size,
                                         cb, cb_ctx);
 }
 
-#ifndef __WIN32__
 /* This function handles reading stream data that is located in an external
  * file,  such as a file that has been added to the WIM image through execution
  * of a wimlib_add_command.
@@ -731,7 +782,7 @@ read_file_on_disk_prefix(const struct wim_lookup_table_entry *lte, u64 size,
 
        DEBUG("Reading %"PRIu64" bytes from \"%"TS"\"", size, lte->file_on_disk);
 
-       raw_fd = open(lte->file_on_disk, O_BINARY | O_RDONLY);
+       raw_fd = topen(lte->file_on_disk, O_BINARY | O_RDONLY);
        if (raw_fd < 0) {
                ERROR_WITH_ERRNO("Can't open \"%"TS"\"", lte->file_on_disk);
                return WIMLIB_ERR_OPEN;
@@ -741,7 +792,34 @@ read_file_on_disk_prefix(const struct wim_lookup_table_entry *lte, u64 size,
        filedes_close(&fd);
        return ret;
 }
-#endif /* !__WIN32__ */
+
+#ifdef WITH_FUSE
+static int
+read_staging_file_prefix(const struct wim_lookup_table_entry *lte, u64 size,
+                        consume_data_callback_t cb, void *cb_ctx)
+{
+       int raw_fd;
+       struct filedes fd;
+       int ret;
+
+       wimlib_assert(size <= lte->size);
+
+       DEBUG("Reading %"PRIu64" bytes from staging file \"%s\"",
+             size, lte->staging_file_name);
+
+       raw_fd = openat(lte->staging_dir_fd, lte->staging_file_name,
+                       O_RDONLY | O_NOFOLLOW);
+       if (raw_fd < 0) {
+               ERROR_WITH_ERRNO("Can't open staging file \"%s\"",
+                                lte->staging_file_name);
+               return WIMLIB_ERR_OPEN;
+       }
+       filedes_init(&fd, raw_fd);
+       ret = read_raw_file_data(&fd, 0, size, cb, cb_ctx);
+       filedes_close(&fd);
+       return ret;
+}
+#endif
 
 /* This function handles the trivial case of reading stream data that is, in
  * fact, already located in an in-memory buffer.  */
@@ -779,19 +857,16 @@ read_stream_prefix(const struct wim_lookup_table_entry *lte, u64 size,
 {
        static const read_stream_prefix_handler_t handlers[] = {
                [RESOURCE_IN_WIM]             = read_wim_stream_prefix,
-       #ifdef __WIN32__
-               [RESOURCE_IN_FILE_ON_DISK]    = read_win32_file_prefix,
-       #else
                [RESOURCE_IN_FILE_ON_DISK]    = read_file_on_disk_prefix,
-       #endif
                [RESOURCE_IN_ATTACHED_BUFFER] = read_buffer_prefix,
        #ifdef WITH_FUSE
-               [RESOURCE_IN_STAGING_FILE]    = read_file_on_disk_prefix,
+               [RESOURCE_IN_STAGING_FILE]    = read_staging_file_prefix,
        #endif
        #ifdef WITH_NTFS_3G
                [RESOURCE_IN_NTFS_VOLUME]     = read_ntfs_file_prefix,
        #endif
        #ifdef __WIN32__
+               [RESOURCE_IN_WINNT_FILE_ON_DISK] = read_winnt_file_prefix,
                [RESOURCE_WIN32_ENCRYPTED]    = read_win32_encrypted_file_prefix,
        #endif
        };
@@ -878,6 +953,34 @@ wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim, void **buf_r
        return wim_resource_spec_to_data(&rspec, buf_ret);
 }
 
+int
+wim_reshdr_to_hash(const struct wim_reshdr *reshdr, WIMStruct *wim,
+                  u8 hash[SHA1_HASH_SIZE])
+{
+       struct wim_resource_spec rspec;
+       int ret;
+       struct wim_lookup_table_entry *lte;
+
+       wim_res_hdr_to_spec(reshdr, wim, &rspec);
+
+       lte = new_lookup_table_entry();
+       if (lte == NULL)
+               return WIMLIB_ERR_NOMEM;
+
+       lte_bind_wim_resource_spec(lte, &rspec);
+       lte->flags = rspec.flags;
+       lte->size = rspec.uncompressed_size;
+       lte->offset_in_res = 0;
+       lte->unhashed = 1;
+
+       ret = sha1_stream(lte);
+
+       lte_unbind_wim_resource_spec(lte);
+       copy_hash(hash, lte->hash);
+       free_lookup_table_entry(lte);
+       return ret;
+}
+
 struct streamifier_context {
        struct read_stream_list_callbacks cbs;
        struct wim_lookup_table_entry *cur_stream;
@@ -912,10 +1015,17 @@ streamifier_cb(const void *chunk, size_t size, void *_ctx)
        wimlib_assert(size <= ctx->cur_stream->size - ctx->cur_stream_offset);
 
        if (ctx->cur_stream_offset == 0) {
+               u32 flags;
+
                /* Starting a new stream.  */
                DEBUG("Begin new stream (size=%"PRIu64").",
                      ctx->cur_stream->size);
-               ret = (*ctx->cbs.begin_stream)(ctx->cur_stream, true,
+
+               flags = BEGIN_STREAM_FLAG_PARTIAL_RESOURCE;
+               if (size == ctx->cur_stream->size)
+                       flags |= BEGIN_STREAM_FLAG_WHOLE_STREAM;
+               ret = (*ctx->cbs.begin_stream)(ctx->cur_stream,
+                                              flags,
                                               ctx->cbs.begin_stream_ctx);
                if (ret)
                        return ret;
@@ -924,9 +1034,9 @@ streamifier_cb(const void *chunk, size_t size, void *_ctx)
        /* Consume the chunk.  */
        ret = (*ctx->cbs.consume_chunk)(chunk, size,
                                        ctx->cbs.consume_chunk_ctx);
+       ctx->cur_stream_offset += size;
        if (ret)
                return ret;
-       ctx->cur_stream_offset += size;
 
        if (ctx->cur_stream_offset == ctx->cur_stream->size) {
                /* Finished reading all the data for a stream.  */
@@ -961,7 +1071,7 @@ struct hasher_context {
 /* Callback for starting to read a stream while calculating its SHA1 message
  * digest.  */
 static int
-hasher_begin_stream(struct wim_lookup_table_entry *lte, bool is_partial_res,
+hasher_begin_stream(struct wim_lookup_table_entry *lte, u32 flags,
                    void *_ctx)
 {
        struct hasher_context *ctx = _ctx;
@@ -971,7 +1081,7 @@ hasher_begin_stream(struct wim_lookup_table_entry *lte, bool is_partial_res,
        if (ctx->cbs.begin_stream == NULL)
                return 0;
        else
-               return (*ctx->cbs.begin_stream)(lte, is_partial_res,
+               return (*ctx->cbs.begin_stream)(lte, flags,
                                                ctx->cbs.begin_stream_ctx);
 }
 
@@ -1035,8 +1145,8 @@ hasher_end_stream(struct wim_lookup_table_entry *lte, int status, void *_ctx)
                                        get_sha1_string(lte->hash, expected_hashstr);
                                        get_sha1_string(hash, actual_hashstr);
                                        ERROR("The stream is corrupted!\n"
-                                             "        (Expected SHA1=%s,\n"
-                                             "              got SHA1=%s)",
+                                             "        (Expected SHA1=%"TS",\n"
+                                             "              got SHA1=%"TS")",
                                              expected_hashstr, actual_hashstr);
                                }
                                ret = WIMLIB_ERR_INVALID_RESOURCE_HASH;
@@ -1061,7 +1171,7 @@ read_full_stream_with_cbs(struct wim_lookup_table_entry *lte,
 {
        int ret;
 
-       ret = (*cbs->begin_stream)(lte, false, cbs->begin_stream_ctx);
+       ret = (*cbs->begin_stream)(lte, 0, cbs->begin_stream_ctx);
        if (ret)
                return ret;
 
@@ -1089,7 +1199,6 @@ read_full_stream_with_sha1(struct wim_lookup_table_entry *lte,
                .consume_chunk_ctx      = &hasher_ctx,
                .end_stream             = hasher_end_stream,
                .end_stream_ctx         = &hasher_ctx,
-
        };
        return read_full_stream_with_cbs(lte, &hasher_cbs);
 }