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

📄 ntfs_vfsops.c

📁 NTFS 磁盘系统 加载源代码
💻 C
字号:
#include <sys/param.h>#include <sys/kernel.h>#include <sys/mount.h>#include <sys/vnode.h>#include <sys/namei.h>#include <sys/systm.h>#include <sys/fcntl.h>#include <sys/malloc.h>#include <miscfs/specfs/specdev.h>/* sysctl.h instead */#include <sys/proc.h>#include "ntfs.h"#ifdef DEBUG#define PRINTF(s,args...)	printf(s,##args)#else#define PRINTF(s,args...)#endif/* XXX */#define VT_NTFS		VT_MSDOSFS#define MOUNT_NTFS	MOUNT_MSDOSextern int (**ntfs_vnodeop_p)();/* support functions */void *ntfs_memcpy(void*dest,const void*src,size_t len){	return memcpy(dest,src,len);}void ntfs_bzero(void *dest,size_t n){	bzero(dest,n);}int ntfs_strlen(char*s){	return strlen(s);}void *ntfs_malloc(int size){	void *ret;	MALLOC(ret,void*,size,M_TEMP,M_WAITOK);	PRINTF("Allocating %x at %x\n",size,(unsigned)ret);	return ret;}void ntfs_free(void *block){	PRINTF("Releasing memory at %x\n",(unsigned)block);	FREE(block,M_TEMP);}int ntfs_getput_clusters(ntfs_volume *vol,int cluster,size_t start_offs,	size_t length,ntfs_io *buf){	struct mount* mnt=NTFS_MNT(vol);	struct buf* bp=NULL;	int error;	if(buf->do_read)		printf("get_clusters %d %d %d\n",cluster,start_offs,length);	else		printf("put_clusters %d %d %d\n",cluster,start_offs,length);	error=bread(vol->devvp,cluster*vol->clusterfactor,start_offs+length,		NOCRED, &bp);	if(error)	{		printf("%s failed\n", buf->do_read?"Reading":"Writing");		if(bp)			brelse(bp);		return 0;	}	if(buf->do_read)		buf->fn_put(buf,bp->b_data+start_offs,length);	else	{		printf("Writing not supported\n");	}	brelse(bp);	return 1;}int ntfs_read_mft_record(ntfs_volume *vol,int mftno,char *buf){	ntfs_io io;	printf("read MFT %x\n",mftno);	if(mftno==FILE_MFT)	{		memcpy(buf,vol->mft,vol->mft_recordsize);		return 0;	}	if(!vol->mft_ino)	{		printf("ntfs:something is terribly wrong here\n");		return -1;	}	io.fn_put=ntfs_put;	io.fn_get=0;	io.param=buf;	if(ntfs_read_attr(vol->mft_ino,AT_DATA,NULL,mftno*vol->mft_recordsize,		&io,vol->mft_recordsize)!=vol->mft_recordsize)	{		printf("read_mft_record: read %x failed\n",mftno);		return -1;	}	printf("read_mft_record: finished read %x\n",mftno);	if(!ntfs_check_mft_record(vol,buf))	{		printf("Invalid MFT record for %x\n",mftno);		return -1;	}	printf("read_mft_record: Done %x\n",mftno);	return 0;}void ntfs_error(const char *s,...){	va_list ap;	va_start(ap,s);	printf("%r",s,ap);	va_end(ap);}void ntfs_debug(const char *s,...){	va_list ap;	va_start(ap,s);	printf("%r",s,ap);	va_end(ap);}ntfs_time_t ntfs_now(){	struct timeval atv;	ntfs_time_t result;	microtime(&atv);	/* seconds since 1.1.1601 */	result = atv.tv_sec + (ntfs_time_t)(369*365+89)*24*3600;	/* microseconds */	result *= 1000000;	result += atv.tv_usec;	/* 100 nanoseconds */	return 10*result;}/* VFS operations */int ntfs_mount(mp, path, data, ndp, p)	struct mount *mp;	char *path;	caddr_t data;	struct nameidata *ndp; /* Will be recycled */	struct proc *p;{	char *devpath;	int size,error,i;	struct vnode *devvp;	dev_t dev;	struct buf *bp0=0;	struct buf *mft_bp=0;	int ronly;	int needclose=0;	ntfs_volume *vol=0;	printf("mount\n");	/* copy arguments*/	devpath = (char*)data;	if((mp->mnt_flag & MNT_RDONLY) == 0)		return EROFS;	ronly=1;	printf("mount1\n");		/* locate and investigate mount device */	NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, devpath, p);	if((error=namei(ndp))){		printf("lookup of device failed\n");		return error;	}	devvp = ndp->ni_vp;	if(devvp->v_type != VBLK){		printf("Not a block device\n");		vrele(devvp);		return ENOTBLK;	}	if(major(devvp->v_rdev) >= nblkdev) {		printf("no driver for block device\n");		vrele(devvp);		return ENXIO;	}	dev = devvp->v_rdev;	error=vfs_mountedon(devvp);	if(error){		printf("Already mounted\n");		return error;	}	if(vcount(devvp)>1)		return EBUSY;	error=vinvalbuf(devvp, V_SAVE, p->p_ucred,p,0,0);	if(error){		printf("could not invalidate buffers\n");		return error;	}		/* read boot record */	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD | FWRITE, FSCRED, p);	if(error)		return error;	printf("Opened device\n");	needclose = 1;	/* Need DIOCGPART ? */	error = bread(devvp, 0, 512, NOCRED, &bp0);	if(error)		goto error_exit;	bp0->b_flags |= B_AGE;	if(!IS_NTFS_VOLUME(bp0->b_data)){		printf("Not an NTFS volume\n");		error=EINVAL;		goto error_exit;	}	printf("boot block successfully read\n");	/* allocate ntfs structure */	vol=ntfs_malloc(sizeof(ntfs_volume));	NTFS_MNT(vol)=mp;	NTFS_MNT2VOL(mp)=vol;	vol->rdev=dev;	vol->devvp=devvp;		/* FIXME: get uid etc from mount options */	vol->uid=0;	vol->gid=0;	vol->umask=0777;	ntfs_init_volume(vol, bp0->b_data);	printf("MFT record at cluster 0x%X\n",vol->mft_cluster);	brelse(bp0);	bp0=0;	/* FIXME: inithash */	vol->inode_hash=ntfs_malloc(sizeof(struct ntfs_head));	LIST_INIT(vol->inode_hash);	if(vol->blocksize!=512)	{		printf("Cannot handle blocks of size %d\n",vol->blocksize);		goto error_exit;	}		/* Allocate MFT record 0 */	vol->mft=ntfs_malloc(vol->mft_recordsize);	/* read the MFT record 0 */	error = bread(devvp, vol->mft_cluster * vol->clusterfactor, 		vol->mft_recordsize, NOCRED, &mft_bp);	if(error)		goto error_exit;	memcpy(vol->mft,mft_bp->b_data,vol->mft_recordsize);	mft_bp->b_flags |= B_AGE;	brelse(mft_bp);	mft_bp=0;	printf("Done reading MFT\n");	if(!ntfs_check_mft_record(vol,vol->mft)){		printf("Invalid MFT record 0\n");		goto error_exit;	}		printf("Getting $UpCase\n");	ntfs_load_special_files(vol);	/* get $UpCase */	{		ntfs_inode upcase;		ntfs_init_inode(&upcase,vol,FILE_UPCASE);		ntfs_init_upcase(&upcase);		ntfs_clear_inode(&upcase);	}	/* fill mp: stat, maxsymlinklen, flag(LOCAL) */	copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN-1, &size);	mp->mnt_stat.f_mntonname[size]='\0';	copyinstr(devpath, mp->mnt_stat.f_mntfromname, MNAMELEN-1, &size);	mp->mnt_stat.f_mntfromname[size]='\0';	mp->mnt_stat.f_fsid.val[0]=(long)dev;	mp->mnt_stat.f_fsid.val[1]=MOUNT_NTFS;	mp->mnt_flag |= MNT_LOCAL;	ntfs_statfs(mp, &mp->mnt_stat, p);	printf("mount:returning\n");	return 0;error_exit:	if(bp0)		brelse(bp0);	if(mft_bp)		brelse(mft_bp);	if(needclose)		VOP_CLOSE(devvp, ronly ? FREAD : FREAD | FWRITE, NOCRED, p);	if(vol && vol->mft)		ntfs_free(vol->mft);	if(vol)		ntfs_free(vol);	return error;}intntfs_start(mp,mntflags,p)	struct mount *mp;	int mntflags;	struct proc *p;{	printf("ntfs started\n");	return 0;}intntfs_unmount(mp, mntflags, p)	struct mount *mp;	int mntflags;	struct proc *p;{	int error=0;	int flags=0;	ntfs_volume *vol=NTFS_MNT2VOL(mp);	if (mntflags & MNT_FORCE) {		/* check ntfs_doforce */;		flags |= FORCECLOSE;	}	/* flush mp */	error = vflush(mp, NULLVP, flags);	if(error)		return error;	/* close+release device */	error = VOP_CLOSE(vol->devvp, FREAD, NOCRED, p);	vrele(vol->devvp);	vol->devvp=0;	/* free ntfs structure */	if(vol->mft_ino){		ntfs_clear_inode(vol->mft_ino);		ntfs_free(vol->mft_ino);		vol->mft_ino=0;	}	ntfs_free(vol->mft);	ntfs_free(vol->upcase);	ntfs_free(vol);	mp->mnt_data = 0;	mp->mnt_flag &= ~MNT_LOCAL;	return error;}intntfs_root(mp, vpp)	struct mount *mp;	struct vnode **vpp;{	struct vnode *nvp;	int error;	error = VFS_VGET(mp, (ino_t)FILE_ROOT, &nvp);	if(error)		return error;	*vpp = nvp;	return 0;}intntfs_quotactl(mp, cmd, uid, arg, p)	struct mount *mp;	int cmd;	uid_t uid;	caddr_t arg;	struct proc *p;{	printf("quotactl\n");	return EOPNOTSUPP;}intntfs_statfs(mp, sbp, p)	struct mount *mp;	struct statfs *sbp;	struct proc *p;{	printf("statfs\n");	/* FIXME: some should be filled at mount time, some are not filled */	sbp->f_type=MOUNT_NTFS;	sbp->f_flags=0;	sbp->f_bsize=512; /*XXX*/	sbp->f_iosize=512;	sbp->f_blocks=1;	sbp->f_bfree=1;	sbp->f_bavail=0;	sbp->f_files=1;	sbp->f_ffree=0;	return 0;}intntfs_sync(mp, waitfor, cred, p)	struct mount *mp;	int waitfor;	struct ucred *cred;	struct proc *p;{	return 0;}intntfs_vget(mp, inum, vpp)	struct mount *mp;	ino_t inum;	struct vnode **vpp;{	struct vnode *vp;	ntfs_inode *it;	ntfs_volume *vol;	ntfs_inode *inode;	int error;	printf("vget %x\n",inum);	vol=NTFS_MNT2VOL(mp);retry:	for(it=vol->inode_hash->lh_first;it;it=it->h_next.le_next)	{		printf("Found %d\n",it->i_number);		if(it->i_number==inum)			break;	}	if(it)	{		if(vget(it->vp,0))			goto retry;		printf("reused\n");		*vpp=it->vp;		return 0;	}	error = getnewvnode(VT_NTFS, mp, ntfs_vnodeop_p, &vp);	if(error)	{		printf("error getting new vnode for %x\n",inum);		*vpp=0;		return error;	}	printf("got vnode\n");	/* malloc into vp->v_data */	switch(inum)	{		case FILE_MFT:			inode=vol->mft_ino;			break;		default:			inode=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));			if(!inode || ntfs_init_inode(inode,vol,inum)==-1)			{				printf("NTFS: Error loading inode %x\n",inum);				*vpp=0;				return EINVAL;			}	}	/* Tie 'em together */	vp->v_data=inode;	inode->vp=vp;	/* we need to return it locked */	VOP_LOCK(vp);		/* special device and fifo suppport */	/* file type */	if(ntfs_find_attr(inode,AT_DATA,0))	{		vp->v_type=VREG;	}else if(ntfs_find_attr(inode,AT_INDEX_ROOT,"$I30"))	{		vp->v_type=VDIR;	}else		/* should not happen */		vp->v_type=VNON;	if(inum==FILE_ROOT)		vp->v_flag |= VROOT;		printf("vnode flags: %x\n",vp->v_flag);	LIST_INSERT_HEAD(vol->inode_hash,inode,h_next);	*vpp = vp;	return 0;}intntfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)	struct mount *mp;	struct fid *fhp;	struct mbuf *nam;	struct vnode **vpp;	int *exflagsp;	struct ucred **credanonp;{	printf("fhtovp\n");	return EOPNOTSUPP;}intntfs_vptofh(mp, fhp)	struct vnode *mp;	struct fid *fhp;{	printf("vptofh\n");	return EOPNOTSUPP;}intntfs_init(){	printf("ntfs_init\n");	return 0;}struct vfsops ntfs_vfsops = {	ntfs_mount,	ntfs_start,	ntfs_unmount,	ntfs_root,	ntfs_quotactl,	ntfs_statfs,	ntfs_sync,	ntfs_vget,	ntfs_fhtovp,	ntfs_vptofh,	ntfs_init,};VFS_SET(ntfs_vfsops, ntfs, -1, VFCF_READONLY);

⌨️ 快捷键说明

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