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

📄 inode.c

📁 EM85XX读NTFS修正代码包
💻 C
📖 第 1 页 / 共 5 页
字号:
		io.fn_get = 0;		io.param = buf + delta;		len = 1024 - delta;		if (len > datasize)			len = datasize;		ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x: len = %i\n",						ino->i_number, len);		ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x: delta = %i\n",						ino->i_number, delta);		io.size = len;		if (ntfs_read_attr(ino, vol->at_attribute_list, 0, offset,				   &io))			ntfs_error("error in load_attributes\n");		delta += len;		ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x: after += len, "				"delta = %i\n", ino->i_number, delta);		parse_attributes(ino, buf, &delta);		ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x: after "				"parse_attr, delta = %i\n", ino->i_number,				delta);		if (delta)			/* Move remaining bytes to buffer start. */			ntfs_memmove(buf, buf + len - delta, delta);	}	ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x 6\n", ino->i_number);	ntfs_free(buf);}	int ntfs_init_inode(ntfs_inode *ino, ntfs_volume *vol, int inum){	char *buf;	int error;	ntfs_debug(DEBUG_FILE1, "Initializing inode 0x%x\n", inum);	ino->i_number = inum;	ino->vol = vol;	ino->attr = buf = ntfs_malloc(vol->mft_record_size);	if (!buf)		return -ENOMEM;	error = ntfs_read_mft_record(vol, inum, ino->attr);	if (error) {		ntfs_debug(DEBUG_OTHER, "Init inode: 0x%x failed\n", inum);		return error;	}	ntfs_debug(DEBUG_FILE2, "Init inode: got mft 0x%x\n", inum);	ino->sequence_number = NTFS_GETU16(buf + 0x10);	ino->attr_count = 0;	ino->record_count = 0;	ino->records = 0;	ino->attrs = 0;	ntfs_load_attributes(ino);	ntfs_debug(DEBUG_FILE2, "Init inode: done 0x%x\n", inum);	return 0;}void ntfs_clear_inode(ntfs_inode *ino){	int i;	if (!ino->attr) {		ntfs_error("ntfs_clear_inode: double free\n");		return;	}	ntfs_free(ino->attr);	ino->attr = 0;	ntfs_free(ino->records);	ino->records = 0;	for (i = 0; i < ino->attr_count; i++) {		if (ino->attrs[i].name)			ntfs_free(ino->attrs[i].name);		if (ino->attrs[i].resident) {			if (ino->attrs[i].d.data)				ntfs_free(ino->attrs[i].d.data);		} else {			if (ino->attrs[i].d.r.runlist)				ntfs_vfree(ino->attrs[i].d.r.runlist);		}	}	ntfs_free(ino->attrs);	ino->attrs = 0;}/* Check and fixup a MFT record. */int ntfs_check_mft_record(ntfs_volume *vol, char *record){	return ntfs_fixup_record(record, "FILE", vol->mft_record_size);}/* Return (in result) the value indicating the next available attribute  * chunk number. Works for inodes w/o extension records only. */int ntfs_allocate_attr_number(ntfs_inode *ino, int *result){	if (ino->record_count != 1)		return -EOPNOTSUPP;	*result = NTFS_GETU16(ino->attr + 0x28);	NTFS_PUTU16(ino->attr + 0x28, (*result) + 1);	return 0;}/* Find the location of an attribute in the inode. A name of NULL indicates * unnamed attributes. Return pointer to attribute or NULL if not found. */char *ntfs_get_attr(ntfs_inode *ino, int attr, char *name){	/* Location of first attribute. */	char *it = ino->attr + NTFS_GETU16(ino->attr + 0x14);	int type;	int len;		/* Only check for magic DWORD here, fixup should have happened before.*/	if (!IS_MFT_RECORD(ino->attr))		return 0;	do {		type = NTFS_GETU32(it);		len = NTFS_GETU16(it + 4);		/* We found the attribute type. Is the name correct, too? */		if (type == attr) {			int namelen = NTFS_GETU8(it + 9);			char *name_it, *n = name;			/* Match given name and attribute name if present.			   Make sure attribute name is Unicode. */			if (!name) {				goto check_namelen;			} else if (namelen) {				for (name_it = it + NTFS_GETU16(it + 10);				     namelen; n++, name_it += 2, namelen--)					if (*name_it != *n || name_it[1])						break;check_namelen:				if (!namelen)					break;			}		}		it += len;	} while (type != -1); /* List of attributes ends with type -1. */	if (type == -1)		return 0;	return it;}__s64 ntfs_get_attr_size(ntfs_inode *ino, int type, char *name){	ntfs_attribute *attr = ntfs_find_attr(ino, type, name);	if (!attr)		return 0;	return		attr->size;}	int ntfs_attr_is_resident(ntfs_inode *ino, int type, char *name){	ntfs_attribute *attr = ntfs_find_attr(ino, type, name);	if (!attr)		return 0;	return attr->resident;}	/* * A run is coded as a type indicator, an unsigned length, and a signed cluster * offset. * . To save space, length and offset are fields of variable length. The low *   nibble of the type indicates the width of the length :), the high nibble *   the width of the offset. * . The first offset is relative to cluster 0, later offsets are relative to *   the previous cluster. * * This function decodes a run. Length is an output parameter, data and cluster * are in/out parameters. */int ntfs_decompress_run(unsigned char **data, int *length, 			ntfs_cluster_t *cluster, int *ctype){	unsigned char type = *(*data)++;	*ctype = 0;	switch (type & 0xF) {	case 1: 		*length = NTFS_GETS8(*data);		break;	case 2: 		*length = NTFS_GETS16(*data);		break;	case 3: 		*length = NTFS_GETS24(*data);		break;        case 4: 		*length = NTFS_GETS32(*data);		break;        	/* Note: cases 5-8 are probably pointless to code, since how		 * many runs > 4GB of length are there? At the most, cases 5		 * and 6 are probably necessary, and would also require making		 * length 64-bit throughout. */	default:		ntfs_error("Can't decode run type field 0x%x\n", type);		return -1;	}//	ntfs_debug(DEBUG_FILE3, "ntfs_decompress_run: length = 0x%x\n",*length);	if (*length < 0)	{		ntfs_error("Negative run length decoded\n");		return -1;	}	*data += (type & 0xF);	switch (type & 0xF0) {	case 0:		*ctype = 2;		break;	case 0x10:		*cluster += NTFS_GETS8(*data);		break;	case 0x20:		*cluster += NTFS_GETS16(*data);		break;	case 0x30:		*cluster += NTFS_GETS24(*data);		break;	case 0x40:		*cluster += NTFS_GETS32(*data);		break;#if 0 /* Keep for future, in case ntfs_cluster_t ever becomes 64bit. */	case 0x50: 		*cluster += NTFS_GETS40(*data);		break;	case 0x60: 		*cluster += NTFS_GETS48(*data);		break;	case 0x70: 		*cluster += NTFS_GETS56(*data);		break;	case 0x80: 		*cluster += NTFS_GETS64(*data);		break;#endif	default:		ntfs_error("Can't decode run type field 0x%x\n", type);		return -1;	}//	ntfs_debug(DEBUG_FILE3, "ntfs_decompress_run: cluster = 0x%x\n",//								*cluster);	*data += (type >> 4);	return 0;}static void dump_runlist(const ntfs_runlist *rl, const int rlen);/* * FIXME: ntfs_readwrite_attr() has the effect of writing @dest to @offset of * the attribute value of the attribute @attr in the in memory inode @ino. * If the attribute value of @attr is non-resident the value's contents at * @offset are actually written to disk (from @dest). The on disk mft record * describing the non-resident attribute value is not updated! * If the attribute value is resident then the value is written only in * memory. The on disk mft record containing the value is not written to disk. * A possible fix would be to call ntfs_update_inode() before returning. (AIA) *//* Reads l bytes of the attribute (attr, name) of ino starting at offset on * vol into buf. Returns the number of bytes read in the ntfs_io struct. * Returns 0 on success, errno on failure */int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,		ntfs_io *dest){	int rnum, s_vcn, error, clustersizebits;	ntfs_cluster_t cluster, s_cluster, vcn, len;	__s64 l, chunk, copied;	ntfs_debug(DEBUG_FILE3, "%s(): %s 0x%x bytes at offset "			"0x%Lx %s inode 0x%x, attr type 0x%x.\n", __FUNCTION__,			dest->do_read ? "Read" : "Write", dest->size, offset,			dest->do_read ? "from" : "to", ino->i_number,			attr->type);	l = dest->size;	if (l == 0)		return 0;	if (dest->do_read) {		/* If read _starts_ beyond end of stream, return nothing. */		if (offset >= attr->size) {			dest->size = 0;			return 0;		}		/* If read _extends_ beyond end of stream, return as much		 * initialised data as we have. */		if (offset + l >= attr->size)			l = dest->size = attr->size - offset;	} else {		/*		 * If write extends beyond _allocated_ size, extend attribute,		 * updating attr->allocated and attr->size in the process. (AIA)		 */		if ((!attr->resident && offset + l > attr->allocated) ||				(attr->resident && offset + l > attr->size)) {			error = ntfs_resize_attr(ino, attr, offset + l);			if (error)				return error;		}		if (!attr->resident) {			/* Has amount of data increased? */			if (offset + l > attr->size)				attr->size = offset + l;			/* Has amount of initialised data increased? */			if (offset + l > attr->initialized) {				/* FIXME: Clear the section between the old			 	 * initialised length and the write start.				 * (AIA) */				attr->initialized = offset + l;			}		}	}	if (attr->resident) {		if (dest->do_read)			dest->fn_put(dest, (ntfs_u8*)attr->d.data + offset, l);		else			dest->fn_get((ntfs_u8*)attr->d.data + offset, dest, l);		dest->size = l;		return 0;	}	if (dest->do_read) {		/* Read uninitialized data. */		if (offset >= attr->initialized)			return ntfs_read_zero(dest, l);		if (offset + l > attr->initialized) {			dest->size = chunk = attr->initialized - offset;			error = ntfs_readwrite_attr(ino, attr, offset, dest);			if (error || (dest->size != chunk && (error = -EIO, 1)))				return error;			dest->size += l - chunk;			return ntfs_read_zero(dest, l - chunk);		}		if (attr->flags & ATTR_IS_COMPRESSED)			return ntfs_read_compressed(ino, attr, offset, dest);	} else {		if (attr->flags & ATTR_IS_COMPRESSED)			return ntfs_write_compressed(ino, attr, offset, dest);	}	vcn = 0;	clustersizebits = ino->vol->cluster_size_bits;	s_vcn = offset >> clustersizebits;	for (rnum = 0; rnum < attr->d.r.len &&			vcn + attr->d.r.runlist[rnum].len <= s_vcn; rnum++)		vcn += attr->d.r.runlist[rnum].len;	if (rnum == attr->d.r.len) {		ntfs_debug(DEBUG_FILE3, "%s(): EOPNOTSUPP: "			"inode = 0x%x, rnum = %i, offset = 0x%Lx, vcn = 0x%x, "			"s_vcn = 0x%x.\n", __FUNCTION__, ino->i_number, rnum,			offset, vcn, s_vcn);		dump_runlist(attr->d.r.runlist, attr->d.r.len);		/*FIXME: Should extend runlist. */		return -EOPNOTSUPP;	}	copied = 0;	while (l) {		s_vcn = offset >> clustersizebits;		cluster = attr->d.r.runlist[rnum].lcn;		len = attr->d.r.runlist[rnum].len;		s_cluster = cluster + s_vcn - vcn;		chunk = ((__s64)(vcn + len) << clustersizebits) - offset;		if (chunk > l)			chunk = l;		dest->size = chunk;		error = ntfs_getput_clusters(ino->vol, s_cluster, offset -				((__s64)s_vcn << clustersizebits), dest);		if (error) {			ntfs_error("Read/write error.\n");			dest->size = copied;			return error;		}		l -= chunk;		copied += chunk;		offset += chunk;		if (l && offset >= ((__s64)(vcn + len) << clustersizebits)) {			rnum++;			vcn += len;			cluster = attr->d.r.runlist[rnum].lcn;			len = attr->d.r.runlist[rnum].len;		}	}	dest->size = copied;	return 0;}int ntfs_read_attr(ntfs_inode *ino, int type, char *name, __s64 offset,		   ntfs_io *buf){	ntfs_attribute *attr;	buf->do_read = 1;	attr = ntfs_find_attr(ino, type, name);	if (!attr) {		ntfs_debug(DEBUG_FILE3, "%s(): attr 0x%x not found in inode "				"0x%x\n", __FUNCTION__, type, ino->i_number);		return -EINVAL;	}	return ntfs_readwrite_attr(ino, attr, offset, buf);}int ntfs_write_attr(ntfs_inode *ino, int type, char *name, __s64 offset,		    ntfs_io *buf){	ntfs_attribute *attr;		buf->do_read = 0;	attr = ntfs_find_attr(ino, type, name);	if (!attr) {		ntfs_debug(DEBUG_FILE3, "%s(): attr 0x%x not found in inode "				"0x%x\n", __FUNCTION__, type, ino->i_number);		return -EINVAL;	}	return ntfs_readwrite_attr(ino, attr, offset, buf);}/* -2 = error, -1 = hole, >= 0 means real disk cluster (lcn). */int ntfs_vcn_to_lcn(ntfs_inode *ino, int vcn){	int rnum;	ntfs_attribute *data;

⌨️ 快捷键说明

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