+/*
+ * Copyright (C) 2012 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 Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 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 Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with wimlib; if not, see http://www.gnu.org/licenses/.
+ */
+
#include "dentry.h"
#include "io.h"
#include "lookup_table.h"
#include "sha1.h"
+#include <errno.h>
/*
* Find the symlink target of a symbolic link or junction point in the WIM.
return buf;
}
+static const struct lookup_table_entry *
+dentry_first_lte(const struct dentry *dentry, const struct lookup_table *table)
+{
+ const struct lookup_table_entry *lte;
+ if (dentry->resolved) {
+ if (dentry->lte)
+ return dentry->lte;
+ for (u16 i = 0; i < dentry->num_ads; i++)
+ if (dentry->ads_entries[i].lte)
+ return dentry->ads_entries[i].lte;
+ } else {
+ const u8 *hash = dentry->hash;
+ u16 i = 0;
+ while (1) {
+ if ((lte = __lookup_resource(table, hash)))
+ break;
+ if (i == dentry->num_ads)
+ return NULL;
+ hash = dentry->ads_entries[i].hash;
+ i++;
+ }
+ }
+ return NULL;
+}
+
/* Get the symlink target from a dentry that's already checked to be either a
* "real" symlink or a junction point. */
ssize_t dentry_readlink(const struct dentry *dentry, char *buf, size_t buf_len,
const WIMStruct *w)
{
- struct resource_entry *res_entry;
- struct lookup_table_entry *lte;
- u16 i = 0;
- const u8 *hash = dentry->hash;
+ const struct resource_entry *res_entry;
+ const struct lookup_table_entry *lte;
wimlib_assert(dentry_is_symlink(dentry));
- while (1) {
- if ((lte = __lookup_resource(w->lookup_table, hash)))
- break;
- if (i == dentry->num_ads)
- return -EIO;
- hash = dentry->ads_entries[i].hash;
- i++;
- }
+ lte = dentry_first_lte(dentry, w->lookup_table);
+ if (!lte)
+ return -EIO;
+
res_entry = <e->resource_entry;
if (res_entry->original_size > 10000)
return -EIO;
if (!ads_entries)
return WIMLIB_ERR_NOMEM;
memcpy(ads_entries[1].hash, symlink_buf_hash, WIM_HASH_SIZE);
- dentry_free_ads_entries(dentry);
+ wimlib_assert(dentry->num_ads == 0);
+ wimlib_assert(!dentry->ads_entries);
+ /*dentry_free_ads_entries(dentry);*/
dentry->num_ads = 2;
dentry->ads_entries = ads_entries;
return 0;
}
int dentry_set_symlink(struct dentry *dentry, const char *target,
- struct lookup_table *lookup_table)
+ struct lookup_table *lookup_table,
+ struct lookup_table_entry **lte_ret)
{
int ret;
if (existing_lte) {
existing_lte->refcnt++;
+ lte = existing_lte;
} else {
DEBUG("Creating new lookup table entry for symlink buf");
lte = new_lookup_table_entry();
if (!existing_lte)
lookup_table_insert(lookup_table, lte);
+ if (lte_ret)
+ *lte_ret = lte;
return 0;
out_free_lte:
- FREE(lte);
+ if (lte != existing_lte)
+ FREE(lte);
out_free_symlink_buf:
FREE(symlink_buf);
return ret;