+/* Return %true iff @dentry has the UTF-8 file name @name that has length
+ * @name_len bytes. */
+static bool dentry_has_name(const struct dentry *dentry, const char *name,
+ size_t name_len)
+{
+ if (dentry->file_name_utf8_len != name_len)
+ return false;
+ return memcmp(dentry->file_name_utf8, name, name_len) == 0;
+}
+
+/* Return %true iff the alternate data stream entry @entry has the UTF-8 stream
+ * name @name that has length @name_len bytes. */
+static inline bool ads_entry_has_name(const struct ads_entry *entry,
+ const char *name, size_t name_len)
+{
+ if (entry->stream_name_utf8_len != name_len)
+ return false;
+ return memcmp(entry->stream_name_utf8, name, name_len) == 0;
+}
+
+/* Duplicates a UTF-8 name into UTF-8 and UTF-16 strings and returns the strings
+ * and their lengths in the pointer arguments */
+int get_names(char **name_utf16_ret, char **name_utf8_ret,
+ u16 *name_utf16_len_ret, u16 *name_utf8_len_ret,
+ const char *name)
+{
+ size_t utf8_len;
+ size_t utf16_len;
+ char *name_utf16, *name_utf8;
+
+ utf8_len = strlen(name);
+
+ name_utf16 = utf8_to_utf16(name, utf8_len, &utf16_len);
+
+ if (!name_utf16)
+ return WIMLIB_ERR_NOMEM;
+
+ name_utf8 = MALLOC(utf8_len + 1);
+ if (!name_utf8) {
+ FREE(name_utf8);
+ return WIMLIB_ERR_NOMEM;
+ }
+ memcpy(name_utf8, name, utf8_len + 1);
+ FREE(*name_utf8_ret);
+ FREE(*name_utf16_ret);
+ *name_utf8_ret = name_utf8;
+ *name_utf16_ret = name_utf16;
+ *name_utf8_len_ret = utf8_len;
+ *name_utf16_len_ret = utf16_len;
+ return 0;
+}
+
+/* Changes the name of a dentry to @new_name. Only changes the file_name and
+ * file_name_utf8 fields; does not change the short_name, short_name_utf8, or
+ * full_path_utf8 fields. Also recalculates its length. */
+static int change_dentry_name(struct dentry *dentry, const char *new_name)
+{
+ int ret;
+
+ ret = get_names(&dentry->file_name, &dentry->file_name_utf8,
+ &dentry->file_name_len, &dentry->file_name_utf8_len,
+ new_name);
+ FREE(dentry->short_name);
+ dentry->short_name_len = 0;
+ if (ret == 0)
+ dentry->length = dentry_correct_length(dentry);
+ return ret;
+}
+
+/*
+ * Changes the name of an alternate data stream */
+static int change_ads_name(struct ads_entry *entry, const char *new_name)
+{
+ return get_names(&entry->stream_name, &entry->stream_name_utf8,
+ &entry->stream_name_len,
+ &entry->stream_name_utf8_len,
+ new_name);
+}
+
+/* Returns the total length of a WIM alternate data stream entry on-disk,
+ * including the stream name, the null terminator, AND the padding after the
+ * entry to align the next one (or the next dentry) on an 8-byte boundary. */
+static u64 ads_entry_total_length(const struct ads_entry *entry)
+{
+ u64 len = WIM_ADS_ENTRY_DISK_SIZE;
+ if (entry->stream_name_len)
+ len += entry->stream_name_len + 2;
+ return (len + 7) & ~7;
+}
+
+