1 /* vfs_vnops.c 4.8 81/03/09 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/filsys.h" 8 #include "../h/file.h" 9 #include "../h/conf.h" 10 #include "../h/inode.h" 11 #include "../h/reg.h" 12 #include "../h/acct.h" 13 #include "../h/mount.h" 14 15 /* 16 * Convert a user supplied 17 * file descriptor into a pointer 18 * to a file structure. 19 * Only task is to check range 20 * of the descriptor. 21 */ 22 struct file * 23 getf(f) 24 register int f; 25 { 26 register struct file *fp; 27 28 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 29 u.u_error = EBADF; 30 return (NULL); 31 } 32 return (fp); 33 } 34 35 /* 36 * Internal form of close. 37 * Decrement reference count on 38 * file structure. 39 * Also make sure the pipe protocol 40 * does not constipate. 41 * 42 * Decrement reference count on the inode following 43 * removal to the referencing file structure. 44 * Call device handler on last close. 45 */ 46 closef(fp) 47 register struct file *fp; 48 { 49 register struct inode *ip; 50 register struct mount *mp; 51 int flag, mode; 52 dev_t dev; 53 register int (*cfunc)(); 54 55 if(fp == NULL) 56 return; 57 if (fp->f_count > 1) { 58 fp->f_count--; 59 return; 60 } 61 ip = fp->f_inode; 62 flag = fp->f_flag; 63 dev = (dev_t)ip->i_un.i_rdev; 64 mode = ip->i_mode & IFMT; 65 66 plock(ip); 67 fp->f_count = 0; 68 if(flag & FPIPE) { 69 ip->i_mode &= ~(IREAD|IWRITE); 70 wakeup((caddr_t)ip+1); 71 wakeup((caddr_t)ip+2); 72 } 73 iput(ip); 74 75 switch(mode) { 76 77 case IFCHR: 78 case IFMPC: 79 cfunc = cdevsw[major(dev)].d_close; 80 break; 81 82 case IFBLK: 83 /* 84 * We don't want to really close the device if it is mounted 85 */ 86 for (mp = mount; mp < &mount[NMOUNT]; mp++) 87 if (mp->m_bufp != NULL && mp->m_dev == dev) 88 return; 89 case IFMPB: 90 cfunc = bdevsw[major(dev)].d_close; 91 break; 92 default: 93 return; 94 } 95 96 if ((flag & FMP) == 0) { 97 for(fp=file; fp < fileNFILE; fp++) 98 if (fp->f_count && (ip=fp->f_inode)->i_un.i_rdev==dev && 99 (ip->i_mode&IFMT) == mode) 100 return; 101 if (mode == IFBLK) { 102 /* 103 * on last close of a block device (that isn't mounted) 104 * we must invalidate any in core blocks 105 */ 106 bflush(dev); 107 binval(dev); 108 } 109 } 110 (*cfunc)(dev, flag, fp); 111 } 112 113 /* 114 * openi called to allow handler 115 * of special files to initialize and 116 * validate before actual IO. 117 */ 118 openi(ip, rw) 119 register struct inode *ip; 120 { 121 dev_t dev; 122 register unsigned int maj; 123 124 dev = (dev_t)ip->i_un.i_rdev; 125 maj = major(dev); 126 switch(ip->i_mode&IFMT) { 127 128 case IFCHR: 129 case IFMPC: 130 if(maj >= nchrdev) 131 goto bad; 132 (*cdevsw[maj].d_open)(dev, rw); 133 break; 134 135 case IFBLK: 136 case IFMPB: 137 if(maj >= nblkdev) 138 goto bad; 139 (*bdevsw[maj].d_open)(dev, rw); 140 } 141 return; 142 143 bad: 144 u.u_error = ENXIO; 145 } 146 147 /* 148 * Check mode permission on inode pointer. 149 * Mode is READ, WRITE or EXEC. 150 * In the case of WRITE, the 151 * read-only status of the file 152 * system is checked. 153 * Also in WRITE, prototype text 154 * segments cannot be written. 155 * The mode is shifted to select 156 * the owner/group/other fields. 157 * The super user is granted all 158 * permissions. 159 */ 160 access(ip, mode) 161 register struct inode *ip; 162 { 163 register m; 164 165 m = mode; 166 if(m == IWRITE) { 167 if(getfs(ip->i_dev)->s_ronly != 0) { 168 u.u_error = EROFS; 169 return(1); 170 } 171 if (ip->i_flag&ITEXT) /* try to free text */ 172 xrele(ip); 173 if(ip->i_flag & ITEXT) { 174 u.u_error = ETXTBSY; 175 return(1); 176 } 177 } 178 if(u.u_uid == 0) 179 return(0); 180 if(u.u_uid != ip->i_uid) { 181 m >>= 3; 182 if(u.u_gid != ip->i_gid) 183 m >>= 3; 184 } 185 if((ip->i_mode&m) != 0) 186 return(0); 187 188 u.u_error = EACCES; 189 return(1); 190 } 191 192 /* 193 * Look up a pathname and test if 194 * the resultant inode is owned by the 195 * current user. 196 * If not, try for super-user. 197 * If permission is granted, 198 * return inode pointer. 199 */ 200 struct inode * 201 owner() 202 { 203 register struct inode *ip; 204 205 ip = namei(uchar, 0); 206 if(ip == NULL) 207 return(NULL); 208 if(u.u_uid == ip->i_uid) 209 return(ip); 210 if(suser()) 211 return(ip); 212 iput(ip); 213 return(NULL); 214 } 215 216 /* 217 * Test if the current user is the 218 * super user. 219 */ 220 suser() 221 { 222 223 if(u.u_uid == 0) { 224 u.u_acflag |= ASU; 225 return(1); 226 } 227 u.u_error = EPERM; 228 return(0); 229 } 230 231 /* 232 * Allocate a user file descriptor. 233 */ 234 ufalloc() 235 { 236 register i; 237 238 for(i=0; i<NOFILE; i++) 239 if(u.u_ofile[i] == NULL) { 240 u.u_r.r_val1 = i; 241 u.u_pofile[i] = 0; 242 return(i); 243 } 244 u.u_error = EMFILE; 245 return(-1); 246 } 247 248 struct file *lastf; 249 /* 250 * Allocate a user file descriptor 251 * and a file structure. 252 * Initialize the descriptor 253 * to point at the file structure. 254 */ 255 struct file * 256 falloc() 257 { 258 register struct file *fp; 259 register i; 260 261 i = ufalloc(); 262 if (i < 0) 263 return(NULL); 264 if (lastf == 0) 265 lastf = file; 266 for (fp = lastf; fp < fileNFILE; fp++) 267 if (fp->f_count == 0) 268 goto slot; 269 for (fp = file; fp < lastf; fp++) 270 if (fp->f_count == 0) 271 goto slot; 272 tablefull("file"); 273 u.u_error = ENFILE; 274 return (NULL); 275 slot: 276 u.u_ofile[i] = fp; 277 fp->f_count++; 278 fp->f_un.f_offset = 0; 279 lastf = fp + 1; 280 return (fp); 281 } 282