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

📄 dir.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 4 页
字号:
	ascii = strdup(pathname);	if (!unicode || !ascii) {		ntfs_log_debug("Out of memory.\n");		err = ENOMEM;		goto close;	}	p = ascii;	/* Remove leading /'s. */	while (p && *p && *p == PATH_SEP)		p++;	while (p && *p) {		/* Find the end of the first token. */		q = strchr(p, PATH_SEP);		if (q != NULL) {			*q = '\0';			q++;		}		len = ntfs_mbstoucs(p, &unicode, MAX_PATH);		if (len < 0) {			ntfs_log_debug("Couldn't convert name to Unicode: %s.\n", p);			err = EILSEQ;			goto close;		}		inum = ntfs_inode_lookup_by_name(ni, unicode, len);		if (inum == (u64) -1) {			ntfs_log_debug("Couldn't find name '%s' in pathname "					"'%s'.\n", p, pathname);			err = ENOENT;			goto close;		}		if (ni != parent)			ntfs_inode_close(ni);		inum = MREF(inum);		ni = ntfs_inode_open(vol, inum);		if (!ni) {			ntfs_log_debug("Cannot open inode %llu: %s.\n",					(unsigned long long)inum, p);			err = EIO;			goto close;		}		p = q;		while (p && *p && *p == PATH_SEP)			p++;	}	result = ni;	ni = NULL;close:	if (ni && (ni != parent))		ntfs_inode_close(ni);	free(ascii);	free(unicode);	if (err)		errno = err;	return result;}/* * The little endian Unicode string ".." for ntfs_readdir(). */static const ntfschar dotdot[3] = { const_cpu_to_le16('.'),				   const_cpu_to_le16('.'),				   const_cpu_to_le16('\0') };/* * union index_union - * More helpers for ntfs_readdir(). */typedef union {	INDEX_ROOT *ir;	INDEX_ALLOCATION *ia;} index_union __attribute__((__transparent_union__));/** * enum INDEX_TYPE - * More helpers for ntfs_readdir(). */typedef enum {	INDEX_TYPE_ROOT,	/* index root */	INDEX_TYPE_ALLOCATION,	/* index allocation */} INDEX_TYPE;/** * ntfs_filldir - ntfs specific filldir method * @dir_ni:	ntfs inode of current directory * @pos:	current position in directory * @ivcn_bits:	log(2) of index vcn size * @index_type:	specifies whether @iu is an index root or an index allocation * @iu:		index root or index block to which @ie belongs * @ie:		current index entry * @dirent:	context for filldir callback supplied by the caller * @filldir:	filldir callback supplied by the caller * * Pass information specifying the current directory entry @ie to the @filldir * callback. */static inline int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,		const INDEX_TYPE index_type, index_union iu, INDEX_ENTRY *ie,		void *dirent, ntfs_filldir_t filldir){	FILE_NAME_ATTR *fn = &ie->key.file_name;	unsigned dt_type;	/* Advance the position even if going to skip the entry. */	if (index_type == INDEX_TYPE_ALLOCATION)		*pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu(				iu.ia->index_block_vcn) << ivcn_bits) +				dir_ni->vol->mft_record_size;	else /* if (index_type == INDEX_TYPE_ROOT) */		*pos = (u8*)ie - (u8*)iu.ir;	/* Skip root directory self reference entry. */	if (MREF_LE(ie->indexed_file) == FILE_root)		return 0;	if (ie->key.file_name.file_attributes & FILE_ATTR_I30_INDEX_PRESENT)		dt_type = NTFS_DT_DIR;	else		dt_type = NTFS_DT_REG;	return filldir(dirent, fn->file_name, fn->file_name_length,			fn->file_name_type, *pos,			le64_to_cpu(ie->indexed_file), dt_type);}/** * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode * @ni:		ntfs inode whose parent directory to find * * Find the parent directory of the ntfs inode @ni. To do this, find the first * file name attribute in the mft record of @ni and return the parent mft * reference from that. * * Note this only makes sense for directories, since files can be hard linked * from multiple directories and there is no way for us to tell which one is * being looked for. * * Technically directories can have hard links, too, but we consider that as * illegal as Linux/UNIX do not support directory hard links. * * Return the mft reference of the parent directory on success or -1 on error * with errno set to the error code. */static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni){	MFT_REF mref;	ntfs_attr_search_ctx *ctx;	FILE_NAME_ATTR *fn;	int eo;	if (!ni) {		errno = EINVAL;		return ERR_MREF(-1);	}	ctx = ntfs_attr_get_search_ctx(ni, NULL);	if (!ctx)		return ERR_MREF(-1);	if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {		ntfs_log_debug("No file name found in inode 0x%llx. Corrupt "				"inode.\n", (unsigned long long)ni->mft_no);		goto err_out;	}	if (ctx->attr->non_resident) {		ntfs_log_debug("File name attribute must be resident. Corrupt inode "				"0x%llx.\n", (unsigned long long)ni->mft_no);		goto io_err_out;	}	fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +			le16_to_cpu(ctx->attr->value_offset));	if ((u8*)fn +	le32_to_cpu(ctx->attr->value_length) >			(u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) {		ntfs_log_debug("Corrupt file name attribute in inode 0x%llx.\n",				(unsigned long long)ni->mft_no);		goto io_err_out;	}	mref = le64_to_cpu(fn->parent_directory);	ntfs_attr_put_search_ctx(ctx);	return mref;io_err_out:	errno = EIO;err_out:	eo = errno;	ntfs_attr_put_search_ctx(ctx);	errno = eo;	return ERR_MREF(-1);}/** * ntfs_readdir - read the contents of an ntfs directory * @dir_ni:	ntfs inode of current directory * @pos:	current position in directory * @dirent:	context for filldir callback supplied by the caller * @filldir:	filldir callback supplied by the caller * * Parse the index root and the index blocks that are marked in use in the * index bitmap and hand each found directory entry to the @filldir callback * supplied by the caller. * * Return 0 on success or -1 on error with errno set to the error code. * * Note: Index blocks are parsed in ascending vcn order, from which follows * that the directory entries are not returned sorted. */int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,		void *dirent, ntfs_filldir_t filldir){	s64 i_size, br, ia_pos, bmp_pos, ia_start;	ntfs_volume *vol;	ntfs_attr *ia_na, *bmp_na = NULL;	ntfs_attr_search_ctx *ctx = NULL;	u8 *index_end, *bmp = NULL;	INDEX_ROOT *ir;	INDEX_ENTRY *ie;	INDEX_ALLOCATION *ia = NULL;	int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo;	u32 index_block_size, index_vcn_size;	u8 index_block_size_bits, index_vcn_size_bits;	if (!dir_ni || !pos || !filldir) {		errno = EINVAL;		return -1;	}	if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {		errno = ENOTDIR;		return -1;	}	vol = dir_ni->vol;	ntfs_log_trace("Entering for inode 0x%llx, *pos 0x%llx.\n",			(unsigned long long)dir_ni->mft_no, (long long)*pos);	/* Open the index allocation attribute. */	ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);	if (!ia_na) {		if (errno != ENOENT) {			ntfs_log_perror("Failed to open index allocation attribute. "				"Directory inode 0x%llx is corrupt or bug",				(unsigned long long)dir_ni->mft_no);			return -1;		}		i_size = 0;	} else		i_size = ia_na->data_size;	rc = 0;	/* Are we at end of dir yet? */	if (*pos >= i_size + vol->mft_record_size)		goto done;	/* Emulate . and .. for all directories. */	if (!*pos) {		rc = filldir(dirent, dotdot, 1, FILE_NAME_POSIX, *pos,				MK_MREF(dir_ni->mft_no,				le16_to_cpu(dir_ni->mrec->sequence_number)),				NTFS_DT_DIR);		if (rc)			goto done;		++*pos;	}	if (*pos == 1) {		MFT_REF parent_mref;		parent_mref = ntfs_mft_get_parent_ref(dir_ni);		if (parent_mref == ERR_MREF(-1)) {			ntfs_log_perror("Parent directory not found");			goto dir_err_out;		}		rc = filldir(dirent, dotdot, 2, FILE_NAME_POSIX, *pos,				parent_mref, NTFS_DT_DIR);		if (rc)			goto done;		++*pos;	}	ctx = ntfs_attr_get_search_ctx(dir_ni, NULL);	if (!ctx)		goto err_out;	/* Get the offset into the index root attribute. */	ir_pos = (int)*pos;	/* Find the index root attribute in the mft record. */	if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL,			0, ctx)) {		ntfs_log_debug("Index root attribute missing in directory inode "				"0x%llx.\n", (unsigned long long)dir_ni->mft_no);		goto dir_err_out;	}	/* Get to the index root value. */	ir = (INDEX_ROOT*)((u8*)ctx->attr +			le16_to_cpu(ctx->attr->value_offset));	/* Determine the size of a vcn in the directory index. */	index_block_size = le32_to_cpu(ir->index_block_size);	if (index_block_size < NTFS_BLOCK_SIZE ||			index_block_size & (index_block_size - 1)) {		ntfs_log_debug("Index block size %u is invalid.\n",				(unsigned)index_block_size);		goto dir_err_out;	}	index_block_size_bits = ffs(index_block_size) - 1;	if (vol->cluster_size <= index_block_size) {		index_vcn_size = vol->cluster_size;		index_vcn_size_bits = vol->cluster_size_bits;	} else {		index_vcn_size = vol->sector_size;		index_vcn_size_bits = vol->sector_size_bits;	}	/* Are we jumping straight into the index allocation attribute? */	if (*pos >= vol->mft_record_size) {		ntfs_attr_put_search_ctx(ctx);		ctx = NULL;		goto skip_index_root;	}	index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length);	/* The first index entry. */	ie = (INDEX_ENTRY*)((u8*)&ir->index +			le32_to_cpu(ir->index.entries_offset));	/*	 * Loop until we exceed valid memory (corruption case) or until we	 * reach the last entry or until 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 root, offset 0x%x.\n", (u8*)ie - (u8*)ir);		/* Bounds checks. */		if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +				sizeof(INDEX_ENTRY_HEADER) > index_end ||				(u8*)ie + le16_to_cpu(ie->key_length) >				index_end)			goto dir_err_out;		/* The last entry cannot contain a name. */		if (ie->flags & INDEX_ENTRY_END)			break;		/* Skip index root entry if continuing previous readdir. */		if (ir_pos > (u8*)ie - (u8*)ir)			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_ROOT, ir, ie, dirent, filldir);		if (rc) {			ntfs_attr_put_search_ctx(ctx);			ctx = NULL;			goto done;		}	}	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 = (INDEX_ALLOCATION*)malloc(index_block_size);	if (!ia) {		ntfs_log_perror("Failed to allocate buffer for index block");		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_debug("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 = (u8*)malloc(bmp_buf_size);	if (!bmp) {		ntfs_log_perror("Failed to allocate bitmap buffer");		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. */		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_debug("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_debug("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_debug("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_debug("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->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 done;	}	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);#ifdef DEBUG	if (!rc)		ntfs_log_debug("EOD, *pos 0x%llx, returning 0.\n", (long long)*pos);	else		ntfs_log_debug("filldir returned %i, *pos 0x%llx, returning 0.\n",				rc, (long long)*pos);#endif	return 0;dir_err_out:	errno = EIO;err_out:	eo = errno;

⌨️ 快捷键说明

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