1*4817Swnj /* vfs_vnops.c 4.14 81/11/08 */ 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" 1418Sbill 1518Sbill /* 16*4817Swnj * Convert a user supplied file descriptor into a pointer 17*4817Swnj * to a file structure. Only task is to check range of the descriptor. 18*4817Swnj * Critical paths should use the GETF macro, defined in inline.h. 1918Sbill */ 2018Sbill struct file * 2118Sbill getf(f) 22*4817Swnj register int f; 2318Sbill { 2418Sbill register struct file *fp; 2518Sbill 262329Swnj if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 272329Swnj u.u_error = EBADF; 282329Swnj return (NULL); 2918Sbill } 302329Swnj return (fp); 3118Sbill } 3218Sbill 3318Sbill /* 3418Sbill * Internal form of close. 3518Sbill * Decrement reference count on 3618Sbill * file structure. 3718Sbill * Also make sure the pipe protocol 3818Sbill * does not constipate. 3918Sbill * 4018Sbill * Decrement reference count on the inode following 4118Sbill * removal to the referencing file structure. 4218Sbill * Call device handler on last close. 4318Sbill */ 4418Sbill closef(fp) 45*4817Swnj register struct file *fp; 4618Sbill { 4718Sbill register struct inode *ip; 482302Skre register struct mount *mp; 4918Sbill int flag, mode; 5018Sbill dev_t dev; 5118Sbill register int (*cfunc)(); 5218Sbill 53*4817Swnj if (fp == NULL) 5418Sbill return; 5518Sbill if (fp->f_count > 1) { 5618Sbill fp->f_count--; 5718Sbill return; 5818Sbill } 593616Sroot flag = fp->f_flag; 60*4817Swnj if (flag & FSOCKET) { 61*4817Swnj skclose(fp->f_socket); 62*4817Swnj fp->f_socket = 0; 633616Sroot fp->f_count = 0; 643616Sroot return; 653616Sroot } 6618Sbill ip = fp->f_inode; 6718Sbill dev = (dev_t)ip->i_un.i_rdev; 682302Skre mode = ip->i_mode & IFMT; 69*4817Swnj ilock(ip); 703616Sroot iput(ip); 7118Sbill fp->f_count = 0; 7218Sbill 733616Sroot switch (mode) { 7418Sbill 7518Sbill case IFCHR: 7618Sbill cfunc = cdevsw[major(dev)].d_close; 7718Sbill break; 7818Sbill 7918Sbill case IFBLK: 802302Skre /* 812302Skre * We don't want to really close the device if it is mounted 822302Skre */ 832302Skre for (mp = mount; mp < &mount[NMOUNT]; mp++) 842302Skre if (mp->m_bufp != NULL && mp->m_dev == dev) 852302Skre return; 8618Sbill cfunc = bdevsw[major(dev)].d_close; 8718Sbill break; 88*4817Swnj 8918Sbill default: 9018Sbill return; 9118Sbill } 92*4817Swnj for (fp = file; fp < fileNFILE; fp++) { 93*4817Swnj if (fp->f_flag & FSOCKET) 94*4817Swnj continue; 954485Swnj if (fp->f_count && (ip = fp->f_inode) && 96*4817Swnj ip->i_un.i_rdev == dev && (ip->i_mode&IFMT) == mode) 974485Swnj return; 982302Skre } 994485Swnj if (mode == IFBLK) { 1004485Swnj /* 101*4817Swnj * On last close of a block device (that isn't mounted) 1024485Swnj * we must invalidate any in core blocks 1034485Swnj */ 1044485Swnj bflush(dev); 1054485Swnj binval(dev); 1064485Swnj } 1072274Swnj (*cfunc)(dev, flag, fp); 10818Sbill } 10918Sbill 11018Sbill /* 111*4817Swnj * Openi called to allow handler 11218Sbill * of special files to initialize and 11318Sbill * validate before actual IO. 11418Sbill */ 11518Sbill openi(ip, rw) 116*4817Swnj register struct inode *ip; 11718Sbill { 11818Sbill dev_t dev; 11918Sbill register unsigned int maj; 12018Sbill 12118Sbill dev = (dev_t)ip->i_un.i_rdev; 12218Sbill maj = major(dev); 123*4817Swnj switch (ip->i_mode&IFMT) { 12418Sbill 12518Sbill case IFCHR: 126*4817Swnj if (maj >= nchrdev) 12718Sbill goto bad; 12818Sbill (*cdevsw[maj].d_open)(dev, rw); 12918Sbill break; 13018Sbill 13118Sbill case IFBLK: 132*4817Swnj if (maj >= nblkdev) 13318Sbill goto bad; 13418Sbill (*bdevsw[maj].d_open)(dev, rw); 13518Sbill } 13618Sbill return; 13718Sbill 13818Sbill bad: 13918Sbill u.u_error = ENXIO; 14018Sbill } 14118Sbill 14218Sbill /* 14318Sbill * Check mode permission on inode pointer. 14418Sbill * Mode is READ, WRITE or EXEC. 14518Sbill * In the case of WRITE, the 14618Sbill * read-only status of the file 14718Sbill * system is checked. 14818Sbill * Also in WRITE, prototype text 14918Sbill * segments cannot be written. 15018Sbill * The mode is shifted to select 15118Sbill * the owner/group/other fields. 15218Sbill * The super user is granted all 15318Sbill * permissions. 15418Sbill */ 15518Sbill access(ip, mode) 156*4817Swnj register struct inode *ip; 157*4817Swnj int mode; 15818Sbill { 15918Sbill register m; 16018Sbill 16118Sbill m = mode; 162*4817Swnj if (m == IWRITE) { 163*4817Swnj if (getfs(ip->i_dev)->s_ronly != 0) { 16418Sbill u.u_error = EROFS; 165*4817Swnj return (1); 16618Sbill } 16718Sbill if (ip->i_flag&ITEXT) /* try to free text */ 16818Sbill xrele(ip); 169*4817Swnj if (ip->i_flag & ITEXT) { 17018Sbill u.u_error = ETXTBSY; 171*4817Swnj return (1); 17218Sbill } 17318Sbill } 174*4817Swnj if (u.u_uid == 0) 175*4817Swnj return (0); 176*4817Swnj if (u.u_uid != ip->i_uid) { 17718Sbill m >>= 3; 178*4817Swnj if (u.u_gid != ip->i_gid) 17918Sbill m >>= 3; 18018Sbill } 181*4817Swnj if ((ip->i_mode&m) != 0) 182*4817Swnj return (0); 18318Sbill u.u_error = EACCES; 184*4817Swnj return (1); 18518Sbill } 18618Sbill 18718Sbill /* 18818Sbill * Look up a pathname and test if 18918Sbill * the resultant inode is owned by the 19018Sbill * current user. 19118Sbill * If not, try for super-user. 19218Sbill * If permission is granted, 19318Sbill * return inode pointer. 19418Sbill */ 19518Sbill struct inode * 19618Sbill owner() 19718Sbill { 19818Sbill register struct inode *ip; 19918Sbill 20018Sbill ip = namei(uchar, 0); 201*4817Swnj if (ip == NULL) 202*4817Swnj return (NULL); 203*4817Swnj if (u.u_uid == ip->i_uid) 204*4817Swnj return (ip); 205*4817Swnj if (suser()) 206*4817Swnj return (ip); 20718Sbill iput(ip); 208*4817Swnj return (NULL); 20918Sbill } 21018Sbill 21118Sbill /* 21218Sbill * Test if the current user is the 21318Sbill * super user. 21418Sbill */ 21518Sbill suser() 21618Sbill { 21718Sbill 218*4817Swnj if (u.u_uid == 0) { 21918Sbill u.u_acflag |= ASU; 220*4817Swnj return (1); 22118Sbill } 22218Sbill u.u_error = EPERM; 223*4817Swnj return (0); 22418Sbill } 22518Sbill 22618Sbill /* 22718Sbill * Allocate a user file descriptor. 22818Sbill */ 22918Sbill ufalloc() 23018Sbill { 23118Sbill register i; 23218Sbill 233*4817Swnj for (i=0; i<NOFILE; i++) 234*4817Swnj if (u.u_ofile[i] == NULL) { 23518Sbill u.u_r.r_val1 = i; 23618Sbill u.u_pofile[i] = 0; 237*4817Swnj return (i); 23818Sbill } 23918Sbill u.u_error = EMFILE; 240*4817Swnj return (-1); 24118Sbill } 24218Sbill 2432768Swnj struct file *lastf; 24418Sbill /* 24518Sbill * Allocate a user file descriptor 24618Sbill * and a file structure. 24718Sbill * Initialize the descriptor 24818Sbill * to point at the file structure. 24918Sbill */ 25018Sbill struct file * 25118Sbill falloc() 25218Sbill { 25318Sbill register struct file *fp; 25418Sbill register i; 25518Sbill 25618Sbill i = ufalloc(); 2572768Swnj if (i < 0) 258*4817Swnj return (NULL); 2592768Swnj if (lastf == 0) 2602768Swnj lastf = file; 2612768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2622768Swnj if (fp->f_count == 0) 263387Sbill goto slot; 2642768Swnj for (fp = file; fp < lastf; fp++) 2652768Swnj if (fp->f_count == 0) 266387Sbill goto slot; 2672932Swnj tablefull("file"); 26818Sbill u.u_error = ENFILE; 2692768Swnj return (NULL); 270387Sbill slot: 271387Sbill u.u_ofile[i] = fp; 272387Sbill fp->f_count++; 273*4817Swnj fp->f_offset = 0; 2743782Sroot fp->f_inode = 0; 275387Sbill lastf = fp + 1; 2762768Swnj return (fp); 27718Sbill } 278