Example #1
0
/**
 * ntfs_index_ctx_reinit - reinitialize an index context
 * @icx:	index context to reinitialize
 *
 * Reinitialize the index context @icx so it can be used for ntfs_index_lookup.
 */
void ntfs_index_ctx_reinit(ntfs_index_context *icx)
{
	ntfs_log_trace("Entering\n");

	ntfs_index_ctx_free(icx);

	*icx = (ntfs_index_context) {
		.ni = icx->ni,
		.name = icx->name,
		.name_len = icx->name_len,
	};
}

static VCN *ntfs_ie_get_vcn_addr(INDEX_ENTRY *ie)
{
	return (VCN *)((u8 *)ie + le16_to_cpu(ie->length) - sizeof(VCN));
}

/**
 *  Get the subnode vcn to which the index entry refers.
 */
VCN ntfs_ie_get_vcn(INDEX_ENTRY *ie)
{
	return sle64_to_cpup(ntfs_ie_get_vcn_addr(ie));
}

static INDEX_ENTRY *ntfs_ie_get_first(INDEX_HEADER *ih)
{
	return (INDEX_ENTRY *)((u8 *)ih + le32_to_cpu(ih->entries_offset));
}

static INDEX_ENTRY *ntfs_ie_get_next(INDEX_ENTRY *ie)
{
	return (INDEX_ENTRY *)((char *)ie + le16_to_cpu(ie->length));
}

static u8 *ntfs_ie_get_end(INDEX_HEADER *ih)
{
	/* FIXME: check if it isn't overflowing the index block size */
	return (u8 *)ih + le32_to_cpu(ih->index_length);
}

static int ntfs_ie_end(INDEX_ENTRY *ie)
{
	return ie->ie_flags & INDEX_ENTRY_END || !ie->length;
}

/**
 *  Find the last entry in the index block
 */
static INDEX_ENTRY *ntfs_ie_get_last(INDEX_ENTRY *ie, char *ies_end)
{
	ntfs_log_trace("Entering\n");

	while ((char *)ie < ies_end && !ntfs_ie_end(ie))
		ie = ntfs_ie_get_next(ie);

	return ie;
}
Example #2
0
void ntfs_ih_filename_dump(INDEX_HEADER *ih)
{
	INDEX_ENTRY *ie;
	
	ntfs_log_trace("Entering\n");
	
	ie = ntfs_ie_get_first(ih);
	while (!ntfs_ie_end(ie)) {
		ntfs_ie_filename_dump(ie);
		ie = ntfs_ie_get_next(ie);
	}
}
Example #3
0
static int ntfs_index_rm_leaf(ntfs_index_context *icx)
{
	INDEX_BLOCK *ib = NULL;
	INDEX_HEADER *parent_ih;
	INDEX_ENTRY *ie;
	int ret = STATUS_ERROR;
	
	ntfs_log_trace("pindex: %d\n", icx->pindex);
	
	if (ntfs_icx_parent_dec(icx))
		return STATUS_ERROR;

	if (ntfs_ibm_clear(icx, icx->parent_vcn[icx->pindex + 1]))
		return STATUS_ERROR;
	
	if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT)
		parent_ih = &icx->ir->index;
	else {
		ib = ntfs_malloc(icx->block_size);
		if (!ib)
			return STATUS_ERROR;
		
		if (ntfs_ib_read(icx, ntfs_icx_parent_vcn(icx), ib))
			goto out;
	
		parent_ih = &ib->index;
	}
	
	ie = ntfs_ie_get_by_pos(parent_ih, ntfs_icx_parent_pos(icx));
	if (!ntfs_ie_end(ie)) {
		ret = ntfs_ih_takeout(icx, parent_ih, ie, ib);
		goto out;
	}
		
	if (ntfs_ih_zero_entry(parent_ih)) {
		
		if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) {
			ntfs_ir_leafify(icx, parent_ih);
			goto ok;
		}
		
		ret = ntfs_index_rm_leaf(icx);
		goto out;
	}
		
	if (ntfs_ih_reparent_end(icx, parent_ih, ib))
		goto out;
ok:	
	ret = STATUS_OK;
