/* * NOTE: 'ie' must be a copy of a real index entry. */ static int ntfs_ie_add_vcn(INDEX_ENTRY **ie) { INDEX_ENTRY *p, *old = *ie; old->length = cpu_to_le16(le16_to_cpu(old->length) + sizeof(VCN)); p = MEM2_realloc(old, le16_to_cpu(old->length)); if (!p) return STATUS_ERROR; p->ie_flags |= INDEX_ENTRY_NODE; *ie = p; return STATUS_OK; }
void RegisterDOL(u8 *dst, int len) { if(!dolList) dolList = (appDOL *) MEM2_alloc(sizeof(appDOL)); appDOL *tmp = (appDOL *) MEM2_realloc(dolList, (dolCount+1)*sizeof(appDOL)); if(!tmp) { MEM2_free(dolList); dolCount = 0; return; } dolList = tmp; dolList[dolCount].dst = dst; dolList[dolCount].len = len; dolCount++; }
void *__wrap_realloc(void *p, size_t size) { void *n; // ptr from mem2 if (((u32)p & 0x10000000) != 0 || (p == 0 && size > MEM2_PRIORITY_SIZE)) { n = MEM2_realloc(p, size); if (n != 0) { return n; } n = __real_malloc(size); if (n == 0) { return 0; } if (p != 0) { memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size); MEM2_free(p); } return n; } // ptr from malloc n = __real_realloc(p, size); if (n != 0) { return n; } n = MEM2_alloc(size); if (n == 0) { return 0; } if (p != 0) { memcpy(n, p, __real_malloc_usable_size(p) < size ? __real_malloc_usable_size(p) : size); __real_free(p); } return n; }
int ntfs_inode_real_close(ntfs_inode *ni) { int ret = -1; if (!ni) return 0; ntfs_log_enter("Entering for inode %lld\n", (long long)ni->mft_no); /* If we have dirty metadata, write it out. */ if (NInoDirty(ni) || NInoAttrListDirty(ni)) { if (ntfs_inode_sync(ni)) { if (errno != EIO) errno = EBUSY; goto err; } } /* Is this a base inode with mapped extent inodes? */ if (ni->nr_extents > 0) { while (ni->nr_extents > 0) { if (ntfs_inode_real_close(ni->extent_nis[0])) { if (errno != EIO) errno = EBUSY; goto err; } } } else if (ni->nr_extents == -1) { ntfs_inode **tmp_nis; ntfs_inode *base_ni; s32 i; /* * If the inode is an extent inode, disconnect it from the * base inode before destroying it. */ base_ni = ni->base_ni; for (i = 0; i < base_ni->nr_extents; ++i) { tmp_nis = base_ni->extent_nis; if (tmp_nis[i] != ni) continue; /* Found it. Disconnect. */ memmove(tmp_nis + i, tmp_nis + i + 1, (base_ni->nr_extents - i - 1) * sizeof(ntfs_inode *)); /* Buffer should be for multiple of four extents. */ if ((--base_ni->nr_extents) & 3) { i = -1; break; } /* * ElectricFence is unhappy with realloc(x,0) as free(x) * thus we explicitly separate these two cases. */ if (base_ni->nr_extents) { /* Resize the memory buffer. */ tmp_nis = MEM2_realloc(tmp_nis, base_ni->nr_extents * sizeof(ntfs_inode *)); /* Ignore errors, they don't really matter. */ if (tmp_nis) base_ni->extent_nis = tmp_nis; } else if (tmp_nis) { free(tmp_nis); base_ni->extent_nis = (ntfs_inode**)NULL; } /* Allow for error checking. */ i = -1; break; } /* * We could successfully sync, so only log this error * and try to sync other inode extents too. */ if (i != -1) ntfs_log_error("Extent inode %lld was not found\n", (long long)ni->mft_no); } __ntfs_inode_release(ni); ret = 0; err: ntfs_log_leave("\n"); return ret; }
/** * ntfs_inode_add_attrlist - add attribute list to inode and fill it * @ni: opened ntfs inode to which add attribute list * * Return 0 on success or -1 on error with errno set to the error code. * The following error codes are defined: * EINVAL - Invalid arguments were passed to the function. * EEXIST - Attribute list already exist. * EIO - Input/Ouput error occurred. * ENOMEM - Not enough memory to perform add. */ int ntfs_inode_add_attrlist(ntfs_inode *ni) { int err; ntfs_attr_search_ctx *ctx; u8 *al = NULL, *aln; int al_len = 0; ATTR_LIST_ENTRY *ale = NULL; ntfs_attr *na; if (!ni) { errno = EINVAL; ntfs_log_perror("%s", __FUNCTION__); return -1; } ntfs_log_trace("inode %llu\n", (unsigned long long) ni->mft_no); if (NInoAttrList(ni) || ni->nr_extents) { errno = EEXIST; ntfs_log_perror("Inode already has attribute list"); return -1; } /* Form attribute list. */ ctx = ntfs_attr_get_search_ctx(ni, NULL); if (!ctx) { err = errno; goto err_out; } /* Walk through all attributes. */ while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) { int ale_size; if (ctx->attr->type == AT_ATTRIBUTE_LIST) { err = EIO; ntfs_log_perror("Attribute list already present"); goto put_err_out; } ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * ctx->attr->name_length + 7) & ~7; al_len += ale_size; aln = MEM2_realloc(al, al_len); if (!aln) { err = errno; ntfs_log_perror("Failed to realloc %d bytes", al_len); goto put_err_out; } ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al)); al = aln; memset(ale, 0, ale_size); /* Add attribute to attribute list. */ ale->type = ctx->attr->type; ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * ctx->attr->name_length + 7) & ~7); ale->name_length = ctx->attr->name_length; ale->name_offset = (u8 *)ale->name - (u8 *)ale; if (ctx->attr->non_resident) ale->lowest_vcn = ctx->attr->lowest_vcn; else ale->lowest_vcn = 0; ale->mft_reference = MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number)); ale->instance = ctx->attr->instance; memcpy(ale->name, (u8 *)ctx->attr + le16_to_cpu(ctx->attr->name_offset), ctx->attr->name_length * sizeof(ntfschar)); ale = (ATTR_LIST_ENTRY *)(al + al_len); } /* Check for real error occurred. */ if (errno != ENOENT) { err = errno; ntfs_log_perror("%s: Attribute lookup failed, inode %lld", __FUNCTION__, (long long)ni->mft_no); goto put_err_out; } /* Set in-memory attribute list. */ ni->attr_list = al; ni->attr_list_size = al_len; NInoSetAttrList(ni); NInoAttrListSetDirty(ni); /* Free space if there is not enough it for $ATTRIBUTE_LIST. */ if (le32_to_cpu(ni->mrec->bytes_allocated) - le32_to_cpu(ni->mrec->bytes_in_use) < offsetof(ATTR_RECORD, resident_end)) { if (ntfs_inode_free_space(ni, offsetof(ATTR_RECORD, resident_end))) { /* Failed to free space. */ err = errno; ntfs_log_perror("Failed to free space for attrlist"); goto rollback; } } /* Add $ATTRIBUTE_LIST to mft record. */ if (ntfs_resident_attr_record_add(ni, AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0) < 0) { err = errno; ntfs_log_perror("Couldn't add $ATTRIBUTE_LIST to MFT"); goto rollback; } /* Resize it. */ na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); if (!na) { err = errno; ntfs_log_perror("Failed to open just added $ATTRIBUTE_LIST"); goto remove_attrlist_record; } if (ntfs_attr_truncate(na, al_len)) { err = errno; ntfs_log_perror("Failed to resize just added $ATTRIBUTE_LIST"); ntfs_attr_close(na); goto remove_attrlist_record;; } ntfs_attr_put_search_ctx(ctx); ntfs_attr_close(na); return 0; remove_attrlist_record: /* Prevent ntfs_attr_recorm_rm from freeing attribute list. */ ni->attr_list = NULL; NInoClearAttrList(ni); /* Remove $ATTRIBUTE_LIST record. */ ntfs_attr_reinit_search_ctx(ctx); if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { if (ntfs_attr_record_rm(ctx)) ntfs_log_perror("Rollback failed to remove attrlist"); } else ntfs_log_perror("Rollback failed to find attrlist"); /* Setup back in-memory runlist. */ ni->attr_list = al; ni->attr_list_size = al_len; NInoSetAttrList(ni); rollback: /* * Scan attribute list for attributes that placed not in the base MFT * record and move them to it. */ ntfs_attr_reinit_search_ctx(ctx); ale = (ATTR_LIST_ENTRY*)al; while ((u8*)ale < al + al_len) { if (MREF_LE(ale->mft_reference) != ni->mft_no) { if (!ntfs_attr_lookup(ale->type, ale->name, ale->name_length, CASE_SENSITIVE, sle64_to_cpu(ale->lowest_vcn), NULL, 0, ctx)) { if (ntfs_attr_record_move_to(ctx, ni)) ntfs_log_perror("Rollback failed to " "move attribute"); } else ntfs_log_perror("Rollback failed to find attr"); ntfs_attr_reinit_search_ctx(ctx); } ale = (ATTR_LIST_ENTRY*)((u8*)ale + le16_to_cpu(ale->length)); } /* Remove in-memory attribute list. */ ni->attr_list = NULL; ni->attr_list_size = 0; NInoClearAttrList(ni); NInoAttrListClearDirty(ni); put_err_out: ntfs_attr_put_search_ctx(ctx); err_out: free(al); errno = err; return -1; }
struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache, const struct CACHED_GENERIC *item, cache_compare compare) { struct CACHED_GENERIC *current; struct CACHED_GENERIC *before; struct HASH_ENTRY *link; int h; current = (struct CACHED_GENERIC*)NULL; if (cache) { if (cache->dohash) { /* * When possible, use the hash table to * find out whether the entry if present */ h = cache->dohash(item); link = cache->first_hash[h]; while (link && compare(link->entry, item)) link = link->next; if (link) { current = link->entry; } } if (!cache->dohash) { /* * Search sequentially in LRU list to locate the end, * and find out whether the entry is already in list * As we normally go to the end, no statistics is * kept. */ current = cache->most_recent_entry; while (current && compare(current, item)) { current = current->next; } } if (!current) { /* * Not in list, get a free entry or reuse the * last entry, and relink as head of list * Note : we assume at least three entries, so * before, previous and first are different when * an entry is reused. */ if (cache->free_entry) { current = cache->free_entry; cache->free_entry = cache->free_entry->next; if (item->varsize) { current->variable = ntfs_malloc( item->varsize); } else current->variable = (void*)NULL; current->varsize = item->varsize; if (!cache->oldest_entry) cache->oldest_entry = current; } else { /* reusing the oldest entry */ current = cache->oldest_entry; before = current->previous; before->next = (struct CACHED_GENERIC*)NULL; if (cache->dohash) drophashindex(cache,current, cache->dohash(current)); if (cache->dofree) cache->dofree(current); cache->oldest_entry = current->previous; if (item->varsize) { if (current->varsize) current->variable = MEM2_realloc( current->variable, item->varsize); else current->variable = ntfs_malloc( item->varsize); } else { if (current->varsize) free(current->variable); current->variable = (void*)NULL; } current->varsize = item->varsize; } current->next = cache->most_recent_entry; current->previous = (struct CACHED_GENERIC*)NULL; if (cache->most_recent_entry) cache->most_recent_entry->previous = current; cache->most_recent_entry = current; memcpy(current->payload, item->payload, cache->fixed_size); if (item->varsize) { if (current->variable) { memcpy(current->variable, item->variable, item->varsize); } else { /* * no more memory for variable part * recycle entry in free list * not an error, just uncacheable */ cache->most_recent_entry = current->next; current->next = cache->free_entry; cache->free_entry = current; current = (struct CACHED_GENERIC*)NULL; } } else { current->variable = (void*)NULL; current->varsize = 0; } if (cache->dohash && current) inserthashindex(cache,current); } cache->writes++; } return (current); }