1*4124Secc /* vfs_vnops.c 4.12 81/08/12 */ 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 case IFMPC: 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 case IFMPB: 9518Sbill cfunc = bdevsw[major(dev)].d_close; 9618Sbill break; 9718Sbill default: 9818Sbill return; 9918Sbill } 10018Sbill 1012302Skre if ((flag & FMP) == 0) { 102*4124Secc for(fp=file; fp < fileNFILE; fp++) { 103*4124Secc #ifdef BBNNET 104*4124Secc if (fp->f_flag & FNET) 105*4124Secc continue; 106*4124Secc #endif 1073616Sroot if (fp->f_count && (ip = fp->f_inode) && 1083616Sroot ip->i_un.i_rdev == dev && 1092302Skre (ip->i_mode&IFMT) == mode) 1102302Skre return; 111*4124Secc } 1122302Skre if (mode == IFBLK) { 1132302Skre /* 1142302Skre * on last close of a block device (that isn't mounted) 1152302Skre * we must invalidate any in core blocks 1162302Skre */ 1172302Skre bflush(dev); 1182302Skre binval(dev); 1192302Skre } 1202302Skre } 1212274Swnj (*cfunc)(dev, flag, fp); 12218Sbill } 12318Sbill 12418Sbill /* 12518Sbill * openi called to allow handler 12618Sbill * of special files to initialize and 12718Sbill * validate before actual IO. 12818Sbill */ 12918Sbill openi(ip, rw) 13018Sbill register struct inode *ip; 13118Sbill { 13218Sbill dev_t dev; 13318Sbill register unsigned int maj; 13418Sbill 13518Sbill dev = (dev_t)ip->i_un.i_rdev; 13618Sbill maj = major(dev); 13718Sbill switch(ip->i_mode&IFMT) { 13818Sbill 13918Sbill case IFCHR: 14018Sbill case IFMPC: 14118Sbill if(maj >= nchrdev) 14218Sbill goto bad; 14318Sbill (*cdevsw[maj].d_open)(dev, rw); 14418Sbill break; 14518Sbill 14618Sbill case IFBLK: 14718Sbill case IFMPB: 14818Sbill if(maj >= nblkdev) 14918Sbill goto bad; 15018Sbill (*bdevsw[maj].d_open)(dev, rw); 15118Sbill } 15218Sbill return; 15318Sbill 15418Sbill bad: 15518Sbill u.u_error = ENXIO; 15618Sbill } 15718Sbill 15818Sbill /* 15918Sbill * Check mode permission on inode pointer. 16018Sbill * Mode is READ, WRITE or EXEC. 16118Sbill * In the case of WRITE, the 16218Sbill * read-only status of the file 16318Sbill * system is checked. 16418Sbill * Also in WRITE, prototype text 16518Sbill * segments cannot be written. 16618Sbill * The mode is shifted to select 16718Sbill * the owner/group/other fields. 16818Sbill * The super user is granted all 16918Sbill * permissions. 17018Sbill */ 17118Sbill access(ip, mode) 17218Sbill register struct inode *ip; 17318Sbill { 17418Sbill register m; 17518Sbill 17618Sbill m = mode; 17718Sbill if(m == IWRITE) { 17818Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 17918Sbill u.u_error = EROFS; 18018Sbill return(1); 18118Sbill } 18218Sbill if (ip->i_flag&ITEXT) /* try to free text */ 18318Sbill xrele(ip); 18418Sbill if(ip->i_flag & ITEXT) { 18518Sbill u.u_error = ETXTBSY; 18618Sbill return(1); 18718Sbill } 18818Sbill } 18918Sbill if(u.u_uid == 0) 19018Sbill return(0); 19118Sbill if(u.u_uid != ip->i_uid) { 19218Sbill m >>= 3; 19318Sbill if(u.u_gid != ip->i_gid) 19418Sbill m >>= 3; 19518Sbill } 19618Sbill if((ip->i_mode&m) != 0) 19718Sbill return(0); 19818Sbill 19918Sbill u.u_error = EACCES; 20018Sbill return(1); 20118Sbill } 20218Sbill 20318Sbill /* 20418Sbill * Look up a pathname and test if 20518Sbill * the resultant inode is owned by the 20618Sbill * current user. 20718Sbill * If not, try for super-user. 20818Sbill * If permission is granted, 20918Sbill * return inode pointer. 21018Sbill */ 21118Sbill struct inode * 21218Sbill owner() 21318Sbill { 21418Sbill register struct inode *ip; 21518Sbill 21618Sbill ip = namei(uchar, 0); 21718Sbill if(ip == NULL) 21818Sbill return(NULL); 21918Sbill if(u.u_uid == ip->i_uid) 22018Sbill return(ip); 22118Sbill if(suser()) 22218Sbill return(ip); 22318Sbill iput(ip); 22418Sbill return(NULL); 22518Sbill } 22618Sbill 22718Sbill /* 22818Sbill * Test if the current user is the 22918Sbill * super user. 23018Sbill */ 23118Sbill suser() 23218Sbill { 23318Sbill 23418Sbill if(u.u_uid == 0) { 23518Sbill u.u_acflag |= ASU; 23618Sbill return(1); 23718Sbill } 23818Sbill u.u_error = EPERM; 23918Sbill return(0); 24018Sbill } 24118Sbill 24218Sbill /* 24318Sbill * Allocate a user file descriptor. 24418Sbill */ 24518Sbill ufalloc() 24618Sbill { 24718Sbill register i; 24818Sbill 24918Sbill for(i=0; i<NOFILE; i++) 25018Sbill if(u.u_ofile[i] == NULL) { 25118Sbill u.u_r.r_val1 = i; 25218Sbill u.u_pofile[i] = 0; 25318Sbill return(i); 25418Sbill } 25518Sbill u.u_error = EMFILE; 25618Sbill return(-1); 25718Sbill } 25818Sbill 2592768Swnj struct file *lastf; 26018Sbill /* 26118Sbill * Allocate a user file descriptor 26218Sbill * and a file structure. 26318Sbill * Initialize the descriptor 26418Sbill * to point at the file structure. 26518Sbill */ 26618Sbill struct file * 26718Sbill falloc() 26818Sbill { 26918Sbill register struct file *fp; 27018Sbill register i; 27118Sbill 27218Sbill i = ufalloc(); 2732768Swnj if (i < 0) 27418Sbill return(NULL); 2752768Swnj if (lastf == 0) 2762768Swnj lastf = file; 2772768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2782768Swnj if (fp->f_count == 0) 279387Sbill goto slot; 2802768Swnj for (fp = file; fp < lastf; fp++) 2812768Swnj if (fp->f_count == 0) 282387Sbill goto slot; 2832932Swnj tablefull("file"); 28418Sbill u.u_error = ENFILE; 2852768Swnj return (NULL); 286387Sbill slot: 287387Sbill u.u_ofile[i] = fp; 288387Sbill fp->f_count++; 289387Sbill fp->f_un.f_offset = 0; 2903782Sroot fp->f_inode = 0; 291387Sbill lastf = fp + 1; 2922768Swnj return (fp); 29318Sbill } 294