1*6569Smckusic /* vfs_vnops.c 4.23 82/04/19 */ 218Sbill 3*6569Smckusic /* merged into kernel: @(#)fio.c 2.2 4/8/82 */ 4*6569Smckusic 518Sbill #include "../h/param.h" 618Sbill #include "../h/systm.h" 718Sbill #include "../h/dir.h" 818Sbill #include "../h/user.h" 9*6569Smckusic #include "../h/fs.h" 1018Sbill #include "../h/file.h" 1118Sbill #include "../h/conf.h" 1218Sbill #include "../h/inode.h" 1318Sbill #include "../h/reg.h" 1418Sbill #include "../h/acct.h" 152302Skre #include "../h/mount.h" 164914Swnj #include "../h/socket.h" 174914Swnj #include "../h/socketvar.h" 185581Swnj #include "../h/proc.h" 1918Sbill 2018Sbill /* 214817Swnj * Convert a user supplied file descriptor into a pointer 224817Swnj * to a file structure. Only task is to check range of the descriptor. 234817Swnj * Critical paths should use the GETF macro, defined in inline.h. 2418Sbill */ 2518Sbill struct file * 2618Sbill getf(f) 274817Swnj register int f; 2818Sbill { 2918Sbill register struct file *fp; 3018Sbill 312329Swnj if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 322329Swnj u.u_error = EBADF; 332329Swnj return (NULL); 3418Sbill } 352329Swnj return (fp); 3618Sbill } 3718Sbill 3818Sbill /* 3918Sbill * Internal form of close. 4018Sbill * Decrement reference count on 4118Sbill * file structure. 4218Sbill * Also make sure the pipe protocol 4318Sbill * does not constipate. 4418Sbill * 4518Sbill * Decrement reference count on the inode following 4618Sbill * removal to the referencing file structure. 4718Sbill * Call device handler on last close. 485581Swnj * Nouser indicates that the user isn't available to present 495581Swnj * errors to. 5018Sbill */ 515581Swnj closef(fp, nouser) 524817Swnj register struct file *fp; 5318Sbill { 5418Sbill register struct inode *ip; 552302Skre register struct mount *mp; 5618Sbill int flag, mode; 5718Sbill dev_t dev; 5818Sbill register int (*cfunc)(); 5918Sbill 604817Swnj if (fp == NULL) 6118Sbill return; 6218Sbill if (fp->f_count > 1) { 6318Sbill fp->f_count--; 6418Sbill return; 6518Sbill } 663616Sroot flag = fp->f_flag; 674817Swnj if (flag & FSOCKET) { 685621Swnj u.u_error = 0; /* XXX */ 695581Swnj soclose(fp->f_socket, nouser); 705621Swnj if (nouser == 0 && u.u_error) 715581Swnj return; 724817Swnj fp->f_socket = 0; 733616Sroot fp->f_count = 0; 743616Sroot return; 753616Sroot } 7618Sbill ip = fp->f_inode; 77*6569Smckusic dev = (dev_t)ip->i_rdev; 782302Skre mode = ip->i_mode & IFMT; 794817Swnj ilock(ip); 803616Sroot iput(ip); 8118Sbill fp->f_count = 0; 8218Sbill 833616Sroot switch (mode) { 8418Sbill 8518Sbill case IFCHR: 8618Sbill cfunc = cdevsw[major(dev)].d_close; 8718Sbill break; 8818Sbill 8918Sbill case IFBLK: 902302Skre /* 912302Skre * We don't want to really close the device if it is mounted 922302Skre */ 932302Skre for (mp = mount; mp < &mount[NMOUNT]; mp++) 942302Skre if (mp->m_bufp != NULL && mp->m_dev == dev) 952302Skre return; 9618Sbill cfunc = bdevsw[major(dev)].d_close; 9718Sbill break; 984817Swnj 9918Sbill default: 10018Sbill return; 10118Sbill } 1024817Swnj for (fp = file; fp < fileNFILE; fp++) { 1034817Swnj if (fp->f_flag & FSOCKET) 1044817Swnj continue; 1054485Swnj if (fp->f_count && (ip = fp->f_inode) && 106*6569Smckusic ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 1074485Swnj return; 1082302Skre } 1094485Swnj if (mode == IFBLK) { 1104485Swnj /* 1114817Swnj * On last close of a block device (that isn't mounted) 1124485Swnj * we must invalidate any in core blocks 1134485Swnj */ 1144485Swnj bflush(dev); 1154485Swnj binval(dev); 1164485Swnj } 1172274Swnj (*cfunc)(dev, flag, fp); 11818Sbill } 11918Sbill 12018Sbill /* 1214817Swnj * Openi called to allow handler 12218Sbill * of special files to initialize and 12318Sbill * validate before actual IO. 12418Sbill */ 12518Sbill openi(ip, rw) 1264817Swnj register struct inode *ip; 12718Sbill { 12818Sbill dev_t dev; 12918Sbill register unsigned int maj; 13018Sbill 131*6569Smckusic dev = (dev_t)ip->i_rdev; 13218Sbill maj = major(dev); 1334817Swnj switch (ip->i_mode&IFMT) { 13418Sbill 13518Sbill case IFCHR: 1364817Swnj if (maj >= nchrdev) 13718Sbill goto bad; 13818Sbill (*cdevsw[maj].d_open)(dev, rw); 13918Sbill break; 14018Sbill 14118Sbill case IFBLK: 1424817Swnj if (maj >= nblkdev) 14318Sbill goto bad; 14418Sbill (*bdevsw[maj].d_open)(dev, rw); 14518Sbill } 14618Sbill return; 14718Sbill 14818Sbill bad: 14918Sbill u.u_error = ENXIO; 15018Sbill } 15118Sbill 15218Sbill /* 15318Sbill * Check mode permission on inode pointer. 15418Sbill * Mode is READ, WRITE or EXEC. 15518Sbill * In the case of WRITE, the 15618Sbill * read-only status of the file 15718Sbill * system is checked. 15818Sbill * Also in WRITE, prototype text 15918Sbill * segments cannot be written. 16018Sbill * The mode is shifted to select 16118Sbill * the owner/group/other fields. 16218Sbill * The super user is granted all 16318Sbill * permissions. 16418Sbill */ 16518Sbill access(ip, mode) 1664817Swnj register struct inode *ip; 1674817Swnj int mode; 16818Sbill { 16918Sbill register m; 17018Sbill 17118Sbill m = mode; 1724817Swnj if (m == IWRITE) { 173*6569Smckusic if (ip->i_fs->fs_ronly != 0) { 17418Sbill u.u_error = EROFS; 1754817Swnj return (1); 17618Sbill } 17718Sbill if (ip->i_flag&ITEXT) /* try to free text */ 17818Sbill xrele(ip); 1794817Swnj if (ip->i_flag & ITEXT) { 18018Sbill u.u_error = ETXTBSY; 1814817Swnj return (1); 18218Sbill } 18318Sbill } 1844817Swnj if (u.u_uid == 0) 1854817Swnj return (0); 1864817Swnj if (u.u_uid != ip->i_uid) { 18718Sbill m >>= 3; 1885855Swnj if (ip->i_gid >= NGRPS || 1895855Swnj (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 1905855Swnj (1 << ip->i_gid%(sizeof(int)*8)) == 0)) 19118Sbill m >>= 3; 19218Sbill } 1934817Swnj if ((ip->i_mode&m) != 0) 1944817Swnj return (0); 19518Sbill u.u_error = EACCES; 1964817Swnj return (1); 19718Sbill } 19818Sbill 19918Sbill /* 20018Sbill * Look up a pathname and test if 20118Sbill * the resultant inode is owned by the 20218Sbill * current user. 20318Sbill * If not, try for super-user. 20418Sbill * If permission is granted, 20518Sbill * return inode pointer. 20618Sbill */ 20718Sbill struct inode * 2085990Swnj owner(follow) 2095990Swnj int follow; 21018Sbill { 21118Sbill register struct inode *ip; 21218Sbill 2135990Swnj ip = namei(uchar, 0, follow); 2144817Swnj if (ip == NULL) 2154817Swnj return (NULL); 2164817Swnj if (u.u_uid == ip->i_uid) 2174817Swnj return (ip); 2184817Swnj if (suser()) 2194817Swnj return (ip); 22018Sbill iput(ip); 2214817Swnj return (NULL); 22218Sbill } 22318Sbill 22418Sbill /* 22518Sbill * Test if the current user is the 22618Sbill * super user. 22718Sbill */ 22818Sbill suser() 22918Sbill { 23018Sbill 2314817Swnj if (u.u_uid == 0) { 23218Sbill u.u_acflag |= ASU; 2334817Swnj return (1); 23418Sbill } 23518Sbill u.u_error = EPERM; 2364817Swnj return (0); 23718Sbill } 23818Sbill 23918Sbill /* 24018Sbill * Allocate a user file descriptor. 24118Sbill */ 24218Sbill ufalloc() 24318Sbill { 24418Sbill register i; 24518Sbill 2464817Swnj for (i=0; i<NOFILE; i++) 2474817Swnj if (u.u_ofile[i] == NULL) { 24818Sbill u.u_r.r_val1 = i; 24918Sbill u.u_pofile[i] = 0; 2504817Swnj return (i); 25118Sbill } 25218Sbill u.u_error = EMFILE; 2534817Swnj return (-1); 25418Sbill } 25518Sbill 2562768Swnj struct file *lastf; 25718Sbill /* 25818Sbill * Allocate a user file descriptor 25918Sbill * and a file structure. 26018Sbill * Initialize the descriptor 26118Sbill * to point at the file structure. 26218Sbill */ 26318Sbill struct file * 26418Sbill falloc() 26518Sbill { 26618Sbill register struct file *fp; 26718Sbill register i; 26818Sbill 26918Sbill i = ufalloc(); 2702768Swnj if (i < 0) 2714817Swnj return (NULL); 2722768Swnj if (lastf == 0) 2732768Swnj lastf = file; 2742768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2752768Swnj if (fp->f_count == 0) 276387Sbill goto slot; 2772768Swnj for (fp = file; fp < lastf; fp++) 2782768Swnj if (fp->f_count == 0) 279387Sbill goto slot; 2802932Swnj tablefull("file"); 28118Sbill u.u_error = ENFILE; 2822768Swnj return (NULL); 283387Sbill slot: 284387Sbill u.u_ofile[i] = fp; 285387Sbill fp->f_count++; 2864817Swnj fp->f_offset = 0; 2873782Sroot fp->f_inode = 0; 288387Sbill lastf = fp + 1; 2892768Swnj return (fp); 29018Sbill } 291