1 /* vfs_syscalls.c 4.27 82/06/25 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/file.h" 8 #include "../h/stat.h" 9 #include "../h/inode.h" 10 #include "../h/fs.h" 11 #include "../h/buf.h" 12 #include "../h/proc.h" 13 #include "../h/inline.h" 14 15 chdir() 16 { 17 18 chdirec(&u.u_cdir); 19 } 20 21 chroot() 22 { 23 24 if (suser()) 25 chdirec(&u.u_rdir); 26 } 27 28 chdirec(ipp) 29 register struct inode **ipp; 30 { 31 register struct inode *ip; 32 struct a { 33 char *fname; 34 }; 35 36 ip = namei(uchar, 0, 1); 37 if(ip == NULL) 38 return; 39 if((ip->i_mode&IFMT) != IFDIR) { 40 u.u_error = ENOTDIR; 41 goto bad; 42 } 43 if(access(ip, IEXEC)) 44 goto bad; 45 iunlock(ip); 46 if (*ipp) 47 irele(*ipp); 48 *ipp = ip; 49 return; 50 51 bad: 52 iput(ip); 53 } 54 55 /* 56 * Open system call. 57 */ 58 open() 59 { 60 register struct inode *ip; 61 register struct a { 62 char *fname; 63 int rwmode; 64 } *uap; 65 66 uap = (struct a *)u.u_ap; 67 ip = namei(uchar, 0, 1); 68 if (ip == NULL) 69 return; 70 open1(ip, ++uap->rwmode, 0); 71 } 72 73 /* 74 * Creat system call. 75 */ 76 creat() 77 { 78 register struct inode *ip; 79 register struct a { 80 char *fname; 81 int fmode; 82 } *uap; 83 84 uap = (struct a *)u.u_ap; 85 ip = namei(uchar, 1, 1); 86 if (ip == NULL) { 87 if (u.u_error) 88 return; 89 ip = maknode(uap->fmode&07777&(~ISVTX)); 90 if (ip==NULL) 91 return; 92 open1(ip, FWRITE, 2); 93 } else 94 open1(ip, FWRITE, 1); 95 } 96 97 /* 98 * Common code for open and creat. 99 * Check permissions, allocate an open file structure, 100 * and call the device open routine if any. 101 */ 102 open1(ip, mode, trf) 103 register struct inode *ip; 104 register mode; 105 { 106 register struct file *fp; 107 int i; 108 109 if (trf != 2) { 110 if (mode&FREAD) 111 (void) access(ip, IREAD); 112 if (mode&FWRITE) { 113 (void) access(ip, IWRITE); 114 if ((ip->i_mode&IFMT) == IFDIR) 115 u.u_error = EISDIR; 116 } 117 } 118 if (u.u_error) { 119 iput(ip); 120 return; 121 } 122 if (trf == 1) 123 itrunc(ip); 124 iunlock(ip); 125 if ((fp = falloc()) == NULL) 126 goto out; 127 fp->f_flag = mode&(FREAD|FWRITE); 128 i = u.u_r.r_val1; 129 fp->f_inode = ip; 130 openi(ip, mode&(FREAD|FWRITE)); 131 if (u.u_error == 0) 132 return; 133 u.u_ofile[i] = NULL; 134 fp->f_count--; 135 out: 136 irele(ip); 137 } 138 139 /* 140 * Mknod system call 141 */ 142 mknod() 143 { 144 register struct inode *ip; 145 register struct a { 146 char *fname; 147 int fmode; 148 int dev; 149 } *uap; 150 151 uap = (struct a *)u.u_ap; 152 if (suser()) { 153 ip = namei(uchar, 1, 0); 154 if (ip != NULL) { 155 u.u_error = EEXIST; 156 goto out; 157 } 158 } 159 if (u.u_error) 160 return; 161 ip = maknode(uap->fmode); 162 if (ip == NULL) 163 return; 164 if (uap->dev) { 165 /* 166 * Want to be able to use this to make badblock 167 * inodes, so don't truncate the dev number. 168 */ 169 ip->i_rdev = uap->dev; 170 ip->i_flag |= IACC|IUPD|ICHG; 171 } 172 173 out: 174 iput(ip); 175 } 176 177 /* 178 * link system call 179 */ 180 link() 181 { 182 register struct inode *ip, *xp; 183 register struct a { 184 char *target; 185 char *linkname; 186 } *uap; 187 188 uap = (struct a *)u.u_ap; 189 ip = namei(uchar, 0, 1); /* well, this routine is doomed anyhow */ 190 if (ip == NULL) 191 return; 192 if ((ip->i_mode&IFMT)==IFDIR && !suser()) 193 goto out1; 194 ip->i_nlink++; 195 ip->i_flag |= ICHG; 196 iupdat(ip, &time, &time, 1); 197 iunlock(ip); 198 u.u_dirp = (caddr_t)uap->linkname; 199 xp = namei(uchar, 1, 0); 200 if (xp != NULL) { 201 u.u_error = EEXIST; 202 iput(xp); 203 goto out; 204 } 205 if (u.u_error) 206 goto out; 207 if (u.u_pdir->i_dev != ip->i_dev) { 208 iput(u.u_pdir); 209 u.u_error = EXDEV; 210 goto out; 211 } 212 wdir(ip); 213 out: 214 if (u.u_error) { 215 ip->i_nlink--; 216 ip->i_flag |= ICHG; 217 } 218 out1: 219 irele(ip); 220 } 221 222 /* 223 * symlink -- make a symbolic link 224 */ 225 symlink() 226 { 227 register struct a { 228 char *target; 229 char *linkname; 230 } *uap; 231 register struct inode *ip; 232 register char *tp; 233 register c, nc; 234 235 uap = (struct a *)u.u_ap; 236 tp = uap->target; 237 nc = 0; 238 while (c = fubyte(tp)) { 239 if (c < 0) { 240 u.u_error = EFAULT; 241 return; 242 } 243 tp++; 244 nc++; 245 } 246 u.u_dirp = uap->linkname; 247 ip = namei(uchar, 1, 0); 248 if (ip) { 249 iput(ip); 250 u.u_error = EEXIST; 251 return; 252 } 253 if (u.u_error) 254 return; 255 ip = maknode(IFLNK | 0777); 256 if (ip == NULL) 257 return; 258 u.u_base = uap->target; 259 u.u_count = nc; 260 u.u_offset = 0; 261 u.u_segflg = 0; 262 writei(ip); 263 iput(ip); 264 } 265 266 /* 267 * Unlink system call. 268 * Hard to avoid races here, especially 269 * in unlinking directories. 270 */ 271 unlink() 272 { 273 register struct inode *ip, *pp; 274 struct a { 275 char *fname; 276 }; 277 struct fs *fs; 278 struct buf *bp; 279 int lbn, bn, base; 280 int unlinkingdot = 0; 281 282 pp = namei(uchar, 2, 0); 283 if(pp == NULL) 284 return; 285 /* 286 * Check for unlink(".") 287 * to avoid hanging on the iget 288 */ 289 if (pp->i_number == u.u_dent.d_ino) { 290 ip = pp; 291 ip->i_count++; 292 unlinkingdot++; 293 } else 294 ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino); 295 if(ip == NULL) 296 goto out1; 297 if((ip->i_mode&IFMT)==IFDIR && !suser()) 298 goto out; 299 /* 300 * Don't unlink a mounted file. 301 */ 302 if (ip->i_dev != pp->i_dev) { 303 u.u_error = EBUSY; 304 goto out; 305 } 306 if (ip->i_flag&ITEXT) 307 xrele(ip); /* try once to free text */ 308 /* 309 if ((ip->i_flag&ITEXT) && ip->i_nlink==1) { 310 u.u_error = ETXTBSY; 311 goto out; 312 } 313 */ 314 if (u.u_count == 0) { 315 /* 316 * first entry in block, so set d_ino to zero. 317 */ 318 u.u_base = (caddr_t)&u.u_dent; 319 u.u_count = DIRSIZ(&u.u_dent); 320 u.u_dent.d_ino = 0; 321 writei(pp); 322 } else { 323 /* 324 * updating preceeding entry to skip over current entry. 325 */ 326 fs = pp->i_fs; 327 lbn = lblkno(fs, u.u_offset); 328 base = blkoff(fs, u.u_offset); 329 bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count)); 330 bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn)); 331 if (bp->b_flags & B_ERROR) { 332 brelse(bp); 333 goto out; 334 } 335 ((struct direct *)(bp->b_un.b_addr + base))->d_reclen += 336 u.u_dent.d_reclen; 337 bwrite(bp); 338 pp->i_flag |= IUPD|ICHG; 339 } 340 ip->i_nlink--; 341 ip->i_flag |= ICHG; 342 343 out: 344 if (unlinkingdot) 345 irele(ip); 346 else 347 iput(ip); 348 out1: 349 iput(pp); 350 } 351 352 /* 353 * Seek system call 354 */ 355 seek() 356 { 357 register struct file *fp; 358 register struct a { 359 int fdes; 360 off_t off; 361 int sbase; 362 } *uap; 363 364 uap = (struct a *)u.u_ap; 365 fp = getf(uap->fdes); 366 if (fp == NULL) 367 return; 368 if (fp->f_flag&FSOCKET) { 369 u.u_error = ESPIPE; 370 return; 371 } 372 if (uap->sbase == 1) 373 uap->off += fp->f_offset; 374 else if (uap->sbase == 2) 375 uap->off += fp->f_inode->i_size; 376 fp->f_offset = uap->off; 377 u.u_r.r_off = uap->off; 378 } 379 380 /* 381 * Access system call 382 */ 383 saccess() 384 { 385 register svuid, svgid; 386 register struct inode *ip; 387 register struct a { 388 char *fname; 389 int fmode; 390 } *uap; 391 392 uap = (struct a *)u.u_ap; 393 svuid = u.u_uid; 394 svgid = u.u_gid; 395 u.u_uid = u.u_ruid; 396 u.u_gid = u.u_rgid; 397 ip = namei(uchar, 0, 1); 398 if (ip != NULL) { 399 if (uap->fmode&(IREAD>>6)) 400 (void) access(ip, IREAD); 401 if (uap->fmode&(IWRITE>>6)) 402 (void) access(ip, IWRITE); 403 if (uap->fmode&(IEXEC>>6)) 404 (void) access(ip, IEXEC); 405 iput(ip); 406 } 407 u.u_uid = svuid; 408 u.u_gid = svgid; 409 } 410 411 /* 412 * the fstat system call. 413 */ 414 fstat() 415 { 416 register struct file *fp; 417 register struct a { 418 int fdes; 419 struct stat *sb; 420 } *uap; 421 422 uap = (struct a *)u.u_ap; 423 fp = getf(uap->fdes); 424 if (fp == NULL) 425 return; 426 if (fp->f_flag & FSOCKET) 427 u.u_error = sostat(fp->f_socket, uap->sb); 428 else 429 stat1(fp->f_inode, uap->sb); 430 } 431 432 /* 433 * Stat system call. This version follows links. 434 */ 435 stat() 436 { 437 register struct inode *ip; 438 register struct a { 439 char *fname; 440 struct stat *sb; 441 } *uap; 442 443 uap = (struct a *)u.u_ap; 444 ip = namei(uchar, 0, 1); 445 if (ip == NULL) 446 return; 447 stat1(ip, uap->sb); 448 iput(ip); 449 } 450 451 /* 452 * Lstat system call. This version does not follow links. 453 */ 454 lstat() 455 { 456 register struct inode *ip; 457 register struct a { 458 char *fname; 459 struct stat *sb; 460 } *uap; 461 462 uap = (struct a *)u.u_ap; 463 ip = namei(uchar, 0, 0); 464 if (ip == NULL) 465 return; 466 stat1(ip, uap->sb); 467 iput(ip); 468 } 469 470 /* 471 * The basic routine for fstat and stat: 472 * get the inode and pass appropriate parts back. 473 */ 474 stat1(ip, ub) 475 register struct inode *ip; 476 struct stat *ub; 477 { 478 struct stat ds; 479 480 IUPDAT(ip, &time, &time, 0); 481 /* 482 * Copy from inode table 483 */ 484 ds.st_dev = ip->i_dev; 485 ds.st_ino = ip->i_number; 486 ds.st_mode = ip->i_mode; 487 ds.st_nlink = ip->i_nlink; 488 ds.st_uid = ip->i_uid; 489 ds.st_gid = ip->i_gid; 490 ds.st_rdev = (dev_t)ip->i_rdev; 491 ds.st_size = ip->i_size; 492 ds.st_atime = ip->i_atime; 493 ds.st_mtime = ip->i_mtime; 494 ds.st_ctime = ip->i_ctime; 495 ds.st_blksize = ip->i_fs->fs_bsize; 496 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 497 u.u_error = EFAULT; 498 } 499 500 /* 501 * Return target name of a symbolic link 502 */ 503 readlink() 504 { 505 register struct inode *ip; 506 register struct a { 507 char *name; 508 char *buf; 509 int count; 510 } *uap; 511 512 ip = namei(uchar, 0, 0); 513 if (ip == NULL) 514 return; 515 if ((ip->i_mode&IFMT) != IFLNK) { 516 u.u_error = ENXIO; 517 goto out; 518 } 519 uap = (struct a *)u.u_ap; 520 u.u_offset = 0; 521 u.u_base = uap->buf; 522 u.u_count = uap->count; 523 u.u_segflg = 0; 524 readi(ip); 525 out: 526 iput(ip); 527 u.u_r.r_val1 = uap->count - u.u_count; 528 } 529 530 chmod() 531 { 532 register struct inode *ip; 533 register struct a { 534 char *fname; 535 int fmode; 536 } *uap; 537 538 uap = (struct a *)u.u_ap; 539 if ((ip = owner(1)) == NULL) 540 return; 541 ip->i_mode &= ~07777; 542 if (u.u_uid) 543 uap->fmode &= ~ISVTX; 544 ip->i_mode |= uap->fmode&07777; 545 ip->i_flag |= ICHG; 546 if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0) 547 xrele(ip); 548 iput(ip); 549 } 550 551 chown() 552 { 553 register struct inode *ip; 554 register struct a { 555 char *fname; 556 int uid; 557 int gid; 558 } *uap; 559 560 uap = (struct a *)u.u_ap; 561 if (!suser() || (ip = owner(0)) == NULL) 562 return; 563 ip->i_uid = uap->uid; 564 ip->i_gid = uap->gid; 565 ip->i_flag |= ICHG; 566 if (u.u_ruid != 0) 567 ip->i_mode &= ~(ISUID|ISGID); 568 iput(ip); 569 } 570 571 /* 572 * Set IUPD and IACC times on file. 573 * Can't set ICHG. 574 */ 575 utime() 576 { 577 register struct a { 578 char *fname; 579 time_t *tptr; 580 } *uap; 581 register struct inode *ip; 582 time_t tv[2]; 583 584 uap = (struct a *)u.u_ap; 585 if ((ip = owner(1)) == NULL) 586 return; 587 if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) { 588 u.u_error = EFAULT; 589 } else { 590 ip->i_flag |= IACC|IUPD|ICHG; 591 iupdat(ip, &tv[0], &tv[1], 0); 592 } 593 iput(ip); 594 } 595 596 sync() 597 { 598 599 update(0); 600 } 601