]> wimlib.net Git - wimlib/blobdiff - src/win32.c
Initial update functionality (library only)
[wimlib] / src / win32.c
index 43336469005f17c89e18a06d35ae4c3ee10cfc07..f49cbeb1f8c1f8fc98c9c697da5c80e2d4b14803 100644 (file)
@@ -48,6 +48,7 @@
 #define MAX_GET_SD_ACCESS_DENIED_WARNINGS 1
 #define MAX_GET_SACL_PRIV_NOTHELD_WARNINGS 1
 #define MAX_CREATE_HARD_LINK_WARNINGS 5
+#define MAX_CREATE_SOFT_LINK_WARNINGS 5
 struct win32_capture_state {
        unsigned long num_get_sd_access_denied;
        unsigned long num_get_sacl_priv_notheld;
@@ -1500,7 +1501,7 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
        inode->i_last_access_time = FILETIME_to_u64(&file_info.ftLastAccessTime);
        inode->i_resolved = 1;
 
-       params->add_image_flags &= ~(WIMLIB_ADD_IMAGE_FLAG_ROOT | WIMLIB_ADD_IMAGE_FLAG_SOURCE);
+       params->add_image_flags &= ~WIMLIB_ADD_IMAGE_FLAG_ROOT;
 
        if (!(params->add_image_flags & WIMLIB_ADD_IMAGE_FLAG_NO_ACLS)
            && (vol_flags & FILE_PERSISTENT_ACLS))
@@ -1733,7 +1734,7 @@ win32_set_reparse_data(HANDLE h,
                       const struct wim_inode *inode,
                       const struct wim_lookup_table_entry *lte,
                       const wchar_t *path,
-                      const struct apply_args *args)
+                      struct apply_args *args)
 {
        int ret;
        u8 rpbuf[REPARSE_POINT_MAX_SIZE];
@@ -1785,15 +1786,30 @@ win32_set_reparse_data(HANDLE h,
                             NULL /* lpOverlapped */))
        {
                DWORD err = GetLastError();
-               ERROR("Failed to set reparse data on \"%ls\"", path);
-               win32_error(err);
                if (err == ERROR_ACCESS_DENIED || err == ERROR_PRIVILEGE_NOT_HELD)
-                       return WIMLIB_ERR_INSUFFICIENT_PRIVILEGES_TO_EXTRACT;
-               else if (inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
-                        inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT)
-                       return WIMLIB_ERR_LINK;
-               else
-                       return WIMLIB_ERR_WRITE;
+               {
+                       args->num_soft_links_failed++;
+                       if (args->num_soft_links_failed <= MAX_CREATE_SOFT_LINK_WARNINGS) {
+                               WARNING("Can't set reparse data on \"%ls\": Access denied!\n"
+                                       "          You may be trying to extract a symbolic "
+                                       "link without the\n"
+                                       "          SeCreateSymbolicLink privilege, which by "
+                                       "default non-Administrator\n"
+                                       "          accounts do not have.", path);
+                       }
+                       if (args->num_hard_links_failed == MAX_CREATE_HARD_LINK_WARNINGS) {
+                               WARNING("Suppressing further warnings regarding failure to extract\n"
+                                       "          reparse points due to insufficient privileges...");
+                       }
+               } else {
+                       ERROR("Failed to set reparse data on \"%ls\"", path);
+                       win32_error(err);
+                       if (inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
+                           inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT)
+                               return WIMLIB_ERR_LINK;
+                       else
+                               return WIMLIB_ERR_WRITE;
+               }
        }
        return 0;
 }
