1*4914Swnj /* vfs_vnops.c 4.16 81/11/16 */ 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" 14*4914Swnj #include "../h/socket.h" 15*4914Swnj #include "../h/socketvar.h" 1618Sbill 1718Sbill /* 184817Swnj * Convert a user supplied file descriptor into a pointer 194817Swnj * to a file structure. Only task is to check range of the descriptor. 204817Swnj * Critical paths should use the GETF macro, defined in inline.h. 2118Sbill */ 2218Sbill struct file * 2318Sbill getf(f) 244817Swnj register int f; 2518Sbill { 2618Sbill register struct file *fp; 2718Sbill 282329Swnj if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 292329Swnj u.u_error = EBADF; 302329Swnj return (NULL); 3118Sbill } 322329Swnj return (fp); 3318Sbill } 3418Sbill 3518Sbill /* 3618Sbill * Internal form of close. 3718Sbill * Decrement reference count on 3818Sbill * file structure. 3918Sbill * Also make sure the pipe protocol 4018Sbill * does not constipate. 4118Sbill * 4218Sbill * Decrement reference count on the inode following 4318Sbill * removal to the referencing file structure. 4418Sbill * Call device handler on last close. 4518Sbill */ 4618Sbill closef(fp) 474817Swnj register struct file *fp; 4818Sbill { 4918Sbill register struct inode *ip; 502302Skre register struct mount *mp; 5118Sbill int flag, mode; 5218Sbill dev_t dev; 5318Sbill register int (*cfunc)(); 5418Sbill 554817Swnj if (fp == NULL) 5618Sbill return; 5718Sbill if (fp->f_count > 1) { 5818Sbill fp->f_count--; 5918Sbill return; 6018Sbill } 613616Sroot flag = fp->f_flag; 624817Swnj if (flag & FSOCKET) { 634888Swnj soclose(fp->f_socket); 644817Swnj fp->f_socket = 0; 653616Sroot fp->f_count = 0; 663616Sroot return; 673616Sroot } 6818Sbill ip = fp->f_inode; 6918Sbill dev = (dev_t)ip->i_un.i_rdev; 702302Skre mode = ip->i_mode & IFMT; 714817Swnj ilock(ip); 723616Sroot iput(ip); 7318Sbill fp->f_count = 0; 7418Sbill 753616Sroot switch (mode) { 7618Sbill 7718Sbill case IFCHR: 7818Sbill cfunc = cdevsw[major(dev)].d_close; 7918Sbill break; 8018Sbill 8118Sbill case IFBLK: 822302Skre /* 832302Skre * We don't want to really close the device if it is mounted 842302Skre */ 852302Skre for (mp = mount; mp < &mount[NMOUNT]; mp++) 862302Skre if (mp->m_bufp != NULL && mp->m_dev == dev) 872302Skre return; 8818Sbill cfunc = bdevsw[major(dev)].d_close; 8918Sbill break; 904817Swnj 9118Sbill default: 9218Sbill return; 9318Sbill } 944817Swnj for (fp = file; fp < fileNFILE; fp++) { 954817Swnj if (fp->f_flag & FSOCKET) 964817Swnj continue; 974485Swnj if (fp->f_count && (ip = fp->f_inode) && 984817Swnj ip->i_un.i_rdev == dev && (ip->i_mode&IFMT) == mode) 994485Swnj return; 1002302Skre } 1014485Swnj if (mode == IFBLK) { 1024485Swnj /* 1034817Swnj * On last close of a block device (that isn't mounted) 1044485Swnj * we must invalidate any in core blocks 1054485Swnj */ 1064485Swnj bflush(dev); 1074485Swnj binval(dev); 1084485Swnj } 1092274Swnj (*cfunc)(dev, flag, fp); 11018Sbill } 11118Sbill 11218Sbill /* 1134817Swnj * Openi called to allow handler 11418Sbill * of special files to initialize and 11518Sbill * validate before actual IO. 11618Sbill */ 11718Sbill openi(ip, rw) 1184817Swnj register struct inode *ip; 11918Sbill { 12018Sbill dev_t dev; 12118Sbill register unsigned int maj; 12218Sbill 12318Sbill dev = (dev_t)ip->i_un.i_rdev; 12418Sbill maj = major(dev); 1254817Swnj switch (ip->i_mode&IFMT) { 12618Sbill 12718Sbill case IFCHR: 1284817Swnj if (maj >= nchrdev) 12918Sbill goto bad; 13018Sbill (*cdevsw[maj].d_open)(dev, rw); 13118Sbill break; 13218Sbill 13318Sbill case IFBLK: 1344817Swnj if (maj >= nblkdev) 13518Sbill goto bad; 13618Sbill (*bdevsw[maj].d_open)(dev, rw); 13718Sbill } 13818Sbill return; 13918Sbill 14018Sbill bad: 14118Sbill u.u_error = ENXIO; 14218Sbill } 14318Sbill 14418Sbill /* 14518Sbill * Check mode permission on inode pointer. 14618Sbill * Mode is READ, WRITE or EXEC. 14718Sbill * In the case of WRITE, the 14818Sbill * read-only status of the file 14918Sbill * system is checked. 15018Sbill * Also in WRITE, prototype text 15118Sbill * segments cannot be written. 15218Sbill * The mode is shifted to select 15318Sbill * the owner/group/other fields. 15418Sbill * The super user is granted all 15518Sbill * permissions. 15618Sbill */ 15718Sbill access(ip, mode) 1584817Swnj register struct inode *ip; 1594817Swnj int mode; 16018Sbill { 16118Sbill register m; 16218Sbill 16318Sbill m = mode; 1644817Swnj if (m == IWRITE) { 1654817Swnj if (getfs(ip->i_dev)->s_ronly != 0) { 16618Sbill u.u_error = EROFS; 1674817Swnj return (1); 16818Sbill } 16918Sbill if (ip->i_flag&ITEXT) /* try to free text */ 17018Sbill xrele(ip); 1714817Swnj if (ip->i_flag & ITEXT) { 17218Sbill u.u_error = ETXTBSY; 1734817Swnj return (1); 17418Sbill } 17518Sbill } 1764817Swnj if (u.u_uid == 0) 1774817Swnj return (0); 1784817Swnj if (u.u_uid != ip->i_uid) { 17918Sbill m >>= 3; 1804817Swnj if (u.u_gid != ip->i_gid) 18118Sbill m >>= 3; 18218Sbill } 1834817Swnj if ((ip->i_mode&m) != 0) 1844817Swnj return (0); 18518Sbill u.u_error = EACCES; 1864817Swnj return (1); 18718Sbill } 18818Sbill 18918Sbill /* 19018Sbill * Look up a pathname and test if 19118Sbill * the resultant inode is owned by the 19218Sbill * current user. 19318Sbill * If not, try for super-user. 19418Sbill * If permission is granted, 19518Sbill * return inode pointer. 19618Sbill */ 19718Sbill struct inode * 19818Sbill owner() 19918Sbill { 20018Sbill register struct inode *ip; 20118Sbill 20218Sbill ip = namei(uchar, 0); 2034817Swnj if (ip == NULL) 2044817Swnj return (NULL); 2054817Swnj if (u.u_uid == ip->i_uid) 2064817Swnj return (ip); 2074817Swnj if (suser()) 2084817Swnj return (ip); 20918Sbill iput(ip); 2104817Swnj return (NULL); 21118Sbill } 21218Sbill 21318Sbill /* 21418Sbill * Test if the current user is the 21518Sbill * super user. 21618Sbill */ 21718Sbill suser() 21818Sbill { 21918Sbill 2204817Swnj if (u.u_uid == 0) { 22118Sbill u.u_acflag |= ASU; 2224817Swnj return (1); 22318Sbill } 22418Sbill u.u_error = EPERM; 2254817Swnj return (0); 22618Sbill } 22718Sbill 22818Sbill /* 22918Sbill * Allocate a user file descriptor. 23018Sbill */ 23118Sbill ufalloc() 23218Sbill { 23318Sbill register i; 23418Sbill 2354817Swnj for (i=0; i<NOFILE; i++) 2364817Swnj if (u.u_ofile[i] == NULL) { 23718Sbill u.u_r.r_val1 = i; 23818Sbill u.u_pofile[i] = 0; 2394817Swnj return (i); 24018Sbill } 24118Sbill u.u_error = EMFILE; 2424817Swnj return (-1); 24318Sbill } 24418Sbill 2452768Swnj struct file *lastf; 24618Sbill /* 24718Sbill * Allocate a user file descriptor 24818Sbill * and a file structure. 24918Sbill * Initialize the descriptor 25018Sbill * to point at the file structure. 25118Sbill */ 25218Sbill struct file * 25318Sbill falloc() 25418Sbill { 25518Sbill register struct file *fp; 25618Sbill register i; 25718Sbill 25818Sbill i = ufalloc(); 2592768Swnj if (i < 0) 2604817Swnj return (NULL); 2612768Swnj if (lastf == 0) 2622768Swnj lastf = file; 2632768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2642768Swnj if (fp->f_count == 0) 265387Sbill goto slot; 2662768Swnj for (fp = file; fp < lastf; fp++) 2672768Swnj if (fp->f_count == 0) 268387Sbill goto slot; 2692932Swnj tablefull("file"); 27018Sbill u.u_error = ENFILE; 2712768Swnj return (NULL); 272387Sbill slot: 273387Sbill u.u_ofile[i] = fp; 274387Sbill fp->f_count++; 2754817Swnj fp->f_offset = 0; 2763782Sroot fp->f_inode = 0; 277387Sbill lastf = fp + 1; 2782768Swnj return (fp); 27918Sbill } 280