Example #1
0
/*
 * 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;
}
Example #2
0
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++;
}
Example #3
0
	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;
	}
Example #4
0
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;
}
Example #5
0
/**
 * 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;
}
Example #6
0
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);
}