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

📄 fs.c

📁 一个linux下NTFS文件格式源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	       ino->i_ino,block,ret);	return (ret==-1) ? 0:ret;}struct file_operations ntfs_file_operations = {	NULL, /* lseek */	ntfs_read,#ifdef CONFIG_NTFS_RW	ntfs_write,#else	NULL,#endif	NULL, /* readdir */	NULL, /* select */	NULL, /* ioctl */	generic_file_mmap,	NULL, /* open */	NULL, /* release */	NULL, /* fsync */	NULL, /* fasync */	NULL, /* check_media_change */	NULL  /* revalidate */};struct inode_operations ntfs_inode_operations = {	&ntfs_file_operations,	NULL, /* create */	NULL, /* lookup */	NULL, /* link */	NULL, /* unlink */	NULL, /* symlink */	NULL, /* mkdir */	NULL, /* rmdir */	NULL, /* mknod */	NULL, /* rename */	NULL, /* readlink */	NULL, /* follow_link */	NULL, /* readpage */	NULL, /* writepage */	ntfs_bmap,	NULL, /* truncate */	NULL, /* permission */	NULL, /* smap */};struct file_operations ntfs_dir_operations = {	NULL, /* lseek */	NULL, /* read */	NULL, /* write */	ntfs_readdir, /* readdir */	NULL, /* select */	NULL, /* ioctl */	NULL, /* mmap */	NULL, /* open */	NULL, /* release */	NULL, /* fsync */	NULL, /* fasync */	NULL, /* check_media_change */	NULL  /* revalidate */};struct inode_operations ntfs_dir_inode_operations = {	&ntfs_dir_operations,#ifdef CONFIG_NTFS_RW	ntfs_create, /* create */#else	NULL,#endif	ntfs_lookup, /* lookup */	NULL, /* link */	NULL, /* unlink */	NULL, /* symlink */#ifdef CONFIG_NTFS_RW	_linux_ntfs_mkdir,#else	NULL, /* mkdir */#endif	NULL, /* rmdir */	NULL, /* mknod */	NULL, /* rename */	NULL, /* readlink */	NULL, /* follow_link */	NULL, /* readpage */	NULL, /* writepage */	NULL, /* bmap */	NULL, /* truncate */	NULL, /* permission */	NULL, /* smap */};/* ntfs_read_inode is called by the Virtual File System (the kernel layer that * deals with filesystems) when iget is called requesting an inode not already * present in the inode table. Typically filesystems have separate * inode_operations for directories, files and symlinks. */static void ntfs_read_inode(struct inode* inode){	ntfs_volume *vol;	int can_mmap=0;	ntfs_inode *ino;	ntfs_attribute *data;	ntfs_attribute *si;	vol=NTFS_INO2VOL(inode);	inode->i_op=NULL;	inode->i_mode=0;	inode->u.generic_ip=NULL;	ntfs_debug(DEBUG_OTHER, "ntfs_read_inode %x\n",(unsigned)inode->i_ino);	switch(inode->i_ino)	{		/* those are loaded special files */	case FILE_MFT:		ino=NTFS_INO2VOL(inode)->mft_ino;break;	default:		ino=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));		if(!ino || ntfs_init_inode(ino,					   NTFS_INO2VOL(inode),inode->i_ino))		{			ntfs_debug(DEBUG_OTHER, "NTFS:Error loading inode %x\n",			       (unsigned int)inode->i_ino);			return;		}	}	inode->u.generic_ip=ino;	/* Set uid/gid from mount options */	inode->i_uid=vol->uid;	inode->i_gid=vol->gid;	inode->i_nlink=1;	/* Use the size of the data attribute as file size */	data = ntfs_find_attr(ino,vol->at_data,NULL);	if(!data)	{		inode->i_size=0;		can_mmap=0;	}	else	{		inode->i_size=data->size;		can_mmap=!data->resident && !data->compressed;	}	/* get the file modification times from the standard information */	si=ntfs_find_attr(ino,vol->at_standard_information,NULL);	if(si){		char *attr=si->d.data;		inode->i_atime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18));		inode->i_ctime=ntfs_ntutc2unixutc(NTFS_GETU64(attr));		inode->i_mtime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+8));	}	/* if it has an index root, it's a directory */	if(ntfs_find_attr(ino,vol->at_index_root,"$I30"))	{		ntfs_attribute *at;		at = ntfs_find_attr (ino, vol->at_index_allocation, "$I30");		inode->i_size = at ? at->size : 0;	  		inode->i_op=&ntfs_dir_inode_operations;		inode->i_mode=S_IFDIR|S_IRUGO|S_IXUGO;	}	else	{		inode->i_op=can_mmap ? &ntfs_inode_operations : 			&ntfs_inode_operations_nobmap;		inode->i_mode=S_IFREG|S_IRUGO|S_IMMUTABLE;		inode->i_mode=S_IFREG|S_IRUGO;	}#ifdef CONFIG_NTFS_RW	inode->i_mode |= S_IWUGO;#endif	inode->i_mode &= ~vol->umask;}static void ntfs_put_inode(struct inode *ino){	ntfs_debug(DEBUG_OTHER, "ntfs_put_inode %lx\n",ino->i_ino);	if(ino->i_ino!=FILE_MFT && ino->u.generic_ip)	{		ntfs_clear_inode(ino->u.generic_ip);		ntfs_free(ino->u.generic_ip);		ino->u.generic_ip=0;	}	clear_inode(ino);}static void ntfs_put_super(struct super_block *sb){	ntfs_volume *vol=NTFS_SB2VOL(sb);	ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");	lock_super(sb);	ntfs_release_volume(vol);	sb->s_dev=0;	ntfs_free(sb->u.generic_sbp);	sb->u.generic_sbp=0;	unlock_super(sb);	MOD_DEC_USE_COUNT;}static void ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize){	struct statfs fs;	struct inode *mft;	ntfs_volume *vol;	ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");	vol=NTFS_SB2VOL(sb);	memset(&fs,0,sizeof(fs));	fs.f_type=NTFS_SUPER_MAGIC;	fs.f_bsize=vol->clustersize;	if(ntfs_get_volumesize( NTFS_SB2VOL( sb ), &fs.f_blocks ))		return;	fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap);	fs.f_bavail=fs.f_bfree;	/* Number of files is limited by free space only, so we lie here */	fs.f_ffree=0;	mft=iget(sb,FILE_MFT);	fs.f_files=mft->i_size/vol->mft_recordsize;	iput(mft);	/* should be read from volume */	fs.f_namelen=255;	memcpy_tofs(sf,&fs,bufsize);}static int ntfs_remount_fs(struct super_block *sb, int* flags, char* options){	if(parse_options(sb,(ntfs_volume*)sb->u.generic_sbp, options))	{		if((*flags & MS_RDONLY) && (sb->s_flags && MS_RDONLY))			return 0;		if(*flags & MS_RDONLY)			/* changing from rw to ro */			sb->s_flags |= MS_RDONLY;		else if(sb->s_flags & MS_RDONLY)			/* changing from rw to rw */			sb->s_flags &= ~MS_RDONLY;		return 0;	}	else		return -EINVAL;}struct super_operations ntfs_super_operations = {	ntfs_read_inode,	NULL, /* notify_change */	NULL, /* write_inode */	ntfs_put_inode,	ntfs_put_super,	NULL, /* write_super */	ntfs_statfs,	ntfs_remount_fs, /* remount */};/* Entry point of the filesystem. It is called after when the filesystem is * mounted. Don't use any pointer into options, as the page containing is is * freed after ntfs_read_super returns. */struct super_block * ntfs_read_super(struct super_block *sb, 				     void *options, int silent){	struct buffer_head *bh;	int dev=sb->s_dev;	int i;	ntfs_volume *vol;#if defined(DEBUG) && !defined(MODULE)	extern int console_loglevel;	console_loglevel=15;#endif	ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");	MOD_INC_USE_COUNT;	lock_super(sb);	ntfs_debug(DEBUG_OTHER, "lock_super\n");#ifndef CONFIG_NTFS_RW	/* set to read only, user option might reset it */	sb->s_flags |= MS_RDONLY;#endif	vol=ntfs_malloc(sizeof(ntfs_volume));	if(!parse_options(sb,vol,(char*)options)){		unlock_super(sb);		ntfs_free(vol);		MOD_DEC_USE_COUNT;		return 0;	}	/* Read the superblock assuming 512 byte blocks for now */	set_blocksize(dev,512);	/* Read the boot block to get the location of the MFT */	if(!(bh=bread(dev,0,512)))	{		printk("Reading super block failed\n");		sb->s_dev=0;		ntfs_free(vol);		unlock_super(sb);		MOD_DEC_USE_COUNT;		return NULL;	}	ntfs_debug(DEBUG_OTHER, "Done reading boot block\n");	/* Check for 'NTFS' magic at offset 3 */	if(!IS_NTFS_VOLUME(bh->b_data)){		ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n");		ntfs_free(vol);		sb->s_dev=0;		brelse(bh);		unlock_super(sb);		MOD_DEC_USE_COUNT;		return NULL;	}	ntfs_debug(DEBUG_OTHER, "Going to init volume\n");	ntfs_init_volume(vol,bh->b_data);	NTFS_SB(vol)=sb;	NTFS_SB2VOL(sb)=vol;	ntfs_debug(DEBUG_OTHER, "Done to init volume\n");	sb->s_blocksize=vol->clustersize;	for(i=sb->s_blocksize,sb->s_blocksize_bits=0;i;i>>=1)		sb->s_blocksize_bits++;	/* inform the kernel that a device block is a NTFS cluster */	set_blocksize(dev,sb->s_blocksize);	ntfs_debug(DEBUG_OTHER, "set_blocksize\n");	ntfs_debug(DEBUG_OTHER, "MFT record at cluster 0x%X\n",vol->mft_cluster);	brelse(bh);	/* Allocate a MFT record */	/* Handle cases where mft record is smaller than a cluster */	vol->mft=ntfs_malloc(max(vol->mft_recordsize,vol->clustersize));	/* read the MFT record 0 */	/* If there is more than one MFT record per cluster, 	   read just one cluster */	for(i=0;i<max(vol->mft_clusters_per_record,1);i++){		if(!(bh=bread(dev,vol->mft_cluster+i,vol->clustersize)))		{			ntfs_error("Could not read MFT record 0\n");			sb->s_dev=0;			unlock_super(sb);			MOD_DEC_USE_COUNT;			return NULL;		}		ntfs_memcpy(vol->mft+i*vol->clustersize,bh->b_data,vol->clustersize);		brelse(bh);		ntfs_debug(DEBUG_OTHER, "Read cluster %x\n",vol->mft_cluster+i);	}	/* Check and fixup MFT record 0 */	if(!ntfs_check_mft_record(vol,vol->mft)){		ntfs_error("Invalid MFT record 0\n");		sb->s_dev=0;		unlock_super(sb);		MOD_DEC_USE_COUNT;		return NULL;	}	/* inform the kernel about which super operations are available */	sb->s_op = &ntfs_super_operations;	sb->s_magic = NTFS_SUPER_MAGIC;		ntfs_debug(DEBUG_OTHER, "Reading master and upcase files\n");	if(ntfs_load_special_files(vol)){		ntfs_error("Error loading special files\n");		sb->s_dev=0;		unlock_super(sb);		MOD_DEC_USE_COUNT;		return NULL;	}	unlock_super(sb);	ntfs_debug(DEBUG_OTHER, "Getting RootDir\n");	/* get the root directory */	if(!(sb->s_mounted=iget(sb,FILE_ROOT))){		sb->s_dev=0;		ntfs_debug(DEBUG_OTHER, "Could not get root dir inode\n");		MOD_DEC_USE_COUNT;		return NULL;	}	ntfs_debug(DEBUG_OTHER, "read_super: done\n");	return sb;}/* This structure defines the filesystem * * Define SECOND if you cannot unload ntfs, and want to avoid rebooting * for just one more test */struct file_system_type ntfs_fs_type = {	ntfs_read_super,/* Entry point of the filesystem */#ifndef SECOND	"ntfs", /* Name of the filesystem, as used in mount -t ntfs */#else	"ntfs2",#endif	1,      /* The filesystem requires a block device to be mounted on */	NULL    /* Will point to the next filesystem in the kernel table */};int init_ntfs_fs(void){	/* Uncomment this if you don't trust klogd. There are reasons	   not to trust it. */#if 0	extern int console_loglevel;	console_loglevel=15;#endif	printk(KERN_NOTICE "NTFS version " NTFS_VERSION "\n");	SYSCTL(1);	ntfs_debug(DEBUG_OTHER, "registering %s\n",ntfs_fs_type.name);	/* add this filesystem to the kernel table of filesystems */	return register_filesystem(&ntfs_fs_type);}#ifdef MODULE/* Every module must contain 2 particular functions whose names are predefined : * . init_module() is called by the kernel when kerneld loads the module in *     memory. Here is the real beginning of the code. * . cleanup_module() is called by the kernel when kerneld removes the module */int init_module(void){	return init_ntfs_fs();}void cleanup_module(void){        SYSCTL(0);	ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name);	unregister_filesystem(&ntfs_fs_type);}#endif#ifdef MODULE/* this is copied from linux/kernel/sysctl.c, because Linux 2.0 fails   to export it */int proc_dointvec(ctl_table *table, int write, struct file *filp,		  void *buffer, size_t *lenp){	int *i, vleft, first=1, len, left, neg, val;	#define TMPBUFLEN 20	char buf[TMPBUFLEN], *p;		if (!table->data || !table->maxlen || !*lenp ||	    (filp->f_pos && !write)) {		*lenp = 0;		return 0;	}		i = (int *) table->data;	vleft = table->maxlen / sizeof(int);	left = *lenp;		for (; left && vleft--; i++, first=0) {		if (write) {			while (left && isspace(get_user((char *) buffer)))				left--, ((char *) buffer)++;			if (!left)				break;			neg = 0;			len = left;			if (len > TMPBUFLEN-1)				len = TMPBUFLEN-1;			memcpy_fromfs(buf, buffer, len);			buf[len] = 0;			p = buf;			if (*p == '-' && left > 1) {				neg = 1;				left--, p++;			}			if (*p < '0' || *p > '9')				break;			val = simple_strtoul(p, &p, 0);			len = p-buf;			if ((len < left) && *p && !isspace(*p))				break;			if (neg)				val = -val;			buffer += len;			left -= len;			*i = val;		} else {			p = buf;			if (!first)				*p++ = '\t';			sprintf(p, "%d", *i);			len = strlen(buf);			if (len > left)				len = left;			memcpy_tofs(buffer, buf, len);			left -= len;			buffer += len;		}	}	if (!write && !first && left) {		put_user('\n', (char *) buffer);		left--, buffer++;	}	if (write) {		p = (char *) buffer;		while (left && isspace(get_user(p++)))			left--;	}	if (write && first)		return -EINVAL;	*lenp -= left;	filp->f_pos += *lenp;	return 0;}#endif/* * Local variables: *  c-file-style: "linux" * End: */

⌨️ 快捷键说明

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