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.1 (Berkeley) 06/05/86 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_pgrp; 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 209 if (fp->f_type == DTYPE_SOCKET) { 210 ((struct socket *)fp->f_data)->so_pgrp = value; 211 return (0); 212 } 213 if (value > 0) { 214 struct proc *p = pfind(value); 215 if (p == 0) 216 return (ESRCH); 217 value = p->p_pgrp; 218 } else 219 value = -value; 220 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 221 } 222 223 fioctl(fp, cmd, value) 224 struct file *fp; 225 int cmd; 226 caddr_t value; 227 { 228 229 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 230 } 231 232 close() 233 { 234 struct a { 235 int i; 236 } *uap = (struct a *)u.u_ap; 237 register int i = uap->i; 238 register struct file *fp; 239 register u_char *pf; 240 241 GETF(fp, i); 242 pf = (u_char *)&u.u_pofile[i]; 243 if (*pf & UF_MAPPED) 244 munmapfd(i); 245 u.u_ofile[i] = NULL; 246 while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 247 u.u_lastfile--; 248 *pf = 0; 249 closef(fp); 250 /* WHAT IF u.u_error ? */ 251 } 252 253 fstat() 254 { 255 register struct file *fp; 256 register struct a { 257 int fdes; 258 struct stat *sb; 259 } *uap; 260 struct stat ub; 261 262 uap = (struct a *)u.u_ap; 263 GETF(fp, uap->fdes); 264 switch (fp->f_type) { 265 266 case DTYPE_INODE: 267 u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 268 break; 269 270 case DTYPE_SOCKET: 271 u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 272 break; 273 274 default: 275 panic("fstat"); 276 /*NOTREACHED*/ 277 } 278 if (u.u_error == 0) 279 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 280 sizeof (ub)); 281 } 282 283 /* 284 * Allocate a user file descriptor. 285 */ 286 ufalloc(i) 287 register int i; 288 { 289 290 for (; i < NOFILE; i++) 291 if (u.u_ofile[i] == NULL) { 292 u.u_r.r_val1 = i; 293 u.u_pofile[i] = 0; 294 if (i > u.u_lastfile) 295 u.u_lastfile = i; 296 return (i); 297 } 298 u.u_error = EMFILE; 299 return (-1); 300 } 301 302 ufavail() 303 { 304 register int i, avail = 0; 305 306 for (i = 0; i < NOFILE; i++) 307 if (u.u_ofile[i] == NULL) 308 avail++; 309 return (avail); 310 } 311 312 struct file *lastf; 313 /* 314 * Allocate a user file descriptor 315 * and a file structure. 316 * Initialize the descriptor 317 * to point at the file structure. 318 */ 319 struct file * 320 falloc() 321 { 322 register struct file *fp; 323 register i; 324 325 i = ufalloc(0); 326 if (i < 0) 327 return (NULL); 328 if (lastf == 0) 329 lastf = file; 330 for (fp = lastf; fp < fileNFILE; fp++) 331 if (fp->f_count == 0) 332 goto slot; 333 for (fp = file; fp < lastf; fp++) 334 if (fp->f_count == 0) 335 goto slot; 336 tablefull("file"); 337 u.u_error = ENFILE; 338 return (NULL); 339 slot: 340 u.u_ofile[i] = fp; 341 fp->f_count = 1; 342 fp->f_data = 0; 343 fp->f_offset = 0; 344 lastf = fp + 1; 345 return (fp); 346 } 347 348 /* 349 * Convert a user supplied file descriptor into a pointer 350 * to a file structure. Only task is to check range of the descriptor. 351 * Critical paths should use the GETF macro. 352 */ 353 struct file * 354 getf(f) 355 register int f; 356 { 357 register struct file *fp; 358 359 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 360 u.u_error = EBADF; 361 return (NULL); 362 } 363 return (fp); 364 } 365 366 /* 367 * Internal form of close. 368 * Decrement reference count on file structure. 369 */ 370 closef(fp) 371 register struct file *fp; 372 { 373 374 if (fp == NULL) 375 return; 376 if (fp->f_count > 1) { 377 fp->f_count--; 378 return; 379 } 380 (*fp->f_ops->fo_close)(fp); 381 fp->f_count = 0; 382 } 383 384 /* 385 * Apply an advisory lock on a file descriptor. 386 */ 387 flock() 388 { 389 register struct a { 390 int fd; 391 int how; 392 } *uap = (struct a *)u.u_ap; 393 register struct file *fp; 394 395 GETF(fp, uap->fd); 396 if (fp->f_type != DTYPE_INODE) { 397 u.u_error = EOPNOTSUPP; 398 return; 399 } 400 if (uap->how & LOCK_UN) { 401 ino_unlock(fp, FSHLOCK|FEXLOCK); 402 return; 403 } 404 if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 405 return; /* error? */ 406 if (uap->how & LOCK_EX) 407 uap->how &= ~LOCK_SH; 408 /* avoid work... */ 409 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 410 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 411 return; 412 u.u_error = ino_lock(fp, uap->how); 413 } 414