* 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.
int
wim_inode_get_reparse_data(const struct wim_inode * restrict inode,
u8 * restrict rpbuf,
- u16 * restrict rpbuflen_ret)
+ u16 * restrict rpbuflen_ret,
+ struct wim_lookup_table_entry *lte_override)
{
struct wim_lookup_table_entry *lte;
int ret;
wimlib_assert(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT);
- lte = inode_unnamed_lte_resolved(inode);
- if (!lte) {
- ERROR("Reparse point has no reparse data!");
- return WIMLIB_ERR_INVALID_REPARSE_DATA;
+ if (!lte_override) {
+ lte = inode_unnamed_lte_resolved(inode);
+ if (!lte) {
+ ERROR("Reparse point has no reparse data!");
+ return WIMLIB_ERR_INVALID_REPARSE_DATA;
+ }
+ } else {
+ 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__)
-/* 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).
*
- * 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. */
+ * @buf
+ * Buffer into which to place the link target.
+ *
+ * @bufsize
+ * Available space in @buf, in bytes.
+ *
+ * @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)
+ char * restrict buf, size_t bufsize,
+ struct wim_lookup_table_entry *lte_override)
{
int ret;
struct reparse_buffer_disk rpbuf_disk _aligned_attribute(8);
wimlib_assert(inode_is_symlink(inode));
- if (wim_inode_get_reparse_data(inode, (u8*)&rpbuf_disk, &rpbuflen))
+ if (wim_inode_get_reparse_data(inode, (u8*)&rpbuf_disk, &rpbuflen,
+ lte_override))
return -EIO;
if (parse_reparse_data((const u8*)&rpbuf_disk, rpbuflen, &rpdata))