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

📄 ntfs_fs.c

📁 NTFS 磁盘系统 加载源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  ntfs_fs.c *  NTFS driver for Linux * *  Copyright (C) 1995,1996 Martin von L鰓is *  Copyright (C) 1996 Richard Russon *  Copyright (C) 1996 Regis Duchesne */#ifdef MODULE#ifdef CONFIG_MODVERSIONS#define MODVERSIONS#include <linux/modversions.h>#endif /* CONFIG_MODVERSIONS */#include <linux/module.h>#else#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#endif /* MODULE */#include <stdarg.h>#include <linux/version.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/locks.h>#include <linux/stat.h>#include <linux/mm.h>#include <linux/malloc.h>#include <linux/string.h>#include <errno.h>#if (LINUX_VERSION_CODE > (2*65536 + 256))#include <asm/uaccess.h>#else#include <asm/segment.h>#endif#include "config.h"#include "ntfs.h"#include "version.h"#if (LINUX_VERSION_CODE<(2*65536))#error Please upgrade to Linux 2.0#endif#define ITEM_SIZE 2040#define NAME_SIZE 300extern struct inode_operations ntfs_inode_operations;extern struct inode_operations ntfs_inode_operations_nobmap;extern struct inode_operations ntfs_dir_inode_operations;extern struct super_operations ntfs_super_operations;void ntfs_free(void*);#ifdef DEBUG#define PRINTK(x,args...)	printk(x, ##args)#define NTFS_DEBUG(x,args...)	ntfs_debug(x, ##args)#else#define PRINTK(x,args...)#define NTFS_DEBUG(x,args...)#endif#define DEBUG_OTHER	1#define DEBUG_MALLOC	2static int ntdebug;/* io functions to user space */static void ntfs_putuser(ntfs_io* dest,void *src,ntfs_size_t len){#if (LINUX_VERSION_CODE > (2*65536 + 256))	copy_to_user(dest->param,src,len);#else	memcpy_tofs(dest->param,src,len);#endif		dest->param+=len;}static void ntfs_getuser(void *dest,ntfs_io *src,ntfs_size_t len){#if (LINUX_VERSION_CODE > (2*65536 + 256))	copy_from_user(dest,src->param,len);#else	memcpy_fromfs(dest,src->param,len);#endif	src->param+=len;}void *ntfs_memcpy(void*dest,const void*src,__kernel_size_t len){	return memcpy(dest,src,len);}void ntfs_bzero(void *dest,__kernel_size_t n){	memset(dest,0,n);}int ntfs_strlen(char*s){	return strlen(s);}#if (LINUX_VERSION_CODE > (2*65536 + 256))static long ntfs_read(struct inode* inode, struct file * filp, 		     char *buf, unsigned long count)#elsestatic int ntfs_read(struct inode* inode, struct file * filp, char *buf, int count)#endif{	int ret;	ntfs_io io;		NTFS_DEBUG("ntfs_read %x,%x,%x ->",	       (unsigned)inode->i_ino,(unsigned)filp->f_pos,(unsigned)count);	/* inode is not properly initialized */	if(!inode || !inode->u.generic_ip)return -EINVAL;	/* inode has no unnamed data attribute */	if(!ntfs_find_attr((ntfs_inode*)inode->u.generic_ip,AT_DATA,NULL))		return -EINVAL;		/* read the data */	io.fn_put=ntfs_putuser;	io.fn_get=0;	io.param=buf;	ret=ntfs_read_attr((ntfs_inode*)inode->u.generic_ip,			   AT_DATA,NULL,filp->f_pos,&io,count);	NTFS_DEBUG("%x\n",ret);	if(ret<0)return -EINVAL;		filp->f_pos+=ret;	return ret;}#if (LINUX_VERSION_CODE > (2*65536 + 256))static long ntfs_write(struct inode* inode, struct file *filp,	const char* buf, unsigned long count)#elsestatic int ntfs_write(struct inode* inode, struct file *filp,	const char* buf, int count)#endif{	struct super_block* sb;	int ret;	ntfs_io io;	NTFS_DEBUG("ntfs_write %x,%x,%x ->",	       (unsigned)inode->i_ino,(unsigned)filp->f_pos,(unsigned)count);	if(!inode || !inode->u.generic_ip)		return -EINVAL;	sb = inode->i_sb;	/* Allows to lock fs ro at any time */	if(sb->s_flags & MS_RDONLY)		return -ENOSPC;	if(!ntfs_find_attr(inode->u.generic_ip,AT_DATA,NULL))		return -EINVAL;	io.fn_put=0;	io.fn_get=ntfs_getuser;	io.param=(void*)buf; /* to get rid of the const */	ret = ntfs_write_attr((ntfs_inode*)inode->u.generic_ip,			      AT_DATA,NULL,filp->f_pos,&io,count);	NTFS_DEBUG("%x\n",ret);	if(ret<0)return -EINVAL;	filp->f_pos+=ret;	return ret;}/* 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("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)==-1)		{			NTFS_DEBUG("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,AT_DATA,NULL);	if(!data)	{		inode->i_size=0;		can_mmap=0;	}	else	{		inode->i_size=DATASIZE(&data->header);		can_mmap=!RESIDENT(&data->header) && !COMPRESSED(&data->header);	}	/* get the file modification times from the standard information */	si=ntfs_find_attr(ino,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,AT_INDEX_ROOT,"$I30"))	{		ntfs_attribute *at;		at = ntfs_find_attr (ino, AT_INDEX_ALLOCATION, "$I30");		inode->i_size = at ? DATASIZE(&at->header) : 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;	}	inode->i_mode &= ~vol->umask;}struct ntfs_filldir{	struct inode *dir;	filldir_t filldir;	enum ntfs_getdent_type type;	ntfs_u32 ph,pl;	void *dirent;	char *name;	int namelen;};	static int ntfs_printcb(ntfs_u8 *entry,void *param){	struct ntfs_filldir* nf=param;	int flags=NTFS_GETU8(entry+0x51);	int show_hidden=0,to_lower=0;	int length=min(NTFS_GETU8(entry+0x50),NAME_SIZE);	int inum=NTFS_GETU32(entry);	int i,error;	switch(nf->type){	case ngt_dos:		if((flags & 2)==0)			return 0;		break;	case ngt_nt:		if((flags & 1)==0)			return 0;		if((flags & 2)==2)			to_lower=1;		break;	case ngt_posix:		break;	case ngt_full:		show_hidden=1;		break;	}	if(!show_hidden && ((NTFS_GETU8(entry+0x48) & 2)==2))		return 0;	/* FIXME: utf 8 handling 	ntfs_uni2ascii(nf->name,entry+0x52,length);*/	if(ntfs_encodeuni(NTFS_INO2VOL(nf->dir),(ntfs_u16*)(entry+0x52),			  length,&nf->name,&nf->namelen))		return 0;	/* Do not return ".", as this is faked */	if(length==1 && *nf->name=='.')		return 0;	if(to_lower)		for(i=0;i<nf->namelen;i++)			/* This supports ASCII only. Since only DOS-only			   names get converted, and since those are restricted			   to ASCII, this should be correct */			if(nf->name[i]>='A' && nf->name[i]<='Z')				nf->name[i]+='a'-'A';	nf->name[nf->namelen]=0;	dcache_add(nf->dir,nf->name,nf->namelen,inum);	NTFS_DEBUG("readdir got %s,len %d\n",nf->name,nf->namelen);	/* filldir expects an off_t rather than an loff_t.	   Hope we don't have more than 65535 index records */	error=nf->filldir(nf->dirent,nf->name,nf->namelen,			(nf->ph<<16)|nf->pl,inum);	/* Linux filldir errors are negative, other errors positive */	return error;}/* readdir returns '..', then '.', then the directory entries in sequence   As the root directory contains a entry for itself, '.' is not emulated   for the root directory */static int ntfs_readdir(struct inode* dir, struct file *filp, 	void *dirent, filldir_t filldir){	struct ntfs_filldir cb;	int error;	NTFS_DEBUG("ntfs_readdir ino %x mode %x\n",	       (unsigned)dir->i_ino,(unsigned int)dir->i_mode);	if(!dir || (dir->i_ino==0) || !S_ISDIR(dir->i_mode))return -EBADF;	NTFS_DEBUG("readdir: Looking for file %x dircount %d\n",	       (unsigned)filp->f_pos,dir->i_count);	cb.pl=filp->f_pos & 0xFFFF;	cb.ph=filp->f_pos >> 16;	/* end of directory */	if(cb.ph==0xFFFF){		/* FIXME: Maybe we can return those with the previous call */		switch(cb.pl){		case 0: filldir(dirent,".",1,filp->f_pos,dir->i_ino);			filp->f_pos=0xFFFF0001;			return 0;			/* FIXME: parent directory */		case 1: filldir(dirent,"..",2,filp->f_pos,0);			filp->f_pos=0xFFFF0002;			return 0;		}		NTFS_DEBUG("readdir: EOD\n");		return 0;	}	cb.dir=dir;	cb.filldir=filldir;	cb.name=ntfs_malloc(NAME_SIZE);	cb.dirent=dirent;	cb.type=NTFS_INO2VOL(dir)->ngt;	do{		error=ntfs_getdir_unsorted(dir->u.generic_ip,&cb.ph,&cb.pl,				   ntfs_printcb,&cb);	}while(!error && cb.ph!=0xFFFFFFFF);	ntfs_free(cb.name);	filp->f_pos=(cb.ph<<16)|cb.pl;	NTFS_DEBUG("new position %x\n",(unsigned)filp->f_pos);        /* -EINVAL is on user buffer full. This is not considered 	   as an error by sys_getdents */	if(error<0) 		error=0;	/* Otherwise (device error, inconsistent data), switch the sign */	return -error;}static void ntfs_put_inode(struct inode *ino){	NTFS_DEBUG("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_statfs(struct super_block *sb, struct statfs *sf, int bufsize){	struct statfs fs;	struct inode *bitmap;	struct inode *mft;	ntfs_volume *vol;	NTFS_DEBUG("ntfs_statfs\n");	vol=NTFS_SB2VOL(sb);	memset(&fs,0,sizeof(fs));	fs.f_type=NTFS_SUPER_MAGIC;	fs.f_bsize=vol->clustersize;	fs.f_blocks=ntfs_get_volumesize(NTFS_SB2VOL(sb));	bitmap=iget(sb,FILE_BITMAP);	fs.f_bfree=ntfs_get_free_cluster_count((ntfs_inode*)bitmap->u.generic_ip);	iput(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;#if (LINUX_VERSION_CODE > (2*65536 + 256))	copy_to_user(sf,&fs,bufsize);#else	memcpy_tofs(sf,&fs,bufsize);#endif}static int parse_options(struct super_block *sb,ntfs_volume* vol,char *opt){	char *value;	vol->uid=vol->gid=0;	vol->umask=0777;	vol->ngt=ngt_nt;	vol->nct=nct_utf8;	if(!opt)return 1;	for(opt = strtok(opt,",");opt;opt=strtok(NULL,","))	{		if ((value = strchr(opt, '=')) != NULL)			*value++='\0';		if(strcmp(opt,"uid")==0)		{			if(!value || !*value){				printk(KERN_ERR "NTFS: uid needs an argument\n");				return 0;			}			vol->uid=simple_strtoul(value,&value,0);			if(*value){				printk(KERN_ERR "NTFS: uid invalid argument\n");				return 0;			}		}else if(strcmp(opt, "gid") == 0)		{			if(!value || !*value){				printk(KERN_ERR "NTFS: gid needs an argument\n");				return 0;			}			vol->gid=simple_strtoul(value,&value,0);			if(*value){				printk(KERN_ERR "gid invalid argument\n");				return 0;			}		}else if(strcmp(opt, "umask") == 0)		{			if(!value || !*value){				printk(KERN_ERR "NTFS: umask needs an argument\n");				return 0;			}			vol->umask=simple_strtoul(value,&value,0);			if(*value){				printk(KERN_ERR "umask invalid argument\n");				return 0;			}		}else if(strcmp(opt, "charset") == 0){			if(!value || !*value){				printk(KERN_ERR "NTFS: charset needs an argument");				return 0;			}			if(strcmp(value,"iso8859-1") == 0)				vol->nct = nct_iso8859_1;			else{				printk(KERN_ERR "NTFS: unknown charset");				return 0;			}		}else if(strcmp(opt, "posix") == 0)			vol->ngt=ngt_posix;		else if(strcmp(opt, "nt") == 0)			vol->ngt=ngt_nt;		else if(strcmp(opt, "dos") == 0)			vol->ngt=ngt_dos;		else if(strcmp(opt, "full") == 0)			vol->ngt=ngt_full;		else if(strcmp(opt, "ntrw") == 0)		{			if(value){				printk(KERN_ERR "NTFS: rw doesn't need an argument\n");				return 0;			}			sb->s_flags &= ~MS_RDONLY;		}else{			printk(KERN_ERR "NTFS: unkown option '%s'\n", opt);			return 0;		}	}	return 1;}			/* 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("ntfs_read_super\n");	MOD_INC_USE_COUNT;	lock_super(sb);	NTFS_DEBUG("lock_super\n");	/* set to read only, user option might reset it */	sb->s_flags |= MS_RDONLY;	vol=ntfs_malloc(sizeof(ntfs_volume));	if(!parse_options(sb,vol,(char*)options)){		unlock_super(sb);		ntfs_free(vol);

⌨️ 快捷键说明

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