1*5855Swnj /* vfs_vnops.c 4.21 82/02/15 */ 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" 132302Skre #include "../h/mount.h" 144914Swnj #include "../h/socket.h" 154914Swnj #include "../h/socketvar.h" 165581Swnj #include "../h/proc.h" 1718Sbill 1818Sbill /* 194817Swnj * Convert a user supplied file descriptor into a pointer 204817Swnj * to a file structure. Only task is to check range of the descriptor. 214817Swnj * Critical paths should use the GETF macro, defined in inline.h. 2218Sbill */ 2318Sbill struct file * 2418Sbill getf(f) 254817Swnj register int f; 2618Sbill { 2718Sbill register struct file *fp; 2818Sbill 292329Swnj if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 302329Swnj u.u_error = EBADF; 312329Swnj return (NULL); 3218Sbill } 332329Swnj return (fp); 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. 465581Swnj * Nouser indicates that the user isn't available to present 475581Swnj * errors to. 4818Sbill */ 495581Swnj closef(fp, nouser) 504817Swnj register struct file *fp; 5118Sbill { 5218Sbill register struct inode *ip; 532302Skre register struct mount *mp; 5418Sbill int flag, mode; 5518Sbill dev_t dev; 5618Sbill register int (*cfunc)(); 5718Sbill 584817Swnj if (fp == NULL) 5918Sbill return; 6018Sbill if (fp->f_count > 1) { 6118Sbill fp->f_count--; 6218Sbill return; 6318Sbill } 643616Sroot flag = fp->f_flag; 654817Swnj if (flag & FSOCKET) { 665621Swnj u.u_error = 0; /* XXX */ 675581Swnj soclose(fp->f_socket, nouser); 685621Swnj if (nouser == 0 && u.u_error) 695581Swnj return; 704817Swnj fp->f_socket = 0; 713616Sroot fp->f_count = 0; 723616Sroot return; 733616Sroot } 7418Sbill ip = fp->f_inode; 7518Sbill dev = (dev_t)ip->i_un.i_rdev; 762302Skre mode = ip->i_mode & IFMT; 774817Swnj ilock(ip); 783616Sroot iput(ip); 7918Sbill fp->f_count = 0; 8018Sbill 813616Sroot switch (mode) { 8218Sbill 8318Sbill case IFCHR: 8418Sbill cfunc = cdevsw[major(dev)].d_close; 8518Sbill break; 8618Sbill 8718Sbill case IFBLK: 882302Skre /* 892302Skre * We don't want to really close the device if it is mounted 902302Skre */ 912302Skre for (mp = mount; mp < &mount[NMOUNT]; mp++) 922302Skre if (mp->m_bufp != NULL && mp->m_dev == dev) 932302Skre return; 9418Sbill cfunc = bdevsw[major(dev)].d_close; 9518Sbill break; 964817Swnj 9718Sbill default: 9818Sbill return; 9918Sbill } 1004817Swnj for (fp = file; fp < fileNFILE; fp++) { 1014817Swnj if (fp->f_flag & FSOCKET) 1024817Swnj continue; 1034485Swnj if (fp->f_count && (ip = fp->f_inode) && 1044817Swnj ip->i_un.i_rdev == dev && (ip->i_mode&IFMT) == mode) 1054485Swnj return; 1062302Skre } 1074485Swnj if (mode == IFBLK) { 1084485Swnj /* 1094817Swnj * On last close of a block device (that isn't mounted) 1104485Swnj * we must invalidate any in core blocks 1114485Swnj */ 1124485Swnj bflush(dev); 1134485Swnj binval(dev); 1144485Swnj } 1152274Swnj (*cfunc)(dev, flag, fp); 11618Sbill } 11718Sbill 11818Sbill /* 1194817Swnj * Openi called to allow handler 12018Sbill * of special files to initialize and 12118Sbill * validate before actual IO. 12218Sbill */ 12318Sbill openi(ip, rw) 1244817Swnj register struct inode *ip; 12518Sbill { 12618Sbill dev_t dev; 12718Sbill register unsigned int maj; 12818Sbill 12918Sbill dev = (dev_t)ip->i_un.i_rdev; 13018Sbill maj = major(dev); 1314817Swnj switch (ip->i_mode&IFMT) { 13218Sbill 13318Sbill case IFCHR: 1344817Swnj if (maj >= nchrdev) 13518Sbill goto bad; 13618Sbill (*cdevsw[maj].d_open)(dev, rw); 13718Sbill break; 13818Sbill 13918Sbill case IFBLK: 1404817Swnj if (maj >= nblkdev) 14118Sbill goto bad; 14218Sbill (*bdevsw[maj].d_open)(dev, rw); 14318Sbill } 14418Sbill return; 14518Sbill 14618Sbill bad: 14718Sbill u.u_error = ENXIO; 14818Sbill } 14918Sbill 15018Sbill /* 15118Sbill * Check mode permission on inode pointer. 15218Sbill * Mode is READ, WRITE or EXEC. 15318Sbill * In the case of WRITE, the 15418Sbill * read-only status of the file 15518Sbill * system is checked. 15618Sbill * Also in WRITE, prototype text 15718Sbill * segments cannot be written. 15818Sbill * The mode is shifted to select 15918Sbill * the owner/group/other fields. 16018Sbill * The super user is granted all 16118Sbill * permissions. 16218Sbill */ 16318Sbill access(ip, mode) 1644817Swnj register struct inode *ip; 1654817Swnj int mode; 16618Sbill { 16718Sbill register m; 16818Sbill 16918Sbill m = mode; 1704817Swnj if (m == IWRITE) { 1714817Swnj if (getfs(ip->i_dev)->s_ronly != 0) { 17218Sbill u.u_error = EROFS; 1734817Swnj return (1); 17418Sbill } 17518Sbill if (ip->i_flag&ITEXT) /* try to free text */ 17618Sbill xrele(ip); 1774817Swnj if (ip->i_flag & ITEXT) { 17818Sbill u.u_error = ETXTBSY; 1794817Swnj return (1); 18018Sbill } 18118Sbill } 1824817Swnj if (u.u_uid == 0) 1834817Swnj return (0); 1844817Swnj if (u.u_uid != ip->i_uid) { 18518Sbill m >>= 3; 186*5855Swnj if (ip->i_gid >= NGRPS || 187*5855Swnj (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 188*5855Swnj (1 << ip->i_gid%(sizeof(int)*8)) == 0)) 18918Sbill m >>= 3; 19018Sbill } 1914817Swnj if ((ip->i_mode&m) != 0) 1924817Swnj return (0); 19318Sbill u.u_error = EACCES; 1944817Swnj return (1); 19518Sbill } 19618Sbill 19718Sbill /* 19818Sbill * Look up a pathname and test if 19918Sbill * the resultant inode is owned by the 20018Sbill * current user. 20118Sbill * If not, try for super-user. 20218Sbill * If permission is granted, 20318Sbill * return inode pointer. 20418Sbill */ 20518Sbill struct inode * 20618Sbill owner() 20718Sbill { 20818Sbill register struct inode *ip; 20918Sbill 21018Sbill ip = namei(uchar, 0); 2114817Swnj if (ip == NULL) 2124817Swnj return (NULL); 2134817Swnj if (u.u_uid == ip->i_uid) 2144817Swnj return (ip); 2154817Swnj if (suser()) 2164817Swnj return (ip); 21718Sbill iput(ip); 2184817Swnj return (NULL); 21918Sbill } 22018Sbill 22118Sbill /* 22218Sbill * Test if the current user is the 22318Sbill * super user. 22418Sbill */ 22518Sbill suser() 22618Sbill { 22718Sbill 2284817Swnj if (u.u_uid == 0) { 22918Sbill u.u_acflag |= ASU; 2304817Swnj return (1); 23118Sbill } 23218Sbill u.u_error = EPERM; 2334817Swnj return (0); 23418Sbill } 23518Sbill 23618Sbill /* 23718Sbill * Allocate a user file descriptor. 23818Sbill */ 23918Sbill ufalloc() 24018Sbill { 24118Sbill register i; 24218Sbill 2434817Swnj for (i=0; i<NOFILE; i++) 2444817Swnj if (u.u_ofile[i] == NULL) { 24518Sbill u.u_r.r_val1 = i; 24618Sbill u.u_pofile[i] = 0; 2474817Swnj return (i); 24818Sbill } 24918Sbill u.u_error = EMFILE; 2504817Swnj return (-1); 25118Sbill } 25218Sbill 2532768Swnj struct file *lastf; 25418Sbill /* 25518Sbill * Allocate a user file descriptor 25618Sbill * and a file structure. 25718Sbill * Initialize the descriptor 25818Sbill * to point at the file structure. 25918Sbill */ 26018Sbill struct file * 26118Sbill falloc() 26218Sbill { 26318Sbill register struct file *fp; 26418Sbill register i; 26518Sbill 26618Sbill i = ufalloc(); 2672768Swnj if (i < 0) 2684817Swnj return (NULL); 2692768Swnj if (lastf == 0) 2702768Swnj lastf = file; 2712768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2722768Swnj if (fp->f_count == 0) 273387Sbill goto slot; 2742768Swnj for (fp = file; fp < lastf; fp++) 2752768Swnj if (fp->f_count == 0) 276387Sbill goto slot; 2772932Swnj tablefull("file"); 27818Sbill u.u_error = ENFILE; 2792768Swnj return (NULL); 280387Sbill slot: 281387Sbill u.u_ofile[i] = fp; 282387Sbill fp->f_count++; 2834817Swnj fp->f_offset = 0; 2843782Sroot fp->f_inode = 0; 285387Sbill lastf = fp + 1; 2862768Swnj return (fp); 28718Sbill } 288