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