]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Safe writes: improve error handling
authorMartin Matuska <martin@matuska.org>
Mon, 2 Mar 2020 07:55:44 +0000 (08:55 +0100)
committerMartin Matuska <martin@matuska.org>
Mon, 2 Mar 2020 08:00:00 +0000 (09:00 +0100)
Print message if creation of temporary file fails.
When rename of temporary file fails, exit with ARCHIVE_FAILED.
Reword message on failed rename.
Revert d84ec3f and 85b9f66, call archive_set_error()w before unlinking.

libarchive/archive_util.c
libarchive/archive_write_disk_posix.c
libarchive/archive_write_disk_windows.c

index 288a44280dc21fa557c18f1c6a811acf15a36285..c76ecc5b05b1fca53402b3e22ee2d0e2c6830409 100644 (file)
@@ -365,6 +365,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
                }
                fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR);
                if (fd == -1) {
+                       la_dosmaperr(GetLastError());
                        CloseHandle(h);
                        goto exit_tmpfile;
                } else
index 35b5aedf7f03040224dfba415c00eff7de2fd605..0168d0d411bd2ba8159e40ab9d58273f689a7b0e 100644 (file)
@@ -1654,7 +1654,6 @@ _archive_write_disk_finish_entry(struct archive *_a)
 {
        struct archive_write_disk *a = (struct archive_write_disk *)_a;
        int ret = ARCHIVE_OK;
-       int oerrno;
 
        archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
            ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
@@ -1856,12 +1855,10 @@ finish_metadata:
                a->fd = -1;
                if (a->tmpname) {
                        if (rename(a->tmpname, a->name) == -1) {
-                               oerrno = errno;
-                               unlink(a->tmpname);
-                               errno = oerrno;
                                archive_set_error(&a->archive, errno,
-                                   "Failed to safe write");
-                               ret = ARCHIVE_FATAL;
+                                   "Failed to rename temporary file");
+                               ret = ARCHIVE_FAILED;
+                               unlink(a->tmpname);
                        }
                        a->tmpname = NULL;
                }
@@ -2148,8 +2145,11 @@ restore_entry(struct archive_write_disk *a)
                        if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
                            S_ISREG(a->st.st_mode)) {
                                /* Use a temporary file to extract */
-                               if ((a->fd = la_mktemp(a)) == -1)
+                               if ((a->fd = la_mktemp(a)) == -1) {
+                                       archive_set_error(&a->archive, errno,
+                                           "Can't create temporary file");
                                        return ARCHIVE_FAILED;
+                               }
                                a->pst = NULL;
                                en = 0;
                        } else {
index 4b703492b147a4408a225d2e329b44bd51b3e035..0c600176cd54325b3c1452f1b84624bb73a1c4a1 100644 (file)
@@ -549,6 +549,8 @@ la_mktemp(struct archive_write_disk *a)
        a->tmpname = a->_tmpname_data.s;
 
        fd = __archive_mkstemp(a->tmpname);
+       if (fd == -1)
+               return -1;
 
        mode = a->mode & 0777 & ~a->user_umask;
        if (la_chmod(a->tmpname, mode) == -1) {
@@ -1174,7 +1176,6 @@ _archive_write_disk_finish_entry(struct archive *_a)
 {
        struct archive_write_disk *a = (struct archive_write_disk *)_a;
        int ret = ARCHIVE_OK;
-       int oerrno;
 
        archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
            ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
@@ -1282,12 +1283,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
                        /* Windows does not support atomic rename */
                        disk_unlink(a->name);
                        if (_wrename(a->tmpname, a->name) != 0) {
-                               oerrno = errno;
-                               disk_unlink(a->tmpname);
-                               errno = oerrno;
+                               la_dosmaperr(GetLastError());
                                archive_set_error(&a->archive, errno,
-                                   "Failed to safe write");
-                               ret = ARCHIVE_FATAL;
+                                   "Failed to rename temporary file");
+                               ret = ARCHIVE_FAILED;
+                               disk_unlink(a->tmpname);
                        }
                        a->tmpname = NULL;
                }
@@ -1577,12 +1577,17 @@ restore_entry(struct archive_write_disk *a)
                                S_ISREG(st_mode)) {
                                int fd = la_mktemp(a);
 
-                               if (fd == -1)
+                               if (fd == -1) {
+                                       la_dosmaperr(GetLastError());
+                                       archive_set_error(&a->archive, errno,
+                                           "Can't create temporary file");
                                        return (ARCHIVE_FAILED);
+                               }
                                a->fh = (HANDLE)_get_osfhandle(fd);
-                               if (a->fh == INVALID_HANDLE_VALUE)
+                               if (a->fh == INVALID_HANDLE_VALUE) {
+                                       la_dosmaperr(GetLastError());
                                        return (ARCHIVE_FAILED);
-
+                               }
                                a->pst = NULL;
                                en = 0;
                        } else {