]> wimlib.net Git - wimlib/blobdiff - src/reparse.c
encoding.c: Upgrade upcase table and rewrite decompression code
[wimlib] / src / reparse.c
index 2f1b4169e609438d70d245d1e61d2ae4bf7a591d..0ae053b9cb06fa749d88dc8fb89edd5c6c88d82f 100644 (file)
@@ -144,7 +144,7 @@ make_reparse_buffer(const struct reparse_data * restrict rpdata,
        data = mempcpy(data, rpdata->print_name, rpdata->print_name_nbytes);
        *(utf16lechar*)data = cpu_to_le16(0);
        data += 2;
-       rpbuf_disk->rpdatalen = cpu_to_le16(data - rpbuf - 8);
+       rpbuf_disk->rpdatalen = cpu_to_le16(data - rpbuf - REPARSE_DATA_OFFSET);
        *rpbuflen_ret = data - rpbuf;
        return 0;
 }
@@ -179,8 +179,7 @@ wim_inode_get_reparse_data(const struct wim_inode * restrict inode,
        } else {
                struct wim_inode_stream *strm;
 
-               strm = inode_get_stream(inode, STREAM_TYPE_REPARSE_POINT,
-                                       NO_STREAM_NAME);
+               strm = inode_get_unnamed_stream(inode, STREAM_TYPE_REPARSE_POINT);
                if (strm)
                        blob = stream_blob_resolved(strm);
                else
@@ -215,7 +214,7 @@ wim_inode_get_reparse_data(const struct wim_inode * restrict inode,
         * XXX this could be one of the unknown fields in the WIM dentry. */
        rpbuf_disk->rpreserved = cpu_to_le16(0);
 
-       *rpbuflen_ret = rpdatalen + 8;
+       *rpbuflen_ret = rpdatalen + REPARSE_DATA_OFFSET;
        return 0;
 }
 
@@ -311,7 +310,7 @@ parse_substitute_name(const utf16lechar *substitute_name,
 /*
  * 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
+ * encoding, strips the drive prefix if present, and swaps backslashes and
  * forward slashes.
  *
  * @inode
@@ -385,9 +384,12 @@ wim_inode_readlink(const struct wim_inode * restrict inode,
        }
 
 out_translate_slashes:
-       for (size_t i = 0; i < link_target_len; i++)
+       for (size_t i = 0; i < link_target_len; i++) {
                if (translated_target[i] == '\\')
                        translated_target[i] = '/';
+               else if (translated_target[i] == '/')
+                       translated_target[i] = '\\';
+       }
 out_have_link:
        if (link_target_len > bufsize) {
                link_target_len = bufsize;
@@ -423,11 +425,14 @@ wim_inode_set_symlink(struct wim_inode *inode, const char *target,
        ret = tstr_to_utf16le(target, strlen(target),
                              &name_utf16le, &name_utf16le_nbytes);
        if (ret)
-               return ret;
+               goto out;
 
-       for (size_t i = 0; i < name_utf16le_nbytes / 2; i++)
+       for (size_t i = 0; i < name_utf16le_nbytes / 2; i++) {
                if (name_utf16le[i] == cpu_to_le16('/'))
                        name_utf16le[i] = cpu_to_le16('\\');
+               else if (name_utf16le[i] == cpu_to_le16('\\'))
+                       name_utf16le[i] = cpu_to_le16('/');
+       }
 
        /* Compatability notes:
         *
@@ -435,12 +440,9 @@ wim_inode_set_symlink(struct wim_inode *inode, const char *target,
         * is a relative symbolic link.  (Quite simple compared to the various
         * ways to provide Windows paths.)
         *
-        * To change a UNIX relative symbolic link to Windows format, we only
-        * need to translate it to UTF-16LE and replace forward slashes with
-        * backslashes.  We do not make any attempt to handle filename character
-        * problems, such as a link target that itself contains backslashes on
-        * UNIX.  Then, for these relative links, we set the reparse header
-        * @flags field to SYMBOLIC_LINK_RELATIVE.
+        * To change a UNIX relative symbolic link to Windows format, we need to
+        * translate it to UTF-16LE, swap forward slashes and backslashes, and
+        * set 'rpflags' to SYMBOLIC_LINK_RELATIVE.
         *
         * For UNIX absolute symbolic links, we must set the @flags field to 0.
         * Then, there are multiple options as to actually represent the
@@ -499,16 +501,22 @@ wim_inode_set_symlink(struct wim_inode *inode, const char *target,
        }
 
        ret = make_reparse_buffer(&rpdata, (u8*)&rpbuf_disk, &rpbuflen);
-       if (ret == 0) {
-               if (!inode_add_stream_with_data(inode,
-                                               STREAM_TYPE_REPARSE_POINT,
-                                               NO_STREAM_NAME,
-                                               (u8*)&rpbuf_disk + 8,
-                                               rpbuflen - 8,
-                                               blob_table))
-                       ret = WIMLIB_ERR_NOMEM;
-       }
+       if (ret)
+               goto out_free_name;
+
+       ret = WIMLIB_ERR_NOMEM;
+       if (!inode_add_stream_with_data(inode,
+                                       STREAM_TYPE_REPARSE_POINT,
+                                       NO_STREAM_NAME,
+                                       (u8*)&rpbuf_disk + REPARSE_DATA_OFFSET,
+                                       rpbuflen - REPARSE_DATA_OFFSET,
+                                       blob_table))
+               goto out_free_name;
+
+       ret = 0;
+out_free_name:
        FREE(name_utf16le);
+out:
        return ret;
 }