1*387Sbill /* vfs_vnops.c 3.3 07/19/80 */ 218Sbill 318Sbill #include "../h/param.h" 418Sbill #include "../h/systm.h" 518Sbill #include "../h/dir.h" 618Sbill #include "../h/user.h" 718Sbill #include "../h/filsys.h" 818Sbill #include "../h/file.h" 918Sbill #include "../h/conf.h" 1018Sbill #include "../h/inode.h" 1118Sbill #include "../h/reg.h" 1218Sbill #include "../h/acct.h" 1318Sbill 1418Sbill /* 1518Sbill * Convert a user supplied 1618Sbill * file descriptor into a pointer 1718Sbill * to a file structure. 1818Sbill * Only task is to check range 1918Sbill * of the descriptor. 2018Sbill */ 2118Sbill struct file * 2218Sbill getf(f) 2318Sbill register int f; 2418Sbill { 2518Sbill register struct file *fp; 2618Sbill 2718Sbill if(0 <= f && f < NOFILE) { 2818Sbill fp = u.u_ofile[f]; 2918Sbill if(fp != NULL) 3018Sbill return(fp); 3118Sbill } 3218Sbill u.u_error = EBADF; 3318Sbill return(NULL); 3418Sbill } 3518Sbill 3618Sbill /* 3718Sbill * Internal form of close. 3818Sbill * Decrement reference count on 3918Sbill * file structure. 4018Sbill * Also make sure the pipe protocol 4118Sbill * does not constipate. 4218Sbill * 4318Sbill * Decrement reference count on the inode following 4418Sbill * removal to the referencing file structure. 4518Sbill * Call device handler on last close. 4618Sbill */ 4718Sbill closef(fp) 4818Sbill register struct file *fp; 4918Sbill { 5018Sbill register struct inode *ip; 5118Sbill int flag, mode; 5218Sbill dev_t dev; 5318Sbill register int (*cfunc)(); 5418Sbill struct chan *cp; 5518Sbill 5618Sbill if(fp == NULL) 5718Sbill return; 5818Sbill if (fp->f_count > 1) { 5918Sbill fp->f_count--; 6018Sbill return; 6118Sbill } 6218Sbill ip = fp->f_inode; 6318Sbill flag = fp->f_flag; 6418Sbill cp = fp->f_un.f_chan; 6518Sbill dev = (dev_t)ip->i_un.i_rdev; 6618Sbill mode = ip->i_mode; 6718Sbill 6818Sbill plock(ip); 6918Sbill fp->f_count = 0; 7018Sbill if(flag & FPIPE) { 7118Sbill ip->i_mode &= ~(IREAD|IWRITE); 7218Sbill wakeup((caddr_t)ip+1); 7318Sbill wakeup((caddr_t)ip+2); 7418Sbill } 7518Sbill iput(ip); 7618Sbill 7718Sbill switch(mode&IFMT) { 7818Sbill 7918Sbill case IFCHR: 8018Sbill case IFMPC: 8118Sbill cfunc = cdevsw[major(dev)].d_close; 8218Sbill break; 8318Sbill 8418Sbill case IFBLK: 8518Sbill case IFMPB: 8618Sbill cfunc = bdevsw[major(dev)].d_close; 8718Sbill break; 8818Sbill default: 8918Sbill return; 9018Sbill } 9118Sbill 9218Sbill if (flag & FMP) 9318Sbill goto call; 9418Sbill 9518Sbill for(fp=file; fp < &file[NFILE]; fp++) 9618Sbill if (fp->f_count && fp->f_inode==ip) 9718Sbill return; 9818Sbill 9918Sbill call: 10018Sbill (*cfunc)(dev, flag, cp); 10118Sbill } 10218Sbill 10318Sbill /* 10418Sbill * openi called to allow handler 10518Sbill * of special files to initialize and 10618Sbill * validate before actual IO. 10718Sbill */ 10818Sbill openi(ip, rw) 10918Sbill register struct inode *ip; 11018Sbill { 11118Sbill dev_t dev; 11218Sbill register unsigned int maj; 11318Sbill 11418Sbill dev = (dev_t)ip->i_un.i_rdev; 11518Sbill maj = major(dev); 11618Sbill switch(ip->i_mode&IFMT) { 11718Sbill 11818Sbill case IFCHR: 11918Sbill case IFMPC: 12018Sbill if(maj >= nchrdev) 12118Sbill goto bad; 12218Sbill (*cdevsw[maj].d_open)(dev, rw); 12318Sbill break; 12418Sbill 12518Sbill case IFBLK: 12618Sbill case IFMPB: 12718Sbill if(maj >= nblkdev) 12818Sbill goto bad; 12918Sbill (*bdevsw[maj].d_open)(dev, rw); 13018Sbill } 13118Sbill return; 13218Sbill 13318Sbill bad: 13418Sbill u.u_error = ENXIO; 13518Sbill } 13618Sbill 13718Sbill /* 13818Sbill * Check mode permission on inode pointer. 13918Sbill * Mode is READ, WRITE or EXEC. 14018Sbill * In the case of WRITE, the 14118Sbill * read-only status of the file 14218Sbill * system is checked. 14318Sbill * Also in WRITE, prototype text 14418Sbill * segments cannot be written. 14518Sbill * The mode is shifted to select 14618Sbill * the owner/group/other fields. 14718Sbill * The super user is granted all 14818Sbill * permissions. 14918Sbill */ 15018Sbill access(ip, mode) 15118Sbill register struct inode *ip; 15218Sbill { 15318Sbill register m; 15418Sbill 15518Sbill m = mode; 15618Sbill if(m == IWRITE) { 15718Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 15818Sbill u.u_error = EROFS; 15918Sbill return(1); 16018Sbill } 16118Sbill if (ip->i_flag&ITEXT) /* try to free text */ 16218Sbill xrele(ip); 16318Sbill if(ip->i_flag & ITEXT) { 16418Sbill u.u_error = ETXTBSY; 16518Sbill return(1); 16618Sbill } 16718Sbill } 16818Sbill if(u.u_uid == 0) 16918Sbill return(0); 17018Sbill if(u.u_uid != ip->i_uid) { 17118Sbill m >>= 3; 17218Sbill if(u.u_gid != ip->i_gid) 17318Sbill m >>= 3; 17418Sbill } 17518Sbill if((ip->i_mode&m) != 0) 17618Sbill return(0); 17718Sbill 17818Sbill u.u_error = EACCES; 17918Sbill return(1); 18018Sbill } 18118Sbill 18218Sbill /* 18318Sbill * Look up a pathname and test if 18418Sbill * the resultant inode is owned by the 18518Sbill * current user. 18618Sbill * If not, try for super-user. 18718Sbill * If permission is granted, 18818Sbill * return inode pointer. 18918Sbill */ 19018Sbill struct inode * 19118Sbill owner() 19218Sbill { 19318Sbill register struct inode *ip; 19418Sbill 19518Sbill ip = namei(uchar, 0); 19618Sbill if(ip == NULL) 19718Sbill return(NULL); 19818Sbill if(u.u_uid == ip->i_uid) 19918Sbill return(ip); 20018Sbill if(suser()) 20118Sbill return(ip); 20218Sbill iput(ip); 20318Sbill return(NULL); 20418Sbill } 20518Sbill 20618Sbill /* 20718Sbill * Test if the current user is the 20818Sbill * super user. 20918Sbill */ 21018Sbill suser() 21118Sbill { 21218Sbill 21318Sbill if(u.u_uid == 0) { 21418Sbill u.u_acflag |= ASU; 21518Sbill return(1); 21618Sbill } 21718Sbill u.u_error = EPERM; 21818Sbill return(0); 21918Sbill } 22018Sbill 22118Sbill /* 22218Sbill * Allocate a user file descriptor. 22318Sbill */ 22418Sbill ufalloc() 22518Sbill { 22618Sbill register i; 22718Sbill 22818Sbill for(i=0; i<NOFILE; i++) 22918Sbill if(u.u_ofile[i] == NULL) { 23018Sbill u.u_r.r_val1 = i; 23118Sbill u.u_pofile[i] = 0; 23218Sbill return(i); 23318Sbill } 23418Sbill u.u_error = EMFILE; 23518Sbill return(-1); 23618Sbill } 23718Sbill 238*387Sbill struct file *lastf = &file[0]; 23918Sbill /* 24018Sbill * Allocate a user file descriptor 24118Sbill * and a file structure. 24218Sbill * Initialize the descriptor 24318Sbill * to point at the file structure. 24418Sbill * 24518Sbill * no file -- if there are no available 24618Sbill * file structures. 24718Sbill */ 24818Sbill struct file * 24918Sbill falloc() 25018Sbill { 25118Sbill register struct file *fp; 25218Sbill register i; 25318Sbill 25418Sbill i = ufalloc(); 25518Sbill if(i < 0) 25618Sbill return(NULL); 257*387Sbill for(fp = lastf; fp < &file[NFILE]; fp++) 258*387Sbill if(fp->f_count == 0) 259*387Sbill goto slot; 260*387Sbill for(fp = &file[0]; fp < lastf; fp++) 261*387Sbill if(fp->f_count == 0) 262*387Sbill goto slot; 26318Sbill printf("no file\n"); 26418Sbill u.u_error = ENFILE; 26518Sbill return(NULL); 266*387Sbill slot: 267*387Sbill u.u_ofile[i] = fp; 268*387Sbill fp->f_count++; 269*387Sbill fp->f_un.f_offset = 0; 270*387Sbill lastf = fp + 1; 271*387Sbill return(fp); 27218Sbill } 273