From a2cc0be5a6e24877e8beee7688816ff7cf56cec4 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 31 Oct 2015 12:59:11 -0500 Subject: [PATCH] ntfs-3g_apply.c: handle ntfs_attr_pwrite() short writes --- src/ntfs-3g_apply.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index 23ffe286..d0f3bb6c 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -855,16 +855,35 @@ out: return ret; } +/* Note: contrary to its documentation, ntfs_attr_pwrite() can return a short + * count in non-error cases --- specifically, when writing to a compressed + * attribute and the requested count exceeds the size of an NTFS "compression + * block". Therefore, we must continue calling ntfs_attr_pwrite() until all + * bytes have been written or a real error has occurred. */ +static bool +ntfs_3g_full_pwrite(ntfs_attr *na, u64 offset, size_t size, const u8 *data) +{ + while (size) { + s64 res = ntfs_attr_pwrite(na, offset, size, data); + if (unlikely(res <= 0)) + return false; + wimlib_assert(res <= size); + offset += res; + size -= res; + data += res; + } + return true; +} + static int ntfs_3g_extract_chunk(const void *chunk, size_t size, void *_ctx) { struct ntfs_3g_apply_ctx *ctx = _ctx; - s64 res; for (unsigned i = 0; i < ctx->num_open_attrs; i++) { - res = ntfs_attr_pwrite(ctx->open_attrs[i], - ctx->offset, size, chunk); - if (res != size) { + if (!ntfs_3g_full_pwrite(ctx->open_attrs[i], + ctx->offset, size, chunk)) + { ERROR_WITH_ERRNO("Error writing data to NTFS volume"); return WIMLIB_ERR_NTFS_3G; } -- 2.43.0