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

📄 dir.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 charcters * * 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, u8 target_len){	ntfs_inode *ni;	int rollback_data = 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;	}	/* Allocate MFT record for new file. */	ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);	if (!ni) {		err = errno;		ntfs_log_error("Failed to allocate new MFT record: %s.\n",				strerror(err));		errno = err;		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 = calloc(1, si_len);	if (!si) {		err = errno;		ntfs_log_error("Not enough memory.\n");		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 (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 = calloc(1, ir_len);		if (!ir) {			err = errno;			ntfs_log_error("Not enough memory.\n");			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_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->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;		}	} else {		INTX_FILE *data;		int data_len;		switch (type) {			case S_IFBLK:			case S_IFCHR:				data_len = offsetof(INTX_FILE, device_end);				data = malloc(data_len);				if (!data) {					err = errno;					ntfs_log_error("Not enough memory for "							"content of DATA "							"attribute.\n");					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 = malloc(data_len);				if (!data) {					err = errno;					ntfs_log_error("Not enough memory for "							"content of DATA "							"attribute.\n");					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");			goto err_out;		}		rollback_data = 1;		free(data);	}	/* Create FILE_NAME attribute. */	fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);	fn = calloc(1, fn_len);	if (!fn) {		err = errno;		ntfs_log_error("Not enough memory.\n");		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);	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_error("Failed to add entry to the index: %s.\n",				strerror(err));		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;	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_data) {		ntfs_attr *na;		na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);		if (!na)			ntfs_log_perror("Failed to open data attribute of "					" inode 0x%llx. Run chkdsk.\n",					(unsigned long long)ni->mft_no);		else if (ntfs_attr_rm(na))			ntfs_log_perror("Failed to remove data attribute of "					"inode 0x%llx. Run chkdsk.\n",					(unsigned long long)ni->mft_no);	}	/*	 * 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, u8 target_len){	if (!target || !target_len) {		ntfs_log_error("Invalid arguments.\n");		return NULL;	}	return __ntfs_create(dir_ni, name, name_len, S_IFLNK, 0,			target, target_len);}/** * 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;	ntfs_index_context *ictx = 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. Mark WIN32 name as POSIX name to prevent	 * chkdsk to complain about DOS name absentation, in case if DOS name	 * had been successfully deleted, but WIN32 name removing failed.	 */	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)) {		errno = 0;		fn = (FILE_NAME_ATTR*)((u8*)actx->attr +				le16_to_cpu(actx->attr->value_offset));		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;		}		if (dir_ni->mft_no == MREF_LE(fn->parent_directory) &&				ntfs_names_are_equal(fn->file_name,				fn->file_name_length, name,				name_len, (fn->file_name_type ==				FILE_NAME_POSIX || case_sensitive_match) ?				CASE_SENSITIVE : IGNORE_CASE, 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 deleting directory check it to be empty. */	if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {		ntfs_attr *na;		na = ntfs_attr_open(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4);		if (!na) {			ntfs_log_error("Corrupt directory or library bug.\n");			errno = EIO;			goto err_out;		}		/*		 * Do not allow non-empty directory deletion if hard links count		 * is 1 (always) or 2 (in case if filename in DOS namespace,		 * because we delete it first in filen which have both WIN32 and		 * DOS names).		 */		if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(				INDEX_ENTRY_HEADER)) && (le16_to_cpu(				ni->mrec->link_count) == 1 ||				(le16_to_cpu(ni->mrec->link_count) == 2 &&				fn->file_name_type == FILE_NAME_DOS))) {			ntfs_attr_close(na);			ntfs_log_error("Directory is not empty.\n");			errno = ENOTEMPTY;			goto err_out;		}		ntfs_attr_close(na);	}	/* Search for such FILE_NAME in index. */	ictx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);	if (!ictx)		goto err_out;	if (ntfs_index_lookup(fn, le32_to_cpu(actx->attr->value_length), ictx))		goto err_out;	/* Set namespace to POSIX for WIN32 name. */	if (fn->file_name_type == FILE_NAME_WIN32) {		fn->file_name_type = FILE_NAME_POSIX;		ntfs_inode_mark_dirty(actx->ntfs_ino);		((FILE_NAME_ATTR*)ictx->data)->file_name_type = FILE_NAME_POSIX;		ntfs_index_entry_mark_dirty(ictx);	}	/* Do not support reparse point deletion yet. */	if (((FILE_NAME_ATTR*)ictx->data)->file_attributes &			FILE_ATTR_REPARSE_POINT) {		errno = EOPNOTSUPP;		goto err_out;	}	/* Remove FILE_NAME from index. */	if (ntfs_index_rm(ictx))		goto err_out;	ictx = NULL;	/* Remove FILE_NAME from inode. */	if (ntfs_attr_record_rm(actx))		goto err_out;	/* Decerement hard link count. */	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)		goto out;	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;out:	if (actx)		ntfs_attr_put_search_ctx(actx);	if (ictx)		ntfs_index_ctx_put(ictx);	if (ni)		ntfs_inode_close(ni);	if (err) {		ntfs_log_error("Failed.\n");		errno = err;		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

⌨️ 快捷键说明

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