out:
	free(ib);
	return ret;
}
Example #4
0
static int ntfs_ih_numof_entries(INDEX_HEADER *ih)
{
	int n;
	INDEX_ENTRY *ie;
	u8 *end;
	
	ntfs_log_trace("Entering\n");
	
	end = ntfs_ie_get_end(ih);
	ie = ntfs_ie_get_first(ih);
	for (n = 0; !ntfs_ie_end(ie) && (u8 *)ie < end; n++)
		ie = ntfs_ie_get_next(ie);
	return n;
}
Example #5
0
/*static JPA*/
int ntfs_index_rm(ntfs_index_context *icx)
{
	INDEX_HEADER *ih = NULL;
	int err, ret = STATUS_OK;

	ntfs_log_trace("Entering\n");
	
	if (!icx || (!icx->ib && !icx->ir) || ntfs_ie_end(icx->entry)) {
		ntfs_log_error("Invalid arguments.\n");
		errno = EINVAL;
		goto err_out;
	}
	if (icx->is_in_root)
		ih = &icx->ir->index;
	else
		ih = &icx->ib->index;
	if(NULL == ih)
	{
        errno = EINVAL;
		goto err_out;
	}
	if (icx->entry->ie_flags & INDEX_ENTRY_NODE) {
		
		ret = ntfs_index_rm_node(icx);

	} else if (icx->is_in_root || !ntfs_ih_one_entry(ih)) {
		
		ntfs_ie_delete(ih, icx->entry);
		
		if (icx->is_in_root) {
			err = ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length));
			if (err != STATUS_OK)
				goto err_out;
		} else
			if (ntfs_icx_ib_write(icx))
				goto err_out;
	} else {
		if (ntfs_index_rm_leaf(icx))
			goto err_out;
	}
out:
	return ret;
err_out:
	ret = STATUS_ERROR;
	goto out;
}
Example #6
0
/** 
 * Find a key in the index block.
 * 
 * Return values:
 *   STATUS_OK with errno set to ESUCCESS if we know for sure that the 
 *             entry exists and @ie_out points to this entry.
 *   STATUS_NOT_FOUND with errno set to ENOENT if we know for sure the
 *                    entry doesn't exist and @ie_out is the insertion point.
 *   STATUS_KEEP_SEARCHING if we can't answer the above question and
 *                         @vcn will contain the node index block.
 *   STATUS_ERROR with errno set if on unexpected error during lookup.
 */
static int ntfs_ie_lookup(const void *key, const int key_len,
			  ntfs_index_context *icx, INDEX_HEADER *ih,
			  VCN *vcn, INDEX_ENTRY **ie_out)
{
	INDEX_ENTRY *ie;
	u8 *index_end;
	int rc, item = 0;
	 
	ntfs_log_trace("Entering\n");
	
	index_end = ntfs_ie_get_end(ih);
	
	/*
	 * Loop until we exceed valid memory (corruption case) or until we
	 * reach the last entry.
	 */
	for (ie = ntfs_ie_get_first(ih); ; ie = ntfs_ie_get_next(ie)) {
		/* Bounds checks. */
		if ((u8 *)ie + sizeof(INDEX_ENTRY_HEADER) > index_end ||
		    (u8 *)ie + le16_to_cpu(ie->length) > index_end) {
			errno = ERANGE;
			ntfs_log_error("Index entry out of bounds in inode "
				       "%llu.\n",
				       (unsigned long long)icx->ni->mft_no);
			return STATUS_ERROR;
		}
		/*
		 * The last entry cannot contain a key.  It can however contain
		 * a pointer to a child node in the B+tree so we just break out.
		 */
		if (ntfs_ie_end(ie))
			break;
		/*
		 * Not a perfect match, need to do full blown collation so we
		 * know which way in the B+tree we have to go.
		 */
		if (!icx->collate) {
			ntfs_log_error("Collation function not defined\n");
			errno = EOPNOTSUPP;
			return STATUS_ERROR;
		}
		rc = icx->collate(icx->ni->vol, key, key_len,
					&ie->key, le16_to_cpu(ie->key_length));
		if (rc == NTFS_COLLATION_ERROR) {
			ntfs_log_error("Collation error. Perhaps a filename "
				       "contains invalid characters?\n");
			errno = ERANGE;
			return STATUS_ERROR;
		}
		/*
		 * If @key collates before the key of the current entry, there
		 * is definitely no such key in this index but we might need to
		 * descend into the B+tree so we just break out of the loop.
		 */
		if (rc == -1)
			break;
		
		if (!rc) {
			*ie_out = ie;
			errno = 0;
			icx->parent_pos[icx->pindex] = item;
			return STATUS_OK;
		}
		
		item++;
	}
	/*
	 * We have finished with this index block without success. Check for the
	 * presence of a child node and if not present return with errno ENOENT,
	 * otherwise we will keep searching in another index block.
	 */
	if (!(ie->ie_flags & INDEX_ENTRY_NODE)) {
		ntfs_log_debug("Index entry wasn't found.\n");
		*ie_out = ie;
		errno = ENOENT;
		return STATUS_NOT_FOUND;
	}
	
	/* Get the starting vcn of the index_block holding the child node. */
	*vcn = ntfs_ie_get_vcn(ie);
	if (*vcn < 0) {
		errno = EINVAL;
		ntfs_log_perror("Negative vcn in inode %llu",
			       	(unsigned long long)icx->ni->mft_no);
		return STATUS_ERROR;
	}

	ntfs_log_trace("Parent entry number %d\n", item);
	icx->parent_pos[icx->pindex] = item;
	
	return STATUS_KEEP_SEARCHING;
}