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

📄 ntfs_vnops.c

📁 一个linux下NTFS文件格式源代码
💻 C
字号:
#include <sys/param.h>#include <sys/kernel.h>#include <sys/vnode.h>#include <sys/dirent.h>#include <sys/namei.h>#include <sys/mount.h>#include <sys/systm.h>#include "ntfstypes.h"#include "struct.h"#include "macros.h"#include "util.h"#include "inode.h"#include "super.h"#include "support.h"#include "dir.h"/* Helper */void ntfs_putuser(ntfs_io* dest,void *src,size_t n){	uiomove(src,n,(struct uio*)(dest->param));}/* vnode operations */intntfs_open(ap)	struct vop_open_args /* {		struct vnode *a_vp;		int  a_mode;		struct ucred *a_cred;		struct proc *a_p;	}*/ *ap;{	/* Check append-only, etc */	return 0;}int ntfs_close(ap)	struct vop_close_args /* {		struct vnode *a_vp;		int  a_fflag;		struct ucred *a_cred;		struct proc *a_p;  	} */ *ap;{	/* write back time stamps */	return 0;}int ntfs_access(ap)	struct vop_access_args /* {		struct vnode *a_vp;		int  a_mode;		struct ucred *a_cred;		struct proc *a_p;	} */ *ap;{	struct vnode *vp = ap->a_vp;	mode_t mask,mode = ap->a_mode;	struct ucred *cred = ap->a_cred;	ntfs_volume *vol = NTFS_V2INO(vp)->vol;	int i;	gid_t *gp;	if (mode & VWRITE) {		switch (vp->v_type) {		case VDIR:		case VLNK:		case VREG:			if (vp->v_mount->mnt_flag & MNT_RDONLY)				return (EROFS);			break;		default:			break;		}	}	/* FIXME missing checks: quota, immutable */	if (cred->cr_uid == 0)		/* root gets always access */		return 0;	/* build the required mask */	mask=0;	if (cred->cr_uid == vol->uid) {		if (mode & VEXEC)      mask |= S_IXUSR;		if (mode & VREAD)      mask |= S_IRUSR;		if (mode & VWRITE)     mask |= S_IWUSR;		if (vol->umask & mask) return EACCES;	}	for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)		if (vol->gid == *gp) {			if (mode & VEXEC)      mask |= S_IXGRP;			if (mode & VREAD)      mask |= S_IRGRP;			if (mode & VWRITE)     mask |= S_IWGRP;			if (vol->umask & mask) return EACCES;		}	if (mode & VEXEC)      mask |= S_IXOTH;	if (mode & VREAD)      mask |= S_IROTH;	if (mode & VWRITE)     mask |= S_IWOTH;	if (vol->umask & mask) return EACCES;	return 0;}intntfs_getattr(ap)	struct vop_getattr_args /* { 		struct vnode *a_vp;		 struct vattr *a_vap; 		struct ucred *a_cred; 		struct proc *a_p;	} */ *ap;{	ntfs_inode *ino = NTFS_V2INO(ap->a_vp);	ntfs_volume *vol = ino->vol;	struct vattr *vap = ap->a_vap;	ntfs_attribute *si,*data;	vap->va_type = ap->a_vp->v_type;	vap->va_mode = 0;	switch(ap->a_vp->v_type)	{	case VDIR:	    vap->va_mode |= S_IFDIR | S_IRUSR | S_IXUSR |		S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;	    break;	case VREG:	    vap->va_mode |= S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;	    break;	default:	    panic("Unknown device type\n");	    break;	}	vap->va_mode &= ~ino->vol->umask;	vap->va_nlink = 1; /* FIXME */	vap->va_uid = ino->vol->uid;	vap->va_gid = ino->vol->gid;	vap->va_fsid = ino->vol->rdev;	vap->va_fileid = ino->i_number;	if((data=ntfs_find_attr(ino,vol->at_data,NULL)))		vap->va_size = data->size;	else		vap->va_size = 0;	vap->va_blocksize = ino->vol->clustersize;	si=ntfs_find_attr(ino,vol->at_standard_information,NULL);	if(si)	{		char *attr=si->d.data;#if 0		/* no FPU allowed here */		vap->va_atime.ts_sec = ntfs_ntutc2unixutc(*(long long*)(attr+0x18));		vap->va_mtime.ts_sec = ntfs_ntutc2unixutc(*(long long*)(attr+8));		vap->va_ctime.ts_sec = ntfs_ntutc2unixutc(*(long long*)(attr));#else		vap->va_atime.tv_sec = 0;		vap->va_mtime.tv_sec = 0;		vap->va_ctime.tv_sec = 0;#endif		/* FIXME: ts_nsec */	}	vap->va_gen = 0; /* FIXME */	vap->va_flags = 0;	vap->va_rdev = VNOVAL;	vap->va_bytes = vap->va_size; /* FIXME: allocated size */	vap->va_filerev = VNOVAL;	/* vap->va_vaflags unused */	/* vap->va_spare unused */	return 0;}intntfs_read(ap)	struct vop_read_args /* {		struct vnode *a_vp;		struct uio *a_uio;		int a_ioflag;		struct ucred *a_cred;	} */ *ap;{	int error=0,ret;	struct uio *uio = ap->a_uio;	struct ntfs_inode *ino = NTFS_V2INO(ap->a_vp);	ntfs_volume *vol = ino->vol;	ntfs_io io;	ntfs_debug(DEBUG_BSD,"ntfs_read\n");	/* no data requested */	if(uio->uio_resid==0)		return 0;	if(uio->uio_offset<0)		return EINVAL;	/* reading directories is not supported */	if(ap->a_vp->v_type == VDIR)		return EISDIR;	if(!ino || !ntfs_find_attr(ino,vol->at_data,0))		return EINVAL;	/* move data */	io.fn_put=ntfs_putuser;	io.fn_get=0;	io.param=uio;	io.size=uio->uio_resid;	ret=ntfs_read_attr(ino,vol->at_data,0,uio->uio_offset,&io);	if(ret<0)		return EINVAL;	return error;}intntfs_ioctl(ap)	struct vop_ioctl_args /* {		struct vnode *a_vp;		int  a_command;		caddr_t  a_data;		int  a_fflag;		struct ucred *a_cred;		struct proc *a_p;	} */ *ap;{	return ENOTTY;}intntfs_select(ap)	struct vop_select_args /* {		struct vnode *a_vp;		int  a_which;		int  a_fflags;		struct ucred *a_cred;		struct proc *a_p;	} */ *ap;{	/*	 * We should really check to see if I/O is possible.	 */	return 1;}/* mmap currently not used by BSD *//* later: seek */struct ntfs_readdir{	ntfs_volume *vol;	/* filldir_t filldir;*/	/* unsigned int type;*/	struct uio* uio;	struct dirent *entry;};static int ntfs_printcb(ntfs_u8* entry, void *param){	struct ntfs_readdir *snr=param;	char *name;	int namelen;	int error=0;	int length=NTFS_GETU8(entry+0x50);	ntfs_debug(DEBUG_DIR2,"Got entry\n");	if((signed)sizeof(struct dirent)>snr->uio->uio_resid)		/* reached end of user memory */		return -1;	/* FIXME: suppress unwanted names */ 	if(ntfs_encodeuni(snr->vol,(ntfs_u16*)(entry+0x52),			  length,&name,&namelen))		/* just skip the entry */		return 0;	ntfs_debug(DEBUG_DIR2,"GOT (%p,%d),%s\n",name,length,name);	/* don't return . */	if(length==1 && name[0]=='.')		goto err_free;	/* don't return oversized names */	if(length > MAXNAMLEN)		goto err_free;	/* FIXME: lower case conversion */	/* now fill the entry */	snr->entry->d_fileno=NTFS_GETU32(entry);	snr->entry->d_namlen=length;	ntfs_memmove(snr->entry->d_name,name,length);	snr->entry->d_name[length]='\0';	/* and pass it to the user */	error=uiomove((caddr_t)(snr->entry),sizeof(struct dirent),snr->uio);	ntfs_debug(DEBUG_DIR1,"return (%d)%s\n",length,name); err_free:	ntfs_free(name);	return error;}intntfs_readdir(ap)	struct vop_readdir_args /* {		struct vnode *a_vp;		struct uio *a_uio;		struct ucred *a_cred;		int *a_eofflag;		u_int *a_cookies;		int a_ncookies;	} */ *ap;       {	int error=0;	struct ntfs_inode *ino = NTFS_V2INO(ap->a_vp);	struct uio *uio = ap->a_uio;	char *item;	struct dirent *entry;	long long offs;	struct ntfs_readdir snr;	ntfs_u32 pl,ph;	ntfs_debug(DEBUG_BSD,"readdir %x offset %x%x, amount %d\n", 		   (u_int)ino->i_number, (u_int)(uio->uio_offset>>32), 		   (u_int)(uio->uio_offset),uio->uio_resid);	/* dir checking should have been done */	/* cookies not supported */	if(ap->a_eofflag || ap->a_cookies || ap->a_ncookies)	{		printf("ntfs: cookies not supported\n");		return EOPNOTSUPP;	}	entry=ntfs_malloc(sizeof(struct dirent));	entry->d_reclen=sizeof(struct dirent);	/* FIXME: better type reporting */	entry->d_type=DT_UNKNOWN;	snr.vol=ino->vol;	snr.uio=uio;	snr.entry=entry;	ph=uio->uio_offset >> 16;	pl=uio->uio_offset & 0xFFFF;	ntfs_debug(DEBUG_DIR2,"readdir %x %x\n",ph,pl);	while(ph!=0xFFFFFFFF){		/* not at end of dir */		error=ntfs_getdir_unsorted(ino,&ph,&pl,ntfs_printcb,&snr);		if(error==-1){			/*user buffer full, success*/			error=0;			goto setoffset;		}		if(error)			/* fail the entire operation */			goto out;	}	/* fake .. */	if(pl==0 && uio->uio_resid>=sizeof(struct dirent))	{		entry->d_fileno=5; /* FIXME */		entry->d_type=DT_DIR;		entry->d_namlen=2;		strcpy(entry->d_name,"..");		error=uiomove((caddr_t)entry,sizeof(struct dirent),uio);		if(error)goto out;		pl=1;	}	if(pl==1 && uio->uio_resid>=sizeof(struct dirent)){		/* return . */		entry->d_fileno=5; /* FIXME */		entry->d_namlen=1;		strcpy(entry->d_name,".");		error=uiomove((caddr_t)entry,sizeof(struct dirent),uio);		if(error)goto out;		pl=2;	} setoffset:	uio->uio_offset=(((off_t)ph)<<16)|pl; out:	ntfs_free(entry);	return error;}intntfs_lookup(ap)	struct vop_lookup_args /* {		struct vnode *a_dvp;		struct vnode **a_vpp;		struct componentname *a_cnp;	} */ *ap; {#define ITEM_SIZE 2050	int error=0;	struct ntfs_inode *dir = NTFS_V2INO(ap->a_dvp);	struct componentname *cnp = ap->a_cnp;	char *item=0;	struct ntfs_iterate_s walk;	if(ap->a_dvp->v_type != VDIR)		return ENOTDIR;	switch(cnp->cn_nameiop)	{		case CREATE:case RENAME:case DELETE:		printf("not supported\n");		return EOPNOTSUPP;	}	/* check credentials */	/* check name cache */	/* check .,.. */	item=ntfs_malloc(ITEM_SIZE);	/* ntfs_getdir will place the directory entry into item,	   and the first long long is the MFT record number */	error=ntfs_decodeuni(dir->vol,cnp->cn_nameptr,cnp->cn_namelen,			     &walk.name,&walk.namelen);	if(error)		return error;	walk.type=BY_NAME;	walk.dir=dir;	walk.result=item;	if(ntfs_getdir_byname(&walk))	{		error=VFS_VGET(ap->a_dvp->v_mount,NTFS_GETU32(item),ap->a_vpp);		if(error)		{			ntfs_free(item);			return error;		}		if(!(cnp->cn_flags & LOCKPARENT) || !(cnp->cn_flags & ISLASTCN))			VOP_UNLOCK(ap->a_dvp);		/* cache put*/	}else		error=ENOENT;	ntfs_free(walk.name);	ntfs_free(item);	return error;}		/* later: readlink *//* TODO: abortop *//* TODO: lock *//* TODO: unlock */intntfs_islocked(ap)	struct vop_islocked_args /* {		struct vnode *a_vp;	} */ *ap;{	/* FIXME: real locking */	return 0;}/* later: strategy */intntfs_reclaim(ap)	struct vop_reclaim_args /* {		struct vnode *a_vp;	} */ *ap;{	struct ntfs_inode *ino=ap->a_vp->v_data;	if(!ino)		return EINVAL;	LIST_REMOVE(ino,h_next);	/* cache purge */	if(ino->i_number!=FILE_MFT)	{		ntfs_clear_inode(ino);		ntfs_free(ino);	}	ap->a_vp->v_data=0;	return 0;}int (**ntfs_vnodeop_p)();struct vnodeopv_entry_desc ntfs_vnodeop_entries[] = {	{ &vop_default_desc, (vop_t*)vn_default_error },        	{ &vop_open_desc, ntfs_open },	{ &vop_close_desc, ntfs_close },	{ &vop_access_desc, ntfs_access },	{ &vop_getattr_desc, ntfs_getattr },	{ &vop_read_desc, ntfs_read },	{ &vop_ioctl_desc, ntfs_ioctl },	{ &vop_select_desc, ntfs_select },	{ &vop_readdir_desc, ntfs_readdir },	{ &vop_lookup_desc, ntfs_lookup },	{ &vop_islocked_desc, ntfs_islocked },	{ &vop_reclaim_desc, ntfs_reclaim },	{ (struct vnodeop_desc *)NULL, (int (*)())NULL }};struct vnodeopv_desc ntfs_vnodeop_opv_desc =	{ &ntfs_vnodeop_p, ntfs_vnodeop_entries };VNODEOP_SET(ntfs_vnodeop_opv_desc);

⌨️ 快捷键说明

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