# 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. */
* 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
bool timeless)
{
struct wim_dentry *dentry;
+ struct wim_inode *inode;
int ret;
ret = new_dentry(name, &dentry);
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;
}
/*
* 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);
}
}
/* 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;
/* 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;