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

📄 dir.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
				INDEX_TYPE_ROOT, ir, ie, dirent, filldir);		if (rc) {			ntfs_attr_put_search_ctx(ctx);			ctx = NULL;			goto err_out;		}	}	ntfs_attr_put_search_ctx(ctx);	ctx = NULL;	/* If there is no index allocation attribute we are finished. */	if (!ia_na)		goto EOD;	/* Advance *pos to the beginning of the index allocation. */	*pos = vol->mft_record_size;skip_index_root:	if (!ia_na)		goto done;	/* Allocate a buffer for the current index block. */	ia = ntfs_malloc(index_block_size);	if (!ia)		goto err_out;	bmp_na = ntfs_attr_open(dir_ni, AT_BITMAP, NTFS_INDEX_I30, 4);	if (!bmp_na) {		ntfs_log_perror("Failed to open index bitmap attribute");		goto dir_err_out;	}	/* Get the offset into the index allocation attribute. */	ia_pos = *pos - vol->mft_record_size;	bmp_pos = ia_pos >> index_block_size_bits;	if (bmp_pos >> 3 >= bmp_na->data_size) {		ntfs_log_error("Current index position exceeds index bitmap "				"size.\n");		goto dir_err_out;	}	bmp_buf_size = min(bmp_na->data_size - (bmp_pos >> 3), 4096);	bmp = ntfs_malloc(bmp_buf_size);	if (!bmp)		goto err_out;	br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);	if (br != bmp_buf_size) {		if (br != -1)			errno = EIO;		ntfs_log_perror("Failed to read from index bitmap attribute");		goto err_out;	}	bmp_buf_pos = 0;	/* If the index block is not in use find the next one that is. */	while (!(bmp[bmp_buf_pos >> 3] & (1 << (bmp_buf_pos & 7)))) {find_next_index_buffer:		bmp_pos++;		bmp_buf_pos++;		/* If we have reached the end of the bitmap, we are done. */		if (bmp_pos >> 3 >= bmp_na->data_size)			goto EOD;		ia_pos = bmp_pos << index_block_size_bits;		if (bmp_buf_pos >> 3 < bmp_buf_size)			continue;		/* Read next chunk from the index bitmap. */		bmp_buf_pos = 0;		if ((bmp_pos >> 3) + bmp_buf_size > bmp_na->data_size)			bmp_buf_size = bmp_na->data_size - (bmp_pos >> 3);		br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp);		if (br != bmp_buf_size) {			if (br != -1)				errno = EIO;			ntfs_log_perror("Failed to read from index bitmap attribute");			goto err_out;		}	}	ntfs_log_debug("Handling index block 0x%llx.\n", (long long)bmp_pos);	/* Read the index block starting at bmp_pos. */	br = ntfs_attr_mst_pread(ia_na, bmp_pos << index_block_size_bits, 1,			index_block_size, ia);	if (br != 1) {		if (br != -1)			errno = EIO;		ntfs_log_perror("Failed to read index block");		goto err_out;	}	ia_start = ia_pos & ~(s64)(index_block_size - 1);	if (sle64_to_cpu(ia->index_block_vcn) != ia_start >>			index_vcn_size_bits) {		ntfs_log_error("Actual VCN (0x%llx) of index buffer is different "				"from expected VCN (0x%llx) in inode 0x%llx.\n",				(long long)sle64_to_cpu(ia->index_block_vcn),				(long long)ia_start >> index_vcn_size_bits,				(unsigned long long)dir_ni->mft_no);		goto dir_err_out;	}	if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) {		ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode 0x%llx "				"has a size (%u) differing from the directory "				"specified size (%u).\n", (long long)ia_start >>				index_vcn_size_bits,				(unsigned long long)dir_ni->mft_no,				(unsigned) le32_to_cpu(ia->index.allocated_size)				+ 0x18, (unsigned)index_block_size);		goto dir_err_out;	}	index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);	if (index_end > (u8*)ia + index_block_size) {		ntfs_log_error("Size of index buffer (VCN 0x%llx) of directory inode "				"0x%llx exceeds maximum size.\n",				(long long)ia_start >> index_vcn_size_bits,				(unsigned long long)dir_ni->mft_no);		goto dir_err_out;	}	/* The first index entry. */	ie = (INDEX_ENTRY*)((u8*)&ia->index +			le32_to_cpu(ia->index.entries_offset));	/*	 * Loop until we exceed valid memory (corruption case) or until we	 * reach the last entry or until ntfs_filldir tells us it has had	 * enough or signals an error (both covered by the rc test).	 */	for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {		ntfs_log_debug("In index allocation, offset 0x%llx.\n",				(long long)ia_start + ((u8*)ie - (u8*)ia));		/* Bounds checks. */		if ((u8*)ie < (u8*)ia || (u8*)ie +				sizeof(INDEX_ENTRY_HEADER) > index_end ||				(u8*)ie + le16_to_cpu(ie->key_length) >				index_end) {			ntfs_log_error("Index entry out of bounds in directory inode "				"0x%llx.\n", (unsigned long long)dir_ni->mft_no);			goto dir_err_out;		}		/* The last entry cannot contain a name. */		if (ie->ie_flags & INDEX_ENTRY_END)			break;		/* Skip index entry if continuing previous readdir. */		if (ia_pos - ia_start > (u8*)ie - (u8*)ia)			continue;		/*		 * Submit the directory entry to ntfs_filldir(), which will		 * invoke the filldir() callback as appropriate.		 */		rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits,				INDEX_TYPE_ALLOCATION, ia, ie, dirent, filldir);		if (rc)			goto err_out;	}	goto find_next_index_buffer;EOD:	/* We are finished, set *pos to EOD. */	*pos = i_size + vol->mft_record_size;done:	free(ia);	free(bmp);	if (bmp_na)		ntfs_attr_close(bmp_na);	if (ia_na)		ntfs_attr_close(ia_na);	ntfs_log_debug("EOD, *pos 0x%llx, returning 0.\n", (long long)*pos);	return 0;dir_err_out:	errno = EIO;err_out:	eo = errno;	ntfs_log_trace("failed.\n");	if (ctx)		ntfs_attr_put_search_ctx(ctx);	free(ia);	free(bmp);	if (bmp_na)		ntfs_attr_close(bmp_na);	if (ia_na)		ntfs_attr_close(ia_na);	errno = eo;	return -1;}/** * __ntfs_create - create object on ntfs volume * @dir_ni:	ntfs inode for directory in which create new object * @name:	unicode name of new object * @name_len:	length of the name in unicode characters * @type:	type of the object to create * @dev:	major and minor device numbers (obtained from makedev()) * @target:	target in unicode (only for symlinks) * @target_len:	length of target in unicode characters * * Internal, use ntfs_create{,_device,_symlink} wrappers instead. * * @type can be: *	S_IFREG		to create regular file *	S_IFDIR		to create directory *	S_IFBLK		to create block device *	S_IFCHR		to create character device *	S_IFLNK		to create symbolic link *	S_IFIFO		to create FIFO *	S_IFSOCK	to create socket * other values are invalid. * * @dev is used only if @type is S_IFBLK or S_IFCHR, in other cases its value * ignored. * * @target and @target_len are used only if @type is S_IFLNK, in other cases * their value ignored. * * Return opened ntfs inode that describes created object on success or NULL * on error with errno set to the error code. */static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni,		ntfschar *name, u8 name_len, dev_t type, dev_t dev,		ntfschar *target, int target_len){	ntfs_inode *ni;	int rollback_data = 0, rollback_sd = 0;	FILE_NAME_ATTR *fn = NULL;	STANDARD_INFORMATION *si = NULL;	int err, fn_len, si_len;	ntfs_log_trace("Entering.\n");		/* Sanity checks. */	if (!dir_ni || !name || !name_len) {		ntfs_log_error("Invalid arguments.\n");		errno = EINVAL;		return NULL;	}		if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {		errno = EOPNOTSUPP;		return NULL;	}		ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);	if (!ni)		return NULL;	/*	 * Create STANDARD_INFORMATION attribute. Write STANDARD_INFORMATION	 * version 1.2, windows will upgrade it to version 3 if needed.	 */	si_len = offsetof(STANDARD_INFORMATION, v1_end);	si = ntfs_calloc(si_len);	if (!si) {		err = errno;		goto err_out;	}	si->creation_time = utc2ntfs(ni->creation_time);	si->last_data_change_time = utc2ntfs(ni->last_data_change_time);	si->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);	si->last_access_time = utc2ntfs(ni->last_access_time);	if (!S_ISREG(type) && !S_ISDIR(type)) {		si->file_attributes = FILE_ATTR_SYSTEM;		ni->flags = FILE_ATTR_SYSTEM;	}	/* Add STANDARD_INFORMATION to inode. */	if (ntfs_attr_add(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0,			(u8*)si, si_len)) {		err = errno;		ntfs_log_error("Failed to add STANDARD_INFORMATION "				"attribute.\n");		goto err_out;	}		if (ntfs_sd_add_everyone(ni)) {		err = errno;		goto err_out;	}	rollback_sd = 1;	if (S_ISDIR(type)) {		INDEX_ROOT *ir = NULL;		INDEX_ENTRY *ie;		int ir_len, index_len;		/* Create INDEX_ROOT attribute. */		index_len = sizeof(INDEX_HEADER) + sizeof(INDEX_ENTRY_HEADER);		ir_len = offsetof(INDEX_ROOT, index) + index_len;		ir = ntfs_calloc(ir_len);		if (!ir) {			err = errno;			goto err_out;		}		ir->type = AT_FILE_NAME;		ir->collation_rule = COLLATION_FILE_NAME;		ir->index_block_size = cpu_to_le32(ni->vol->indx_record_size);		if (ni->vol->cluster_size <= ni->vol->indx_record_size)			ir->clusters_per_index_block =					ni->vol->indx_record_size >>					ni->vol->cluster_size_bits;		else			ir->clusters_per_index_block = 					ni->vol->indx_record_size >>					ni->vol->sector_size_bits;		ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));		ir->index.index_length = cpu_to_le32(index_len);		ir->index.allocated_size = cpu_to_le32(index_len);		ie = (INDEX_ENTRY*)((u8*)ir + sizeof(INDEX_ROOT));		ie->length = cpu_to_le16(sizeof(INDEX_ENTRY_HEADER));		ie->key_length = 0;		ie->ie_flags = INDEX_ENTRY_END;		/* Add INDEX_ROOT attribute to inode. */		if (ntfs_attr_add(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4,				(u8*)ir, ir_len)) {			err = errno;			free(ir);			ntfs_log_error("Failed to add INDEX_ROOT attribute.\n");			goto err_out;		}		free(ir);	} else {		INTX_FILE *data;		int data_len;		switch (type) {			case S_IFBLK:			case S_IFCHR:				data_len = offsetof(INTX_FILE, device_end);				data = ntfs_malloc(data_len);				if (!data) {					err = errno;					goto err_out;				}				data->major = cpu_to_le64(major(dev));				data->minor = cpu_to_le64(minor(dev));				if (type == S_IFBLK)					data->magic = INTX_BLOCK_DEVICE;				if (type == S_IFCHR)					data->magic = INTX_CHARACTER_DEVICE;				break;			case S_IFLNK:				data_len = sizeof(INTX_FILE_TYPES) +						target_len * sizeof(ntfschar);				data = ntfs_malloc(data_len);				if (!data) {					err = errno;					goto err_out;				}				data->magic = INTX_SYMBOLIC_LINK;				memcpy(data->target, target,						target_len * sizeof(ntfschar));				break;			case S_IFSOCK:				data = NULL;				data_len = 1;				break;			default: /* FIFO or regular file. */				data = NULL;				data_len = 0;				break;		}		/* Add DATA attribute to inode. */		if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, (u8*)data,				data_len)) {			err = errno;			ntfs_log_error("Failed to add DATA attribute.\n");			free(data);			goto err_out;		}		rollback_data = 1;		free(data);	}	/* Create FILE_NAME attribute. */	fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);	fn = ntfs_calloc(fn_len);	if (!fn) {		err = errno;		goto err_out;	}	fn->parent_directory = MK_LE_MREF(dir_ni->mft_no,			le16_to_cpu(dir_ni->mrec->sequence_number));	fn->file_name_length = name_len;	fn->file_name_type = FILE_NAME_POSIX;	if (S_ISDIR(type))		fn->file_attributes = FILE_ATTR_I30_INDEX_PRESENT;	if (!S_ISREG(type) && !S_ISDIR(type))		fn->file_attributes = FILE_ATTR_SYSTEM;	fn->creation_time = utc2ntfs(ni->creation_time);	fn->last_data_change_time = utc2ntfs(ni->last_data_change_time);	fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);	fn->last_access_time = utc2ntfs(ni->last_access_time);	fn->data_size = cpu_to_sle64(ni->data_size);	fn->allocated_size = cpu_to_sle64(ni->allocated_size);	memcpy(fn->file_name, name, name_len * sizeof(ntfschar));	/* Add FILE_NAME attribute to inode. */	if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) {		err = errno;		ntfs_log_error("Failed to add FILE_NAME attribute.\n");		goto err_out;	}	/* Add FILE_NAME attribute to index. */	if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no,			le16_to_cpu(ni->mrec->sequence_number)))) {		err = errno;		ntfs_log_perror("Failed to add entry to the index");		goto err_out;	}	/* Set hard links count and directory flag. */	ni->mrec->link_count = cpu_to_le16(1);	if (S_ISDIR(type))		ni->mrec->flags |= MFT_RECORD_IS_DIRECTORY;

⌨️ 快捷键说明

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