#include "wimlib/security.h"
#include "wimlib/timestamp.h"
+#include <errno.h>
+
/* Allocate a new inode. Set the timestamps to the current time. */
struct wim_inode *
new_inode(void)
destroy_ads_entry(&inode->i_ads_entries[i]);
FREE(inode->i_ads_entries);
}
+ if (inode->i_extra)
+ FREE(inode->i_extra);
/* HACK: This may instead delete the inode from i_list, but hlist_del()
* behaves the same as list_del(). */
if (!hlist_unhashed(&inode->i_hlist))
*
* If @p stream_name is the empty string, NULL is returned --- that is, this
* function will not return "unnamed" alternate data stream entries.
+ *
+ * If NULL is returned, errno is set.
*/
struct wim_ads_entry *
-inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name,
- u16 *idx_ret)
+inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name)
{
int ret;
const utf16lechar *stream_name_utf16le;
u16 i;
struct wim_ads_entry *result;
- if (inode->i_num_ads == 0)
+ if (inode->i_num_ads == 0) {
+ errno = ENOENT;
return NULL;
+ }
- if (stream_name[0] == T('\0'))
+ if (stream_name[0] == T('\0')) {
+ errno = ENOENT;
return NULL;
+ }
ret = tstr_get_utf16le_and_len(stream_name, &stream_name_utf16le,
&stream_name_utf16le_nbytes);
stream_name_utf16le_nbytes,
default_ignore_case))
{
- if (idx_ret)
- *idx_ret = i;
result = &inode->i_ads_entries[i];
break;
}
tstr_put_utf16le(stream_name_utf16le);
+ if (!result)
+ errno = ENOENT;
return result;
}
if (inode->i_num_ads >= 0xfffe) {
ERROR("Too many alternate data streams in one inode!");
+ errno = EFBIG;
return NULL;
}
num_ads = inode->i_num_ads + 1;
/*
* Add an alternate stream entry to a WIM inode. On success, returns a pointer
- * to the new entry; on failure, returns NULL.
+ * to the new entry; on failure, returns NULL and sets errno.
*/
struct wim_ads_entry *
inode_add_ads(struct wim_inode *inode, const tchar *stream_name)
{
utf16lechar *stream_name_utf16le = NULL;
size_t stream_name_utf16le_nbytes = 0;
- int ret;
struct wim_ads_entry *result;
- if (stream_name && *stream_name) {
- ret = tstr_to_utf16le(stream_name,
- tstrlen(stream_name) * sizeof(tchar),
- &stream_name_utf16le,
- &stream_name_utf16le_nbytes);
- if (ret)
+ if (stream_name && *stream_name)
+ if (tstr_to_utf16le(stream_name,
+ tstrlen(stream_name) * sizeof(tchar),
+ &stream_name_utf16le,
+ &stream_name_utf16le_nbytes))
return NULL;
- }
result = do_inode_add_ads(inode, stream_name_utf16le,
stream_name_utf16le_nbytes);
return result;
}
-int
+struct wim_ads_entry *
inode_add_ads_with_data(struct wim_inode *inode, const tchar *name,
const void *value, size_t size,
struct wim_lookup_table *lookup_table)
{
- struct wim_ads_entry *new_ads_entry;
+ struct wim_ads_entry *new_entry;
wimlib_assert(inode->i_resolved);
- new_ads_entry = inode_add_ads(inode, name);
- if (new_ads_entry == NULL)
- return WIMLIB_ERR_NOMEM;
+ new_entry = inode_add_ads(inode, name);
+ if (!new_entry)
+ return NULL;
- new_ads_entry->lte = new_stream_from_data_buffer(value, size,
- lookup_table);
- if (new_ads_entry->lte == NULL) {
- inode_remove_ads(inode, new_ads_entry - inode->i_ads_entries,
- lookup_table);
- return WIMLIB_ERR_NOMEM;
+ new_entry->lte = new_stream_from_data_buffer(value, size, lookup_table);
+ if (!new_entry->lte) {
+ inode_remove_ads(inode, new_entry, lookup_table);
+ return NULL;
}
- return 0;
+ return new_entry;
}
bool
/* Remove an alternate data stream from a WIM inode */
void
-inode_remove_ads(struct wim_inode *inode, u16 idx,
+inode_remove_ads(struct wim_inode *inode, struct wim_ads_entry *entry,
struct wim_lookup_table *lookup_table)
{
- struct wim_ads_entry *ads_entry;
struct wim_lookup_table_entry *lte;
+ unsigned idx = entry - inode->i_ads_entries;
wimlib_assert(idx < inode->i_num_ads);
wimlib_assert(inode->i_resolved);
- ads_entry = &inode->i_ads_entries[idx];
-
- DEBUG("Remove alternate data stream \"%"WS"\"", ads_entry->stream_name);
-
- lte = ads_entry->lte;
+ lte = entry->lte;
if (lte)
lte_decrement_refcnt(lte, lookup_table);
- destroy_ads_entry(ads_entry);
+ destroy_ads_entry(entry);
memmove(&inode->i_ads_entries[idx],
&inode->i_ads_entries[idx + 1],
inode->i_num_ads--;
}
-bool
-inode_has_unix_data(const struct wim_inode *inode)
-{
- for (u16 i = 0; i < inode->i_num_ads; i++)
- if (ads_entry_is_unix_data(&inode->i_ads_entries[i]))
- return true;
- return false;
-}
-
-#ifndef __WIN32__
-int
-inode_get_unix_data(const struct wim_inode *inode,
- struct wimlib_unix_data *unix_data,
- u16 *stream_idx_ret)
-{
- const struct wim_ads_entry *ads_entry;
- const struct wim_lookup_table_entry *lte;
- size_t size;
- int ret;
-
- wimlib_assert(inode->i_resolved);
-
- ads_entry = inode_get_ads_entry((struct wim_inode*)inode,
- WIMLIB_UNIX_DATA_TAG, NULL);
- if (ads_entry == NULL)
- return NO_UNIX_DATA;
-
- if (stream_idx_ret)
- *stream_idx_ret = ads_entry - inode->i_ads_entries;
-
- lte = ads_entry->lte;
- if (lte == NULL)
- return NO_UNIX_DATA;
-
- size = lte->size;
- if (size != sizeof(struct wimlib_unix_data))
- return BAD_UNIX_DATA;
-
- ret = read_full_stream_into_buf(lte, unix_data);
- if (ret)
- return ret;
-
- if (unix_data->version != 0)
- return BAD_UNIX_DATA;
- return 0;
-}
-
-int
-inode_set_unix_data(struct wim_inode *inode, u16 uid, u16 gid, u16 mode,
- struct wim_lookup_table *lookup_table, int which)
-{
- struct wimlib_unix_data unix_data;
- int ret;
- bool have_good_unix_data = false;
- bool have_unix_data = false;
- u16 stream_idx;
-
- if (!(which & UNIX_DATA_CREATE)) {
- ret = inode_get_unix_data(inode, &unix_data, &stream_idx);
- if (ret == 0 || ret == BAD_UNIX_DATA || ret > 0)
- have_unix_data = true;
- if (ret == 0)
- have_good_unix_data = true;
- }
- unix_data.version = 0;
- if (which & UNIX_DATA_UID || !have_good_unix_data)
- unix_data.uid = uid;
- if (which & UNIX_DATA_GID || !have_good_unix_data)
- unix_data.gid = gid;
- if (which & UNIX_DATA_MODE || !have_good_unix_data)
- unix_data.mode = mode;
- ret = inode_add_ads_with_data(inode, WIMLIB_UNIX_DATA_TAG,
- &unix_data,
- sizeof(struct wimlib_unix_data),
- lookup_table);
- if (ret == 0 && have_unix_data)
- inode_remove_ads(inode, stream_idx, lookup_table);
- return ret;
-}
-#endif /* __WIN32__ */
-
/*
* Resolve an inode's lookup table entries.
*
{
if (wimlib_print_errors) {
ERROR("\"%"TS"\": stream not found", inode_first_full_path(inode));
- tfprintf(stderr, T(" SHA-1 message digest of missing stream:\n "));
- print_hash(hash, stderr);
- tputc(T('\n'), stderr);
+ tfprintf(wimlib_error_file,
+ T(" SHA-1 message digest of missing stream:\n "));
+ print_hash(hash, wimlib_error_file);
+ tputc(T('\n'), wimlib_error_file);
}
return WIMLIB_ERR_RESOURCE_NOT_FOUND;
}
* Inode to load the alternate data streams into. @inode->i_num_ads must
* have been set to the number of alternate data streams that are expected.
*
- * @remaining_size:
+ * @nbytes_remaining_p:
* Number of bytes of data remaining in the buffer pointed to by @p.
+ * On success this will be updated to point just past the ADS entries.
*
* On success, inode->i_ads_entries is set to an array of `struct
* wim_ads_entry's of length inode->i_num_ads. On failure, @inode is not
*/
int
read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode,
- size_t nbytes_remaining)
+ size_t *nbytes_remaining_p)
{
+ size_t nbytes_remaining = *nbytes_remaining_p;
u16 num_ads;
struct wim_ads_entry *ads_entries;
int ret;
* that less than @length is actually remaining in the metadata
* resource. We should set the remaining bytes to 0 if this
* happens. */
- length = (length + 7) & ~(u64)7;
+ length = (length + 7) & ~7;
p += length;
if (nbytes_remaining < length)
nbytes_remaining = 0;
}
inode->i_ads_entries = ads_entries;
inode->i_next_stream_id = inode->i_num_ads + 1;
+ *nbytes_remaining_p = nbytes_remaining;
ret = 0;
goto out;
out_of_memory: