#include "wimlib/assert.h"
#include "wimlib/compiler.h"
#include "wimlib/endianness.h"
-#include "wimlib/dentry.h"
#include "wimlib/encoding.h"
#include "wimlib/error.h"
+#include "wimlib/inode.h"
#include "wimlib/lookup_table.h"
#include "wimlib/reparse.h"
#include "wimlib/resource.h"
-#ifdef __WIN32__
-# include "wimlib/win32.h" /* for win32_get_file_and_vol_ids() */
-#endif
-
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
static const utf16lechar volume_junction_prefix[11] = {
cpu_to_le16('\\'),
- cpu_to_le16('\\'),
+ cpu_to_le16('?'),
cpu_to_le16('?'),
cpu_to_le16('\\'),
cpu_to_le16('V'),
* Return value is:
*
* Non-negative integer:
- * The name is an absolute symbolic link in one of several formats,
- * and the return value is the number of UTF-16LE characters that need to
- * be advanced to reach a simple "absolute" path starting with a backslash
- * (i.e. skip over \??\ and/or drive letter)
+ * The name is an absolute symbolic link in one of several formats,
+ * and the return value is the number of UTF-16LE characters that need to
+ * be advanced to reach a simple "absolute" path starting with a backslash
+ * (i.e. skip over \??\ and/or drive letter)
* Negative integer:
* SUBST_NAME_IS_VOLUME_JUNCTION:
- * The name is a volume junction.
+ * The name is a volume junction.
* SUBST_NAME_IS_RELATIVE_LINK:
- * The name is a relative symbolic link.
+ * The name is a relative symbolic link.
* SUBST_NAME_IS_UNKNOWN:
* The name does not appear to be a valid symbolic link, junction,
* or mount point.
lte = lte_override;
}
- if (wim_resource_size(lte) > REPARSE_POINT_MAX_SIZE - 8) {
+ if (lte->size > REPARSE_POINT_MAX_SIZE - 8) {
ERROR("Reparse data is too long!");
return WIMLIB_ERR_INVALID_REPARSE_DATA;
}
- rpdatalen = wim_resource_size(lte);
+ rpdatalen = lte->size;
/* Read the data from the WIM file */
- ret = read_full_resource_into_buf(lte, rpbuf + 8);
+ ret = read_full_stream_into_buf(lte, rpbuf + 8);
if (ret)
return ret;
}
/* UNIX version of getting and setting the data in reparse points */
-#if !defined(__WIN32__)
+#ifndef __WIN32__
-/* Get the UNIX symlink target from a WIM inode. The inode may be either a
- * "real" symlink (reparse tag WIM_IO_REPARSE_TAG_SYMLINK), or it may be a
- * junction point (reparse tag WIM_IO_REPARSE_TAG_MOUNT_POINT).
+/*
+ * Get the UNIX-style symlink target from the WIM inode for a reparse point.
+ * Specifically, this translates the target from UTF-16 to the current multibyte
+ * encoding, strips the drive prefix if present, and replaces backslashes with
+ * forward slashes.
+ *
+ * @inode
+ * The inode to read the symlink from. It must be a reparse point with
+ * tag WIM_IO_REPARSE_TAG_SYMLINK (a real symlink) or
+ * WIM_IO_REPARSE_TAG_MOUNT_POINT (a mount point or junction point).
+ *
+ * @buf
+ * Buffer into which to place the link target.
+ *
+ * @bufsize
+ * Available space in @buf, in bytes.
*
- * This has similar semantics to the UNIX readlink() function, except the path
- * argument is swapped out with the `struct wim_inode' for a reparse point, and
- * on failure a negated error code is returned rather than -1 with errno set. */
+ * @lte_override
+ * If not NULL, the stream from which to read the reparse data. Otherwise,
+ * the reparse data will be read from the unnamed stream of @inode.
+ *
+ * If the entire symbolic link target was placed in the buffer, returns the
+ * number of bytes written. The resulting string is not null-terminated. If
+ * the symbolic link target was too large to be placed in the buffer, the first
+ * @bufsize bytes of it are placed in the buffer and
+ * -ENAMETOOLONG is returned. Otherwise, a negative errno value indicating
+ * another error is returned.
+ */
ssize_t
wim_inode_readlink(const struct wim_inode * restrict inode,
char * restrict buf, size_t bufsize,
return ret;
}
-#include <sys/stat.h>
-
-static int
-unix_get_ino_and_dev(const char *path, u64 *ino_ret, u64 *dev_ret)
-{
- struct stat stbuf;
- if (stat(path, &stbuf)) {
- if (errno != ENOENT)
- WARNING_WITH_ERRNO("Failed to stat \"%s\"", path);
- /* Treat as a link pointing outside the capture root (it
- * most likely is). */
- return WIMLIB_ERR_STAT;
- } else {
- *ino_ret = stbuf.st_ino;
- *dev_ret = stbuf.st_dev;
- return 0;
- }
-}
-
-#endif /* !defined(__WIN32__) */
-
-/* is_rp_path_separator() - characters treated as path separators in absolute
- * symbolic link targets */
-
-#ifdef __WIN32__
-# define is_rp_path_separator(c) ((c) == L'\\' || (c) == L'/')
-# define os_get_ino_and_dev win32_get_file_and_vol_ids
-#else
-# define is_rp_path_separator(c) ((c) == '/')
-# define os_get_ino_and_dev unix_get_ino_and_dev
-#endif
-
-/* Fix up absolute symbolic link targets--- mostly shared between UNIX and
- * Windows */
-tchar *
-capture_fixup_absolute_symlink(tchar *dest,
- u64 capture_root_ino, u64 capture_root_dev)
-{
- tchar *p = dest;
-
-#ifdef __WIN32__
- /* Skip drive letter */
- if (!is_rp_path_separator(*dest))
- p += 2;
-#endif
-
- DEBUG("Fixing symlink or junction \"%"TS"\"", dest);
- for (;;) {
- tchar save;
- int ret;
- u64 ino;
- u64 dev;
-
- while (is_rp_path_separator(*p))
- p++;
-
- save = *p;
- *p = T('\0');
- ret = os_get_ino_and_dev(dest, &ino, &dev);
- *p = save;
-
- if (ret) /* stat() failed before we got to the capture root---
- assume the link points outside it. */
- return NULL;
-
- if (ino == capture_root_ino && dev == capture_root_dev) {
- /* Link points inside capture root. Return abbreviated
- * path. */
- if (*p == T('\0'))
- *(p - 1) = OS_PREFERRED_PATH_SEPARATOR;
- while (p - 1 >= dest && is_rp_path_separator(*(p - 1)))
- p--;
- #ifdef __WIN32__
- if (!is_rp_path_separator(dest[0])) {
- *--p = dest[1];
- *--p = dest[0];
- }
- #endif
- wimlib_assert(p >= dest);
- return p;
- }
-
- if (*p == T('\0')) {
- /* Link points outside capture root. */
- return NULL;
- }
-
- do {
- p++;
- } while (!is_rp_path_separator(*p) && *p != T('\0'));
- }
-}
+#endif /* !__WIN32__ */