⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 index.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 3 页
字号:
	return STATUS_OK;}static int ntfs_ih_insert(INDEX_HEADER *ih, INDEX_ENTRY *orig_ie, VCN new_vcn, 			  int pos){	INDEX_ENTRY *ie_node, *ie;	int ret = STATUS_ERROR;	VCN old_vcn;		ntfs_log_trace("Entering\n");		ie = ntfs_ie_dup(orig_ie);	if (!ie)		return STATUS_ERROR;		if (!(ie->ie_flags & INDEX_ENTRY_NODE))		if (ntfs_ie_add_vcn(&ie))			goto out;	ie_node = ntfs_ie_get_by_pos(ih, pos);	old_vcn = ntfs_ie_get_vcn(ie_node);	ntfs_ie_set_vcn(ie_node, new_vcn);		ntfs_ie_insert(ih, ie, ie_node);	ntfs_ie_set_vcn(ie_node, old_vcn);	ret = STATUS_OK;out:		free(ie);		return ret;}static VCN ntfs_icx_parent_vcn(ntfs_index_context *icx){	return icx->parent_vcn[icx->pindex];}static VCN ntfs_icx_parent_pos(ntfs_index_context *icx){	return icx->parent_pos[icx->pindex];}static int ntfs_ir_insert_median(ntfs_index_context *icx, INDEX_ENTRY *median,				 VCN new_vcn){	u32 new_size;	int ret;		ntfs_log_trace("Entering\n");		icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len);	if (!icx->ir)		return STATUS_ERROR;	new_size = le32_to_cpu(icx->ir->index.index_length) + 			le16_to_cpu(median->length);	if (!(median->ie_flags & INDEX_ENTRY_NODE))		new_size += sizeof(VCN);	ret = ntfs_ir_make_space(icx, new_size);	if (ret != STATUS_OK)		return ret;		icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len);	if (!icx->ir)		return STATUS_ERROR;	return ntfs_ih_insert(&icx->ir->index, median, new_vcn, 			      ntfs_icx_parent_pos(icx));}static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib);/** * On success return STATUS_OK or STATUS_KEEP_SEARCHING. * On error return STATUS_ERROR. */static int ntfs_ib_insert(ntfs_index_context *icx, INDEX_ENTRY *ie, VCN new_vcn){			  	INDEX_BLOCK *ib;	u32 idx_size, allocated_size;	int err = STATUS_ERROR;	VCN old_vcn;	ntfs_log_trace("Entering\n");		ib = ntfs_malloc(icx->block_size);	if (!ib)		return -1;		old_vcn = ntfs_icx_parent_vcn(icx);		if (ntfs_ib_read(icx, old_vcn, ib))		goto err_out;	idx_size       = le32_to_cpu(ib->index.index_length);	allocated_size = le32_to_cpu(ib->index.allocated_size);	/* FIXME: sizeof(VCN) should be included only if ie has no VCN */	if (idx_size + le16_to_cpu(ie->length) + sizeof(VCN) > allocated_size) {		err = ntfs_ib_split(icx, ib);		if (err == STATUS_OK)			err = STATUS_KEEP_SEARCHING;		goto err_out;	}		if (ntfs_ih_insert(&ib->index, ie, new_vcn, ntfs_icx_parent_pos(icx)))		goto err_out;		if (ntfs_ib_write(icx, ib))		goto err_out;		err = STATUS_OK;err_out:		free(ib);	return err;}/** * ntfs_ib_split - Split an index block *  * On success return STATUS_OK or STATUS_KEEP_SEARCHING. * On error return is STATUS_ERROR. */static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib){			  	INDEX_ENTRY *median;	VCN new_vcn;	int ret;	ntfs_log_trace("Entering\n");		if (ntfs_icx_parent_dec(icx))		return STATUS_ERROR;		median  = ntfs_ie_get_median(&ib->index);	new_vcn = ntfs_ibm_get_free(icx);	if (new_vcn == -1)		return STATUS_ERROR;		if (ntfs_ib_copy_tail(icx, ib, median, new_vcn)) {		ntfs_ibm_clear(icx, new_vcn);		return STATUS_ERROR;	}		if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT)		ret = ntfs_ir_insert_median(icx, median, new_vcn);	else		ret = ntfs_ib_insert(icx, median, new_vcn);		if (ret != STATUS_OK) {		ntfs_ibm_clear(icx, new_vcn);		return ret;	}		ret = ntfs_ib_cut_tail(icx, ib, median);		return ret;}static int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie){	char *fn;	INDEX_HEADER *ih;	int allocated_size, new_size;	int ret = STATUS_ERROR;		fn = ntfs_ie_filename_get(ie);	ntfs_log_trace("file: '%s'\n", fn);	ntfs_attr_name_free(&fn);		while (1) {						if (!ntfs_index_lookup(&ie->key, le16_to_cpu(ie->key_length), icx)) {			errno = EEXIST;			ntfs_log_perror("Index already have such entry");			goto err_out;		}		if (errno != ENOENT) {			ntfs_log_perror("Failed to find place for new entry");			goto err_out;		}				if (icx->is_in_root)			ih = &icx->ir->index;		else			ih = &icx->ib->index;				allocated_size = le32_to_cpu(ih->allocated_size);		new_size = le32_to_cpu(ih->index_length) + le16_to_cpu(ie->length);			if (new_size <= allocated_size)			break;				ntfs_log_trace("index block sizes: allocated: %d  needed: %d\n",			       allocated_size, new_size);				if (icx->is_in_root) {			if (ntfs_ir_make_space(icx, new_size) == STATUS_ERROR)				goto err_out;		} else {			if (ntfs_ib_split(icx, icx->ib) == STATUS_ERROR)				goto err_out;		}				ntfs_inode_mark_dirty(icx->actx->ntfs_ino);		ntfs_index_ctx_reinit(icx);	}		ntfs_ie_insert(ih, ie, icx->entry);	ntfs_index_entry_mark_dirty(icx);		ret = STATUS_OK;err_out:	ntfs_log_trace("%s\n", ret ? "Failed" : "Done");	return ret;}/** * ntfs_index_add_filename - add filename to directory index * @ni:		ntfs inode describing directory to which index add filename * @fn:		FILE_NAME attribute to add * @mref:	reference of the inode which @fn describes * * Return 0 on success or -1 on error with errno set to the error code. */int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref){	INDEX_ENTRY *ie;	ntfs_index_context *icx;	int fn_size, ie_size, err, ret = -1;	ntfs_log_trace("Entering\n");		if (!ni || !fn) {		ntfs_log_error("Invalid arguments.\n");		errno = EINVAL;		return -1;	}		fn_size = (fn->file_name_length * sizeof(ntfschar)) +			sizeof(FILE_NAME_ATTR);	ie_size = (sizeof(INDEX_ENTRY_HEADER) + fn_size + 7) & ~7;		ie = ntfs_calloc(ie_size);	if (!ie)		return -1;	ie->indexed_file = cpu_to_le64(mref);	ie->length 	 = cpu_to_le16(ie_size);	ie->key_length 	 = cpu_to_le16(fn_size);	memcpy(&ie->key, fn, fn_size);		icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4);	if (!icx)		goto out;		ret = ntfs_ie_add(icx, ie);	err = errno;	ntfs_index_ctx_put(icx);	errno = err;out:	free(ie);	return ret;}static int ntfs_ih_takeout(ntfs_index_context *icx, INDEX_HEADER *ih,			   INDEX_ENTRY *ie, INDEX_BLOCK *ib){	INDEX_ENTRY *ie_roam;	int ret = STATUS_ERROR;		ntfs_log_trace("Entering\n");		ie_roam = ntfs_ie_dup_novcn(ie);	if (!ie_roam)		return STATUS_ERROR;	ntfs_ie_delete(ih, ie);	if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT)		ntfs_inode_mark_dirty(icx->actx->ntfs_ino);	else		if (ntfs_ib_write(icx, ib))			goto out;		ntfs_index_ctx_reinit(icx);	ret = ntfs_ie_add(icx, ie_roam);out:	free(ie_roam);	return ret;}/** *  Used if an empty index block to be deleted has END entry as the parent *  in the INDEX_ROOT which is the only one there. */static void ntfs_ir_leafify(ntfs_index_context *icx, INDEX_HEADER *ih){	INDEX_ENTRY *ie;		ntfs_log_trace("Entering\n");		ie = ntfs_ie_get_first(ih);	ie->ie_flags &= ~INDEX_ENTRY_NODE;	ie->length = cpu_to_le16(le16_to_cpu(ie->length) - sizeof(VCN));		ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) - sizeof(VCN));	ih->ih_flags &= ~LARGE_INDEX;		/* Not fatal error */	ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length));}/** *  Used if an empty index block to be deleted has END entry as the parent  *  in the INDEX_ROOT which is not the only one there. */static int ntfs_ih_reparent_end(ntfs_index_context *icx, INDEX_HEADER *ih,				INDEX_BLOCK *ib){	INDEX_ENTRY *ie, *ie_prev;		ntfs_log_trace("Entering\n");		ie = ntfs_ie_get_by_pos(ih, ntfs_icx_parent_pos(icx));	ie_prev = ntfs_ie_prev(ih, ie);		ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(ie_prev));		return ntfs_ih_takeout(icx, ih, ie_prev, ib);}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;}static int ntfs_index_rm_node(ntfs_index_context *icx){	int entry_pos, pindex;	VCN vcn;	INDEX_BLOCK *ib = NULL;	INDEX_ENTRY *ie_succ, *ie, *entry = icx->entry;	INDEX_HEADER *ih;	u32 new_size;	int delta, ret = STATUS_ERROR;	ntfs_log_trace("Entering\n");		if (!icx->ia_na) {		icx->ia_na = ntfs_ia_open(icx, icx->ni);		if (!icx->ia_na)			return STATUS_ERROR;	}	ib = ntfs_malloc(icx->block_size);	if (!ib)		return STATUS_ERROR;		ie_succ = ntfs_ie_get_next(icx->entry);	entry_pos = icx->parent_pos[icx->pindex]++;	pindex = icx->pindex;descend:	vcn = ntfs_ie_get_vcn(ie_succ);	if (ntfs_ib_read(icx, vcn, ib))		goto out;		ie_succ = ntfs_ie_get_first(&ib->index);	if (ntfs_icx_parent_inc(icx))		goto out;		icx->parent_vcn[icx->pindex] = vcn;	icx->parent_pos[icx->pindex] = 0;	if ((ib->index.ih_flags & NODE_MASK) == INDEX_NODE)		goto descend;	if (ntfs_ih_zero_entry(&ib->index)) {		errno = EIO;		ntfs_log_perror("Empty index block");		goto out;	}	ie = ntfs_ie_dup(ie_succ);	if (!ie)		goto out;		if (ntfs_ie_add_vcn(&ie))		goto out2;	ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(icx->entry));	if (icx->is_in_root)		ih = &icx->ir->index;	else		ih = &icx->ib->index;	delta = le16_to_cpu(ie->length) - le16_to_cpu(icx->entry->length);	new_size = le32_to_cpu(ih->index_length) + delta;	if (delta > 0) {		if (icx->is_in_root) {			ret = ntfs_ir_make_space(icx, new_size);			if (ret != STATUS_OK)				goto out2;						ih = &icx->ir->index;			entry = ntfs_ie_get_by_pos(ih, entry_pos);					} else if (new_size > le32_to_cpu(ih->allocated_size)) {			icx->pindex = pindex;			ret = ntfs_ib_split(icx, icx->ib);			if (ret == STATUS_OK)				ret = STATUS_KEEP_SEARCHING;			goto out2;		}	}	ntfs_ie_delete(ih, entry);	ntfs_ie_insert(ih, ie, entry);		if (icx->is_in_root) {		if (ntfs_ir_truncate(icx, new_size))			goto out2;	} else		if (ntfs_icx_ib_write(icx))			goto out2;		ntfs_ie_delete(&ib->index, ie_succ);		if (ntfs_ih_zero_entry(&ib->index)) {		if (ntfs_index_rm_leaf(icx))			goto out2;	} else 		if (ntfs_ib_write(icx, ib))			goto out2;	ret = STATUS_OK;out2:	free(ie);out:	free(ib);	return ret;}/** * ntfs_index_rm - remove entry from the index * @icx:	index context describing entry to delete * * Delete entry described by @icx from the index. Index context is always  * reinitialized after use of this function, so it can be used for index  * lookup once again. * * Return 0 on success or -1 on error with errno set to the error code. */static int ntfs_index_rm(ntfs_index_context *icx){	INDEX_HEADER *ih;	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 (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;}int ntfs_index_remove(ntfs_inode *ni, const void *key, const int keylen){	int ret = STATUS_ERROR;	ntfs_index_context *icx;	icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4);	if (!icx)		return -1;	while (1) {						if (ntfs_index_lookup(key, keylen, icx))			goto err_out;		if (((FILE_NAME_ATTR *)icx->data)->file_attributes &				FILE_ATTR_REPARSE_POINT) {			errno = EOPNOTSUPP;			goto err_out;		}		ret = ntfs_index_rm(icx);		if (ret == STATUS_ERROR)			goto err_out;		else if (ret == STATUS_OK)			break;				ntfs_inode_mark_dirty(icx->actx->ntfs_ino);		ntfs_index_ctx_reinit(icx);	}	ntfs_inode_mark_dirty(icx->actx->ntfs_ino);out:		ntfs_index_ctx_put(icx);	return ret;err_out:	ret = STATUS_ERROR;	ntfs_log_perror("Delete failed");	goto out;}/** * ntfs_index_root_get - read the index root of an attribute * @ni:		open ntfs inode in which the ntfs attribute resides * @attr:	attribute for which we want its index root  * * This function will read the related index root an ntfs attribute. * * On success a buffer is allocated with the content of the index root * and which needs to be freed when it's not needed anymore. * * On error NULL is returned with errno set to the error code. */INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr){	ntfs_attr_search_ctx *ctx;	ntfschar *name;	INDEX_ROOT *root = NULL;	name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));	if (!ntfs_ir_lookup(ni, name, attr->name_length, &ctx))		return NULL;		root = ntfs_malloc(sizeof(INDEX_ROOT));	if (!root)		goto out;		*root = *((INDEX_ROOT *)((u8 *)ctx->attr +				le16_to_cpu(ctx->attr->value_offset)));out:		ntfs_attr_put_search_ctx(ctx);	return root;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -