1*5581Swnj /* vfs_vnops.c 4.19 82/01/19 */ 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" 16*5581Swnj #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. 46*5581Swnj * Nouser indicates that the user isn't available to present 47*5581Swnj * errors to. 4818Sbill */ 49*5581Swnj 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*5581Swnj soclose(fp->f_socket, nouser); 67*5581Swnj if (u.u_error) 68*5581Swnj return; 694817Swnj fp->f_socket = 0; 703616Sroot fp->f_count = 0; 713616Sroot return; 723616Sroot } 7318Sbill ip = fp->f_inode; 7418Sbill dev = (dev_t)ip->i_un.i_rdev; 752302Skre mode = ip->i_mode & IFMT; 764817Swnj ilock(ip); 773616Sroot iput(ip); 7818Sbill fp->f_count = 0; 7918Sbill 803616Sroot switch (mode) { 8118Sbill 8218Sbill case IFCHR: 8318Sbill cfunc = cdevsw[major(dev)].d_close; 8418Sbill break; 8518Sbill 8618Sbill case IFBLK: 872302Skre /* 882302Skre * We don't want to really close the device if it is mounted 892302Skre */ 902302Skre for (mp = mount; mp < &mount[NMOUNT]; mp++) 912302Skre if (mp->m_bufp != NULL && mp->m_dev == dev) 922302Skre return; 9318Sbill cfunc = bdevsw[major(dev)].d_close; 9418Sbill break; 954817Swnj 9618Sbill default: 9718Sbill return; 9818Sbill } 994817Swnj for (fp = file; fp < fileNFILE; fp++) { 1004817Swnj if (fp->f_flag & FSOCKET) 1014817Swnj continue; 1024485Swnj if (fp->f_count && (ip = fp->f_inode) && 1034817Swnj ip->i_un.i_rdev == dev && (ip->i_mode&IFMT) == mode) 1044485Swnj return; 1052302Skre } 1064485Swnj if (mode == IFBLK) { 1074485Swnj /* 1084817Swnj * On last close of a block device (that isn't mounted) 1094485Swnj * we must invalidate any in core blocks 1104485Swnj */ 1114485Swnj bflush(dev); 1124485Swnj binval(dev); 1134485Swnj } 1142274Swnj (*cfunc)(dev, flag, fp); 11518Sbill } 11618Sbill 11718Sbill /* 1184817Swnj * Openi called to allow handler 11918Sbill * of special files to initialize and 12018Sbill * validate before actual IO. 12118Sbill */ 12218Sbill openi(ip, rw) 1234817Swnj register struct inode *ip; 12418Sbill { 12518Sbill dev_t dev; 12618Sbill register unsigned int maj; 12718Sbill 12818Sbill dev = (dev_t)ip->i_un.i_rdev; 12918Sbill maj = major(dev); 1304817Swnj switch (ip->i_mode&IFMT) { 13118Sbill 13218Sbill case IFCHR: 1334817Swnj if (maj >= nchrdev) 13418Sbill goto bad; 13518Sbill (*cdevsw[maj].d_open)(dev, rw); 13618Sbill break; 13718Sbill 13818Sbill case IFBLK: 1394817Swnj if (maj >= nblkdev) 14018Sbill goto bad; 14118Sbill (*bdevsw[maj].d_open)(dev, rw); 14218Sbill } 14318Sbill return; 14418Sbill 14518Sbill bad: 14618Sbill u.u_error = ENXIO; 14718Sbill } 14818Sbill 14918Sbill /* 15018Sbill * Check mode permission on inode pointer. 15118Sbill * Mode is READ, WRITE or EXEC. 15218Sbill * In the case of WRITE, the 15318Sbill * read-only status of the file 15418Sbill * system is checked. 15518Sbill * Also in WRITE, prototype text 15618Sbill * segments cannot be written. 15718Sbill * The mode is shifted to select 15818Sbill * the owner/group/other fields. 15918Sbill * The super user is granted all 16018Sbill * permissions. 16118Sbill */ 16218Sbill access(ip, mode) 1634817Swnj register struct inode *ip; 1644817Swnj int mode; 16518Sbill { 16618Sbill register m; 16718Sbill 16818Sbill m = mode; 1694817Swnj if (m == IWRITE) { 1704817Swnj if (getfs(ip->i_dev)->s_ronly != 0) { 17118Sbill u.u_error = EROFS; 1724817Swnj return (1); 17318Sbill } 17418Sbill if (ip->i_flag&ITEXT) /* try to free text */ 17518Sbill xrele(ip); 1764817Swnj if (ip->i_flag & ITEXT) { 17718Sbill u.u_error = ETXTBSY; 1784817Swnj return (1); 17918Sbill } 18018Sbill } 1814817Swnj if (u.u_uid == 0) 1824817Swnj return (0); 1834817Swnj if (u.u_uid != ip->i_uid) { 18418Sbill m >>= 3; 1854817Swnj if (u.u_gid != ip->i_gid) 18618Sbill m >>= 3; 18718Sbill } 1884817Swnj if ((ip->i_mode&m) != 0) 1894817Swnj return (0); 19018Sbill u.u_error = EACCES; 1914817Swnj return (1); 19218Sbill } 19318Sbill 19418Sbill /* 19518Sbill * Look up a pathname and test if 19618Sbill * the resultant inode is owned by the 19718Sbill * current user. 19818Sbill * If not, try for super-user. 19918Sbill * If permission is granted, 20018Sbill * return inode pointer. 20118Sbill */ 20218Sbill struct inode * 20318Sbill owner() 20418Sbill { 20518Sbill register struct inode *ip; 20618Sbill 20718Sbill ip = namei(uchar, 0); 2084817Swnj if (ip == NULL) 2094817Swnj return (NULL); 2104817Swnj if (u.u_uid == ip->i_uid) 2114817Swnj return (ip); 2124817Swnj if (suser()) 2134817Swnj return (ip); 21418Sbill iput(ip); 2154817Swnj return (NULL); 21618Sbill } 21718Sbill 21818Sbill /* 21918Sbill * Test if the current user is the 22018Sbill * super user. 22118Sbill */ 22218Sbill suser() 22318Sbill { 22418Sbill 2254817Swnj if (u.u_uid == 0) { 22618Sbill u.u_acflag |= ASU; 2274817Swnj return (1); 22818Sbill } 22918Sbill u.u_error = EPERM; 2304817Swnj return (0); 23118Sbill } 23218Sbill 23318Sbill /* 23418Sbill * Allocate a user file descriptor. 23518Sbill */ 23618Sbill ufalloc() 23718Sbill { 23818Sbill register i; 23918Sbill 2404817Swnj for (i=0; i<NOFILE; i++) 2414817Swnj if (u.u_ofile[i] == NULL) { 24218Sbill u.u_r.r_val1 = i; 24318Sbill u.u_pofile[i] = 0; 2444817Swnj return (i); 24518Sbill } 24618Sbill u.u_error = EMFILE; 2474817Swnj return (-1); 24818Sbill } 24918Sbill 2502768Swnj struct file *lastf; 25118Sbill /* 25218Sbill * Allocate a user file descriptor 25318Sbill * and a file structure. 25418Sbill * Initialize the descriptor 25518Sbill * to point at the file structure. 25618Sbill */ 25718Sbill struct file * 25818Sbill falloc() 25918Sbill { 26018Sbill register struct file *fp; 26118Sbill register i; 26218Sbill 26318Sbill i = ufalloc(); 2642768Swnj if (i < 0) 2654817Swnj return (NULL); 2662768Swnj if (lastf == 0) 2672768Swnj lastf = file; 2682768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2692768Swnj if (fp->f_count == 0) 270387Sbill goto slot; 2712768Swnj for (fp = file; fp < lastf; fp++) 2722768Swnj if (fp->f_count == 0) 273387Sbill goto slot; 2742932Swnj tablefull("file"); 27518Sbill u.u_error = ENFILE; 2762768Swnj return (NULL); 277387Sbill slot: 278387Sbill u.u_ofile[i] = fp; 279387Sbill fp->f_count++; 2804817Swnj fp->f_offset = 0; 2813782Sroot fp->f_inode = 0; 282387Sbill lastf = fp + 1; 2832768Swnj return (fp); 28418Sbill } 285