📄 ntfs_vfsops.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 + -