1*2932Swnj /* vfs_vnops.c 4.7 03/06/81 */ 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 } 6118Sbill ip = fp->f_inode; 6218Sbill flag = fp->f_flag; 6318Sbill dev = (dev_t)ip->i_un.i_rdev; 642302Skre mode = ip->i_mode & IFMT; 6518Sbill 6618Sbill plock(ip); 6718Sbill fp->f_count = 0; 6818Sbill if(flag & FPIPE) { 6918Sbill ip->i_mode &= ~(IREAD|IWRITE); 7018Sbill wakeup((caddr_t)ip+1); 7118Sbill wakeup((caddr_t)ip+2); 7218Sbill } 7318Sbill iput(ip); 7418Sbill 752302Skre switch(mode) { 7618Sbill 7718Sbill case IFCHR: 7818Sbill case IFMPC: 7918Sbill cfunc = cdevsw[major(dev)].d_close; 8018Sbill break; 8118Sbill 8218Sbill case IFBLK: 832302Skre /* 842302Skre * We don't want to really close the device if it is mounted 852302Skre */ 862302Skre for (mp = mount; mp < &mount[NMOUNT]; mp++) 872302Skre if (mp->m_bufp != NULL && mp->m_dev == dev) 882302Skre return; 8918Sbill case IFMPB: 9018Sbill cfunc = bdevsw[major(dev)].d_close; 9118Sbill break; 9218Sbill default: 9318Sbill return; 9418Sbill } 9518Sbill 962302Skre if ((flag & FMP) == 0) { 972738Swnj for(fp=file; fp < fileNFILE; fp++) 982302Skre if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev && 992302Skre (ip->i_mode&IFMT) == mode) 1002302Skre return; 1012302Skre if (mode == IFBLK) { 1022302Skre /* 1032302Skre * on last close of a block device (that isn't mounted) 1042302Skre * we must invalidate any in core blocks 1052302Skre */ 1062302Skre bflush(dev); 1072302Skre binval(dev); 1082302Skre } 1092302Skre } 1102274Swnj (*cfunc)(dev, flag, fp); 11118Sbill } 11218Sbill 11318Sbill /* 11418Sbill * openi called to allow handler 11518Sbill * of special files to initialize and 11618Sbill * validate before actual IO. 11718Sbill */ 11818Sbill openi(ip, rw) 11918Sbill register struct inode *ip; 12018Sbill { 12118Sbill dev_t dev; 12218Sbill register unsigned int maj; 12318Sbill 12418Sbill dev = (dev_t)ip->i_un.i_rdev; 12518Sbill maj = major(dev); 12618Sbill switch(ip->i_mode&IFMT) { 12718Sbill 12818Sbill case IFCHR: 12918Sbill case IFMPC: 13018Sbill if(maj >= nchrdev) 13118Sbill goto bad; 13218Sbill (*cdevsw[maj].d_open)(dev, rw); 13318Sbill break; 13418Sbill 13518Sbill case IFBLK: 13618Sbill case IFMPB: 13718Sbill if(maj >= nblkdev) 13818Sbill goto bad; 13918Sbill (*bdevsw[maj].d_open)(dev, rw); 14018Sbill } 14118Sbill return; 14218Sbill 14318Sbill bad: 14418Sbill u.u_error = ENXIO; 14518Sbill } 14618Sbill 14718Sbill /* 14818Sbill * Check mode permission on inode pointer. 14918Sbill * Mode is READ, WRITE or EXEC. 15018Sbill * In the case of WRITE, the 15118Sbill * read-only status of the file 15218Sbill * system is checked. 15318Sbill * Also in WRITE, prototype text 15418Sbill * segments cannot be written. 15518Sbill * The mode is shifted to select 15618Sbill * the owner/group/other fields. 15718Sbill * The super user is granted all 15818Sbill * permissions. 15918Sbill */ 16018Sbill access(ip, mode) 16118Sbill register struct inode *ip; 16218Sbill { 16318Sbill register m; 16418Sbill 16518Sbill m = mode; 16618Sbill if(m == IWRITE) { 16718Sbill if(getfs(ip->i_dev)->s_ronly != 0) { 16818Sbill u.u_error = EROFS; 16918Sbill return(1); 17018Sbill } 17118Sbill if (ip->i_flag&ITEXT) /* try to free text */ 17218Sbill xrele(ip); 17318Sbill if(ip->i_flag & ITEXT) { 17418Sbill u.u_error = ETXTBSY; 17518Sbill return(1); 17618Sbill } 17718Sbill } 17818Sbill if(u.u_uid == 0) 17918Sbill return(0); 18018Sbill if(u.u_uid != ip->i_uid) { 18118Sbill m >>= 3; 18218Sbill if(u.u_gid != ip->i_gid) 18318Sbill m >>= 3; 18418Sbill } 18518Sbill if((ip->i_mode&m) != 0) 18618Sbill return(0); 18718Sbill 18818Sbill u.u_error = EACCES; 18918Sbill return(1); 19018Sbill } 19118Sbill 19218Sbill /* 19318Sbill * Look up a pathname and test if 19418Sbill * the resultant inode is owned by the 19518Sbill * current user. 19618Sbill * If not, try for super-user. 19718Sbill * If permission is granted, 19818Sbill * return inode pointer. 19918Sbill */ 20018Sbill struct inode * 20118Sbill owner() 20218Sbill { 20318Sbill register struct inode *ip; 20418Sbill 20518Sbill ip = namei(uchar, 0); 20618Sbill if(ip == NULL) 20718Sbill return(NULL); 20818Sbill if(u.u_uid == ip->i_uid) 20918Sbill return(ip); 21018Sbill if(suser()) 21118Sbill return(ip); 21218Sbill iput(ip); 21318Sbill return(NULL); 21418Sbill } 21518Sbill 21618Sbill /* 21718Sbill * Test if the current user is the 21818Sbill * super user. 21918Sbill */ 22018Sbill suser() 22118Sbill { 22218Sbill 22318Sbill if(u.u_uid == 0) { 22418Sbill u.u_acflag |= ASU; 22518Sbill return(1); 22618Sbill } 22718Sbill u.u_error = EPERM; 22818Sbill return(0); 22918Sbill } 23018Sbill 23118Sbill /* 23218Sbill * Allocate a user file descriptor. 23318Sbill */ 23418Sbill ufalloc() 23518Sbill { 23618Sbill register i; 23718Sbill 23818Sbill for(i=0; i<NOFILE; i++) 23918Sbill if(u.u_ofile[i] == NULL) { 24018Sbill u.u_r.r_val1 = i; 24118Sbill u.u_pofile[i] = 0; 24218Sbill return(i); 24318Sbill } 24418Sbill u.u_error = EMFILE; 24518Sbill return(-1); 24618Sbill } 24718Sbill 2482768Swnj struct file *lastf; 24918Sbill /* 25018Sbill * Allocate a user file descriptor 25118Sbill * and a file structure. 25218Sbill * Initialize the descriptor 25318Sbill * to point at the file structure. 25418Sbill */ 25518Sbill struct file * 25618Sbill falloc() 25718Sbill { 25818Sbill register struct file *fp; 25918Sbill register i; 26018Sbill 26118Sbill i = ufalloc(); 2622768Swnj if (i < 0) 26318Sbill return(NULL); 2642768Swnj if (lastf == 0) 2652768Swnj lastf = file; 2662768Swnj for (fp = lastf; fp < fileNFILE; fp++) 2672768Swnj if (fp->f_count == 0) 268387Sbill goto slot; 2692768Swnj for (fp = file; fp < lastf; fp++) 2702768Swnj if (fp->f_count == 0) 271387Sbill goto slot; 272*2932Swnj tablefull("file"); 27318Sbill u.u_error = ENFILE; 2742768Swnj return (NULL); 275387Sbill slot: 276387Sbill u.u_ofile[i] = fp; 277387Sbill fp->f_count++; 278387Sbill fp->f_un.f_offset = 0; 279387Sbill lastf = fp + 1; 2802768Swnj return (fp); 28118Sbill } 282