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

📄 dir.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
	ntfs_inode_mark_dirty(ni);	/* Done! */	free(fn);	free(si);	ntfs_log_trace("Done.\n");	return ni;err_out:	ntfs_log_trace("Failed.\n");	if (rollback_sd)		ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0);		if (rollback_data)		ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0);	/*	 * Free extent MFT records (should not exist any with current	 * ntfs_create implementation, but for any case if something will be	 * changed in the future).	 */	while (ni->nr_extents)		if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) {			err = errno;			ntfs_log_error("Failed to free extent MFT record.  "					"Leaving inconsistent metadata.\n");		}	if (ntfs_mft_record_free(ni->vol, ni))		ntfs_log_error("Failed to free MFT record.  "				"Leaving inconsistent metadata. Run chkdsk.\n");	free(fn);	free(si);	errno = err;	return NULL;}/** * Some wrappers around __ntfs_create() ... */ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,		dev_t type){	if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO &&			type != S_IFSOCK) {		ntfs_log_error("Invalid arguments.\n");		return NULL;	}	return __ntfs_create(dir_ni, name, name_len, type, 0, NULL, 0);}ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,		dev_t type, dev_t dev){	if (type != S_IFCHR && type != S_IFBLK) {		ntfs_log_error("Invalid arguments.\n");		return NULL;	}	return __ntfs_create(dir_ni, name, name_len, type, dev, NULL, 0);}ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, ntfschar *name, u8 name_len,		ntfschar *target, int target_len){	if (!target || !target_len) {		ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__,			       target, target_len);		return NULL;	}	return __ntfs_create(dir_ni, name, name_len, S_IFLNK, 0,			target, target_len);}int ntfs_check_empty_dir(ntfs_inode *ni){	ntfs_attr *na;	int ret = 0;		if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY))		return 0;	na = ntfs_attr_open(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4);	if (!na) {		errno = EIO;		ntfs_log_perror("Failed to open directory");		return -1;	}		/* Non-empty directory? */	if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){		/* Both ENOTEMPTY and EEXIST are ok. We use the more common. */		errno = ENOTEMPTY;		ntfs_log_debug("Directory is not empty\n");		ret = -1;	}		ntfs_attr_close(na);	return ret;}static int ntfs_check_unlinkable_dir(ntfs_inode *ni, FILE_NAME_ATTR *fn){	int link_count = le16_to_cpu(ni->mrec->link_count);	int ret;		ret = ntfs_check_empty_dir(ni);	if (!ret || errno != ENOTEMPTY)		return ret;	/* 	 * Directory is non-empty, so we can unlink only if there is more than	 * one "real" hard link, i.e. links aren't different DOS and WIN32 names	 */	if ((link_count == 1) || 	    (link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) {		errno = ENOTEMPTY;		ntfs_log_debug("Non-empty directory without hard links\n");		goto no_hardlink;	}		ret = 0;no_hardlink:		return ret;}/** * ntfs_delete - delete file or directory from ntfs volume * @ni:		ntfs inode for object to delte * @dir_ni:	ntfs inode for directory in which delete object * @name:	unicode name of the object to delete * @name_len:	length of the name in unicode characters * * @ni is always closed after the call to this function (even if it failed), * user does not need to call ntfs_inode_close himself. * * Return 0 on success or -1 on error with errno set to the error code. */int ntfs_delete(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len){	ntfs_attr_search_ctx *actx = NULL;	FILE_NAME_ATTR *fn = NULL;	BOOL looking_for_dos_name = FALSE, looking_for_win32_name = FALSE;	BOOL case_sensitive_match = TRUE;	int err = 0;	ntfs_log_trace("Entering.\n");		if (!ni || !dir_ni || !name || !name_len) {		ntfs_log_error("Invalid arguments.\n");		errno = EINVAL;		goto err_out;	}	if (ni->nr_extents == -1)		ni = ni->base_ni;	if (dir_ni->nr_extents == -1)		dir_ni = dir_ni->base_ni;	/*	 * Search for FILE_NAME attribute with such name. If it's in POSIX or	 * WIN32_AND_DOS namespace, then simply remove it from index and inode.	 * If filename in DOS or in WIN32 namespace, then remove DOS name first,	 * only then remove WIN32 name.	 */	actx = ntfs_attr_get_search_ctx(ni, NULL);	if (!actx)		goto err_out;search:	while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,			0, NULL, 0, actx)) {		char *s;		BOOL case_sensitive = IGNORE_CASE;		errno = 0;		fn = (FILE_NAME_ATTR*)((u8*)actx->attr +				le16_to_cpu(actx->attr->value_offset));		s = ntfs_attr_name_get(fn->file_name, fn->file_name_length);		ntfs_log_trace("name: '%s'  type: %d  dos: %d  win32: %d  "			       "case: %d\n", s, fn->file_name_type,			       looking_for_dos_name, looking_for_win32_name,			       case_sensitive_match);		ntfs_attr_name_free(&s);		if (looking_for_dos_name) {			if (fn->file_name_type == FILE_NAME_DOS)				break;			else				continue;		}		if (looking_for_win32_name) {			if  (fn->file_name_type == FILE_NAME_WIN32)				break;			else				continue;		}				/* Ignore hard links from other directories */		if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) {			ntfs_log_debug("MFT record numbers don't match "				       "(%llu != %llu)\n", dir_ni->mft_no, 				       MREF_LE(fn->parent_directory));			continue;		}		     		if (fn->file_name_type == FILE_NAME_POSIX || case_sensitive_match)			case_sensitive = CASE_SENSITIVE;				if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,					 name, name_len, case_sensitive, 					 ni->vol->upcase, ni->vol->upcase_len)){						if (fn->file_name_type == FILE_NAME_WIN32) {				looking_for_dos_name = TRUE;				ntfs_attr_reinit_search_ctx(actx);				continue;			}			if (fn->file_name_type == FILE_NAME_DOS)				looking_for_dos_name = TRUE;			break;		}	}	if (errno) {		/*		 * If case sensitive search failed, then try once again		 * ignoring case.		 */		if (errno == ENOENT && case_sensitive_match) {			case_sensitive_match = FALSE;			ntfs_attr_reinit_search_ctx(actx);			goto search;		}		goto err_out;	}		if (ntfs_check_unlinkable_dir(ni, fn) < 0)		goto err_out;			if (ntfs_index_remove(dir_ni, fn, le32_to_cpu(actx->attr->value_length)))		goto err_out;		if (ntfs_attr_record_rm(actx))		goto err_out;		ni->mrec->link_count = cpu_to_le16(le16_to_cpu(			ni->mrec->link_count) - 1);		ntfs_inode_mark_dirty(ni);	if (looking_for_dos_name) {		looking_for_dos_name = FALSE;		looking_for_win32_name = TRUE;		ntfs_attr_reinit_search_ctx(actx);		goto search;	}	/* TODO: Update object id, quota and securiry indexes if required. */	/*	 * If hard link count is not equal to zero then we are done. In other	 * case there are no reference to this inode left, so we should free all	 * non-resident attributes and mark all MFT record as not in use.	 */	if (ni->mrec->link_count) {		ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME);		goto ok;	}	ntfs_attr_reinit_search_ctx(actx);	while (!ntfs_attrs_walk(actx)) {		if (actx->attr->non_resident) {			runlist *rl;			rl = ntfs_mapping_pairs_decompress(ni->vol, actx->attr,					NULL);			if (!rl) {				err = errno;				ntfs_log_error("Failed to decompress runlist.  "						"Leaving inconsistent metadata.\n");				continue;			}			if (ntfs_cluster_free_from_rl(ni->vol, rl)) {				err = errno;				ntfs_log_error("Failed to free clusters.  "						"Leaving inconsistent metadata.\n");				continue;			}			free(rl);		}	}	if (errno != ENOENT) {		err = errno;		ntfs_log_error("Attribute enumeration failed.  "				"Probably leaving inconsistent metadata.\n");	}	/* All extents should be attached after attribute walk. */	while (ni->nr_extents)		if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) {			err = errno;			ntfs_log_error("Failed to free extent MFT record.  "					"Leaving inconsistent metadata.\n");		}	if (ntfs_mft_record_free(ni->vol, ni)) {		err = errno;		ntfs_log_error("Failed to free base MFT record.  "				"Leaving inconsistent metadata.\n");	}	ni = NULL;ok:		ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);out:	if (actx)		ntfs_attr_put_search_ctx(actx);	if (ntfs_inode_close(dir_ni) && !err)		err = errno;	if (ntfs_inode_close(ni) && !err)		err = errno;	if (err) {		errno = err;		ntfs_log_debug("Could not delete file: %s\n", strerror(errno));		return -1;	}	ntfs_log_trace("Done.\n");	return 0;err_out:	err = errno;	goto out;}/** * ntfs_link - create hard link for file or directory * @ni:		ntfs inode for object to create hard link * @dir_ni:	ntfs inode for directory in which new link should be placed * @name:	unicode name of the new link * @name_len:	length of the name in unicode characters * * NOTE: At present we allow creating hardlinks to directories, we use them * in a temporary state during rename. But it's defenitely bad idea to have * hard links to directories as a result of operation. * FIXME: Create internal  __ntfs_link that allows hard links to a directories * and external ntfs_link that do not. Write ntfs_rename that uses __ntfs_link. * * Return 0 on success or -1 on error with errno set to the error code. */int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len){	FILE_NAME_ATTR *fn = NULL;	int fn_len, err;	ntfs_log_trace("Entering.\n");		if (!ni || !dir_ni || !name || !name_len || 			ni->mft_no == dir_ni->mft_no) {		err = EINVAL;		ntfs_log_perror("ntfs_link wrong arguments");		goto err_out;	}		if (ni->flags & FILE_ATTR_REPARSE_POINT) {		err = EOPNOTSUPP;		goto err_out;	}		/* 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;	fn->file_attributes = ni->flags;	if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)		fn->file_attributes |= FILE_ATTR_I30_INDEX_PRESENT;	fn->allocated_size = cpu_to_sle64(ni->allocated_size);	fn->data_size = cpu_to_sle64(ni->data_size);	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);	memcpy(fn->file_name, name, name_len * sizeof(ntfschar));	/* 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 filename to the index");		goto err_out;	}	/* Add FILE_NAME attribute to inode. */	if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) {		ntfs_log_error("Failed to add FILE_NAME attribute.\n");		err = errno;		/* Try to remove just added attribute from index. */		if (ntfs_index_remove(dir_ni, fn, fn_len))			goto rollback_failed;		goto err_out;	}	/* Increment hard links count. */	ni->mrec->link_count = cpu_to_le16(le16_to_cpu(			ni->mrec->link_count) + 1);	/* Done! */	ntfs_inode_mark_dirty(ni);	free(fn);	ntfs_log_trace("Done.\n");	return 0;rollback_failed:	ntfs_log_error("Rollback failed. Leaving inconsistent metadata.\n");err_out:	free(fn);	errno = err;	return -1;}

⌨️ 快捷键说明

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