]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Use FILE_SHARE_WRITE and FILE_SHARE_DELETE when opening files on Windows 1806/head
authorVladimir Kikhtenko <kikht@yandex-team.ru>
Fri, 18 Nov 2022 06:46:18 +0000 (12:46 +0600)
committerVladimir Kikhtenko <kikht@yandex-team.ru>
Fri, 18 Nov 2022 06:54:14 +0000 (12:54 +0600)
Many standard libraries(
[libc++](https://github.com/llvm/llvm-project/blob/main/libcxx/src/filesystem/posix_compat.h#L159),
[go](https://cs.opensource.google/go/go/+/refs/tags/go1.19.3:src/syscall/syscall_windows.go;l=331),
[rust](https://doc.rust-lang.org/src/std/os/windows/fs.rs.html#126-131)
) open files on windows with `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`
mode by default. Libarchive uses only `FILE_SHARE_READ`, so when file is
being opened by any program that uses these standard libraries
libarchive fails to open it. Here we change libarchive shared flags, so
it plays well with common practice in other programs.

libarchive/archive_read_disk_windows.c

index ea32e2aac0ac085e939d8a34e71ad9c180bcaa74..f9d139557ee0a71132a35ddfc2be7cea9e973fb5 100644 (file)
@@ -418,8 +418,9 @@ la_linkname_from_pathw(const wchar_t *path, wchar_t **outbuf, int *linktype)
            FILE_FLAG_OPEN_REPARSE_POINT;
        int ret;
 
-       h = CreateFileW(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, flag,
-           NULL);
+       h = CreateFileW(path, 0,
+           FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
+           OPEN_EXISTING, flag, NULL);
        if (h == INVALID_HANDLE_VALUE) {
                la_dosmaperr(GetLastError());
                return (-1);
@@ -1073,7 +1074,9 @@ next_entry(struct archive_read_disk *a, struct tree *t,
                else
                        flags |= FILE_FLAG_SEQUENTIAL_SCAN;
                t->entry_fh = CreateFileW(tree_current_access_path(t),
-                   GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
+                   GENERIC_READ,
+                   FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                   NULL, OPEN_EXISTING, flags, NULL);
                if (t->entry_fh == INVALID_HANDLE_VALUE) {
                        la_dosmaperr(GetLastError());
                        archive_set_error(&a->archive, errno,
@@ -2046,7 +2049,8 @@ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st,
        
        if (sim_lstat && tree_current_is_physical_link(t))
                flag |= FILE_FLAG_OPEN_REPARSE_POINT;
-       h = CreateFileW(tree_current_access_path(t), 0, FILE_SHARE_READ, NULL,
+       h = CreateFileW(tree_current_access_path(t), 0,
+           FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
            OPEN_EXISTING, flag, NULL);
        if (h == INVALID_HANDLE_VALUE) {
                la_dosmaperr(GetLastError());
@@ -2275,7 +2279,8 @@ archive_read_disk_entry_from_file(struct archive *_a,
                        } else
                                desiredAccess = GENERIC_READ;
 
-                       h = CreateFileW(path, desiredAccess, FILE_SHARE_READ, NULL,
+                       h = CreateFileW(path, desiredAccess,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
                            OPEN_EXISTING, flag, NULL);
                        if (h == INVALID_HANDLE_VALUE) {
                                la_dosmaperr(GetLastError());
@@ -2337,7 +2342,8 @@ archive_read_disk_entry_from_file(struct archive *_a,
                if (fd >= 0) {
                        h = (HANDLE)_get_osfhandle(fd);
                } else {
-                       h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
+                       h = CreateFileW(path, GENERIC_READ,
+                           FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
                            OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
                        if (h == INVALID_HANDLE_VALUE) {
                                la_dosmaperr(GetLastError());