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

📄 inode.c

📁 EM85XX读NTFS修正代码包
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * inode.c * * Copyright (C) 1995-1999 Martin von L鰓is * Copyright (C) 1996 Albert D. Cahalan * Copyright (C) 1996-1997 R間is Duchesne * Copyright (C) 1998 Joseph Malicki * Copyright (C) 1999 Steve Dodd * Copyright (C) 2000-2001 Anton Altaparmakov (AIA) */#include "ntfstypes.h"#include "ntfsendian.h"#include "struct.h"#include "inode.h"#include <linux/errno.h>#include "macros.h"#include "attr.h"#include "super.h"#include "dir.h"#include "support.h"#include "util.h"#include <linux/ntfs_fs.h>#include <linux/smp_lock.h>typedef struct {	int recno;	unsigned char *record;} ntfs_mft_record;typedef struct {	int size;	int count;	ntfs_mft_record *records;} ntfs_disk_inode;static void ntfs_fill_mft_header(ntfs_u8 *mft, int rec_size, int seq_no,		int links, int flags){	int fixup_ofs = 0x2a;	int fixup_cnt = rec_size / NTFS_SECTOR_SIZE + 1;	int attr_ofs = (fixup_ofs + 2 * fixup_cnt + 7) & ~7;	NTFS_PUTU32(mft + 0x00, 0x454c4946);	/* FILE */	NTFS_PUTU16(mft + 0x04, fixup_ofs);	/* Offset to fixup. */	NTFS_PUTU16(mft + 0x06, fixup_cnt);	/* Number of fixups. */	NTFS_PUTU64(mft + 0x08, 0);		/* Logical sequence number. */	NTFS_PUTU16(mft + 0x10, seq_no);	/* Sequence number. */	NTFS_PUTU16(mft + 0x12, links);		/* Hard link count. */	NTFS_PUTU16(mft + 0x14, attr_ofs);	/* Offset to attributes. */	NTFS_PUTU16(mft + 0x16, flags);		/* Flags: 1 = In use,							  2 = Directory. */	NTFS_PUTU32(mft + 0x18, attr_ofs + 8);	/* Bytes in use. */	NTFS_PUTU32(mft + 0x1c, rec_size);	/* Total allocated size. */	NTFS_PUTU64(mft + 0x20, 0);		/* Base mft record. */	NTFS_PUTU16(mft + 0x28, 0);		/* Next attr instance. */	NTFS_PUTU16(mft + fixup_ofs, 1);	/* Fixup word. */	NTFS_PUTU32(mft + attr_ofs, (__u32)-1);	/* End of attributes marker. */}/* * Search in an inode an attribute by type and name.  * FIXME: Check that when attributes are inserted all attribute list * attributes are expanded otherwise need to modify this function to deal * with attribute lists. (AIA) */ntfs_attribute *ntfs_find_attr(ntfs_inode *ino, int type, char *name){	int i;		if (!ino) {		ntfs_error("ntfs_find_attr: NO INODE!\n");		return 0;	}	for (i = 0; i < ino->attr_count; i++) {		if (type < ino->attrs[i].type)			return 0;		if (type == ino->attrs[i].type) {			if (!name) {				if (!ino->attrs[i].name)					return ino->attrs + i;			} else if (ino->attrs[i].name &&				   !ntfs_ua_strncmp(ino->attrs[i].name, name,						    strlen(name)))				return ino->attrs + i;		}	}	return 0;}/* * Insert all attributes from the record mftno of the MFT in the inode ino. * If mftno is a base mft record we abort as soon as we find the attribute * list, but only on the first pass. We will get called later when the attribute * list attribute is being parsed so we need to distinguish the two cases. * FIXME: We should be performing structural consistency checks. (AIA) * Return 0 on success or -errno on error. */static int ntfs_insert_mft_attributes(ntfs_inode* ino, char *mft, int mftno){	int i, error, type, len, present = 0;	char *it;	/* Check for duplicate extension record. */	for(i = 0; i < ino->record_count; i++)		if (ino->records[i] == mftno) {			if (i)				return 0;			present = 1;			break;		}	if (!present) {		/* (re-)allocate space if necessary. */		if (ino->record_count % 8 == 0)	{			int *new;			new = ntfs_malloc((ino->record_count + 8) *								sizeof(int));			if (!new)				return -ENOMEM;			if (ino->records) {				for (i = 0; i < ino->record_count; i++)					new[i] = ino->records[i];				ntfs_free(ino->records);			}			ino->records = new;		}		ino->records[ino->record_count] = mftno;		ino->record_count++;	}	it = mft + NTFS_GETU16(mft + 0x14); /* mft->attrs_offset */	do {		type = NTFS_GETU32(it);		len = NTFS_GETU32(it + 4);		if (type != -1) {			error = ntfs_insert_attribute(ino, it);			if (error)				return error;		}		/* If we have just processed the attribute list and this is		 * the first time we are parsing this (base) mft record then we		 * are done so that the attribute list gets parsed before the		 * entries in the base mft record. Otherwise we run into		 * problems with encountering attributes out of order and when		 * this happens with different attribute extents we die. )-:		 * This way we are ok as the attribute list is always sorted		 * fully and correctly. (-: */		if (type == 0x20 && !present)			return 0;		it += len;	} while (type != -1); /* Attribute listing ends with type -1. */	return 0;}/* * Insert a single specific attribute from the record mftno of the MFT in the * inode ino. We disregard the attribute list assuming we have already parsed * it. * FIXME: We should be performing structural consistency checks. (AIA) * Return 0 on success or -errno on error. */static int ntfs_insert_mft_attribute(ntfs_inode* ino, int mftno,		ntfs_u8 *attr){	int i, error, present = 0;	/* Check for duplicate extension record. */	for(i = 0; i < ino->record_count; i++)		if (ino->records[i] == mftno) {			present = 1;			break;		}	if (!present) {		/* (re-)allocate space if necessary. */		if (ino->record_count % 8 == 0)	{			int *new;			new = ntfs_malloc((ino->record_count + 8) *								sizeof(int));			if (!new)				return -ENOMEM;			if (ino->records) {				for (i = 0; i < ino->record_count; i++)					new[i] = ino->records[i];				ntfs_free(ino->records);			}			ino->records = new;		}		ino->records[ino->record_count] = mftno;		ino->record_count++;	}	if (NTFS_GETU32(attr) == -1) {		ntfs_debug(DEBUG_FILE3, "ntfs_insert_mft_attribute: attribute "				"type is -1.\n");		return 0;	}	error = ntfs_insert_attribute(ino, attr);	if (error)		return error;	return 0;}/* Read and insert all the attributes of an 'attribute list' attribute. * Return the number of remaining bytes in *plen. */static int parse_attributes(ntfs_inode *ino, ntfs_u8 *alist, int *plen){	ntfs_u8 *mft, *attr;	int mftno, l, error;	int last_mft = -1;	int len = *plen;	int tries = 0;		if (!ino->attr) {		ntfs_error("parse_attributes: called on inode 0x%x without a "				"loaded base mft record.\n", ino->i_number);		return -EINVAL;	}	mft = ntfs_malloc(ino->vol->mft_record_size);	if (!mft)		return -ENOMEM;	while (len > 8)	{		l = NTFS_GETU16(alist + 4);		if (l > len)			break;	        /* Process an attribute description. */		mftno = NTFS_GETU32(alist + 0x10); 			/* FIXME: The mft reference (alist + 0x10) is __s64.			* - Not a problem unless we encounter a huge partition.			* - Should be consistency checking the sequence numbers			*   though! This should maybe happen in 			*   ntfs_read_mft_record() itself and a hotfix could			*   then occur there or the user notified to run			*   ntfsck. (AIA) */		if (mftno != ino->i_number && mftno != last_mft) {continue_after_loading_mft_data:			last_mft = mftno;			error = ntfs_read_mft_record(ino->vol, mftno, mft);			if (error) {				if (error == -EINVAL && !tries)					goto force_load_mft_data;failed_reading_mft_data:				ntfs_debug(DEBUG_FILE3, "parse_attributes: "					"ntfs_read_mft_record(mftno = 0x%x) "					"failed\n", mftno);				ntfs_free(mft);				return error;			}		}		attr = ntfs_find_attr_in_mft_rec(				ino->vol,		/* ntfs volume */				mftno == ino->i_number ?/* mft record is: */					ino->attr:	/*   base record */					mft,		/*   extension record */				NTFS_GETU32(alist + 0),	/* type */				(wchar_t*)(alist + alist[7]),	/* name */				alist[6], 		/* name length */				1,			/* ignore case */				NTFS_GETU16(alist + 24)	/* instance number */				);		if (!attr) {			ntfs_error("parse_attributes: mft records 0x%x and/or "				       "0x%x corrupt!\n", ino->i_number, mftno);			ntfs_free(mft);			return -EINVAL; /* FIXME: Better error code? (AIA) */		}		error = ntfs_insert_mft_attribute(ino, mftno, attr);		if (error) {			ntfs_debug(DEBUG_FILE3, "parse_attributes: "				"ntfs_insert_mft_attribute(mftno 0x%x, "				"attribute type 0x%x) failed\n", mftno,				NTFS_GETU32(alist + 0));			ntfs_free(mft);			return error;		}		len -= l;		alist += l;	}	ntfs_free(mft);	*plen = len;	return 0;force_load_mft_data:{	ntfs_u8 *mft2, *attr2;	int mftno2;	int last_mft2 = last_mft;	int len2 = len;	int error2;	int found2 = 0;	ntfs_u8 *alist2 = alist;	/*	 * We only get here if $DATA wasn't found in $MFT which only happens	 * on volume mount when $MFT has an attribute list and there are	 * attributes before $DATA which are inside extent mft records. So	 * we just skip forward to the $DATA attribute and read that. Then we	 * restart which is safe as an attribute will not be inserted twice.	 *	 * This still will not fix the case where the attribute list is non-	 * resident, larger than 1024 bytes, and the $DATA attribute list entry	 * is not in the first 1024 bytes. FIXME: This should be implemented	 * somehow! Perhaps by passing special error code up to	 * ntfs_load_attributes() so it keeps going trying to get to $DATA	 * regardless. Then it would have to restart just like we do here.	 */	mft2 = ntfs_malloc(ino->vol->mft_record_size);	if (!mft2) {		ntfs_free(mft);		return -ENOMEM;	}	ntfs_memcpy(mft2, mft, ino->vol->mft_record_size);	while (len2 > 8) {		l = NTFS_GETU16(alist2 + 4);		if (l > len2)			break;		if (NTFS_GETU32(alist2 + 0x0) < ino->vol->at_data) {			len2 -= l;			alist2 += l;			continue;		}		if (NTFS_GETU32(alist2 + 0x0) > ino->vol->at_data) {			if (found2)				break;			/* Uh-oh! It really isn't there! */			ntfs_error("Either the $MFT is corrupt or, equally "					"likely, the $MFT is too complex for "					"the current driver to handle. Please "					"email the ntfs maintainer that you "					"saw this message. Thank you.\n");			goto failed_reading_mft_data;		}	        /* Process attribute description. */		mftno2 = NTFS_GETU32(alist2 + 0x10); 		if (mftno2 != ino->i_number && mftno2 != last_mft2) {			last_mft2 = mftno2;			error2 = ntfs_read_mft_record(ino->vol, mftno2, mft2);			if (error2) {				ntfs_debug(DEBUG_FILE3, "parse_attributes: "					"ntfs_read_mft_record(mftno2 = 0x%x) "					"failed\n", mftno2);				ntfs_free(mft2);				goto failed_reading_mft_data;			}		}		attr2 = ntfs_find_attr_in_mft_rec(				ino->vol,		 /* ntfs volume */				mftno2 == ino->i_number ?/* mft record is: */					ino->attr:	 /*  base record */					mft2,		 /*  extension record */				NTFS_GETU32(alist2 + 0),	/* type */				(wchar_t*)(alist2 + alist2[7]),	/* name */				alist2[6], 		 /* name length */				1,			 /* ignore case */				NTFS_GETU16(alist2 + 24) /* instance number */				);		if (!attr2) {			ntfs_error("parse_attributes: mft records 0x%x and/or "				       "0x%x corrupt!\n", ino->i_number,				       mftno2);			ntfs_free(mft2);			goto failed_reading_mft_data;		}		error2 = ntfs_insert_mft_attribute(ino, mftno2, attr2);		if (error2) {			ntfs_debug(DEBUG_FILE3, "parse_attributes: "				"ntfs_insert_mft_attribute(mftno2 0x%x, "				"attribute2 type 0x%x) failed\n", mftno2,				NTFS_GETU32(alist2 + 0));			ntfs_free(mft2);			goto failed_reading_mft_data;		}		len2 -= l;		alist2 += l;		found2 = 1;	}	ntfs_free(mft2);	tries = 1;	goto continue_after_loading_mft_data;}}static void ntfs_load_attributes(ntfs_inode *ino){	ntfs_attribute *alist;	int datasize;	int offset, len, delta;	char *buf;	ntfs_volume *vol = ino->vol;		ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x 1\n", ino->i_number);	if (ntfs_insert_mft_attributes(ino, ino->attr, ino->i_number))		return;	ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x 2\n", ino->i_number);	alist = ntfs_find_attr(ino, vol->at_attribute_list, 0);	ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x 3\n", ino->i_number);	if (!alist)		return;	ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x 4\n", ino->i_number);	datasize = alist->size;	ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x: alist->size = 0x%x\n",			ino->i_number, alist->size);	if (alist->resident) {		parse_attributes(ino, alist->d.data, &datasize);		return;	}	ntfs_debug(DEBUG_FILE2, "load_attributes 0x%x 5\n", ino->i_number);	buf = ntfs_malloc(1024);	if (!buf)    /* FIXME: Should be passing error code to caller. (AIA) */		return;	delta = 0;	for (offset = 0; datasize; datasize -= len, offset += len) {		ntfs_io io;				io.fn_put = ntfs_put;

⌨️ 快捷键说明

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