1*3782Sroot /* vfs_vnops.c 4.11 81/05/15 */ 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) { 1022738Swnj for(fp=file; fp < fileNFILE; fp++) 1033616Sroot if (fp->f_count && (ip = fp->f_inode) && 1043616Sroot ip->i_un.i_rdev == dev && 1052302Skre (ip->i_mode&IFMT) == mode) 1062302Skre return; 1072302Skre if (mode == IFBLK) { 1082302Skre /* 1092302Skre * on last close of a block device (that isn't mounted) 1102302Skre * we must invalidate any in core blocks 1112302Skre */ 1122302Skre bflush(dev); 1132302Skre binval(dev); 1142302Skre } 1152302Skre } 1162274Swnj (*cfunc)(dev, flag, fp); 11718Sbill } 11818Sbill 11918Sbill /* 12018Sbill * openi called to allow handler 12118Sbill * of special files to initialize and 12218Sbill * validate before actual IO. 12318Sbill */ 12418Sbill openi(ip, rw) 12518Sbill register struct inode *ip; 12618Sbill { 12718Sbill dev_t dev; 12818Sbill register unsigned int maj; 12918Sbill 13018Sbill dev = (dev_t)ip->i_un.i_rdev; 13118Sbill maj = major(dev); 13218Sbill switch(ip->i_mode&IFMT) { 13318Sbill 13418Sbill case IFCHR: 13518Sbill case IFMPC: 13618Sbill if(maj >= nchrdev) 13718Sbill goto bad; 13818Sbill (*cdevsw[maj].d_open)(dev, rw); 13918Sbill break; 14018Sbill 14118Sbill case IFBLK: 14218Sbill case IFMPB: 14318Sbill if(maj >= nblkdev) 14418Sbill goto bad; 14518Sbill (*bdevsw[maj].d_open)(dev, rw); 14618Sbill } 14718Sbill return; 14818Sbill 14918Sbill bad: 15018Sbill u.u_error = ENXIO; 15118Sbill } 15218Sbill 15318Sbill /* 15418Sbill * Check mode permission on inode pointer. 15518Sbill * Mode is READ, WRITE or EXEC. 15618Sbill * In the case of WRITE, the 15718Sbill * read-only status of the file 15818Sbill * system is checked. 15918Sbill * Also in WRITE, prototype text 16018Sbill * segments cannot be written. 16118Sbill * The mode is shifted to select 16218Sbill * the owner/group/other fields. 16318Sbill * The super user is granted all 16418Sbill * permissions. 16518Sbill */ 16618Sbill access(ip, mode) 16718Sbill register struct inode *ip; 16818Sbill { 16918Sbill register m; 17018Sbill 17118Sbill m = mode; 17218Sbill if(m == IWRITE) { 17318Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 17418Sbill u.u_error = EROFS; 17518Sbill return(1); 17618Sbill } 17718Sbill if (ip->i_flag&ITEXT) /* try to free text */ 17818Sbill xrele(ip); 17918Sbill if(ip->i_flag & ITEXT) { 18018Sbill u.u_error = ETXTBSY; 18118Sbill return(1); 18218Sbill } 18318Sbill } 18418Sbill if(u.u_uid == 0) 18518Sbill return(0); 18618Sbill if(u.u_uid != ip->i_uid) { 18718Sbill m >>= 3; 18818Sbill if(u.u_gid != ip->i_gid) 18918Sbill m >>= 3; 19018Sbill } 19118Sbill if((ip->i_mode&m) != 0) 19218Sbill return(0); 19318Sbill 19418Sbill u.u_error = EACCES; 19518Sbill return(1); 19618Sbill } 19718Sbill 19818Sbill /* 19918Sbill * Look up a pathname and test if 20018Sbill * the resultant inode is owned by the 20118Sbill * current user. 20218Sbill * If not, try for super-user. 20318Sbill * If permission is granted, 20418Sbill * return inode pointer. 20518Sbill */ 20618Sbill struct inode * 20718Sbill owner() 20818Sbill { 20918Sbill register struct inode *ip; 21018Sbill 21118Sbill ip = namei(uchar, 0); 21218Sbill if(ip == NULL) 21318Sbill return(NULL); 21418Sbill if(u.u_uid == ip->i_uid) 21518Sbill return(ip); 21618Sbill if(suser()) 21718Sbill return(ip); 21818Sbill iput(ip); 21918Sbill return(NULL); 22018Sbill } 22118Sbill 22218Sbill /* 22318Sbill * Test if the current user is the 22418Sbill * super user. 22518Sbill */ 22618Sbill suser() 22718Sbill { 22818Sbill 22918Sbill if(u.u_uid == 0) { 23018Sbill u.u_acflag |= ASU; 23118Sbill return(1); 23218Sbill } 23318Sbill u.u_error = EPERM; 23418Sbill return(0); 23518Sbill } 23618Sbill 23718Sbill /* 23818Sbill * Allocate a user file descriptor. 23918Sbill */ 24018Sbill ufalloc() 24118Sbill { 24218Sbill register i; 24318Sbill 24418Sbill for(i=0; i<NOFILE; i++) 24518Sbill if(u.u_ofile[i] == NULL) { 24618Sbill u.u_r.r_val1 = i; 24718Sbill u.u_pofile[i] = 0; 24818Sbill return(i); 24918Sbill } 25018Sbill u.u_error = EMFILE; 25118Sbill return(-1); 25218Sbill } 25318Sbill 2542768Swnj struct file *lastf; 25518Sbill /* 25618Sbill * Allocate a user file descriptor 25718Sbill * and a file structure. 25818Sbill * Initialize the descriptor 25918Sbill * to point at the file structure. 26018Sbill */ 26118Sbill struct file * 26218Sbill falloc() 26318Sbill { 26418Sbill register struct file *fp; 26518Sbill register i; 26618Sbill 26718Sbill i = ufalloc(); 2682768Swnj if (i < 0) 26918Sbill return(NULL); 2702768Swnj if (lastf == 0) 2712768Swnj lastf = file; 2722768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2732768Swnj if (fp->f_count == 0) 274387Sbill goto slot; 2752768Swnj for (fp = file; fp < lastf; fp++) 2762768Swnj if (fp->f_count == 0) 277387Sbill goto slot; 2782932Swnj tablefull("file"); 27918Sbill u.u_error = ENFILE; 2802768Swnj return (NULL); 281387Sbill slot: 282387Sbill u.u_ofile[i] = fp; 283387Sbill fp->f_count++; 284387Sbill fp->f_un.f_offset = 0; 285*3782Sroot fp->f_inode = 0; 286387Sbill lastf = fp + 1; 2872768Swnj return (fp); 28818Sbill } 289