1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)kern_descrip.c 7.2 (Berkeley) 10/18/88 7 */ 8 9 #include "param.h" 10 #include "systm.h" 11 #include "dir.h" 12 #include "user.h" 13 #include "kernel.h" 14 #include "inode.h" 15 #include "proc.h" 16 #include "file.h" 17 #include "socket.h" 18 #include "socketvar.h" 19 #include "mount.h" 20 #include "stat.h" 21 22 #include "ioctl.h" 23 24 /* 25 * Descriptor management. 26 */ 27 28 /* 29 * TODO: 30 * eliminate u.u_error side effects 31 */ 32 33 /* 34 * System calls on descriptors. 35 */ 36 getdtablesize() 37 { 38 39 u.u_r.r_val1 = NOFILE; 40 } 41 42 getdopt() 43 { 44 45 } 46 47 setdopt() 48 { 49 50 } 51 52 dup() 53 { 54 register struct a { 55 int i; 56 } *uap = (struct a *) u.u_ap; 57 struct file *fp; 58 int j; 59 60 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 61 62 GETF(fp, uap->i); 63 j = ufalloc(0); 64 if (j < 0) 65 return; 66 dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 67 } 68 69 dup2() 70 { 71 register struct a { 72 int i, j; 73 } *uap = (struct a *) u.u_ap; 74 register struct file *fp; 75 76 GETF(fp, uap->i); 77 if (uap->j < 0 || uap->j >= NOFILE) { 78 u.u_error = EBADF; 79 return; 80 } 81 u.u_r.r_val1 = uap->j; 82 if (uap->i == uap->j) 83 return; 84 if (u.u_ofile[uap->j]) { 85 if (u.u_pofile[uap->j] & UF_MAPPED) 86 munmapfd(uap->j); 87 closef(u.u_ofile[uap->j]); 88 if (u.u_error) 89 return; 90 } 91 dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 92 } 93 94 dupit(fd, fp, flags) 95 int fd; 96 register struct file *fp; 97 register int flags; 98 { 99 100 u.u_ofile[fd] = fp; 101 u.u_pofile[fd] = flags; 102 fp->f_count++; 103 if (fd > u.u_lastfile) 104 u.u_lastfile = fd; 105 } 106 107 /* 108 * The file control system call. 109 */ 110 fcntl() 111 { 112 register struct file *fp; 113 register struct a { 114 int fdes; 115 int cmd; 116 int arg; 117 } *uap; 118 register i; 119 register char *pop; 120 121 uap = (struct a *)u.u_ap; 122 GETF(fp, uap->fdes); 123 pop = &u.u_pofile[uap->fdes]; 124 switch(uap->cmd) { 125 case F_DUPFD: 126 i = uap->arg; 127 if (i < 0 || i >= NOFILE) { 128 u.u_error = EINVAL; 129 return; 130 } 131 if ((i = ufalloc(i)) < 0) 132 return; 133 dupit(i, fp, *pop &~ UF_EXCLOSE); 134 break; 135 136 case F_GETFD: 137 u.u_r.r_val1 = *pop & 1; 138 break; 139 140 case F_SETFD: 141 *pop = (*pop &~ 1) | (uap->arg & 1); 142 break; 143 144 case F_GETFL: 145 u.u_r.r_val1 = fp->f_flag+FOPEN; 146 break; 147 148 case F_SETFL: 149 fp->f_flag &= FCNTLCANT; 150 fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 151 u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); 152 if (u.u_error) 153 break; 154 u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 155 if (u.u_error) 156 (void) fset(fp, FNDELAY, 0); 157 break; 158 159 case F_GETOWN: 160 u.u_error = fgetown(fp, &u.u_r.r_val1); 161 break; 162 163 case F_SETOWN: 164 u.u_error = fsetown(fp, uap->arg); 165 break; 166 167 default: 168 u.u_error = EINVAL; 169 } 170 } 171 172 fset(fp, bit, value) 173 struct file *fp; 174 int bit, value; 175 { 176 177 if (value) 178 fp->f_flag |= bit; 179 else 180 fp->f_flag &= ~bit; 181 return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 182 (caddr_t)&value)); 183 } 184 185 fgetown(fp, valuep) 186 struct file *fp; 187 int *valuep; 188 { 189 int error; 190 191 switch (fp->f_type) { 192 193 case DTYPE_SOCKET: 194 *valuep = ((struct socket *)fp->f_data)->so_pgid; 195 return (0); 196 197 default: 198 error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 199 *valuep = -*valuep; 200 return (error); 201 } 202 } 203 204 fsetown(fp, value) 205 struct file *fp; 206 int value; 207 { 208 if (fp->f_type == DTYPE_SOCKET) { 209 ((struct socket *)fp->f_data)->so_pgid = value; 210 return (0); 211 } 212 if (value > 0) { 213 struct proc *p = pfind(value); 214 if (p == 0) 215 return (ESRCH); 216 value = p->p_pgrp->pg_id; 217 } else 218 value = -value; 219 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 220 } 221 222 fioctl(fp, cmd, value) 223 struct file *fp; 224 int cmd; 225 caddr_t value; 226 { 227 228 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 229 } 230 231 close() 232 { 233 struct a { 234 int i; 235 } *uap = (struct a *)u.u_ap; 236 register int i = uap->i; 237 register struct file *fp; 238 register u_char *pf; 239 240 GETF(fp, i); 241 pf = (u_char *)&u.u_pofile[i]; 242 if (*pf & UF_MAPPED) 243 munmapfd(i); 244 u.u_ofile[i] = NULL; 245 while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 246 u.u_lastfile--; 247 *pf = 0; 248 closef(fp); 249 /* WHAT IF u.u_error ? */ 250 } 251 252 fstat() 253 { 254 register struct file *fp; 255 register struct a { 256 int fdes; 257 struct stat *sb; 258 } *uap; 259 struct stat ub; 260 261 uap = (struct a *)u.u_ap; 262 GETF(fp, uap->fdes); 263 switch (fp->f_type) { 264 265 case DTYPE_INODE: 266 u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 267 break; 268 269 case DTYPE_SOCKET: 270 u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 271 break; 272 273 default: 274 panic("fstat"); 275 /*NOTREACHED*/ 276 } 277 if (u.u_error == 0) 278 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 279 sizeof (ub)); 280 } 281 282 /* 283 * Allocate a user file descriptor. 284 */ 285 ufalloc(i) 286 register int i; 287 { 288 289 for (; i < NOFILE; i++) 290 if (u.u_ofile[i] == NULL) { 291 u.u_r.r_val1 = i; 292 u.u_pofile[i] = 0; 293 if (i > u.u_lastfile) 294 u.u_lastfile = i; 295 return (i); 296 } 297 u.u_error = EMFILE; 298 return (-1); 299 } 300 301 ufavail() 302 { 303 register int i, avail = 0; 304 305 for (i = 0; i < NOFILE; i++) 306 if (u.u_ofile[i] == NULL) 307 avail++; 308 return (avail); 309 } 310 311 struct file *lastf; 312 /* 313 * Allocate a user file descriptor 314 * and a file structure. 315 * Initialize the descriptor 316 * to point at the file structure. 317 */ 318 struct file * 319 falloc() 320 { 321 register struct file *fp; 322 register i; 323 324 i = ufalloc(0); 325 if (i < 0) 326 return (NULL); 327 if (lastf == 0) 328 lastf = file; 329 for (fp = lastf; fp < fileNFILE; fp++) 330 if (fp->f_count == 0) 331 goto slot; 332 for (fp = file; fp < lastf; fp++) 333 if (fp->f_count == 0) 334 goto slot; 335 tablefull("file"); 336 u.u_error = ENFILE; 337 return (NULL); 338 slot: 339 u.u_ofile[i] = fp; 340 fp->f_count = 1; 341 fp->f_data = 0; 342 fp->f_offset = 0; 343 lastf = fp + 1; 344 return (fp); 345 } 346 347 /* 348 * Convert a user supplied file descriptor into a pointer 349 * to a file structure. Only task is to check range of the descriptor. 350 * Critical paths should use the GETF macro. 351 */ 352 struct file * 353 getf(f) 354 register int f; 355 { 356 register struct file *fp; 357 358 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 359 u.u_error = EBADF; 360 return (NULL); 361 } 362 return (fp); 363 } 364 365 /* 366 * Internal form of close. 367 * Decrement reference count on file structure. 368 */ 369 closef(fp) 370 register struct file *fp; 371 { 372 373 if (fp == NULL) 374 return; 375 if (fp->f_count > 1) { 376 fp->f_count--; 377 return; 378 } 379 (*fp->f_ops->fo_close)(fp); 380 fp->f_count = 0; 381 } 382 383 /* 384 * Apply an advisory lock on a file descriptor. 385 */ 386 flock() 387 { 388 register struct a { 389 int fd; 390 int how; 391 } *uap = (struct a *)u.u_ap; 392 register struct file *fp; 393 394 GETF(fp, uap->fd); 395 if (fp->f_type != DTYPE_INODE) { 396 u.u_error = EOPNOTSUPP; 397 return; 398 } 399 if (uap->how & LOCK_UN) { 400 ino_unlock(fp, FSHLOCK|FEXLOCK); 401 return; 402 } 403 if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 404 return; /* error? */ 405 if (uap->how & LOCK_EX) 406 uap->how &= ~LOCK_SH; 407 /* avoid work... */ 408 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 409 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 410 return; 411 u.u_error = ino_lock(fp, uap->how); 412 } 413