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

📄 utils.c

📁 一个在linux下挂载ntfs文件系统的好工具
💻 C
📖 第 1 页 / 共 2 页
字号:
		len = snprintf(buffer + offset, bufsize - offset, "%c%s", PATH_SEP, names[i]);		if (len >= (bufsize - offset)) {			ntfs_log_error("Pathname was truncated.\n");			break;		}		offset += len;	}	/* Free all the allocated memory */	for (i = 0; i < max_path; i++)		free(names[i]);	ntfs_log_debug("Pathname: %s\n", buffer);	return 1;}/** * utils_attr_get_name */int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int bufsize){	int len, namelen;	char *name;	ATTR_DEF *attrdef;	// flags: attr, name, or both	if (!attr || !buffer) {		errno = EINVAL;		return 0;	}	attrdef = ntfs_attr_find_in_attrdef(vol, attr->type);	if (attrdef) {		name    = NULL;		namelen = ntfs_ucsnlen(attrdef->name, sizeof(attrdef->name));		if (ntfs_ucstombs(attrdef->name, namelen, &name, 0) < 0) {			ntfs_log_error("Couldn't translate attribute type to current locale.\n");			// <UNKNOWN>?			return 0;		}		len = snprintf(buffer, bufsize, "%s", name);	} else {		ntfs_log_error("Unknown attribute type 0x%02x\n", attr->type);		len = snprintf(buffer, bufsize, "<UNKNOWN>");	}	if (len >= bufsize) {		ntfs_log_error("Attribute type was truncated.\n");		return 0;	}	if (!attr->name_length) {		return 0;	}	buffer  += len;	bufsize -= len;	name    = NULL;	namelen = attr->name_length;	if (ntfs_ucstombs((ntfschar *)((char *)attr + attr->name_offset),	    namelen, &name, 0) < 0) {		ntfs_log_error("Couldn't translate attribute name to current locale.\n");		// <UNKNOWN>?		len = snprintf(buffer, bufsize, "<UNKNOWN>");		return 0;	}	len = snprintf(buffer, bufsize, "(%s)", name);	free(name);	if (len >= bufsize) {		ntfs_log_error("Attribute name was truncated.\n");		return 0;	}	return 0;}/** * utils_cluster_in_use - Determine if a cluster is in use * @vol:  An ntfs volume obtained from ntfs_mount * @lcn:  The Logical Cluster Number to test * * The metadata file $Bitmap has one binary bit representing each cluster on * disk.  The bit will be set for each cluster that is in use.  The function * reads the relevant part of $Bitmap into a buffer and tests the bit. * * This function has a static buffer in which it caches a section of $Bitmap. * If the lcn, being tested, lies outside the range, the buffer will be * refreshed. * * Return:  1  Cluster is in use *	    0  Cluster is free space *	   -1  Error occurred */int utils_cluster_in_use(ntfs_volume *vol, long long lcn){	static unsigned char buffer[512];	static long long bmplcn = -sizeof(buffer) - 1;	/* Which bit of $Bitmap is in the buffer */	int byte, bit;	ntfs_attr *attr;	if (!vol) {		errno = EINVAL;		return -1;	}	/* Does lcn lie in the section of $Bitmap we already have cached? */	if ((lcn < bmplcn) || (lcn >= (bmplcn + (sizeof(buffer) << 3)))) {		ntfs_log_debug("Bit lies outside cache.\n");		attr = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);		if (!attr) {			ntfs_log_perror("Couldn't open $Bitmap");			return -1;		}		/* Mark the buffer as in use, in case the read is shorter. */		memset(buffer, 0xFF, sizeof(buffer));		bmplcn = lcn & (~((sizeof(buffer) << 3) - 1));		if (ntfs_attr_pread(attr, (bmplcn>>3), sizeof(buffer), buffer) < 0) {			ntfs_log_perror("Couldn't read $Bitmap");			ntfs_attr_close(attr);			return -1;		}		ntfs_log_debug("Reloaded bitmap buffer.\n");		ntfs_attr_close(attr);	}	bit  = 1 << (lcn & 7);	byte = (lcn >> 3) & (sizeof(buffer) - 1);	ntfs_log_debug("cluster = %lld, bmplcn = %lld, byte = %d, bit = %d, in use %d\n", lcn, bmplcn, byte, bit, buffer[byte] & bit);	return (buffer[byte] & bit);}/** * utils_mftrec_in_use - Determine if a MFT Record is in use * @vol:   An ntfs volume obtained from ntfs_mount * @mref:  MFT Reference (inode number) * * The metadata file $BITMAP has one binary bit representing each record in the * MFT.  The bit will be set for each record that is in use.  The function * reads the relevant part of $BITMAP into a buffer and tests the bit. * * This function has a static buffer in which it caches a section of $BITMAP. * If the mref, being tested, lies outside the range, the buffer will be * refreshed. * * Return:  1  MFT Record is in use *	    0  MFT Record is unused *	   -1  Error occurred */int utils_mftrec_in_use(ntfs_volume *vol, MFT_REF mref){	static u8 buffer[512];	static s64 bmpmref = -sizeof(buffer) - 1; /* Which bit of $BITMAP is in the buffer */	int byte, bit;	if (!vol) {		errno = EINVAL;		return -1;	}	ntfs_log_trace("entering\n");	/* Does mref lie in the section of $Bitmap we already have cached? */	if (((s64)MREF(mref) < bmpmref) || ((s64)MREF(mref) >= (bmpmref +			(sizeof(buffer) << 3)))) {		ntfs_log_debug("Bit lies outside cache.\n");		/* Mark the buffer as not in use, in case the read is shorter. */		memset(buffer, 0, sizeof(buffer));		bmpmref = mref & (~((sizeof(buffer) << 3) - 1));		if (ntfs_attr_pread(vol->mftbmp_na, (bmpmref>>3), sizeof(buffer), buffer) < 0) {			ntfs_log_perror("Couldn't read $MFT/$BITMAP");			return -1;		}		ntfs_log_debug("Reloaded bitmap buffer.\n");	}	bit  = 1 << (mref & 7);	byte = (mref >> 3) & (sizeof(buffer) - 1);	ntfs_log_debug("cluster = %lld, bmpmref = %lld, byte = %d, bit = %d, in use %d\n", mref, bmpmref, byte, bit, buffer[byte] & bit);	return (buffer[byte] & bit);}/** * __metadata */static int __metadata(ntfs_volume *vol, u64 num){	if (num <= FILE_UpCase)		return 1;	if (!vol)		return -1;	if ((vol->major_ver == 3) && (num == FILE_Extend))		return 1;	return 0;}/** * utils_is_metadata - Determine if an inode represents a metadata file * @inode:  An ntfs inode to be tested * * A handful of files in the volume contain filesystem data - metadata. * They can be identified by their inode number (offset in MFT/$DATA) or by * their parent. * * Return:  1  inode is a metadata file *	    0  inode is not a metadata file *	   -1  Error occurred */int utils_is_metadata(ntfs_inode *inode){	ntfs_volume *vol;	ATTR_RECORD *rec;	FILE_NAME_ATTR *attr;	MFT_RECORD *file;	u64 num;	if (!inode) {		errno = EINVAL;		return -1;	}	vol = inode->vol;	if (!vol)		return -1;	num = inode->mft_no;	if (__metadata(vol, num) == 1)		return 1;	file = inode->mrec;	if (file && (file->base_mft_record != 0)) {		num = MREF(file->base_mft_record);		if (__metadata(vol, num) == 1)			return 1;	}	file = inode->mrec;	rec = find_first_attribute(AT_FILE_NAME, inode->mrec);	if (!rec)		return -1;	/* We know this will always be resident. */	attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu(rec->value_offset));	num = MREF(attr->parent_directory);	if ((num != FILE_root) && (__metadata(vol, num) == 1))		return 1;	return 0;}/** * utils_dump_mem - Display a block of memory in hex and ascii * @buf:     Buffer to be displayed * @start:   Offset into @buf to start from * @length:  Number of bytes to display * @flags:   Options to change the style of the output * * Display a block of memory in a tradition hex-dump manner. * Optionally the ascii part can be turned off. * * The flags, described fully in utils.h, default to 0 (DM_DEFAULTS). * Examples are: DM_INDENT (indent the output by one tab); DM_RED (colour the * output); DM_NO_ASCII (only print the hex values). */void utils_dump_mem(void *buf, int start, int length, int flags){	int off, i, s, e, col;	u8 *mem = buf;	s =  start                & ~15;	// round down	e = (start + length + 15) & ~15;	// round up	for (off = s; off < e; off += 16) {		col = 30;		if (flags & DM_RED)			col += 1;		if (flags & DM_GREEN)			col += 2;		if (flags & DM_BLUE)			col += 4;		if (flags & DM_INDENT)			ntfs_log_debug("\t");		if (flags & DM_BOLD)			ntfs_log_debug("\e[01m");		if (flags & (DM_RED | DM_BLUE | DM_GREEN | DM_BOLD))			ntfs_log_debug("\e[%dm", col);		if (off == s)			ntfs_log_debug("%6.6x ", start);		else			ntfs_log_debug("%6.6x ", off);		for (i = 0; i < 16; i++) {			if ((i == 8) && (!(flags & DM_NO_DIVIDER)))				ntfs_log_debug(" -");			if (((off+i) >= start) && ((off+i) < (start+length)))				ntfs_log_debug(" %02X", mem[off+i]);			else				ntfs_log_debug("   ");		}		if (!(flags & DM_NO_ASCII)) {			ntfs_log_debug("  ");			for (i = 0; i < 16; i++) {				if (((off+i) < start) || ((off+i) >= (start+length)))					ntfs_log_debug(" ");				else if (isprint(mem[off + i]))					ntfs_log_debug("%c", mem[off + i]);				else					ntfs_log_debug(".");			}		}		if (flags & (DM_RED | DM_BLUE | DM_GREEN | DM_BOLD))			ntfs_log_debug("\e[0m");		ntfs_log_debug("\n");	}}/** * mft_get_search_ctx */struct mft_search_ctx * mft_get_search_ctx(ntfs_volume *vol){	struct mft_search_ctx *ctx;	if (!vol) {		errno = EINVAL;		return NULL;	}	ctx = calloc(1, sizeof *ctx);	ctx->mft_num = -1;	ctx->vol = vol;	return ctx;}/** * mft_put_search_ctx */void mft_put_search_ctx(struct mft_search_ctx *ctx){	if (!ctx)		return;	if (ctx->inode)		ntfs_inode_close(ctx->inode);	free(ctx);}/** * mft_next_record */int mft_next_record(struct mft_search_ctx *ctx){	s64 nr_mft_records;	ATTR_RECORD *attr10 = NULL;	ATTR_RECORD *attr20 = NULL;	ATTR_RECORD *attr80 = NULL;	ntfs_attr_search_ctx *attr_ctx;	if (!ctx) {		errno = EINVAL;		return -1;	}	if (ctx->inode) {		ntfs_inode_close(ctx->inode);		ctx->inode = NULL;	}	nr_mft_records = ctx->vol->mft_na->initialized_size >>			ctx->vol->mft_record_size_bits;	for (ctx->mft_num++; (s64)ctx->mft_num < nr_mft_records; ctx->mft_num++) {		int in_use;		ctx->flags_match = 0;		in_use = utils_mftrec_in_use(ctx->vol, (MFT_REF) ctx->mft_num);		if (in_use == -1) {			ntfs_log_error("Error reading inode %llu.  Aborting.\n",					(unsigned long long)ctx->mft_num);			return -1;		}		if (in_use) {			ctx->flags_match |= FEMR_IN_USE;			ctx->inode = ntfs_inode_open(ctx->vol, (MFT_REF) ctx->mft_num);			if (ctx->inode == NULL) {				ntfs_log_error("Error reading inode %llu.\n", (unsigned						long long) ctx->mft_num);				continue;			}			attr10 = find_first_attribute(AT_STANDARD_INFORMATION, ctx->inode->mrec);			attr20 = find_first_attribute(AT_ATTRIBUTE_LIST,       ctx->inode->mrec);			attr80 = find_first_attribute(AT_DATA, ctx->inode->mrec);			if (attr10)				ctx->flags_match |= FEMR_BASE_RECORD;			else				ctx->flags_match |= FEMR_NOT_BASE_RECORD;			if (attr20)				ctx->flags_match |= FEMR_BASE_RECORD;			if (attr80)				ctx->flags_match |= FEMR_FILE;			if (ctx->flags_search & FEMR_DIR) {				attr_ctx = ntfs_attr_get_search_ctx(ctx->inode, NULL);				if (attr_ctx) {					if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, 0, 0, NULL, 0, attr_ctx) == 0)						ctx->flags_match |= FEMR_DIR;					ntfs_attr_put_search_ctx(attr_ctx);				} else {					ntfs_log_error("Couldn't create a search context.\n");					return -1;				}			}			switch (utils_is_metadata(ctx->inode)) {				case 1: ctx->flags_match |= FEMR_METADATA;     break;				case 0: ctx->flags_match |= FEMR_NOT_METADATA; break;				default:					ctx->flags_match |= FEMR_NOT_METADATA; break;					//ntfs_log_error("Error reading inode %lld.\n", ctx->mft_num);					//return -1;			}		} else {		// !in_use			ntfs_attr *mft;			ctx->flags_match |= FEMR_NOT_IN_USE;			ctx->inode = calloc(1, sizeof(*ctx->inode));			if (!ctx->inode) {				ntfs_log_error("Out of memory.  Aborting.\n");				return -1;			}			ctx->inode->mft_no = ctx->mft_num;			ctx->inode->vol    = ctx->vol;			ctx->inode->mrec   = ntfs_malloc(ctx->vol->mft_record_size);			if (!ctx->inode->mrec) {				free(ctx->inode); // == ntfs_inode_close				return -1;			}			mft = ntfs_attr_open(ctx->vol->mft_ni, AT_DATA,					AT_UNNAMED, 0);			if (!mft) {				ntfs_log_perror("Couldn't open $MFT/$DATA");				// free / close				return -1;			}			if (ntfs_attr_pread(mft, ctx->vol->mft_record_size * ctx->mft_num, ctx->vol->mft_record_size, ctx->inode->mrec) < ctx->vol->mft_record_size) {				ntfs_log_perror("Couldn't read MFT Record %llu",					(unsigned long long) ctx->mft_num);				// free / close				ntfs_attr_close(mft);				return -1;			}			ntfs_attr_close(mft);		}		if (ctx->flags_match & ctx->flags_search) {			break;		}		if (ntfs_inode_close(ctx->inode)) {			ntfs_log_error("Error closing inode %llu.\n",					(unsigned long long)ctx->mft_num);			return -errno;		}		ctx->inode = NULL;	}	return (ctx->inode == NULL);}

⌨️ 快捷键说明

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