+ link.rptag = WIM_IO_REPARSE_TAG_SYMLINK;
+ link.rpreserved = 0;
+
+ /* Note: an absolute link that was rewritten to be relative to another
+ * directory is assumed to either be empty or to have a leading slash.
+ * See unix_relativize_link_target(). */
+ if (*target == cpu_to_le16('\\') || !*target) {
+ /*
+ * UNIX link target was absolute. In this case we represent the
+ * link as a symlink reparse point with SYMBOLIC_LINK_RELATIVE
+ * cleared. For this to work we need to assign it a path that
+ * can be resolved from the root of the Windows NT kernel object
+ * namespace. We do this by using "\??\C:" as a dummy prefix.
+ *
+ * Note that we could instead represent UNIX absolute links by
+ * setting SYMBOLIC_LINK_RELATIVE and then leaving the path
+ * backslash-prefixed like "\Users\Public". On Windows this is
+ * valid and denotes a path relative to the root of the
+ * filesystem on which the reparse point resides. The problem
+ * with this is that neither WIMGAPI nor wimlib (on Windows)
+ * will do "reparse point fixups" when extracting such links
+ * (modifying the link target to point into the actual
+ * extraction directory). So for the greatest cross-platform
+ * consistency, we have to use the fake C: drive approach.
+ */
+ static const utf16lechar prefix[6] = {
+ cpu_to_le16('\\'),
+ cpu_to_le16('?'),
+ cpu_to_le16('?'),
+ cpu_to_le16('\\'),
+ cpu_to_le16('C'),
+ cpu_to_le16(':'),
+ };
+
+ /* Do not show \??\ in print name */
+ const size_t num_unprintable_chars = 4;
+
+ link.symlink_flags = 0;
+ link.substitute_name_nbytes = sizeof(prefix) + target_nbytes;
+ link.substitute_name = alloca(link.substitute_name_nbytes);
+ memcpy(link.substitute_name, prefix, sizeof(prefix));
+ memcpy(link.substitute_name + ARRAY_LEN(prefix), target, target_nbytes);
+ link.print_name_nbytes = link.substitute_name_nbytes -
+ (num_unprintable_chars * sizeof(utf16lechar));
+ link.print_name = link.substitute_name + num_unprintable_chars;
+ } else {
+ /* UNIX link target was relative. In this case we represent the
+ * link as a symlink reparse point with SYMBOLIC_LINK_RELATIVE
+ * set. This causes Windows to interpret the link relative to
+ * the directory containing the reparse point file. */
+ link.symlink_flags = SYMBOLIC_LINK_RELATIVE;
+ link.substitute_name_nbytes = target_nbytes;
+ link.substitute_name = target;
+ link.print_name_nbytes = target_nbytes;
+ link.print_name = target;