@@ -2708,12 +2724,13 @@ win32_try_hard_link(const wchar_t *output_path, const struct wim_inode *inode,
                return WIMLIB_ERR_LINK;
        } else {
                args->num_hard_links_failed++;
-               if (args->num_hard_links_failed < MAX_CREATE_HARD_LINK_WARNINGS) {
+               if (args->num_hard_links_failed <= MAX_CREATE_HARD_LINK_WARNINGS) {
                        WARNING("Can't create hard link \"%ls => %ls\":\n"
                                "          Volume does not support hard links!\n"
                                "          Falling back to extracting a copy of the file.",
                                output_path, inode->i_extracted_file);
-               } else if (args->num_hard_links_failed == MAX_CREATE_HARD_LINK_WARNINGS) {
+               }
+               if (args->num_hard_links_failed == MAX_CREATE_HARD_LINK_WARNINGS) {
                        WARNING("Suppressing further hard linking warnings...");
                }
                return -1;
@@ -2788,8 +2805,8 @@ win32_do_apply_dentry(const wchar_t *output_path,
 int
 win32_do_apply_dentry_timestamps(const wchar_t *path,
                                 size_t path_num_chars,
-                                const struct wim_dentry *dentry,
-                                const struct apply_args *args)
+                                struct wim_dentry *dentry,
+                                struct apply_args *args)
 {
        DWORD err;
        HANDLE h;
@@ -2846,17 +2863,17 @@ out:
 int
 fsync(int fd)
 {
-       DWORD err;
        HANDLE h;
 
        h = (HANDLE)_get_osfhandle(fd);
        if (h == INVALID_HANDLE_VALUE)
                goto err;
        if (!FlushFileBuffers(h))
-               goto err;
+               goto err_set_errno;
        return 0;
-err:
+err_set_errno:
        set_errno_from_GetLastError();
+err:
        return -1;
 }
 
@@ -2985,15 +3002,13 @@ do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset,
        wimlib_assert(count <= 0xffffffff);
 
        h = (HANDLE)_get_osfhandle(fd);
-       if (h == INVALID_HANDLE_VALUE) {
-               errno = EBADF;
-               return -1;
-       }
+       if (h == INVALID_HANDLE_VALUE)
+               goto err;
 
        /* Get original position */
        relative_offset.QuadPart = 0;
        if (!SetFilePointerEx(h, relative_offset, &orig_offset, FILE_CURRENT))
-               goto err;
+               goto err_set_errno;
 
        memset(&overlapped, 0, sizeof(overlapped));
        overlapped.Offset = offset;
@@ -3005,15 +3020,16 @@ do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset,
        else
                bret = ReadFile(h, buf, count, &bytes_read_or_written, &overlapped);
        if (!bret)
-               goto err;
+               goto err_set_errno;
 
        /* Restore the original position */
        if (!SetFilePointerEx(h, orig_offset, NULL, FILE_BEGIN))
-               goto err;
+               goto err_set_errno;
 
        return bytes_read_or_written;
-err:
+err_set_errno:
        set_errno_from_GetLastError();
+err:
        return -1;
 }
 
@@ -3040,14 +3056,23 @@ win32_pwrite(int fd, const void *buf, size_t count, off_t offset)
 extern ssize_t
 win32_writev(int fd, const struct iovec *iov, int iovcnt)
 {
-       size_t total_bytes_written = 0;
-       for (int i = 0; i < iovcnt; i++) {
-               size_t bytes_written;
+       ssize_t total_bytes_written = 0;
 
-               bytes_written = full_write(fd, iov[i].iov_base, iov[i].iov_len);
-               total_bytes_written += bytes_written;
-               if (bytes_written != iov[i].iov_len)
+       if (iovcnt <= 0) {
+               errno = EINVAL;
+               return -1;
+       }
+       for (int i = 0; i < iovcnt; i++) {
+               ssize_t bytes_written;
+
+               bytes_written = write(fd, iov[i].iov_base, iov[i].iov_len);
+               if (bytes_written >= 0)
+                       total_bytes_written += bytes_written;
+               if (bytes_written != iov[i].iov_len) {
+                       if (total_bytes_written == 0)
+                               total_bytes_written = -1;
                        break;
+               }
        }
        return total_bytes_written;
 }