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