📄 ntfs_vnops.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 "ntfs.h"#ifdef DEBUG#define DO_DEBUG(x) x#else#define DO_DEBUG(x)#endif/* 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;{ DO_DEBUG(printk("open\n")); 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;{ DO_DEBUG(printk("close\n")); 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;{ DO_DEBUG(printk("close\n")); 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); 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; } 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,AT_DATA,NULL))) vap->va_size = DATASIZE(&data->header); else vap->va_size = 0; vap->va_blocksize = ino->vol->clustersize; si=ntfs_find_attr(ino,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.ts_sec = 0; vap->va_mtime.ts_sec = 0; vap->va_ctime.ts_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_io io; /* 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,AT_DATA,0)) return EINVAL; /* move data */ io.fn_put=ntfs_putuser; io.fn_get=0; io.param=uio; ret=ntfs_read_attr(ino,AT_DATA,0,uio->uio_offset,&io,uio->uio_resid); if(ret<0) return EINVAL; return error;}/* later: ioctl *//* later select *//* later: mmap *//* later: seek */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; {#define ITEM_SIZE 2040 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; printf("readdir %x offset %x\n", ino->i_number, uio->uio_offset); /* 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; } item=ntfs_malloc(ITEM_SIZE); entry=ntfs_malloc(sizeof(struct dirent)); entry->d_reclen=sizeof(struct dirent); /* check buffer size */ /* fake .. */ if(uio->uio_offset == 0) { printf("returning ..\n"); entry->d_fileno=5; /* FIXME */ entry->d_type=DT_DIR; entry->d_namlen=2; strcpy(entry->d_name,".."); offs=-2; }else if(uio->uio_offset==-2 && ino->i_number!=FILE_ROOT){ printf("returning .\n"); /* return ., position on first entry */ offs=0; entry->d_fileno=5; /* FIXME */ entry->d_namlen=1; strcpy(entry->d_name,"."); ntfs_getdir_byposition(ino,&offs,item); }else{ /* proceed to first entry for root */ if(uio->uio_offset==-2) { printf("advancing to first entry\n"); offs=0; ntfs_getdir_byposition(ino,&offs,item); printf("entry is %x\n",offs); uio->uio_offset=offs; } offs=uio->uio_offset; printf("advancing to next entry after %x\n",offs); /* proceed to the next entry, find the current entry */ if(!ntfs_getdir_byposition(ino,&offs,item)) { printf("getdir failed, position is %x\n",offs); uio->uio_offset=offs; ntfs_free(item); ntfs_free(entry); return 0; } uio->uio_offset=offs; printf("position is now %x\n",offs); entry->d_namlen=min((unsigned char)*(item+0x50),MAXNAMLEN); ntfs_uni2ascii(entry->d_name,item+0x52,entry->d_namlen); /* dcache? */ } printf("returning data\n"); error=uiomove(entry,sizeof(struct dirent),uio); uio->uio_offset=offs; ntfs_free(item); 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; { int error=0; struct ntfs_inode *dir = NTFS_V2INO(ap->a_dvp); struct componentname *cnp = ap->a_cnp; char *item=0; printf("Looking up %s in %d\n", cnp->cn_nameptr, dir->i_number); 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 */ if(ntfs_getdir_byname(dir,cnp->cn_nameptr,cnp->cn_namelen,item)) { error=VFS_VGET(ap->a_dvp->v_mount,*(int*)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(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; printf("ntfs_reclaim %x\n",ino->i_number); 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, vn_default_error }, { &vop_open_desc, ntfs_open }, { &vop_close_desc, ntfs_close }, { &vop_access_desc, ntfs_access }, { &vop_getattr_desc, ntfs_getattr }, { &vop_readdir_desc, ntfs_readdir }, { &vop_lookup_desc, ntfs_lookup }, { &vop_read_desc, ntfs_read }, { &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 + -