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

📄 fs.c

📁 NTFS(NT文件系统) for Linux的一个实现源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	r->u.generic_ip = ino;#endif	error = ntfs_mkdir(NTFS_LINO2NINO(dir), 			   d->d_name.name, d->d_name.len, ino);	if(error)		goto out;	r->i_uid = vol->uid;	r->i_gid = vol->gid;	r->i_nlink = 1;	r->i_sb = dir->i_sb;	si = ntfs_find_attr(ino,vol->at_standard_information,NULL);	if(si){		char *attr = si->d.data;		r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18));		r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));		r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr+8));	}	/* It's a directory */	r->i_op = &ntfs_dir_inode_operations;	r->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;#ifdef CONFIG_NTFS_RW	r->i_mode|=S_IWUGO;#endif	r->i_mode &= ~vol->umask;			insert_inode_hash(r);	d_instantiate(d, r);	error = 0; out: 	ntfs_debug (DEBUG_DIR1, "mkdir returns %d\n", -error);	return -error;}#endifstatic int ntfs_bmap(struct inode *ino,int block){	int ret=ntfs_vcn_to_lcn(NTFS_LINO2NINO(ino),block);	ntfs_debug(DEBUG_OTHER, "bmap of %lx,block %x is %x\n",	       ino->i_ino,block,ret);	return (ret==-1) ? 0:ret;}static 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, /* flush */	NULL, /* release */	NULL, /* fsync */	NULL, /* fasync */	NULL, /* check_media_change */	NULL, /* revalidate */	NULL, /* lock */};static 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 */	generic_readpage,	NULL, /* writepage */	ntfs_bmap,	NULL, /* truncate */	NULL, /* permission */	NULL, /* smap */	NULL, /* updatepage */	NULL, /* revalidate */};static struct file_operations ntfs_dir_operations = {	NULL, /* lseek */	NULL, /* read */	NULL, /* write */	ntfs_readdir, /* readdir */	NULL, /* poll */	NULL, /* ioctl */	NULL, /* mmap */	NULL, /* open */	NULL, /* flush */	NULL, /* release */	NULL, /* fsync */	NULL, /* fasync */	NULL, /* check_media_change */	NULL, /* revalidate */	NULL, /* lock */};static 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, /* mkdir */#else	NULL,#endif	NULL, /* rmdir */	NULL, /* mknod */	NULL, /* rename */	NULL, /* readlink */	NULL, /* follow_link */	NULL, /* readpage */	NULL, /* writepage */	NULL, /* bmap */	NULL, /* truncate */	NULL, /* permission */	NULL, /* smap */	NULL, /* updatepage */	NULL, /* revalidate */};/* 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;	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:		ntfs_error("Trying to open MFT\n");return;	default:		#ifdef NTFS_IN_LINUX_KERNEL		ino=&inode->u.ntfs_i;		#else		/* FIXME: check for ntfs_malloc failure */		ino=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));		inode->u.generic_ip=ino;		#endif		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;		}	}	/* 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;	}#ifdef CONFIG_NTFS_RW	if(!data || !data->compressed)		inode->i_mode|=S_IWUGO;#endif	inode->i_mode &= ~vol->umask;}#ifdef CONFIG_NTFS_RWstatic void ntfs_write_inode (struct inode *ino){	ntfs_debug (DEBUG_LINUX, "ntfs:write inode %x\n", ino->i_ino);	ntfs_update_inode (NTFS_LINO2NINO (ino));}#endifstatic void _ntfs_clear_inode(struct inode *ino){	ntfs_debug(DEBUG_OTHER, "ntfs_clear_inode %lx\n",ino->i_ino);#ifdef NTFS_IN_LINUX_KERNEL	if(ino->i_ino!=FILE_MFT)		ntfs_clear_inode(&ino->u.ntfs_i);#else	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;	}#endif	return;}/* Called when umounting a filesystem by do_umount() in fs/super.c */static void ntfs_put_super(struct super_block *sb){	ntfs_volume *vol;	ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");	vol=NTFS_SB2VOL(sb);	ntfs_release_volume(vol);	if(vol->nls_map)		unload_nls(vol->nls_map);#ifndef NTFS_IN_LINUX_KERNEL	ntfs_free(vol);#endif	ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");	MOD_DEC_USE_COUNT;}/* Called by the kernel when asking for stats */static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize){	struct statfs fs;	struct inode *mft;	ntfs_volume *vol;	int error;	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;	error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &fs.f_blocks );	if( error )		return error;	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;	copy_to_user(sf,&fs,bufsize);	return 0;}/* Called when remounting a filesystem by do_remount_sb() in fs/super.c */static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options){	if(!parse_options(NTFS_SB2VOL(sb), options))		return -EINVAL;	return 0;}/* Define the super block operation that are implemented */static struct super_operations ntfs_super_operations = {	ntfs_read_inode,#ifdef CONFIG_NTFS_RW	ntfs_write_inode,#else	NULL,#endif	NULL, /* put_inode */	NULL, /* delete_inode */	NULL, /* notify_change */	ntfs_put_super,	NULL, /* write_super */	ntfs_statfs,	ntfs_remount_fs, /* remount */	_ntfs_clear_inode, /* clear_inode */ };/* Called to mount a filesystem by read_super() in fs/super.c * Return a super block, the main structure of a filesystem * * NOTE : Don't store a pointer to an option, as the page containing the * options is freed after ntfs_read_super() returns. * * NOTE : A context switch can happen in kernel code only if the code blocks * (= calls schedule() in kernel/sched.c). */struct super_block * ntfs_read_super(struct super_block *sb, 				     void *options, int silent){	ntfs_volume *vol;	struct buffer_head *bh;	int i;	/* When the driver is compiled as a module, kmod must know when it	 * can safely remove it from memory. To do this, each module owns a	 * reference counter.	 */	MOD_INC_USE_COUNT;	/* Don't put ntfs_debug() before MOD_INC_USE_COUNT, printk() can block	 * so this could lead to a race condition with kmod.	 */	ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");#ifdef NTFS_IN_LINUX_KERNEL	vol = NTFS_SB2VOL(sb);#else	if(!(vol = ntfs_malloc(sizeof(ntfs_volume))))		goto ntfs_read_super_dec;	NTFS_SB2VOL(sb)=vol;#endif		if(!parse_options(vol,(char*)options))		goto ntfs_read_super_vol;	/* Ensure that the super block won't be used until it is completed */	lock_super(sb);	ntfs_debug(DEBUG_OTHER, "lock_super\n");#if 0	/* Set to read only, user option might reset it */	sb->s_flags |= MS_RDONLY;#endif	/* Assume a 512 bytes block device for now */	set_blocksize(sb->s_dev, 512);	/* Read the super block (boot block) */	if(!(bh=bread(sb->s_dev,0,512))) {		ntfs_error("Reading super block failed\n");		goto ntfs_read_super_unl;	}	ntfs_debug(DEBUG_OTHER, "Done reading boot block\n");	/* Check for 'NTFS' magic number */	if(!IS_NTFS_VOLUME(bh->b_data)){		ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n");		brelse(bh);		goto ntfs_read_super_unl;	}	ntfs_debug(DEBUG_OTHER, "Going to init volume\n");	ntfs_init_volume(vol,bh->b_data);	ntfs_debug(DEBUG_OTHER, "MFT record at cluster 0x%X\n",vol->mft_cluster);	brelse(bh);	NTFS_SB(vol)=sb;	ntfs_debug(DEBUG_OTHER, "Done to init volume\n");	/* Inform the kernel that a device block is a NTFS cluster */	sb->s_blocksize=vol->clustersize;	for(i=sb->s_blocksize,sb->s_blocksize_bits=0;i != 1;i>>=1)		sb->s_blocksize_bits++;	set_blocksize(sb->s_dev,sb->s_blocksize);	ntfs_debug(DEBUG_OTHER, "set_blocksize\n");	/* Allocate a MFT record (MFT record can be smaller than a cluster) */	if(!(vol->mft=ntfs_malloc(max(vol->mft_recordsize,vol->clustersize))))		goto ntfs_read_super_unl;	/* Read at least the MFT record for $MFT */	for(i=0;i<max(vol->mft_clusters_per_record,1);i++){		if(!(bh=bread(sb->s_dev,vol->mft_cluster+i,vol->clustersize))) {			ntfs_error("Could not read MFT record 0\n");			goto ntfs_read_super_mft;		}		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 this MFT record */	if(!ntfs_check_mft_record(vol,vol->mft)){		ntfs_error("Invalid MFT record 0\n");		goto ntfs_read_super_mft;	}	/* 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 special files\n");	if(ntfs_load_special_files(vol)){		ntfs_error("Error loading special files\n");		goto ntfs_read_super_mft;	}	ntfs_debug(DEBUG_OTHER, "Getting RootDir\n");	/* Get the root directory */	if(!(sb->s_root=d_alloc_root(iget(sb,FILE_ROOT),NULL))){		ntfs_error("Could not get root dir inode\n");		goto ntfs_read_super_mft;	}	unlock_super(sb);	ntfs_debug(DEBUG_OTHER, "unlock_super\n");	ntfs_debug(DEBUG_OTHER, "read_super: done\n");	return sb;ntfs_read_super_mft:	ntfs_free(vol->mft);ntfs_read_super_unl:	sb->s_dev = 0;	unlock_super(sb);	ntfs_debug(DEBUG_OTHER, "unlock_super\n");ntfs_read_super_vol:	#ifndef NTFS_IN_LINUX_KERNEL	ntfs_free(vol);ntfs_read_super_dec:	#endif	ntfs_debug(DEBUG_OTHER, "read_super: done\n");	MOD_DEC_USE_COUNT;	return NULL;}/* Define the filesystem * * Define SECOND if you cannot unload ntfs, and want to avoid rebooting * for just one more test */static struct file_system_type ntfs_fs_type = {/* Filesystem name, as used after mount -t */#ifndef SECOND	"ntfs",#else	"ntfs2",#endif/* This filesystem requires a device (a hard disk) * May want to add FS_IBASKET when it works */	FS_REQUIRES_DEV,/* Entry point of the filesystem */	ntfs_read_super,/* Will point to the next filesystem in the kernel table */	NULL};/* When this code is not compiled as a module, this is the main entry point, * called by do_sys_setup() in fs/filesystems.c * * NOTE : __initfunc() is a macro used to remove this function from memory * once initialization is done */__initfunc(int init_ntfs_fs(void)){	/* Comment this if you trust klogd. There are reasons not to trust it	 */#if defined(DEBUG) && !defined(MODULE)	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/* A module is a piece of code which can be inserted in and removed * from the running kernel whenever you want using lsmod, or on demand using * kmod *//* No function of this module is needed by another module */EXPORT_NO_SYMBOLS;/* Only used for documentation purposes at the moment, * see include/linux/module.h */MODULE_AUTHOR("Martin von L鰓is");MODULE_DESCRIPTION("NTFS driver");/* no MODULE_SUPPORTED_DEVICE() *//* Load-time parameter */MODULE_PARM(ntdebug, "i");MODULE_PARM_DESC(ntdebug, "Debug level");/* When this code is compiled as a module, if you use mount -t ntfs when no * ntfs filesystem is registered (see /proc/filesystems), get_fs_type() in * fs/super.c asks kmod to load the module named ntfs in memory. * * Therefore, this function is the main entry point in this case */int init_module(void){	return init_ntfs_fs();}/* Called by kmod just before the kernel removes the module from memory */void cleanup_module(void){	SYSCTL(0);	ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name);	unregister_filesystem(&ntfs_fs_type);}#endif/* * Local variables: *  c-file-style: "linux" * End: */

⌨️ 快捷键说明

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