]> wimlib.net Git - wimlib/blobdiff - src/win32.c
win32.c realpath(): Don't allocate extra byte
[wimlib] / src / win32.c
index fb30b5f08d3f29e9577bb05ef29578e92e91e3c2..f094656a0c35df39b6d2cd747d276356a9a54aee 100644 (file)
 
 #include <errno.h>
 
+static const char *access_denied_msg =
+"         If you are not running this program as the administrator, you may\n"
+"         need to do so, so that all data and metadata can be backed up.\n"
+"         Otherwise, there may be no way to access the desired data or\n"
+"         metadata without taking ownership of the file or directory.\n";
+
 #ifdef ENABLE_ERROR_MESSAGES
 void
 win32_error(u32 err_code)
@@ -171,10 +177,17 @@ win32_get_security_descriptor(struct wim_dentry *dentry,
                        err = GetLastError();
                }
        }
-       ERROR("Win32 API: Failed to read security descriptor of \"%ls\"",
-             path_utf16);
-       win32_error(err);
-       return WIMLIB_ERR_READ;
+
+       if (err == ERROR_ACCESS_DENIED) {
+               WARNING("Failed to read security descriptor of \"%ls\": "
+                       "Access denied!\n%s", path_utf16, access_denied_msg);
+               return 0;
+       } else {
+               ERROR("Win32 API: Failed to read security descriptor of \"%ls\"",
+                     path_utf16);
+               win32_error(err);
+               return WIMLIB_ERR_READ;
+       }
 }
 
 /* Reads the directory entries of directory using a Win32 API and recursively
@@ -229,7 +242,7 @@ win32_recurse_directory(struct wim_dentry *root,
                {
                        struct wim_dentry *child;
 
-                       char *mbs_name;
+                       mbchar *mbs_name;
                        size_t mbs_name_nbytes;
                        ret = utf16le_to_mbs(dat.cFileName,
                                             wcslen(dat.cFileName) * sizeof(wchar_t),
@@ -238,7 +251,7 @@ win32_recurse_directory(struct wim_dentry *root,
                        if (ret)
                                goto out_find_close;
 
-                       char name[strlen(root_disk_path) + 1 + mbs_name_nbytes + 1];
+                       mbchar name[strlen(root_disk_path) + 1 + mbs_name_nbytes + 1];
                        sprintf(name, "%s/%s", root_disk_path, mbs_name);
                        FREE(mbs_name);
                        ret = win32_build_dentry_tree(&child, name, lookup_table,
@@ -281,7 +294,7 @@ static int
 win32_capture_reparse_point(HANDLE hFile,
                            struct wim_inode *inode,
                            struct wim_lookup_table *lookup_table,
-                           const char *path)
+                           const mbchar *path)
 {
        /* "Reparse point data, including the tag and optional GUID,
         * cannot exceed 16 kilobytes." - MSDN  */
@@ -401,7 +414,7 @@ win32_capture_stream(const wchar_t *path_utf16,
        is_named_stream = (p != colon);
        if (is_named_stream) {
                /* Allocate an ADS entry for the named stream. */
-               char *mbs_stream_name;
+               mbchar *mbs_stream_name;
                size_t mbs_stream_name_nbytes;
                ret = utf16le_to_mbs(p,
                                     (colon - p) * sizeof(wchar_t),
@@ -514,10 +527,17 @@ win32_capture_streams(const wchar_t *path_utf16,
                {
                        return 0;
                } else {
-                       ERROR("Win32 API: Failed to look up data streams of \"%ls\"",
-                             path_utf16);
-                       win32_error(err);
-                       return WIMLIB_ERR_READ;
+                       if (err == ERROR_ACCESS_DENIED) {
+                               WARNING("Failed to look up data streams of \"%ls\": "
+                                       "Access denied!\n%s", path_utf16,
+                                       access_denied_msg);
+                               return 0;
+                       } else {
+                               ERROR("Win32 API: Failed to look up data streams of \"%ls\"",
+                                     path_utf16);
+                               win32_error(err);
+                               return WIMLIB_ERR_READ;
+                       }
                }
        }
        do {
@@ -542,7 +562,7 @@ out_find_close:
 /* Win32 version of capturing a directory tree */
 int
 win32_build_dentry_tree(struct wim_dentry **root_ret,
-                       const char *root_disk_path,
+                       const mbchar *root_disk_path,
                        struct wim_lookup_table *lookup_table,
                        struct wim_security_data *sd,
                        const struct capture_config *config,
@@ -1160,7 +1180,7 @@ realpath(const mbchar *path, mbchar *resolved_path)
        if (!ret)
                goto fail_win32;
 
-       resolved_path = MALLOC(ret + 1);
+       resolved_path = MALLOC(ret);
        if (!resolved_path)
                goto fail;
        ret = GetFullPathNameA(path, ret, resolved_path, NULL);
@@ -1183,3 +1203,20 @@ nl_langinfo(nl_item item)
        strcpy(buf, "Unknown");
        return buf;
 }
+
+/* rename() on Windows fails if the destination file exists.  Fix it. */
+int
+rename_replacement(const char *oldpath, const char *newpath)
+{
+       if (MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) {
+               return 0;
+       } else {
+               /* As usual, the possible error values are not documented */
+               DWORD err = GetLastError();
+               ERROR("MoveFileExA(): Can't rename \"%s\" to \"%s\"",
+                     oldpath, newpath);
+               win32_error(err);
+               errno = 0;
+               return -1;
+       }
+}