1*5990Swnj /* vfs_vnops.c 4.22 82/02/27 */ 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; 1865855Swnj if (ip->i_gid >= NGRPS || 1875855Swnj (u.u_grps[ip->i_gid/(sizeof(int)*8)] & 1885855Swnj (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 * 206*5990Swnj owner(follow) 207*5990Swnj int follow; 20818Sbill { 20918Sbill register struct inode *ip; 21018Sbill 211*5990Swnj ip = namei(uchar, 0, follow); 2124817Swnj if (ip == NULL) 2134817Swnj return (NULL); 2144817Swnj if (u.u_uid == ip->i_uid) 2154817Swnj return (ip); 2164817Swnj if (suser()) 2174817Swnj return (ip); 21818Sbill iput(ip); 2194817Swnj return (NULL); 22018Sbill } 22118Sbill 22218Sbill /* 22318Sbill * Test if the current user is the 22418Sbill * super user. 22518Sbill */ 22618Sbill suser() 22718Sbill { 22818Sbill 2294817Swnj if (u.u_uid == 0) { 23018Sbill u.u_acflag |= ASU; 2314817Swnj return (1); 23218Sbill } 23318Sbill u.u_error = EPERM; 2344817Swnj return (0); 23518Sbill } 23618Sbill 23718Sbill /* 23818Sbill * Allocate a user file descriptor. 23918Sbill */ 24018Sbill ufalloc() 24118Sbill { 24218Sbill register i; 24318Sbill 2444817Swnj for (i=0; i<NOFILE; i++) 2454817Swnj if (u.u_ofile[i] == NULL) { 24618Sbill u.u_r.r_val1 = i; 24718Sbill u.u_pofile[i] = 0; 2484817Swnj return (i); 24918Sbill } 25018Sbill u.u_error = EMFILE; 2514817Swnj return (-1); 25218Sbill } 25318Sbill 2542768Swnj struct file *lastf; 25518Sbill /* 25618Sbill * Allocate a user file descriptor 25718Sbill * and a file structure. 25818Sbill * Initialize the descriptor 25918Sbill * to point at the file structure. 26018Sbill */ 26118Sbill struct file * 26218Sbill falloc() 26318Sbill { 26418Sbill register struct file *fp; 26518Sbill register i; 26618Sbill 26718Sbill i = ufalloc(); 2682768Swnj if (i < 0) 2694817Swnj return (NULL); 2702768Swnj if (lastf == 0) 2712768Swnj lastf = file; 2722768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2732768Swnj if (fp->f_count == 0) 274387Sbill goto slot; 2752768Swnj for (fp = file; fp < lastf; fp++) 2762768Swnj if (fp->f_count == 0) 277387Sbill goto slot; 2782932Swnj tablefull("file"); 27918Sbill u.u_error = ENFILE; 2802768Swnj return (NULL); 281387Sbill slot: 282387Sbill u.u_ofile[i] = fp; 283387Sbill fp->f_count++; 2844817Swnj fp->f_offset = 0; 2853782Sroot fp->f_inode = 0; 286387Sbill lastf = fp + 1; 2872768Swnj return (fp); 28818Sbill } 289