1*2302Skre /* vfs_vnops.c 4.3 01/28/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" 13*2302Skre #include "../h/mount.h" 1418Sbill 1518Sbill /* 1618Sbill * Convert a user supplied 1718Sbill * file descriptor into a pointer 1818Sbill * to a file structure. 1918Sbill * Only task is to check range 2018Sbill * of the descriptor. 2118Sbill */ 2218Sbill struct file * 2318Sbill getf(f) 2418Sbill register int f; 2518Sbill { 2618Sbill register struct file *fp; 2718Sbill 2818Sbill if(0 <= f && f < NOFILE) { 2918Sbill fp = u.u_ofile[f]; 3018Sbill if(fp != NULL) 3118Sbill return(fp); 3218Sbill } 3318Sbill u.u_error = EBADF; 3418Sbill return(NULL); 3518Sbill } 3618Sbill 3718Sbill /* 3818Sbill * Internal form of close. 3918Sbill * Decrement reference count on 4018Sbill * file structure. 4118Sbill * Also make sure the pipe protocol 4218Sbill * does not constipate. 4318Sbill * 4418Sbill * Decrement reference count on the inode following 4518Sbill * removal to the referencing file structure. 4618Sbill * Call device handler on last close. 4718Sbill */ 4818Sbill closef(fp) 4918Sbill register struct file *fp; 5018Sbill { 5118Sbill register struct inode *ip; 52*2302Skre register struct mount *mp; 5318Sbill int flag, mode; 5418Sbill dev_t dev; 5518Sbill register int (*cfunc)(); 5618Sbill 5718Sbill if(fp == NULL) 5818Sbill return; 5918Sbill if (fp->f_count > 1) { 6018Sbill fp->f_count--; 6118Sbill return; 6218Sbill } 6318Sbill ip = fp->f_inode; 6418Sbill flag = fp->f_flag; 6518Sbill dev = (dev_t)ip->i_un.i_rdev; 66*2302Skre mode = ip->i_mode & IFMT; 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 77*2302Skre switch(mode) { 7818Sbill 7918Sbill case IFCHR: 8018Sbill case IFMPC: 8118Sbill cfunc = cdevsw[major(dev)].d_close; 8218Sbill break; 8318Sbill 8418Sbill case IFBLK: 85*2302Skre /* 86*2302Skre * We don't want to really close the device if it is mounted 87*2302Skre */ 88*2302Skre for (mp = mount; mp < &mount[NMOUNT]; mp++) 89*2302Skre if (mp->m_bufp != NULL && mp->m_dev == dev) 90*2302Skre return; 9118Sbill case IFMPB: 9218Sbill cfunc = bdevsw[major(dev)].d_close; 9318Sbill break; 9418Sbill default: 9518Sbill return; 9618Sbill } 9718Sbill 98*2302Skre if ((flag & FMP) == 0) { 99*2302Skre for(fp=file; fp < &file[NFILE]; fp++) 100*2302Skre if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev && 101*2302Skre (ip->i_mode&IFMT) == mode) 102*2302Skre return; 10318Sbill 104*2302Skre if (mode == IFBLK) { 105*2302Skre /* 106*2302Skre * on last close of a block device (that isn't mounted) 107*2302Skre * we must invalidate any in core blocks 108*2302Skre */ 109*2302Skre bflush(dev); 110*2302Skre binval(dev); 111*2302Skre } 112*2302Skre } 11318Sbill 1142274Swnj (*cfunc)(dev, flag, fp); 11518Sbill } 11618Sbill 11718Sbill /* 11818Sbill * openi called to allow handler 11918Sbill * of special files to initialize and 12018Sbill * validate before actual IO. 12118Sbill */ 12218Sbill openi(ip, rw) 12318Sbill register struct inode *ip; 12418Sbill { 12518Sbill dev_t dev; 12618Sbill register unsigned int maj; 12718Sbill 12818Sbill dev = (dev_t)ip->i_un.i_rdev; 12918Sbill maj = major(dev); 13018Sbill switch(ip->i_mode&IFMT) { 13118Sbill 13218Sbill case IFCHR: 13318Sbill case IFMPC: 13418Sbill if(maj >= nchrdev) 13518Sbill goto bad; 13618Sbill (*cdevsw[maj].d_open)(dev, rw); 13718Sbill break; 13818Sbill 13918Sbill case IFBLK: 14018Sbill case IFMPB: 14118Sbill if(maj >= nblkdev) 14218Sbill goto bad; 14318Sbill (*bdevsw[maj].d_open)(dev, rw); 14418Sbill } 14518Sbill return; 14618Sbill 14718Sbill bad: 14818Sbill u.u_error = ENXIO; 14918Sbill } 15018Sbill 15118Sbill /* 15218Sbill * Check mode permission on inode pointer. 15318Sbill * Mode is READ, WRITE or EXEC. 15418Sbill * In the case of WRITE, the 15518Sbill * read-only status of the file 15618Sbill * system is checked. 15718Sbill * Also in WRITE, prototype text 15818Sbill * segments cannot be written. 15918Sbill * The mode is shifted to select 16018Sbill * the owner/group/other fields. 16118Sbill * The super user is granted all 16218Sbill * permissions. 16318Sbill */ 16418Sbill access(ip, mode) 16518Sbill register struct inode *ip; 16618Sbill { 16718Sbill register m; 16818Sbill 16918Sbill m = mode; 17018Sbill if(m == IWRITE) { 17118Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 17218Sbill u.u_error = EROFS; 17318Sbill return(1); 17418Sbill } 17518Sbill if (ip->i_flag&ITEXT) /* try to free text */ 17618Sbill xrele(ip); 17718Sbill if(ip->i_flag & ITEXT) { 17818Sbill u.u_error = ETXTBSY; 17918Sbill return(1); 18018Sbill } 18118Sbill } 18218Sbill if(u.u_uid == 0) 18318Sbill return(0); 18418Sbill if(u.u_uid != ip->i_uid) { 18518Sbill m >>= 3; 18618Sbill if(u.u_gid != ip->i_gid) 18718Sbill m >>= 3; 18818Sbill } 18918Sbill if((ip->i_mode&m) != 0) 19018Sbill return(0); 19118Sbill 19218Sbill u.u_error = EACCES; 19318Sbill return(1); 19418Sbill } 19518Sbill 19618Sbill /* 19718Sbill * Look up a pathname and test if 19818Sbill * the resultant inode is owned by the 19918Sbill * current user. 20018Sbill * If not, try for super-user. 20118Sbill * If permission is granted, 20218Sbill * return inode pointer. 20318Sbill */ 20418Sbill struct inode * 20518Sbill owner() 20618Sbill { 20718Sbill register struct inode *ip; 20818Sbill 20918Sbill ip = namei(uchar, 0); 21018Sbill if(ip == NULL) 21118Sbill return(NULL); 21218Sbill if(u.u_uid == ip->i_uid) 21318Sbill return(ip); 21418Sbill if(suser()) 21518Sbill return(ip); 21618Sbill iput(ip); 21718Sbill return(NULL); 21818Sbill } 21918Sbill 22018Sbill /* 22118Sbill * Test if the current user is the 22218Sbill * super user. 22318Sbill */ 22418Sbill suser() 22518Sbill { 22618Sbill 22718Sbill if(u.u_uid == 0) { 22818Sbill u.u_acflag |= ASU; 22918Sbill return(1); 23018Sbill } 23118Sbill u.u_error = EPERM; 23218Sbill return(0); 23318Sbill } 23418Sbill 23518Sbill /* 23618Sbill * Allocate a user file descriptor. 23718Sbill */ 23818Sbill ufalloc() 23918Sbill { 24018Sbill register i; 24118Sbill 24218Sbill for(i=0; i<NOFILE; i++) 24318Sbill if(u.u_ofile[i] == NULL) { 24418Sbill u.u_r.r_val1 = i; 24518Sbill u.u_pofile[i] = 0; 24618Sbill return(i); 24718Sbill } 24818Sbill u.u_error = EMFILE; 24918Sbill return(-1); 25018Sbill } 25118Sbill 252387Sbill struct file *lastf = &file[0]; 25318Sbill /* 25418Sbill * Allocate a user file descriptor 25518Sbill * and a file structure. 25618Sbill * Initialize the descriptor 25718Sbill * to point at the file structure. 25818Sbill * 25918Sbill * no file -- if there are no available 26018Sbill * file structures. 26118Sbill */ 26218Sbill struct file * 26318Sbill falloc() 26418Sbill { 26518Sbill register struct file *fp; 26618Sbill register i; 26718Sbill 26818Sbill i = ufalloc(); 26918Sbill if(i < 0) 27018Sbill return(NULL); 271387Sbill for(fp = lastf; fp < &file[NFILE]; fp++) 272387Sbill if(fp->f_count == 0) 273387Sbill goto slot; 274387Sbill for(fp = &file[0]; fp < lastf; fp++) 275387Sbill if(fp->f_count == 0) 276387Sbill goto slot; 27718Sbill printf("no file\n"); 27818Sbill u.u_error = ENFILE; 27918Sbill return(NULL); 280387Sbill slot: 281387Sbill u.u_ofile[i] = fp; 282387Sbill fp->f_count++; 283387Sbill fp->f_un.f_offset = 0; 284387Sbill lastf = fp + 1; 285387Sbill return(fp); 28618Sbill } 287