1*4485Swnj /* vfs_vnops.c 4.13 81/10/11 */ 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 /* 1618Sbill * Convert a user supplied 1718Sbill * file descriptor into a pointer 1818Sbill * to a file structure. 1918Sbill * Only task is to check range 2018Sbill * of the descriptor. 2118Sbill */ 2218Sbill struct file * 2318Sbill getf(f) 2418Sbill 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) 4718Sbill 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 5518Sbill if(fp == NULL) 5618Sbill return; 5718Sbill if (fp->f_count > 1) { 5818Sbill fp->f_count--; 5918Sbill return; 6018Sbill } 613616Sroot flag = fp->f_flag; 623742Sroot #ifdef BBNNET 633742Sroot if (flag&FNET) { 643742Sroot netclose(fp); 653742Sroot return; 663742Sroot } 673742Sroot #endif 683616Sroot if (flag & FPORT) { 693616Sroot ptclose(fp); 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; 7618Sbill plock(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; 9518Sbill default: 9618Sbill return; 9718Sbill } 9818Sbill 99*4485Swnj for(fp=file; fp < fileNFILE; fp++) { 1004124Secc #ifdef BBNNET 1014124Secc if (fp->f_flag & FNET) 1024124Secc continue; 1034124Secc #endif 104*4485Swnj if (fp->f_count && (ip = fp->f_inode) && 105*4485Swnj ip->i_un.i_rdev == dev && 106*4485Swnj (ip->i_mode&IFMT) == mode) 107*4485Swnj return; 1082302Skre } 109*4485Swnj if (mode == IFBLK) { 110*4485Swnj /* 111*4485Swnj * on last close of a block device (that isn't mounted) 112*4485Swnj * we must invalidate any in core blocks 113*4485Swnj */ 114*4485Swnj bflush(dev); 115*4485Swnj binval(dev); 116*4485Swnj } 1172274Swnj (*cfunc)(dev, flag, fp); 11818Sbill } 11918Sbill 12018Sbill /* 12118Sbill * openi called to allow handler 12218Sbill * of special files to initialize and 12318Sbill * validate before actual IO. 12418Sbill */ 12518Sbill openi(ip, rw) 12618Sbill register struct inode *ip; 12718Sbill { 12818Sbill dev_t dev; 12918Sbill register unsigned int maj; 13018Sbill 13118Sbill dev = (dev_t)ip->i_un.i_rdev; 13218Sbill maj = major(dev); 13318Sbill switch(ip->i_mode&IFMT) { 13418Sbill 13518Sbill case IFCHR: 13618Sbill if(maj >= nchrdev) 13718Sbill goto bad; 13818Sbill (*cdevsw[maj].d_open)(dev, rw); 13918Sbill break; 14018Sbill 14118Sbill case IFBLK: 14218Sbill if(maj >= nblkdev) 14318Sbill goto bad; 14418Sbill (*bdevsw[maj].d_open)(dev, rw); 14518Sbill } 14618Sbill return; 14718Sbill 14818Sbill bad: 14918Sbill u.u_error = ENXIO; 15018Sbill } 15118Sbill 15218Sbill /* 15318Sbill * Check mode permission on inode pointer. 15418Sbill * Mode is READ, WRITE or EXEC. 15518Sbill * In the case of WRITE, the 15618Sbill * read-only status of the file 15718Sbill * system is checked. 15818Sbill * Also in WRITE, prototype text 15918Sbill * segments cannot be written. 16018Sbill * The mode is shifted to select 16118Sbill * the owner/group/other fields. 16218Sbill * The super user is granted all 16318Sbill * permissions. 16418Sbill */ 16518Sbill access(ip, mode) 16618Sbill register struct inode *ip; 16718Sbill { 16818Sbill register m; 16918Sbill 17018Sbill m = mode; 17118Sbill if(m == IWRITE) { 17218Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 17318Sbill u.u_error = EROFS; 17418Sbill return(1); 17518Sbill } 17618Sbill if (ip->i_flag&ITEXT) /* try to free text */ 17718Sbill xrele(ip); 17818Sbill if(ip->i_flag & ITEXT) { 17918Sbill u.u_error = ETXTBSY; 18018Sbill return(1); 18118Sbill } 18218Sbill } 18318Sbill if(u.u_uid == 0) 18418Sbill return(0); 18518Sbill if(u.u_uid != ip->i_uid) { 18618Sbill m >>= 3; 18718Sbill if(u.u_gid != ip->i_gid) 18818Sbill m >>= 3; 18918Sbill } 19018Sbill if((ip->i_mode&m) != 0) 19118Sbill return(0); 19218Sbill 19318Sbill u.u_error = EACCES; 19418Sbill 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 * 20618Sbill owner() 20718Sbill { 20818Sbill register struct inode *ip; 20918Sbill 21018Sbill ip = namei(uchar, 0); 21118Sbill if(ip == NULL) 21218Sbill return(NULL); 21318Sbill if(u.u_uid == ip->i_uid) 21418Sbill return(ip); 21518Sbill if(suser()) 21618Sbill return(ip); 21718Sbill iput(ip); 21818Sbill return(NULL); 21918Sbill } 22018Sbill 22118Sbill /* 22218Sbill * Test if the current user is the 22318Sbill * super user. 22418Sbill */ 22518Sbill suser() 22618Sbill { 22718Sbill 22818Sbill if(u.u_uid == 0) { 22918Sbill u.u_acflag |= ASU; 23018Sbill return(1); 23118Sbill } 23218Sbill u.u_error = EPERM; 23318Sbill return(0); 23418Sbill } 23518Sbill 23618Sbill /* 23718Sbill * Allocate a user file descriptor. 23818Sbill */ 23918Sbill ufalloc() 24018Sbill { 24118Sbill register i; 24218Sbill 24318Sbill for(i=0; i<NOFILE; i++) 24418Sbill if(u.u_ofile[i] == NULL) { 24518Sbill u.u_r.r_val1 = i; 24618Sbill u.u_pofile[i] = 0; 24718Sbill return(i); 24818Sbill } 24918Sbill u.u_error = EMFILE; 25018Sbill return(-1); 25118Sbill } 25218Sbill 2532768Swnj struct file *lastf; 25418Sbill /* 25518Sbill * Allocate a user file descriptor 25618Sbill * and a file structure. 25718Sbill * Initialize the descriptor 25818Sbill * to point at the file structure. 25918Sbill */ 26018Sbill struct file * 26118Sbill falloc() 26218Sbill { 26318Sbill register struct file *fp; 26418Sbill register i; 26518Sbill 26618Sbill i = ufalloc(); 2672768Swnj if (i < 0) 26818Sbill return(NULL); 2692768Swnj if (lastf == 0) 2702768Swnj lastf = file; 2712768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2722768Swnj if (fp->f_count == 0) 273387Sbill goto slot; 2742768Swnj for (fp = file; fp < lastf; fp++) 2752768Swnj if (fp->f_count == 0) 276387Sbill goto slot; 2772932Swnj tablefull("file"); 27818Sbill u.u_error = ENFILE; 2792768Swnj return (NULL); 280387Sbill slot: 281387Sbill u.u_ofile[i] = fp; 282387Sbill fp->f_count++; 283387Sbill fp->f_un.f_offset = 0; 2843782Sroot fp->f_inode = 0; 285387Sbill lastf = fp + 1; 2862768Swnj return (fp); 28718Sbill } 288