]> wimlib.net Git - wimlib/blobdiff - src/util.c
Preliminary support for native fds (UNIX only so far)
[wimlib] / src / util.c
index 5463c83af45748c07271ee50ec6c015e7d8f52ca..f1ec74f0730176770f44f88927c05497be5fe71f 100644 (file)
 
 #include "config.h"
 
+
 #undef _GNU_SOURCE
 /* Make sure the POSIX-compatible strerror_r() is declared, rather than the GNU
  * version, which has a different return type. */
-#define _POSIX_C_SOURCE 200112
 #include <string.h>
+
 #define _GNU_SOURCE
+#include <unistd.h>
 
 #include "wimlib_internal.h"
 #include "endianness.h"
@@ -39,8 +41,6 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
-#include <unistd.h> /* for getpid() */
-
 #ifdef __WIN32__
 #include "win32.h"
 #endif
@@ -158,6 +158,7 @@ wimlib_vmsg(const tchar *tag, const tchar *format,
                        tfprintf(stderr, T(": %"TS), buf);
                }
                tputc(T('\n'), stderr);
+               fflush(stderr);
                errno = errno_save;
 #ifndef DEBUG
        }
@@ -177,7 +178,7 @@ wimlib_error(const tchar *format, ...)
        va_list va;
 
        va_start(va, format);
-       wimlib_vmsg(T("[ERROR] "), format, va, false);
+       wimlib_vmsg(T("\r[ERROR] "), format, va, false);
        va_end(va);
 }
 
@@ -187,7 +188,7 @@ wimlib_error_with_errno(const tchar *format, ...)
        va_list va;
 
        va_start(va, format);
-       wimlib_vmsg(T("[ERROR] "), format, va, true);
+       wimlib_vmsg(T("\r[ERROR] "), format, va, true);
        va_end(va);
 }
 
@@ -197,7 +198,7 @@ wimlib_warning(const tchar *format, ...)
        va_list va;
 
        va_start(va, format);
-       wimlib_vmsg(T("[WARNING] "), format, va, false);
+       wimlib_vmsg(T("\r[WARNING] "), format, va, false);
        va_end(va);
 }
 
@@ -207,7 +208,7 @@ wimlib_warning_with_errno(const tchar *format, ...)
        va_list va;
 
        va_start(va, format);
-       wimlib_vmsg(T("[WARNING] "), format, va, true);
+       wimlib_vmsg(T("\r[WARNING] "), format, va, true);
        va_end(va);
 }
 
