X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fdentry.c;h=324fbcf8a63b4f72dba20625fa927d6cbcaf48c4;hb=65adcad3e3d5eb01aaaf0dab9d3e509364dac673;hp=62283c18b2e7a15f49c9ebc40f5b641ed635ff59;hpb=b79d426cd90c506974f6c956a9af141b5d257d42;p=wimlib diff --git a/src/dentry.c b/src/dentry.c index 62283c18..324fbcf8 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -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/. */ /* @@ -59,14 +58,15 @@ # include "config.h" #endif +#include + #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 +#include "wimlib/paths.h" /* On-disk format of a WIM dentry (directory entry), located in the metadata * resource for a WIM image. */ @@ -299,7 +299,7 @@ dentry_set_name_utf16le(struct wim_dentry *dentry, const utf16lechar *name, * indices. For dentries that are currently linked into the tree, use * rename_wim_path(). * - * Returns 0 or an error code resulting from string conversion. + * Returns 0 or an error code resulting from a failed string conversion. */ int dentry_set_name(struct wim_dentry *dentry, const tchar *name) @@ -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 @@ -472,7 +486,7 @@ for_dentry_in_tree_depth(struct wim_dentry *root, * Whenever possible, use dentry_full_path() instead of calling this and * accessing _full_path directly. * - * Returns 0 or an error code resulting from string conversion. + * Returns 0 or an error code resulting from a failed string conversion. */ int calculate_dentry_full_path(struct wim_dentry *dentry) @@ -896,7 +910,7 @@ get_parent_dentry(WIMStruct *wim, const tchar *path, * * On success, returns 0 and a pointer to the new, allocated dentry is stored in * *dentry_ret. On failure, returns WIMLIB_ERR_NOMEM or an error code resulting - * from string conversion. + * from a failed string conversion. */ int new_dentry(const tchar *name, struct wim_dentry **dentry_ret) @@ -912,8 +926,6 @@ new_dentry(const tchar *name, struct wim_dentry **dentry_ret) ret = dentry_set_name(dentry, name); if (ret) { FREE(dentry); - ERROR("Failed to set name on new dentry with name \"%"TS"\"", - name); return ret; } } @@ -927,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); @@ -934,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; } @@ -999,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); } } @@ -1344,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; @@ -1357,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;