#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 "wimlib_internal.h"
#include "endianness.h"
#include "timestamp.h"
+#include "wimlib_internal.h"
#include <ctype.h>
#include <errno.h>
-#include <stdlib.h>
#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
-#include <unistd.h> /* for getpid() */
#ifdef __WIN32__
-#include "win32.h"
+# include "win32.h"
+# define pread win32_pread
+# define pwrite win32_pwrite
+# define writev win32_writev
+#else
+# include <sys/uio.h> /* for writev() and `struct iovec' */
#endif
static size_t
tchar *tstr;
size_t tstr_nbytes;
utf16lechar *ucs = va_arg(va, utf16lechar*);
- size_t ucs_nbytes = utf16le_strlen(ucs);
- ret = utf16le_to_tstr(ucs, ucs_nbytes,
- &tstr, &tstr_nbytes);
- if (ret) {
- ret = tfprintf(fp, T("??????"));
+ if (ucs) {
+ size_t ucs_nbytes = utf16le_strlen(ucs);
+
+ ret = utf16le_to_tstr(ucs, ucs_nbytes,
+ &tstr, &tstr_nbytes);
+ if (ret) {
+ ret = tfprintf(fp, T("??????"));
+ } else {
+ ret = tfprintf(fp, T("%"TS), tstr);
+ FREE(tstr);
+ }
+ if (ret < 0)
+ return -1;
+ else
+ n += ret;
} else {
- ret = tfprintf(fp, T("%"TS), tstr);
- FREE(tstr);
+ n += tfprintf(fp, T("(null)"));
}
- if (ret < 0)
- return -1;
- else
- n += ret;
p++;
} else {
if (tputc(*p, fp) == EOF)
tfprintf(stderr, T(": %"TS), buf);
}
tputc(T('\n'), stderr);
+ fflush(stderr);
errno = errno_save;
#ifndef DEBUG
}
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);
}
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);
}
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);
}
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);
}
void wimlib_debug(const tchar *file, int line, const char *func,
const tchar *format, ...)
{
-
va_list va;
tchar buf[tstrlen(file) + strlen(func) + 30];
- tsprintf(buf, "[%"TS" %d] %s(): ", file, line, func);
+ tsprintf(buf, T("[%"TS" %d] %s(): "), file, line, func);
va_start(va, format);
wimlib_vmsg(buf, format, va, false);
[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]
= 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]
= T("A string provided as input by the user was not a valid UTF-8 string"),
[WIMLIB_ERR_INVALID_UTF16_STRING]
= T("A string in a WIM dentry is not a valid UTF-16LE string"),
+ [WIMLIB_ERR_IS_DIRECTORY]
+ = T("One of the specified paths to delete was a directory"),
[WIMLIB_ERR_LIBXML_UTF16_HANDLER_NOT_AVAILABLE]
= T("libxml2 was unable to find a character encoding conversion handler "
"for UTF-16LE"),
= T("Ran out of memory"),
[WIMLIB_ERR_NOTDIR]
= T("Expected a directory"),
+ [WIMLIB_ERR_NOTEMPTY]
+ = T("Directory was not empty"),
[WIMLIB_ERR_NOT_A_WIM_FILE]
= T("The file did not begin with the magic characters that "
"identify a WIM file"),
+ [WIMLIB_ERR_NOT_A_REGULAR_FILE]
+ = T("One of the specified paths to extract did not "
+ "correspond to a regular file"),
[WIMLIB_ERR_NO_FILENAME]
= T("The WIM is not identified with a filename"),
[WIMLIB_ERR_NTFS_3G]
= T("Failed to open a file"),
[WIMLIB_ERR_OPENDIR]
= T("Failed to open a directory"),
+ [WIMLIB_ERR_PATH_DOES_NOT_EXIST]
+ = T("The path does not exist in the WIM image"),
[WIMLIB_ERR_READ]
= T("Could not read data from a file"),
[WIMLIB_ERR_READLINK]
= 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]
= T("The WIM file is marked with an unknown version number"),
[WIMLIB_ERR_UNSUPPORTED]
= T("The requested operation is unsupported"),
+ [WIMLIB_ERR_VOLUME_LACKS_FEATURES]
+ = T("The volume did not support a feature necessary to complete the operation"),
[WIMLIB_ERR_WRITE]
= T("Failed to write data to a file"),
[WIMLIB_ERR_XML]
}
}
}
+
+tchar *
+canonicalize_fs_path(const tchar *fs_path)
+{
+ tchar *canonical_path;
+
+ if (!fs_path)
+ fs_path = T("");
+ canonical_path = TSTRDUP(fs_path);
+ zap_backslashes(canonical_path);
+ return canonical_path;
+}
+
+/* Strip leading and trailing slashes from a string. Also translates
+ * backslashes into forward slashes. */
+tchar *
+canonicalize_wim_path(const tchar *wim_path)
+{
+ tchar *p;
+ tchar *canonical_path;
+
+ if (wim_path == NULL) {
+ wim_path = T("");
+ } else {
+ while (*wim_path == T('/') || *wim_path == T('\\'))
+ wim_path++;
+ }
+ canonical_path = TSTRDUP(wim_path);
+ if (canonical_path) {
+ zap_backslashes(canonical_path);
+ for (p = tstrchr(canonical_path, T('\0')) - 1;
+ p >= canonical_path && *p == T('/');
+ p--)
+ {
+ *p = T('\0');
+ }
+ }
+ return canonical_path;
+}
+
+/* Like read(), but keep trying until everything has been written or we know for
+ * sure that there was an error (or end-of-file). */
+size_t
+full_read(int fd, void *buf, size_t count)
+{
+ ssize_t bytes_read;
+ size_t bytes_remaining;
+
+ for (bytes_remaining = count;
+ bytes_remaining != 0;
+ bytes_remaining -= bytes_read, buf += bytes_read)
+ {
+ bytes_read = read(fd, buf, bytes_remaining);
+ if (bytes_read <= 0) {
+ if (bytes_read == 0)
+ errno = EIO;
+ else if (errno == EINTR)
+ continue;
+ break;
+ }
+ }
+ return count - bytes_remaining;
+}
+
+/* Like write(), but keep trying until everything has been written or we know
+ * for sure that there was an error. */
+size_t
+full_write(int fd, const void *buf, size_t count)
+{
+ ssize_t bytes_written;
+ size_t bytes_remaining;
+
+ for (bytes_remaining = count;
+ bytes_remaining != 0;
+ bytes_remaining -= bytes_written, buf += bytes_written)
+ {
+ bytes_written = write(fd, buf, bytes_remaining);
+ if (bytes_written < 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+ }
+ return count - bytes_remaining;
+}
+
+/* Like pread(), but keep trying until everything has been read or we know for
+ * sure that there was an error (or end-of-file) */
+size_t
+full_pread(int fd, void *buf, size_t count, off_t offset)
+{
+ ssize_t bytes_read;
+ size_t bytes_remaining;
+
+ for (bytes_remaining = count;
+ bytes_remaining != 0;
+ bytes_remaining -= bytes_read, buf += bytes_read,
+ offset += bytes_read)
+ {
+ bytes_read = pread(fd, buf, bytes_remaining, offset);
+ if (bytes_read <= 0) {
+ if (bytes_read == 0)
+ errno = EIO;
+ else if (errno == EINTR)
+ continue;
+ break;
+ }
+ }
+ return count - 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_written;
+ size_t bytes_remaining;
+
+ for (bytes_remaining = count;
+ bytes_remaining != 0;
+ bytes_remaining -= bytes_written, buf += bytes_written,
+ offset += bytes_written)
+ {
+ bytes_written = pwrite(fd, buf, bytes_remaining, offset);
+ if (bytes_written < 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+ }
+ return count - bytes_remaining;
+}
+
+/* Like writev(), but keep trying until everything has been written or we know
+ * for sure that there was an error. */
+size_t
+full_writev(int fd, struct iovec *iov, int iovcnt)
+{
+ size_t total_bytes_written = 0;
+ while (iovcnt > 0) {
+ ssize_t bytes_written;
+
+ bytes_written = writev(fd, iov, iovcnt);
+ if (bytes_written < 0) {
+ if (errno == EINTR)
+ continue;
+ break;
+ }
+ total_bytes_written += bytes_written;
+ while (bytes_written) {
+ if (bytes_written >= iov[0].iov_len) {
+ bytes_written -= iov[0].iov_len;
+ iov++;
+ iovcnt--;
+ } else {
+ iov[0].iov_base += bytes_written;
+ iov[0].iov_len -= bytes_written;
+ bytes_written = 0;
+ }
+ }
+ }
+ return total_bytes_written;
+}
+
+off_t
+filedes_offset(int fd)
+{
+ return lseek(fd, 0, SEEK_CUR);
+}