@@ -217,7 +218,6 @@ wimlib_warning_with_errno(const tchar *format, ...)
 void wimlib_debug(const tchar *file, int line, const char *func,
                  const tchar *format, ...)
 {
-
        va_list va;
        tchar buf[tstrlen(file) + strlen(func) + 30];
 
@@ -269,6 +269,8 @@ static const tchar *error_strings[] = {
        [WIMLIB_ERR_IMAGE_COUNT]
                = T("Inconsistent image count among the metadata "
                        "resources, the WIM header, and/or the XML data"),
+       [WIMLIB_ERR_INSUFFICIENT_PRIVILEGES_TO_EXTRACT]
+               = T("User does not have sufficient privileges to correctly extract the data"),
        [WIMLIB_ERR_IMAGE_NAME_COLLISION]
                = T("Tried to add an image with a name that is already in use"),
        [WIMLIB_ERR_INTEGRITY]
@@ -299,6 +301,8 @@ static const tchar *error_strings[] = {
                = T("An invalid parameter was given"),
        [WIMLIB_ERR_INVALID_PART_NUMBER]
                = T("The part number or total parts of the WIM is invalid"),
+       [WIMLIB_ERR_INVALID_REPARSE_DATA]
+               = T("The reparse data of a reparse point was invalid"),
        [WIMLIB_ERR_INVALID_RESOURCE_HASH]
                = T("The SHA1 message digest of a WIM resource did not match the expected value"),
        [WIMLIB_ERR_INVALID_RESOURCE_SIZE]
@@ -343,8 +347,8 @@ static const tchar *error_strings[] = {
                = T("Could not read the target of a symbolic link"),
        [WIMLIB_ERR_RENAME]
                = T("Could not rename a file"),
-       [WIMLIB_ERR_REOPEN]
-               = T("Could not re-open the WIM after overwriting it"),
+       [WIMLIB_ERR_REPARSE_POINT_FIXUP_FAILED]
+               = T("Unable to complete reparse point fixup"),
        [WIMLIB_ERR_RESOURCE_ORDER]
                = T("The components of the WIM were arranged in an unexpected order"),
        [WIMLIB_ERR_SPECIAL_FILE]
@@ -559,3 +563,109 @@ zap_backslashes(tchar *s)
                }
        }
 }
+
+/* Write @n bytes from @buf to the file descriptor @fd, retrying on internupt
+ * and on short writes.
+ *
+ * Returns short count and set errno on failure. */
+size_t
+full_write(int fd, const void *buf, size_t n)
+{
+       const void *p = buf;
+       ssize_t ret;
+       ssize_t total = 0;
+
+       while (total != n) {
+               ret = write(fd, p, n);
+               if (ret <= 0) {
+                       if (errno == EINTR)
+                               continue;
+                       if (ret == 0)
+                               errno = EIO;
+                       break;
+               }
+               total += ret;
+               p += ret;
+       }
+       return total;
+}
+
+/* Read @n bytes from the file descriptor @fd to the buffer @buf, retrying on
+ * interrupt and on short reads.
+ *
+ * Returns short count and set errno on failure. */
+size_t
+full_read(int fd, void *buf, size_t n)
+{
+       size_t bytes_remaining = n;
+       while (bytes_remaining) {
+               ssize_t bytes_read = read(fd, buf, bytes_remaining);
+               if (bytes_read <= 0) {
+                       if (errno == EINTR)
+                               continue;
+                       if (bytes_read == 0)
+                               errno = EIO;
+                       break;
+               }
+               bytes_remaining -= bytes_read;
+               buf += bytes_read;
+       }
+       return n - bytes_remaining;
+}
+
+/* Read @n bytes from the file descriptor @fd at the offset @offset to the
+ * buffer @buf, retrying on interrupt and on short reads.
+ *
+ * Returns short count and set errno on failure. */
+size_t
+full_pread(int fd, void *buf, size_t nbyte, off_t offset)
+{
+       size_t bytes_remaining = nbyte;
+       ssize_t bytes_read;
+
+       while (bytes_remaining) {
+               bytes_read = pread(fd, buf, bytes_remaining, offset);
+               if (bytes_read <= 0) {
+                       if (errno == EINTR)
+                               continue;
+                       if (bytes_read == 0)
+                               errno = EIO;
+                       break;
+               }
+               bytes_remaining -= bytes_read;
+               buf += bytes_read;
+               offset += bytes_read;
+       }
+       return nbyte - bytes_remaining;
+}
+
+/* Like pwrite(), but keep trying until everything has been written or we know
+ * for sure that there was an error. */
+size_t
+full_pwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+       ssize_t bytes_remaining = count;
+       ssize_t bytes_written;
+
+       while (bytes_remaining > 0) {
+               bytes_written = pwrite(fd, buf, bytes_remaining, offset);
+               if (bytes_written <= 0) {
+                       if (errno == EINTR)
+                               continue;
+                       if (bytes_written == 0)
+                               errno = EIO;
+                       break;
+               }
+               bytes_remaining -= bytes_written;
+               buf += bytes_written;
+               offset += bytes_written;
+       }
+       return count - bytes_remaining;
+}
+
+
+off_t
+filedes_offset(filedes_t fd)
+{
+       return lseek(fd, 0, SEEK_CUR);
+}