+ /* NTFS filename namespaces need careful consideration. A name for a
+ * NTFS file may be in either the POSIX, Win32, DOS, or Win32+DOS
+ * namespaces. A NTFS file (a.k.a. inode) may have multiple names in
+ * multiple directories (i.e. hard links); however, a NTFS file can have
+ * at most 1 DOS name total. Furthermore, a Win32 name is always
+ * associated with a DOS name (either as a Win32+DOS name, or a Win32
+ * name and a DOS name separately), which implies that a NTFS file can
+ * have at most 1 Win32 name.
+ *
+ * A WIM dentry just contains a "long name", which wimlib makes sure is
+ * non-empty, and a "short name", which may be empty. So, wimlib must
+ * map these to the correct NTFS names. wimlib collects all WIM
+ * dentries that map to the same NTFS inode and factors out the common
+ * information into a 'struct wim_inode', so this should make the
+ * mapping a little more obvious. As a NTFS file can have at most 1 DOS
+ * name, a WIM inode cannot have more than 1 dentry with a non-empty
+ * short name, and this is checked in the verify_inode() function in
+ * verify.c. Furthermore, a WIM dentry, if any, that has a DOS name
+ * must have a long name that corresponds to a Win32 name or Win32+DOS
+ * name.
+ *
+ * WIM dentries that have a long name but no associated short name are
+ * assumed to be in the POSIX namespace.
+ *
+ * So, given a WIM inode that is to map to a NTFS inode, we must apply
+ * the Win32 and DOS or Win32+DOS names, if they exist, then any
+ * additional (POSIX) names. A caveat when actually doing this: as
+ * confirmed by the libntfs-3g authors, ntfs_set_ntfs_dos_name() is only
+ * guaranteed to associate a DOS name with the appropriate long name if
+ * it's called when that long name is the only one in existence for that
+ * file. So, this implies that the correct ordering of function calls
+ * to extract a NTFS file are:
+ *
+ * if (file has a DOS name) {
+ * - Call ntfs_create() to create long name associated with
+ * the DOS name (this initially creates a POSIX name)
+ * - Call ntfs_set_ntfs_dos_name() to associate a DOS name
+ * with the long name just created. This either changes
+ * the POSIX name to Win32+DOS, or changes the POSIX name
+ * to Win32 and creates a separate DOS name.
+ * } else {
+ * - Call ntfs_create() to create the first link to the
+ * file in the POSIX namespace
+ * }
+ * - Call ntfs_link() to create the other names of the file, in the
+ * POSIX namespace.
+ */
+again:
+ orig_dentry = NULL;
+ if (!dentry->d_inode->i_dos_name_extracted &&
+ dentry->short_name_len == 0)
+ {
+ inode_for_each_dentry(other, dentry->d_inode) {
+ if (other->short_name_len != 0) {
+ orig_dentry = dentry;
+ dentry = other;
+ break;
+ }
+ }
+ }
+ dentry->d_inode->i_dos_name_extracted = 1;
+ ntfs_inode *dir_ni = dentry_open_parent_ni(dentry, vol);
+ if (dir_ni) {
+ ret = do_apply_dentry_ntfs(dentry, dir_ni, arg);
+ if (ret == 0 && orig_dentry != NULL) {
+ dentry = orig_dentry;
+ goto again;
+ }
+ } else {
+ ret = WIMLIB_ERR_NTFS_3G;