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

📄 super.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * super.c * * Copyright (C) 1995-1997, 1999 Martin von L鰓is * Copyright (C) 1996-1997 R間is Duchesne * Copyright (C) 1999 Steve Dodd * Copyright (C) 2000-2001 Anton Altparmakov (AIA) */#include <linux/ntfs_fs.h>#include <linux/errno.h>#include <linux/bitops.h>#include <linux/module.h>#include "ntfstypes.h"#include "struct.h"#include "super.h"#include "macros.h"#include "inode.h"#include "support.h"#include "util.h"#include <linux/smp_lock.h>/* All important structures in NTFS use 2 consistency checks: * . a magic structure identifier (FILE, INDX, RSTR, RCRD...) * . a fixup technique : the last word of each sector (called a fixup) of a *   structure's record should end with the word at offset <n> of the first *   sector, and if it is the case, must be replaced with the words following *   <n>. The value of <n> and the number of fixups is taken from the fields *   at the offsets 4 and 6. Note that the sector size is defined as *   NTFS_SECTOR_SIZE and not as the hardware sector size (this is concordant *   with what the Windows NTFS driver does). * * This function performs these 2 checks, and _fails_ if: * . the input size is invalid * . the fixup header is invalid * . the size does not match the number of sectors * . the magic identifier is wrong * . a fixup is invalid */int ntfs_fixup_record(char *record, char *magic, int size){	int start, count, offset;	ntfs_u16 fixup;	if (!IS_MAGIC(record, magic))		return 0;	start = NTFS_GETU16(record + 4);	count = NTFS_GETU16(record + 6) - 1;	if (size & (NTFS_SECTOR_SIZE - 1) || start & 1 ||			start + count * 2 > size || size >> 9 != count) {		if (size <= 0)			printk(KERN_ERR "NTFS: BUG: ntfs_fixup_record() got "					"zero size! Please report this to "					"linux-ntfs-dev@lists.sf.net\n");		return 0;	}	fixup = NTFS_GETU16(record + start);	start += 2;	offset = NTFS_SECTOR_SIZE - 2;	while (count--) {		if (NTFS_GETU16(record + offset) != fixup)			return 0;		NTFS_PUTU16(record + offset, NTFS_GETU16(record + start));		start += 2;		offset += NTFS_SECTOR_SIZE;	}	return 1;}/* * Get vital informations about the ntfs partition from the boot sector. * Return 0 on success or -1 on error. */int ntfs_init_volume(ntfs_volume *vol, char *boot){	int sectors_per_cluster_bits;	__s64 ll;	ntfs_cluster_t mft_zone_size, tc;	/* System defined default values, in case we don't load $AttrDef. */	vol->at_standard_information = 0x10;	vol->at_attribute_list = 0x20;	vol->at_file_name = 0x30;	vol->at_volume_version = 0x40;	vol->at_security_descriptor = 0x50;	vol->at_volume_name = 0x60;	vol->at_volume_information = 0x70;	vol->at_data = 0x80;	vol->at_index_root = 0x90;	vol->at_index_allocation = 0xA0;	vol->at_bitmap = 0xB0;	vol->at_symlink = 0xC0;	/* Sector size. */	vol->sector_size = NTFS_GETU16(boot + 0xB);	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->sector_size = 0x%x\n",				vol->sector_size);	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: sectors_per_cluster = "				"0x%x\n", NTFS_GETU8(boot + 0xD));	sectors_per_cluster_bits = ffs(NTFS_GETU8(boot + 0xD)) - 1;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: sectors_per_cluster_bits "				"= 0x%x\n", sectors_per_cluster_bits); 	vol->mft_clusters_per_record = NTFS_GETS8(boot + 0x40);	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_clusters_per_record"				" = 0x%x\n", vol->mft_clusters_per_record); 	vol->index_clusters_per_record = NTFS_GETS8(boot + 0x44);	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: "				"vol->index_clusters_per_record = 0x%x\n",				vol->index_clusters_per_record); 	vol->cluster_size = vol->sector_size << sectors_per_cluster_bits;	vol->cluster_size_bits = ffs(vol->cluster_size) - 1;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->cluster_size = 0x%x\n",				vol->cluster_size); 	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->cluster_size_bits = "				"0x%x\n", vol->cluster_size_bits); 	if (vol->mft_clusters_per_record > 0)		vol->mft_record_size = vol->cluster_size <<				(ffs(vol->mft_clusters_per_record) - 1);	else		/*		 * When mft_record_size < cluster_size, mft_clusters_per_record		 * = -log2(mft_record_size) bytes. mft_record_size normaly is		 * 1024 bytes, which is encoded as 0xF6 (-10 in decimal).		 */		vol->mft_record_size = 1 << -vol->mft_clusters_per_record;	vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_record_size = 0x%x"				"\n", vol->mft_record_size); 	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_record_size_bits = "				"0x%x\n", vol->mft_record_size_bits); 	if (vol->index_clusters_per_record > 0)		vol->index_record_size = vol->cluster_size <<				(ffs(vol->index_clusters_per_record) - 1);	else		/*		 * When index_record_size < cluster_size,		 * index_clusters_per_record = -log2(index_record_size) bytes.		 * index_record_size normaly equals 4096 bytes, which is		 * encoded as 0xF4 (-12 in decimal).		 */		vol->index_record_size = 1 << -vol->index_clusters_per_record;	vol->index_record_size_bits = ffs(vol->index_record_size) - 1;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->index_record_size = "				"0x%x\n", vol->index_record_size);	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->index_record_size_bits "				"= 0x%x\n", vol->index_record_size_bits);	/*	 * Get the size of the volume in clusters (ofs 0x28 is nr_sectors) and	 * check for 64-bit-ness. Windows currently only uses 32 bits to save	 * the clusters so we do the same as it is much faster on 32-bit CPUs.	 */	ll = NTFS_GETS64(boot + 0x28) >> sectors_per_cluster_bits;	if (ll >= (__s64)1 << 31) {		ntfs_error("Cannot handle 64-bit clusters. Please inform "				"linux-ntfs-dev@lists.sf.net that you got this "				"error.\n");		return -1;	}	vol->nr_clusters = (ntfs_cluster_t)ll;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->nr_clusters = 0x%x\n",			vol->nr_clusters);	vol->mft_lcn = (ntfs_cluster_t)NTFS_GETS64(boot + 0x30);	vol->mft_mirr_lcn = (ntfs_cluster_t)NTFS_GETS64(boot + 0x38);	/* Determine MFT zone size. */	mft_zone_size = vol->nr_clusters;	switch (vol->mft_zone_multiplier) {  /* % of volume size in clusters */	case 4:		mft_zone_size >>= 1;			/* 50%   */		break;	case 3:		mft_zone_size = mft_zone_size * 3 >> 3;	/* 37.5% */		break;	case 2:		mft_zone_size >>= 2;			/* 25%   */		break;	/* case 1: */	default:		mft_zone_size >>= 3;			/* 12.5% */		break;	}	/* Setup mft zone. */	vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_zone_pos = %x\n",			vol->mft_zone_pos);	/*	 * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs	 * source) and if the actual mft_lcn is in the expected place or even	 * further to the front of the volume, extend the mft_zone to cover the	 * beginning of the volume as well. This is in order to protect the	 * area reserved for the mft bitmap as well within the mft_zone itself.	 * On non-standard volumes we don't protect it as well as the overhead	 * would be higher than the speed increase we would get by doing it.	 */	tc = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size;	if (tc * vol->cluster_size < 16 * 1024)		tc = (16 * 1024 + vol->cluster_size - 1) / vol->cluster_size;	if (vol->mft_zone_start <= tc)		vol->mft_zone_start = (ntfs_cluster_t)0;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_zone_start = %x\n",			vol->mft_zone_start);	/*	 * Need to cap the mft zone on non-standard volumes so that it does	 * not point outside the boundaries of the volume, we do this by	 * halving the zone size until we are inside the volume.	 */	vol->mft_zone_end = vol->mft_lcn + mft_zone_size;	while (vol->mft_zone_end >= vol->nr_clusters) {		mft_zone_size >>= 1;		vol->mft_zone_end = vol->mft_lcn + mft_zone_size;	}	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_zone_end = %x\n",			vol->mft_zone_end);	/*	 * Set the current position within each data zone to the start of the	 * respective zone.	 */	vol->data1_zone_pos = vol->mft_zone_end;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->data1_zone_pos = %x\n",			vol->data1_zone_pos);	vol->data2_zone_pos = (ntfs_cluster_t)0;	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->data2_zone_pos = %x\n",			vol->data2_zone_pos);	/* Set the mft data allocation position to mft record 24. */	vol->mft_data_pos = 24UL;	/* This will be initialized later. */	vol->upcase = 0;	vol->upcase_length = 0;	vol->mft_ino = 0;	return 0;}static void ntfs_init_upcase(ntfs_inode *upcase){	ntfs_io io;#define UPCASE_LENGTH  256	upcase->vol->upcase = ntfs_malloc(UPCASE_LENGTH << 1);	if (!upcase->vol->upcase)		return;	io.fn_put = ntfs_put;	io.fn_get = 0;	io.param = (char*)upcase->vol->upcase;	io.size = UPCASE_LENGTH << 1;	ntfs_read_attr(upcase, upcase->vol->at_data, 0, 0, &io);	upcase->vol->upcase_length = io.size >> 1;}static int process_attrdef(ntfs_inode* attrdef, ntfs_u8* def){	int type = NTFS_GETU32(def+0x80);	int check_type = 0;	ntfs_volume *vol = attrdef->vol;	ntfs_u16* name = (ntfs_u16*)def;	if (!type) {		ntfs_debug(DEBUG_OTHER, "process_atrdef: finished processing "							"and returning 1\n");		return 1;	}	if (ntfs_ua_strncmp(name, "$STANDARD_INFORMATION", 64) == 0) {		vol->at_standard_information = type;		check_type = 0x10;	} else if (ntfs_ua_strncmp(name, "$ATTRIBUTE_LIST", 64) == 0) {		vol->at_attribute_list = type;		check_type = 0x20;	} else if (ntfs_ua_strncmp(name, "$FILE_NAME", 64) == 0) {		vol->at_file_name = type;		check_type = 0x30;	} else if (ntfs_ua_strncmp(name, "$VOLUME_VERSION", 64) == 0) {		vol->at_volume_version = type;		check_type = 0x40;	} else if (ntfs_ua_strncmp(name, "$SECURITY_DESCRIPTOR", 64) == 0) {		vol->at_security_descriptor = type;		check_type = 0x50;	} else if (ntfs_ua_strncmp(name, "$VOLUME_NAME", 64) == 0) {		vol->at_volume_name = type;		check_type = 0x60;	} else if (ntfs_ua_strncmp(name, "$VOLUME_INFORMATION", 64) == 0) {		vol->at_volume_information = type;		check_type = 0x70;	} else if (ntfs_ua_strncmp(name, "$DATA", 64) == 0) {		vol->at_data = type;		check_type = 0x80;	} else if (ntfs_ua_strncmp(name, "$INDEX_ROOT", 64) == 0) {		vol->at_index_root = type;		check_type = 0x90;	} else if (ntfs_ua_strncmp(name, "$INDEX_ALLOCATION", 64) == 0) {		vol->at_index_allocation = type;		check_type = 0xA0;	} else if (ntfs_ua_strncmp(name, "$BITMAP", 64) == 0) {		vol->at_bitmap = type;		check_type = 0xB0;	} else if (ntfs_ua_strncmp(name, "$SYMBOLIC_LINK", 64) == 0 ||		 ntfs_ua_strncmp(name, "$REPARSE_POINT", 64) == 0) {		vol->at_symlink = type;		check_type = 0xC0;	}	if (check_type && check_type != type) {		ntfs_error("process_attrdef: unexpected type 0x%x for 0x%x\n",							type, check_type);		return -EINVAL;	}	ntfs_debug(DEBUG_OTHER, "process_attrdef: found %s attribute of type "			"0x%x\n", check_type ? "known" : "unknown", type);	return 0;}int ntfs_init_attrdef(ntfs_inode* attrdef){	ntfs_u8 *buf;	ntfs_io io;	__s64 offset;	unsigned i;	int error;	ntfs_attribute *data;	ntfs_debug(DEBUG_BSD, "Entered ntfs_init_attrdef()\n");	buf = ntfs_malloc(4050); /* 90*45 */	if (!buf)		return -ENOMEM;	io.fn_put = ntfs_put;	io.fn_get = ntfs_get;	io.do_read = 1;	offset = 0;	data = ntfs_find_attr(attrdef, attrdef->vol->at_data, 0);	ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after call to "			"ntfs_find_attr.\n");	if (!data) {		ntfs_free(buf);		return -EINVAL;	}	do {		io.param = buf;		io.size = 4050;		ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() going to call "				"ntfs_readwrite_attr.\n");		error = ntfs_readwrite_attr(attrdef, data, offset, &io);		ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after call to "				"ntfs_readwrite_attr.\n");		for (i = 0; !error && i <= io.size - 0xA0; i += 0xA0) {			ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() going "					"to call process_attrdef.\n");			error = process_attrdef(attrdef, buf + i);			ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after "					"call to process_attrdef.\n");		}		offset += 4096;	} while (!error && io.size);	ntfs_debug(DEBUG_BSD, "Exiting ntfs_init_attrdef()\n");	ntfs_free(buf);	return error == 1 ? 0 : error;}/* ntfs_get_version will determine the NTFS version of the volume and will * return the version in a BCD format, with the MSB being the major version * number and the LSB the minor one. Otherwise return <0 on error.

⌨️ 快捷键说明

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