X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Finode.c;h=ae971d8343da5bc239aec20cbf9401546b27efc2;hp=992a424378e0d6e7054f15036c42e5a1972396a8;hb=d444f2e5ddee51e7d9d0401cffcf88477c180422;hpb=ced16a28e197645a40fa04a54793d117a04526d7 diff --git a/src/inode.c b/src/inode.c index 992a4243..ae971d83 100644 --- a/src/inode.c +++ b/src/inode.c @@ -39,6 +39,8 @@ #include "wimlib/security.h" #include "wimlib/timestamp.h" +#include + /* Allocate a new inode. Set the timestamps to the current time. */ struct wim_inode * new_inode(void) @@ -108,6 +110,8 @@ free_inode(struct wim_inode *inode) 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)) @@ -136,10 +140,11 @@ ads_entry_has_name(const struct wim_ads_entry *entry, * * 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; @@ -147,11 +152,15 @@ inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name, 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); @@ -166,8 +175,6 @@ inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name, stream_name_utf16le_nbytes, default_ignore_case)) { - if (idx_ret) - *idx_ret = i; result = &inode->i_ads_entries[i]; break; } @@ -175,6 +182,8 @@ inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name, tstr_put_utf16le(stream_name_utf16le); + if (!result) + errno = ENOENT; return result; } @@ -188,6 +197,7 @@ do_inode_add_ads(struct wim_inode *inode, 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; @@ -230,24 +240,21 @@ inode_add_ads_utf16le(struct wim_inode *inode, /* * 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); @@ -256,27 +263,25 @@ inode_add_ads(struct wim_inode *inode, const tchar *stream_name) 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 @@ -294,33 +299,29 @@ int inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len, struct wim_lookup_table *lookup_table) { + wimlib_assert(inode->i_resolved); inode->i_lte = new_stream_from_data_buffer(data, len, lookup_table); if (inode->i_lte == NULL) return WIMLIB_ERR_NOMEM; - inode->i_resolved = 1; return 0; } /* 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], @@ -328,87 +329,6 @@ inode_remove_ads(struct wim_inode *inode, u16 idx, 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. *