1*18Sbill /* vfs_vnops.c 3.1 10/14/12 */ 2*18Sbill 3*18Sbill #include "../h/param.h" 4*18Sbill #include "../h/systm.h" 5*18Sbill #include "../h/dir.h" 6*18Sbill #include "../h/user.h" 7*18Sbill #include "../h/filsys.h" 8*18Sbill #include "../h/file.h" 9*18Sbill #include "../h/conf.h" 10*18Sbill #include "../h/inode.h" 11*18Sbill #include "../h/reg.h" 12*18Sbill #include "../h/acct.h" 13*18Sbill 14*18Sbill /* 15*18Sbill * Convert a user supplied 16*18Sbill * file descriptor into a pointer 17*18Sbill * to a file structure. 18*18Sbill * Only task is to check range 19*18Sbill * of the descriptor. 20*18Sbill */ 21*18Sbill struct file * 22*18Sbill getf(f) 23*18Sbill register int f; 24*18Sbill { 25*18Sbill register struct file *fp; 26*18Sbill 27*18Sbill if(0 <= f && f < NOFILE) { 28*18Sbill fp = u.u_ofile[f]; 29*18Sbill if(fp != NULL) 30*18Sbill return(fp); 31*18Sbill } 32*18Sbill u.u_error = EBADF; 33*18Sbill return(NULL); 34*18Sbill } 35*18Sbill 36*18Sbill /* 37*18Sbill * Internal form of close. 38*18Sbill * Decrement reference count on 39*18Sbill * file structure. 40*18Sbill * Also make sure the pipe protocol 41*18Sbill * does not constipate. 42*18Sbill * 43*18Sbill * Decrement reference count on the inode following 44*18Sbill * removal to the referencing file structure. 45*18Sbill * Call device handler on last close. 46*18Sbill */ 47*18Sbill closef(fp) 48*18Sbill register struct file *fp; 49*18Sbill { 50*18Sbill register struct inode *ip; 51*18Sbill int flag, mode; 52*18Sbill dev_t dev; 53*18Sbill register int (*cfunc)(); 54*18Sbill struct chan *cp; 55*18Sbill 56*18Sbill if(fp == NULL) 57*18Sbill return; 58*18Sbill if (fp->f_count > 1) { 59*18Sbill fp->f_count--; 60*18Sbill return; 61*18Sbill } 62*18Sbill ip = fp->f_inode; 63*18Sbill flag = fp->f_flag; 64*18Sbill cp = fp->f_un.f_chan; 65*18Sbill dev = (dev_t)ip->i_un.i_rdev; 66*18Sbill mode = ip->i_mode; 67*18Sbill 68*18Sbill plock(ip); 69*18Sbill fp->f_count = 0; 70*18Sbill if(flag & FPIPE) { 71*18Sbill ip->i_mode &= ~(IREAD|IWRITE); 72*18Sbill wakeup((caddr_t)ip+1); 73*18Sbill wakeup((caddr_t)ip+2); 74*18Sbill } 75*18Sbill iput(ip); 76*18Sbill 77*18Sbill switch(mode&IFMT) { 78*18Sbill 79*18Sbill case IFCHR: 80*18Sbill case IFMPC: 81*18Sbill cfunc = cdevsw[major(dev)].d_close; 82*18Sbill break; 83*18Sbill 84*18Sbill case IFBLK: 85*18Sbill case IFMPB: 86*18Sbill cfunc = bdevsw[major(dev)].d_close; 87*18Sbill break; 88*18Sbill default: 89*18Sbill return; 90*18Sbill } 91*18Sbill 92*18Sbill if (flag & FMP) 93*18Sbill goto call; 94*18Sbill 95*18Sbill for(fp=file; fp < &file[NFILE]; fp++) 96*18Sbill if (fp->f_count && fp->f_inode==ip) 97*18Sbill return; 98*18Sbill 99*18Sbill call: 100*18Sbill (*cfunc)(dev, flag, cp); 101*18Sbill } 102*18Sbill 103*18Sbill /* 104*18Sbill * openi called to allow handler 105*18Sbill * of special files to initialize and 106*18Sbill * validate before actual IO. 107*18Sbill */ 108*18Sbill openi(ip, rw) 109*18Sbill register struct inode *ip; 110*18Sbill { 111*18Sbill dev_t dev; 112*18Sbill register unsigned int maj; 113*18Sbill 114*18Sbill dev = (dev_t)ip->i_un.i_rdev; 115*18Sbill maj = major(dev); 116*18Sbill switch(ip->i_mode&IFMT) { 117*18Sbill 118*18Sbill case IFCHR: 119*18Sbill case IFMPC: 120*18Sbill if(maj >= nchrdev) 121*18Sbill goto bad; 122*18Sbill (*cdevsw[maj].d_open)(dev, rw); 123*18Sbill break; 124*18Sbill 125*18Sbill case IFBLK: 126*18Sbill case IFMPB: 127*18Sbill if(maj >= nblkdev) 128*18Sbill goto bad; 129*18Sbill (*bdevsw[maj].d_open)(dev, rw); 130*18Sbill } 131*18Sbill return; 132*18Sbill 133*18Sbill bad: 134*18Sbill u.u_error = ENXIO; 135*18Sbill } 136*18Sbill 137*18Sbill /* 138*18Sbill * Check mode permission on inode pointer. 139*18Sbill * Mode is READ, WRITE or EXEC. 140*18Sbill * In the case of WRITE, the 141*18Sbill * read-only status of the file 142*18Sbill * system is checked. 143*18Sbill * Also in WRITE, prototype text 144*18Sbill * segments cannot be written. 145*18Sbill * The mode is shifted to select 146*18Sbill * the owner/group/other fields. 147*18Sbill * The super user is granted all 148*18Sbill * permissions. 149*18Sbill */ 150*18Sbill access(ip, mode) 151*18Sbill register struct inode *ip; 152*18Sbill { 153*18Sbill register m; 154*18Sbill 155*18Sbill m = mode; 156*18Sbill if(m == IWRITE) { 157*18Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 158*18Sbill u.u_error = EROFS; 159*18Sbill return(1); 160*18Sbill } 161*18Sbill if (ip->i_flag&ITEXT) /* try to free text */ 162*18Sbill xrele(ip); 163*18Sbill if(ip->i_flag & ITEXT) { 164*18Sbill u.u_error = ETXTBSY; 165*18Sbill return(1); 166*18Sbill } 167*18Sbill } 168*18Sbill if(u.u_uid == 0) 169*18Sbill return(0); 170*18Sbill if(u.u_uid != ip->i_uid) { 171*18Sbill m >>= 3; 172*18Sbill if(u.u_gid != ip->i_gid) 173*18Sbill m >>= 3; 174*18Sbill } 175*18Sbill if((ip->i_mode&m) != 0) 176*18Sbill return(0); 177*18Sbill 178*18Sbill u.u_error = EACCES; 179*18Sbill return(1); 180*18Sbill } 181*18Sbill 182*18Sbill /* 183*18Sbill * Look up a pathname and test if 184*18Sbill * the resultant inode is owned by the 185*18Sbill * current user. 186*18Sbill * If not, try for super-user. 187*18Sbill * If permission is granted, 188*18Sbill * return inode pointer. 189*18Sbill */ 190*18Sbill struct inode * 191*18Sbill owner() 192*18Sbill { 193*18Sbill register struct inode *ip; 194*18Sbill 195*18Sbill ip = namei(uchar, 0); 196*18Sbill if(ip == NULL) 197*18Sbill return(NULL); 198*18Sbill if(u.u_uid == ip->i_uid) 199*18Sbill return(ip); 200*18Sbill if(suser()) 201*18Sbill return(ip); 202*18Sbill iput(ip); 203*18Sbill return(NULL); 204*18Sbill } 205*18Sbill 206*18Sbill /* 207*18Sbill * Test if the current user is the 208*18Sbill * super user. 209*18Sbill */ 210*18Sbill suser() 211*18Sbill { 212*18Sbill 213*18Sbill if(u.u_uid == 0) { 214*18Sbill u.u_acflag |= ASU; 215*18Sbill return(1); 216*18Sbill } 217*18Sbill u.u_error = EPERM; 218*18Sbill return(0); 219*18Sbill } 220*18Sbill 221*18Sbill /* 222*18Sbill * Allocate a user file descriptor. 223*18Sbill */ 224*18Sbill ufalloc() 225*18Sbill { 226*18Sbill register i; 227*18Sbill 228*18Sbill for(i=0; i<NOFILE; i++) 229*18Sbill if(u.u_ofile[i] == NULL) { 230*18Sbill u.u_r.r_val1 = i; 231*18Sbill u.u_pofile[i] = 0; 232*18Sbill return(i); 233*18Sbill } 234*18Sbill u.u_error = EMFILE; 235*18Sbill return(-1); 236*18Sbill } 237*18Sbill 238*18Sbill /* 239*18Sbill * Allocate a user file descriptor 240*18Sbill * and a file structure. 241*18Sbill * Initialize the descriptor 242*18Sbill * to point at the file structure. 243*18Sbill * 244*18Sbill * no file -- if there are no available 245*18Sbill * file structures. 246*18Sbill */ 247*18Sbill struct file * 248*18Sbill falloc() 249*18Sbill { 250*18Sbill register struct file *fp; 251*18Sbill register i; 252*18Sbill 253*18Sbill i = ufalloc(); 254*18Sbill if(i < 0) 255*18Sbill return(NULL); 256*18Sbill for(fp = &file[0]; fp < &file[NFILE]; fp++) 257*18Sbill if(fp->f_count == 0) { 258*18Sbill u.u_ofile[i] = fp; 259*18Sbill fp->f_count++; 260*18Sbill fp->f_un.f_offset = 0; 261*18Sbill return(fp); 262*18Sbill } 263*18Sbill printf("no file\n"); 264*18Sbill u.u_error = ENFILE; 265*18Sbill return(NULL); 266*18Sbill } 267