1*2274Swnj /* vfs_vnops.c 4.2 01/26/81 */ 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 5518Sbill if(fp == NULL) 5618Sbill return; 5718Sbill if (fp->f_count > 1) { 5818Sbill fp->f_count--; 5918Sbill return; 6018Sbill } 6118Sbill ip = fp->f_inode; 6218Sbill flag = fp->f_flag; 6318Sbill dev = (dev_t)ip->i_un.i_rdev; 6418Sbill mode = ip->i_mode; 6518Sbill 6618Sbill plock(ip); 6718Sbill fp->f_count = 0; 6818Sbill if(flag & FPIPE) { 6918Sbill ip->i_mode &= ~(IREAD|IWRITE); 7018Sbill wakeup((caddr_t)ip+1); 7118Sbill wakeup((caddr_t)ip+2); 7218Sbill } 7318Sbill iput(ip); 7418Sbill 7518Sbill switch(mode&IFMT) { 7618Sbill 7718Sbill case IFCHR: 7818Sbill case IFMPC: 7918Sbill cfunc = cdevsw[major(dev)].d_close; 8018Sbill break; 8118Sbill 8218Sbill case IFBLK: 8318Sbill case IFMPB: 8418Sbill cfunc = bdevsw[major(dev)].d_close; 8518Sbill break; 8618Sbill default: 8718Sbill return; 8818Sbill } 8918Sbill 9018Sbill if (flag & FMP) 9118Sbill goto call; 9218Sbill 9318Sbill for(fp=file; fp < &file[NFILE]; fp++) 94869Sbill if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev && 95869Sbill (ip->i_mode&IFMT) == (mode&IFMT)) 9618Sbill return; 9718Sbill 9818Sbill call: 99*2274Swnj (*cfunc)(dev, flag, fp); 10018Sbill } 10118Sbill 10218Sbill /* 10318Sbill * openi called to allow handler 10418Sbill * of special files to initialize and 10518Sbill * validate before actual IO. 10618Sbill */ 10718Sbill openi(ip, rw) 10818Sbill register struct inode *ip; 10918Sbill { 11018Sbill dev_t dev; 11118Sbill register unsigned int maj; 11218Sbill 11318Sbill dev = (dev_t)ip->i_un.i_rdev; 11418Sbill maj = major(dev); 11518Sbill switch(ip->i_mode&IFMT) { 11618Sbill 11718Sbill case IFCHR: 11818Sbill case IFMPC: 11918Sbill if(maj >= nchrdev) 12018Sbill goto bad; 12118Sbill (*cdevsw[maj].d_open)(dev, rw); 12218Sbill break; 12318Sbill 12418Sbill case IFBLK: 12518Sbill case IFMPB: 12618Sbill if(maj >= nblkdev) 12718Sbill goto bad; 12818Sbill (*bdevsw[maj].d_open)(dev, rw); 12918Sbill } 13018Sbill return; 13118Sbill 13218Sbill bad: 13318Sbill u.u_error = ENXIO; 13418Sbill } 13518Sbill 13618Sbill /* 13718Sbill * Check mode permission on inode pointer. 13818Sbill * Mode is READ, WRITE or EXEC. 13918Sbill * In the case of WRITE, the 14018Sbill * read-only status of the file 14118Sbill * system is checked. 14218Sbill * Also in WRITE, prototype text 14318Sbill * segments cannot be written. 14418Sbill * The mode is shifted to select 14518Sbill * the owner/group/other fields. 14618Sbill * The super user is granted all 14718Sbill * permissions. 14818Sbill */ 14918Sbill access(ip, mode) 15018Sbill register struct inode *ip; 15118Sbill { 15218Sbill register m; 15318Sbill 15418Sbill m = mode; 15518Sbill if(m == IWRITE) { 15618Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 15718Sbill u.u_error = EROFS; 15818Sbill return(1); 15918Sbill } 16018Sbill if (ip->i_flag&ITEXT) /* try to free text */ 16118Sbill xrele(ip); 16218Sbill if(ip->i_flag & ITEXT) { 16318Sbill u.u_error = ETXTBSY; 16418Sbill return(1); 16518Sbill } 16618Sbill } 16718Sbill if(u.u_uid == 0) 16818Sbill return(0); 16918Sbill if(u.u_uid != ip->i_uid) { 17018Sbill m >>= 3; 17118Sbill if(u.u_gid != ip->i_gid) 17218Sbill m >>= 3; 17318Sbill } 17418Sbill if((ip->i_mode&m) != 0) 17518Sbill return(0); 17618Sbill 17718Sbill u.u_error = EACCES; 17818Sbill return(1); 17918Sbill } 18018Sbill 18118Sbill /* 18218Sbill * Look up a pathname and test if 18318Sbill * the resultant inode is owned by the 18418Sbill * current user. 18518Sbill * If not, try for super-user. 18618Sbill * If permission is granted, 18718Sbill * return inode pointer. 18818Sbill */ 18918Sbill struct inode * 19018Sbill owner() 19118Sbill { 19218Sbill register struct inode *ip; 19318Sbill 19418Sbill ip = namei(uchar, 0); 19518Sbill if(ip == NULL) 19618Sbill return(NULL); 19718Sbill if(u.u_uid == ip->i_uid) 19818Sbill return(ip); 19918Sbill if(suser()) 20018Sbill return(ip); 20118Sbill iput(ip); 20218Sbill return(NULL); 20318Sbill } 20418Sbill 20518Sbill /* 20618Sbill * Test if the current user is the 20718Sbill * super user. 20818Sbill */ 20918Sbill suser() 21018Sbill { 21118Sbill 21218Sbill if(u.u_uid == 0) { 21318Sbill u.u_acflag |= ASU; 21418Sbill return(1); 21518Sbill } 21618Sbill u.u_error = EPERM; 21718Sbill return(0); 21818Sbill } 21918Sbill 22018Sbill /* 22118Sbill * Allocate a user file descriptor. 22218Sbill */ 22318Sbill ufalloc() 22418Sbill { 22518Sbill register i; 22618Sbill 22718Sbill for(i=0; i<NOFILE; i++) 22818Sbill if(u.u_ofile[i] == NULL) { 22918Sbill u.u_r.r_val1 = i; 23018Sbill u.u_pofile[i] = 0; 23118Sbill return(i); 23218Sbill } 23318Sbill u.u_error = EMFILE; 23418Sbill return(-1); 23518Sbill } 23618Sbill 237387Sbill struct file *lastf = &file[0]; 23818Sbill /* 23918Sbill * Allocate a user file descriptor 24018Sbill * and a file structure. 24118Sbill * Initialize the descriptor 24218Sbill * to point at the file structure. 24318Sbill * 24418Sbill * no file -- if there are no available 24518Sbill * file structures. 24618Sbill */ 24718Sbill struct file * 24818Sbill falloc() 24918Sbill { 25018Sbill register struct file *fp; 25118Sbill register i; 25218Sbill 25318Sbill i = ufalloc(); 25418Sbill if(i < 0) 25518Sbill return(NULL); 256387Sbill for(fp = lastf; fp < &file[NFILE]; fp++) 257387Sbill if(fp->f_count == 0) 258387Sbill goto slot; 259387Sbill for(fp = &file[0]; fp < lastf; fp++) 260387Sbill if(fp->f_count == 0) 261387Sbill goto slot; 26218Sbill printf("no file\n"); 26318Sbill u.u_error = ENFILE; 26418Sbill return(NULL); 265387Sbill slot: 266387Sbill u.u_ofile[i] = fp; 267387Sbill fp->f_count++; 268387Sbill fp->f_un.f_offset = 0; 269387Sbill lastf = fp + 1; 270387Sbill return(fp); 27118Sbill } 272