]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
Do not use ADS entry workaround on encrypted files
[wimlib] / src / dentry.c
index 7b0f0d645554965bb8001760e76883273cd6f0e7..324fbcf8a63b4f72dba20625fa927d6cbcaf48c4 100644 (file)
@@ -5,19 +5,18 @@
 /*
  * Copyright (C) 2012, 2013, 2014 Eric Biggers
  *
- * This file is part of wimlib, a library for working with WIM files.
- *
- * wimlib is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 3 of the License, or (at your option) any later
- * version.
- *
- * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * wimlib; if not, see http://www.gnu.org/licenses/.
+ * This file is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This file is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file; if not, see http://www.gnu.org/licenses/.
  */
 
 /*
 #  include "config.h"
 #endif
 
+#include <errno.h>
+
 #include "wimlib/assert.h"
 #include "wimlib/dentry.h"
 #include "wimlib/inode.h"
 #include "wimlib/encoding.h"
 #include "wimlib/endianness.h"
 #include "wimlib/metadata.h"
-
-#include <errno.h>
+#include "wimlib/paths.h"
 
 /* On-disk format of a WIM dentry (directory entry), located in the metadata
  * resource for a WIM image.  */
@@ -348,14 +348,28 @@ ads_entry_out_total_length(const struct wim_ads_entry *entry)
  * though there is already a field in the dentry itself for the unnamed stream
  * reference, which then goes to waste.
  */
-static inline bool
+static bool
 inode_needs_dummy_stream(const struct wim_inode *inode)
 {
-       return (inode->i_num_ads > 0 &&
-               inode->i_num_ads < 0xffff && /* overflow check */
-               inode->i_canonical_streams); /* assume the dentry is okay if it
-                                               already had an unnamed ADS entry
-                                               when it was read in  */
+       /* Normal case  */
+       if (likely(inode->i_num_ads <= 0))
+               return false;
+
+       /* Overflow check  */
+       if (inode->i_num_ads >= 0xFFFF)
+               return false;
+
+       /* Assume the dentry is okay if it already had an unnamed ADS entry when
+        * it was read in.  */
+       if (!inode->i_canonical_streams)
+               return false;
+
+       /* We can't use use this workaround on encrypted files because WIMGAPI
+        * reports that the WIM is in an incorrect format.  */
+       if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED)
+               return false;
+
+       return true;
 }
 
 /* Calculate the total number of bytes that will be consumed when a dentry is
@@ -925,6 +939,7 @@ _new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret,
                       bool timeless)
 {
        struct wim_dentry *dentry;
+       struct wim_inode *inode;
        int ret;
 
        ret = new_dentry(name, &dentry);
@@ -932,15 +947,16 @@ _new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret,
                return ret;
 
        if (timeless)
-               dentry->d_inode = new_timeless_inode();
+               inode = new_timeless_inode();
        else
-               dentry->d_inode = new_inode();
-       if (dentry->d_inode == NULL) {
+               inode = new_inode();
+       if (!inode) {
                free_dentry(dentry);
                return WIMLIB_ERR_NOMEM;
        }
 
-       inode_add_dentry(dentry, dentry->d_inode);
+       d_associate(dentry, inode);
+
        *dentry_ret = dentry;
        return 0;
 }
@@ -997,19 +1013,17 @@ dentry_tree_clear_inode_visited(struct wim_dentry *root)
 /*
  * Free a WIM dentry.
  *
- * In addition to freeing the dentry itself, this decrements the link count of
- * the corresponding inode (if any).  If the inode's link count reaches 0, the
- * inode is freed as well.
+ * In addition to freeing the dentry itself, this disassociates the dentry from
+ * its inode.  If the inode is no longer in use, it will be freed as well.
  */
 void
 free_dentry(struct wim_dentry *dentry)
 {
        if (dentry) {
+               d_disassociate(dentry);
                FREE(dentry->file_name);
                FREE(dentry->short_name);
                FREE(dentry->_full_path);
-               if (dentry->d_inode)
-                       put_inode(dentry->d_inode);
                FREE(dentry);
        }
 }
@@ -1342,8 +1356,7 @@ read_dentry(const u8 * restrict buf, size_t buf_len,
        /* Read the filename if present.  Note: if the filename is empty, there
         * is no null terminator following it.  */
        if (file_name_nbytes) {
-               dentry->file_name = utf16le_dupz((const utf16lechar *)p,
-                                                file_name_nbytes);
+               dentry->file_name = utf16le_dupz(p, file_name_nbytes);
                if (dentry->file_name == NULL) {
                        ret = WIMLIB_ERR_NOMEM;
                        goto err_free_dentry;
@@ -1355,8 +1368,7 @@ read_dentry(const u8 * restrict buf, size_t buf_len,
        /* Read the short filename if present.  Note: if there is no short
         * filename, there is no null terminator following it. */
        if (short_name_nbytes) {
-               dentry->short_name = utf16le_dupz((const utf16lechar *)p,
-                                                 short_name_nbytes);
+               dentry->short_name = utf16le_dupz(p, short_name_nbytes);
                if (dentry->short_name == NULL) {
                        ret = WIMLIB_ERR_NOMEM;
                        goto err_free_dentry;