1*869Sbill /* vfs_vnops.c 3.4 09/14/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++) 96*869Sbill if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev && 97*869Sbill (ip->i_mode&IFMT) == (mode&IFMT)) 9818Sbill return; 9918Sbill 10018Sbill call: 10118Sbill (*cfunc)(dev, flag, cp); 10218Sbill } 10318Sbill 10418Sbill /* 10518Sbill * openi called to allow handler 10618Sbill * of special files to initialize and 10718Sbill * validate before actual IO. 10818Sbill */ 10918Sbill openi(ip, rw) 11018Sbill register struct inode *ip; 11118Sbill { 11218Sbill dev_t dev; 11318Sbill register unsigned int maj; 11418Sbill 11518Sbill dev = (dev_t)ip->i_un.i_rdev; 11618Sbill maj = major(dev); 11718Sbill switch(ip->i_mode&IFMT) { 11818Sbill 11918Sbill case IFCHR: 12018Sbill case IFMPC: 12118Sbill if(maj >= nchrdev) 12218Sbill goto bad; 12318Sbill (*cdevsw[maj].d_open)(dev, rw); 12418Sbill break; 12518Sbill 12618Sbill case IFBLK: 12718Sbill case IFMPB: 12818Sbill if(maj >= nblkdev) 12918Sbill goto bad; 13018Sbill (*bdevsw[maj].d_open)(dev, rw); 13118Sbill } 13218Sbill return; 13318Sbill 13418Sbill bad: 13518Sbill u.u_error = ENXIO; 13618Sbill } 13718Sbill 13818Sbill /* 13918Sbill * Check mode permission on inode pointer. 14018Sbill * Mode is READ, WRITE or EXEC. 14118Sbill * In the case of WRITE, the 14218Sbill * read-only status of the file 14318Sbill * system is checked. 14418Sbill * Also in WRITE, prototype text 14518Sbill * segments cannot be written. 14618Sbill * The mode is shifted to select 14718Sbill * the owner/group/other fields. 14818Sbill * The super user is granted all 14918Sbill * permissions. 15018Sbill */ 15118Sbill access(ip, mode) 15218Sbill register struct inode *ip; 15318Sbill { 15418Sbill register m; 15518Sbill 15618Sbill m = mode; 15718Sbill if(m == IWRITE) { 15818Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 15918Sbill u.u_error = EROFS; 16018Sbill return(1); 16118Sbill } 16218Sbill if (ip->i_flag&ITEXT) /* try to free text */ 16318Sbill xrele(ip); 16418Sbill if(ip->i_flag & ITEXT) { 16518Sbill u.u_error = ETXTBSY; 16618Sbill return(1); 16718Sbill } 16818Sbill } 16918Sbill if(u.u_uid == 0) 17018Sbill return(0); 17118Sbill if(u.u_uid != ip->i_uid) { 17218Sbill m >>= 3; 17318Sbill if(u.u_gid != ip->i_gid) 17418Sbill m >>= 3; 17518Sbill } 17618Sbill if((ip->i_mode&m) != 0) 17718Sbill return(0); 17818Sbill 17918Sbill u.u_error = EACCES; 18018Sbill return(1); 18118Sbill } 18218Sbill 18318Sbill /* 18418Sbill * Look up a pathname and test if 18518Sbill * the resultant inode is owned by the 18618Sbill * current user. 18718Sbill * If not, try for super-user. 18818Sbill * If permission is granted, 18918Sbill * return inode pointer. 19018Sbill */ 19118Sbill struct inode * 19218Sbill owner() 19318Sbill { 19418Sbill register struct inode *ip; 19518Sbill 19618Sbill ip = namei(uchar, 0); 19718Sbill if(ip == NULL) 19818Sbill return(NULL); 19918Sbill if(u.u_uid == ip->i_uid) 20018Sbill return(ip); 20118Sbill if(suser()) 20218Sbill return(ip); 20318Sbill iput(ip); 20418Sbill return(NULL); 20518Sbill } 20618Sbill 20718Sbill /* 20818Sbill * Test if the current user is the 20918Sbill * super user. 21018Sbill */ 21118Sbill suser() 21218Sbill { 21318Sbill 21418Sbill if(u.u_uid == 0) { 21518Sbill u.u_acflag |= ASU; 21618Sbill return(1); 21718Sbill } 21818Sbill u.u_error = EPERM; 21918Sbill return(0); 22018Sbill } 22118Sbill 22218Sbill /* 22318Sbill * Allocate a user file descriptor. 22418Sbill */ 22518Sbill ufalloc() 22618Sbill { 22718Sbill register i; 22818Sbill 22918Sbill for(i=0; i<NOFILE; i++) 23018Sbill if(u.u_ofile[i] == NULL) { 23118Sbill u.u_r.r_val1 = i; 23218Sbill u.u_pofile[i] = 0; 23318Sbill return(i); 23418Sbill } 23518Sbill u.u_error = EMFILE; 23618Sbill return(-1); 23718Sbill } 23818Sbill 239387Sbill struct file *lastf = &file[0]; 24018Sbill /* 24118Sbill * Allocate a user file descriptor 24218Sbill * and a file structure. 24318Sbill * Initialize the descriptor 24418Sbill * to point at the file structure. 24518Sbill * 24618Sbill * no file -- if there are no available 24718Sbill * file structures. 24818Sbill */ 24918Sbill struct file * 25018Sbill falloc() 25118Sbill { 25218Sbill register struct file *fp; 25318Sbill register i; 25418Sbill 25518Sbill i = ufalloc(); 25618Sbill if(i < 0) 25718Sbill return(NULL); 258387Sbill for(fp = lastf; fp < &file[NFILE]; fp++) 259387Sbill if(fp->f_count == 0) 260387Sbill goto slot; 261387Sbill for(fp = &file[0]; fp < lastf; fp++) 262387Sbill if(fp->f_count == 0) 263387Sbill goto slot; 26418Sbill printf("no file\n"); 26518Sbill u.u_error = ENFILE; 26618Sbill return(NULL); 267387Sbill slot: 268387Sbill u.u_ofile[i] = fp; 269387Sbill fp->f_count++; 270387Sbill fp->f_un.f_offset = 0; 271387Sbill lastf = fp + 1; 272387Sbill return(fp); 27318Sbill } 274