1*5621Swnj /* vfs_vnops.c 4.20 82/01/25 */ 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) { 66*5621Swnj u.u_error = 0; /* XXX */ 675581Swnj soclose(fp->f_socket, nouser); 68*5621Swnj 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; 1864817Swnj if (u.u_gid != ip->i_gid) 18718Sbill m >>= 3; 18818Sbill } 1894817Swnj if ((ip->i_mode&m) != 0) 1904817Swnj return (0); 19118Sbill u.u_error = EACCES; 1924817Swnj return (1); 19318Sbill } 19418Sbill 19518Sbill /* 19618Sbill * Look up a pathname and test if 19718Sbill * the resultant inode is owned by the 19818Sbill * current user. 19918Sbill * If not, try for super-user. 20018Sbill * If permission is granted, 20118Sbill * return inode pointer. 20218Sbill */ 20318Sbill struct inode * 20418Sbill owner() 20518Sbill { 20618Sbill register struct inode *ip; 20718Sbill 20818Sbill ip = namei(uchar, 0); 2094817Swnj if (ip == NULL) 2104817Swnj return (NULL); 2114817Swnj if (u.u_uid == ip->i_uid) 2124817Swnj return (ip); 2134817Swnj if (suser()) 2144817Swnj return (ip); 21518Sbill iput(ip); 2164817Swnj return (NULL); 21718Sbill } 21818Sbill 21918Sbill /* 22018Sbill * Test if the current user is the 22118Sbill * super user. 22218Sbill */ 22318Sbill suser() 22418Sbill { 22518Sbill 2264817Swnj if (u.u_uid == 0) { 22718Sbill u.u_acflag |= ASU; 2284817Swnj return (1); 22918Sbill } 23018Sbill u.u_error = EPERM; 2314817Swnj return (0); 23218Sbill } 23318Sbill 23418Sbill /* 23518Sbill * Allocate a user file descriptor. 23618Sbill */ 23718Sbill ufalloc() 23818Sbill { 23918Sbill register i; 24018Sbill 2414817Swnj for (i=0; i<NOFILE; i++) 2424817Swnj if (u.u_ofile[i] == NULL) { 24318Sbill u.u_r.r_val1 = i; 24418Sbill u.u_pofile[i] = 0; 2454817Swnj return (i); 24618Sbill } 24718Sbill u.u_error = EMFILE; 2484817Swnj return (-1); 24918Sbill } 25018Sbill 2512768Swnj struct file *lastf; 25218Sbill /* 25318Sbill * Allocate a user file descriptor 25418Sbill * and a file structure. 25518Sbill * Initialize the descriptor 25618Sbill * to point at the file structure. 25718Sbill */ 25818Sbill struct file * 25918Sbill falloc() 26018Sbill { 26118Sbill register struct file *fp; 26218Sbill register i; 26318Sbill 26418Sbill i = ufalloc(); 2652768Swnj if (i < 0) 2664817Swnj return (NULL); 2672768Swnj if (lastf == 0) 2682768Swnj lastf = file; 2692768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2702768Swnj if (fp->f_count == 0) 271387Sbill goto slot; 2722768Swnj for (fp = file; fp < lastf; fp++) 2732768Swnj if (fp->f_count == 0) 274387Sbill goto slot; 2752932Swnj tablefull("file"); 27618Sbill u.u_error = ENFILE; 2772768Swnj return (NULL); 278387Sbill slot: 279387Sbill u.u_ofile[i] = fp; 280387Sbill fp->f_count++; 2814817Swnj fp->f_offset = 0; 2823782Sroot fp->f_inode = 0; 283387Sbill lastf = fp + 1; 2842768Swnj return (fp); 28518Sbill } 286