|
|
1.1 ! root 1: /* ! 2: * system calls introduced by the 386 port ! 3: * ! 4: * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991 ! 5: */ ! 6: #include <sys/coherent.h> ! 7: #include <sys/buf.h> ! 8: #include <errno.h> ! 9: #include <canon.h> ! 10: #include <sys/con.h> ! 11: #include <fcntl.h> ! 12: #include <sys/fd.h> ! 13: #include <sys/filsys.h> ! 14: #include <sys/ino.h> ! 15: #include <sys/inode.h> ! 16: #include <sys/io.h> ! 17: #include <sys/mount.h> ! 18: #include <sys/stat.h> ! 19: #include <sys/dir.h> ! 20: #include <sys/dirent.h> ! 21: #include <sys/utsname.h> ! 22: #include <sys/mount.h> ! 23: #include <ustat.h> ! 24: #include <sys/statfs.h> ! 25: ! 26: utime(tp) ! 27: long *tp; ! 28: { ! 29: return timer.t_time; ! 30: } ! 31: ! 32: /* ! 33: * Return an unique number. ! 34: */ ! 35: usysi86(f, arg1, arg2, arg3) ! 36: { ! 37: register MOUNT *mp; ! 38: register struct filsys *fsp; ! 39: ! 40: switch (f) { ! 41: case SYI86UNEEK: ! 42: if ((mp=getment(rootdev, 1)) == NULL) ! 43: return; ! 44: fsp = &mp->m_super; ! 45: fsp->s_fmod = 1; ! 46: return (++fsp->s_unique); ! 47: case 40: ! 48: /* ! 49: * bit 2: floating point is present (80287/80387) ! 50: * bit 1: 80387 is present ! 51: */ ! 52: if (!useracc(arg1, sizeof(int))) { ! 53: SET_U_ERROR(EFAULT, "sysi386:40"); ! 54: return; ! 55: } ! 56: putuwd(arg1, 0); ! 57: break; ! 58: } ! 59: } ! 60: ! 61: ushmsys(func, arg1, arg2, arg3) ! 62: int func, arg1, arg2, arg3; ! 63: { ! 64: switch(func){ ! 65: ! 66: #if 0 ! 67: case 0: return ushmat(arg1, arg2, arg3); ! 68: case 1: return ushmdt(arg1); ! 69: #endif ! 70: case 2: return ushmctl(arg1, arg2, arg3); ! 71: case 3: return ushmget(arg1, arg2, arg3); ! 72: default: u.u_error = EINVAL; ! 73: } ! 74: } ! 75: ! 76: usemsys(func, arg1, arg2, arg3, arg4) ! 77: int func, arg1, arg2, arg3, arg4; ! 78: { ! 79: switch(func){ ! 80: case 0: return usemctl(arg1, arg2, arg3, arg4); ! 81: case 1: return usemget(arg1, arg2, arg3); ! 82: case 2: return usemop(arg1, arg2, arg3); ! 83: default: u.u_error = EINVAL; ! 84: } ! 85: } ! 86: ! 87: /* ! 88: * uname and ustat system calls. ! 89: * ! 90: * int uname(struct utsname *name) ! 91: * Before lcall instruction 4(%esp) contains name, 8(%esp) contains ! 92: * an unspecified value, and 12(%esp) contains the value 0. ! 93: * ! 94: * int ustat(int dev, struct ustat *buf) ! 95: * Before lcall instruction 4(%esp) contains buf (REVERSE order of argument) ! 96: * 8(%esp) contains dev, and 12(%esp) contains the value 0. ! 97: */ ! 98: ! 99: uutssys(arg1, arg2, func) ! 100: { ! 101: switch(func) { ! 102: case 0: return uname(arg1); ! 103: case 2: return u_ustat(arg2, arg1); ! 104: default:u.u_error = EINVAL; ! 105: } ! 106: } ! 107: ! 108: /* ! 109: * uname - get name of the current operating system. ! 110: */ ! 111: extern char version[]; /* Defined in main.c */ ! 112: extern char release[]; /* Defined in main.c */ ! 113: ! 114: uname(name) ! 115: struct utsname *name; ! 116: { ! 117: register char *rcp; /**/ ! 118: register int i; /* Counter, loop index */ ! 119: register INODE *ip; /* /etc/uucpname inode */ ! 120: BUF *bp; /* Read buffer */ ! 121: char namebuf[SYS_NMLN]; /* System name */ ! 122: int fl; /* File length*/ ! 123: ! 124: /* Check if *name is an available user area */ ! 125: if (!useracc((char *) name, sizeof(struct utsname))) { ! 126: u.u_error = EFAULT; ! 127: return(0); ! 128: } ! 129: /* Find the size of the version number */ ! 130: for (rcp = version, i = 0; *rcp != '\0' && i < SYS_NMLN; i++, rcp++) ! 131: ; ! 132: /* Write version number to user area */ ! 133: if (!kucopy(version, name->version, i)) ! 134: return(0); ! 135: /* Find the size of the release number */ ! 136: for (rcp = release, i = 0; *rcp != '\0' && i < SYS_NMLN; i++, rcp++) ! 137: ; ! 138: /* Write release number to user area */ ! 139: if (!kucopy(release, name->release, i)) ! 140: return; ! 141: /* Write "machine" to user area */ ! 142: if (!kucopy("i386", name->machine, 4)) ! 143: return; ! 144: /* We supposed that system name and nodename are in /etc/uucpname */ ! 145: if (ftoi("/etc/uucpname", 'r') != 0) ! 146: return(sys_unknown(name)); ! 147: ip = u.u_cdiri; ! 148: if ((fl = ip->i_size) == 0) { ! 149: idetach(ip); ! 150: return(sys_unknown(name)); ! 151: } ! 152: if (iaccess(ip, IPR) == 0) { ! 153: idetach(ip); ! 154: return; ! 155: } ! 156: if ((bp = vread(ip, (daddr_t) 0)) == NULL) { ! 157: brelease(bp); ! 158: idetach(ip); ! 159: return; ! 160: } ! 161: /* namebuf should be not more than SYS_NMLN - 1 characters long */ ! 162: fl = (fl > SYS_NMLN) ? SYS_NMLN : fl; ! 163: kkcopy(bp->b_vaddr, namebuf, fl); ! 164: brelease(bp); ! 165: idetach(ip); ! 166: ! 167: if (fl == 1 && namebuf[0] == '\n') ! 168: return(sys_unknown(name)); ! 169: for (rcp = namebuf, i = 0; i < fl; rcp++) { ! 170: i++; ! 171: if (*rcp == '\n') { ! 172: *rcp = '\0'; ! 173: break; ! 174: } ! 175: } ! 176: namebuf[i - 1] = '\0'; ! 177: /* Write system name to user area */ ! 178: if (!kucopy(namebuf, name->sysname, i)) ! 179: return(0); ! 180: ! 181: /* Write system name to user area */ ! 182: if (!kucopy(namebuf, name->nodename, i)) ! 183: return(0); ! 184: return 0; ! 185: } ! 186: ! 187: /* ! 188: * sys_unknown - write name unknown to utsname struct ! 189: */ ! 190: char unknown[] = "UNKNOWN"; ! 191: sys_unknown(name) ! 192: struct utsname *name; ! 193: { ! 194: if (!kucopy(unknown, name->sysname, sizeof(unknown))) ! 195: return; ! 196: if (!kucopy(unknown, name->nodename, sizeof(unknown))) ! 197: return; ! 198: } ! 199: ! 200: /* ! 201: * u_ustat - get file system statistics. (Name ustat in use for stat s.c.) ! 202: */ ! 203: u_ustat(dev, buf) ! 204: dev_t dev; ! 205: struct ustat *buf; ! 206: { ! 207: register MOUNT *mp; ! 208: ! 209: /* Check if buf is an available user area. */ ! 210: /* B_READ | B_WRITE is not implemented yet. */ ! 211: if (!useracc((char *) buf, sizeof(struct ustat))) { ! 212: u.u_error = EFAULT; ! 213: return; ! 214: } ! 215: ! 216: /* Take mount filesystem, check if dev is mounted device */ ! 217: for (mp = mountp; mp != NULL; mp = mp->m_next) ! 218: if (mp->m_dev == dev) ! 219: break; ! 220: if (mp == NULL) { ! 221: u.u_error = EINVAL; ! 222: return; ! 223: } ! 224: ! 225: /* Pickup information from superblock */ ! 226: /* Number of free blocks */ ! 227: if (!kucopy(&(mp->m_super.s_tfree), &(buf->f_tfree), ! 228: sizeof(mp->m_super.s_tfree))) ! 229: return; ! 230: /* Number of free inodes */ ! 231: if (!kucopy(&(mp->m_super.s_tinode), &(buf->f_tinode), ! 232: sizeof(mp->m_super.s_tinode))) ! 233: return; ! 234: /* File system name */ ! 235: if (!kucopy(mp->m_super.s_fname, buf->f_fname, ! 236: sizeof(mp->m_super.s_fname))) ! 237: return; ! 238: /* File system pack name */ ! 239: if (!kucopy(mp->m_super.s_fpack, buf->f_fpack, ! 240: sizeof(mp->m_super.s_fpack))) ! 241: return; ! 242: } ! 243: ! 244: umsgsys(func, arg1, arg2, arg3, arg4, arg5) ! 245: { ! 246: switch (func) { ! 247: case 0: return umsgget(arg1, arg2); ! 248: case 1: return umsgctl(arg1, arg2, arg3); ! 249: case 2: return umsgrcv(arg1, arg2, arg3, arg4, arg5); ! 250: case 3: return umsgsnd(arg1, arg2, arg3, arg4); ! 251: default:u.u_error = EINVAL; ! 252: } ! 253: } ! 254: ! 255: uulimit() ! 256: { ! 257: u.u_error = EINVAL; ! 258: } ! 259: ! 260: /* ! 261: * Remove a directory. ! 262: */ ! 263: urmdir(path) ! 264: char *path; ! 265: { ! 266: register INODE *ip; ! 267: int isdirempty(); ! 268: ! 269: if (ftoi(path, 'r') != 0) ! 270: return; ! 271: ip = u.u_cdiri; ! 272: ! 273: /* Check if path is a directory */ ! 274: if ((ip->i_mode & IFMT) != IFDIR) { ! 275: idetach(ip); ! 276: SET_U_ERROR(ENOTDIR, "rmdir: no such file or directory"); ! 277: return; ! 278: } ! 279: /* We have to check if directory is empty */ ! 280: if (!isdirempty(ip)) { ! 281: idetach(ip); ! 282: SET_U_ERROR(EEXIST, "rmdir: directory is not empty"); ! 283: return; ! 284: } ! 285: idetach(ip); ! 286: removedir(path); ! 287: return (u.u_error); ! 288: } ! 289: ! 290: /* ! 291: * remove a directory entry. ! 292: * path is a pointer to user area. ! 293: */ ! 294: removedir(path) ! 295: char *path; ! 296: { ! 297: char buf[512]; ! 298: char *cpbuf, /* to internal file_name buffer */ ! 299: *cppath; /* to user file_name buffer */ ! 300: ! 301: /* Write path to a kernel buffer buf */ ! 302: cpbuf = buf; ! 303: cppath = path; ! 304: ! 305: while ((*cpbuf = getubd(cppath)) != '\0') { ! 306: cppath++; ! 307: if (++cpbuf >= &buf[sizeof(buf) - 3]) { ! 308: SET_U_ERROR(ENOENT, "rmdir: path too long"); ! 309: return; ! 310: } ! 311: } ! 312: *cpbuf++ = '/'; ! 313: *cpbuf++ = '.'; ! 314: *cpbuf = '\0'; ! 315: u.u_io.io_seg = IOSYS; ! 316: dunlink(buf); ! 317: *cpbuf++ = '.'; ! 318: *cpbuf = '\0'; ! 319: dunlink(buf); ! 320: u.u_io.io_seg = IOUSR; ! 321: dunlink(path); ! 322: return; ! 323: } ! 324: ! 325: /* ! 326: * Unlink the given directory. ! 327: */ ! 328: dunlink(np) ! 329: char *np; ! 330: { ! 331: register INODE *ip; ! 332: register dev_t dev; ! 333: ! 334: if (ftoi(np, 'u') != 0) ! 335: return; ! 336: ! 337: ip = u.u_pdiri; ! 338: if (iaccess(ip, IPW) == 0) { ! 339: u.u_error = EACCES; ! 340: goto err; ! 341: } ! 342: ! 343: dev = ip->i_dev; ! 344: if (diucheck(dev, u.u_cdirn) == 0) ! 345: goto err; ! 346: idirent(0); ! 347: idetach(ip); ! 348: ! 349: if ((ip=iattach(dev, u.u_cdirn)) == NULL) ! 350: return; ! 351: ! 352: if (ip->i_nlink > 0) ! 353: --ip->i_nlink; ! 354: icrt(ip); /* unlink - ctime */ ! 355: ! 356: err: ! 357: idetach(ip); ! 358: return (0); ! 359: } ! 360: ! 361: /* ! 362: * This is a copy of iucheck. The only one difference is that that allows ! 363: * to remove a directory to a regular user. ! 364: */ ! 365: diucheck(dev, ino) ! 366: register dev_t dev; ! 367: register ino_t ino; ! 368: { ! 369: register INODE *ip; ! 370: INODE inode; ! 371: ! 372: for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) { ! 373: if (ip->i_ino==ino && ip->i_dev==dev) ! 374: break; ! 375: } ! 376: if (ip < inodep) { ! 377: ip = &inode; ! 378: ip->i_dev = dev; ! 379: ip->i_ino = ino; ! 380: if (icopydm(ip) == 0) ! 381: return (0); ! 382: } ! 383: return (1); ! 384: } ! 385: ! 386: /* ! 387: * Check if directory is empty. ! 388: */ ! 389: int isdirempty(ip) ! 390: register INODE *ip; ! 391: { ! 392: register char *cp; ! 393: int count; ! 394: BUF *bp; ! 395: ! 396: for (count = 0; count < ip->i_size; count += 512) { ! 397: if ((bp = vread(ip, count)) == NULL) ! 398: break; ! 399: for (cp = (char *) bp->b_vaddr; ! 400: cp < (char *) bp->b_vaddr + BSIZE; cp += 16) { ! 401: if (*cp == '\0' && *(cp + 1) == '\0') ! 402: continue; ! 403: if (*(cp + 2) != '.') ! 404: goto bad; ! 405: if (*(cp + 3) == '\0') ! 406: continue; ! 407: if (*(cp + 3) != '.' || *(cp + 4) != '\0') ! 408: goto bad; ! 409: } ! 410: brelease(bp); ! 411: } ! 412: return 1; ! 413: bad: ! 414: brelease(bp); ! 415: return 0; ! 416: } ! 417: ! 418: /* ! 419: * SysV compatible mkdir() system call. ! 420: * ! 421: * Create a directory of the given "path" and "mode", if possible. ! 422: * Creating the directory is straight forward. Trying to clean ! 423: * up in case we run out of inodes or freee blocks in the process ! 424: * is not trivial. ! 425: * This system call was implemented in very press time. ! 426: * Vlad 6-04-92 ! 427: */ ! 428: umkdir(path, mode) ! 429: char *path; ! 430: int mode; ! 431: { ! 432: INODE *dmknod(); /* make directory node */ ! 433: register INODE *pip; /* parent inode pointer */ ! 434: register char *cp_path, ! 435: *cpb_path, ! 436: *cp_dot, ! 437: *cp_dotdot, ! 438: *cp_parent; ! 439: char bufpath[512], ! 440: bufdot[512], ! 441: bufdotdot[512], ! 442: bufparent[512]; ! 443: int uid; ! 444: int error; ! 445: /* ! 446: * Create a local copies of "path" which we can use to build up ! 447: * the required directory links: ! 448: * path/. -- bufdot ! 449: * path/..-- bufdotdot ! 450: * Verify that the given path is not too long. ! 451: */ ! 452: cp_path = path; ! 453: cpb_path = bufpath; ! 454: cp_dot = bufdot; ! 455: cp_dotdot = bufdotdot; ! 456: cp_parent = bufparent; ! 457: ! 458: while ((*cpb_path = getubd(cp_path)) != '\0') { ! 459: *cp_dot++ = *cp_dotdot++ = *cp_parent++ = *cpb_path; ! 460: ++cp_path; ! 461: if (++cpb_path >= &bufpath[sizeof(bufpath) - 3]) { ! 462: SET_U_ERROR(ENOENT, "sys5: mkdir: path too long"); ! 463: return; ! 464: } ! 465: } ! 466: while (--cp_parent >= bufparent) { ! 467: if (*cp_parent == '/') { ! 468: *++cp_parent = '\0'; ! 469: break; ! 470: } ! 471: } ! 472: if (cp_parent < bufparent) { ! 473: *++cp_parent = '.'; ! 474: *++cp_parent = '\0'; ! 475: } ! 476: ! 477: *cp_dotdot++ = *cp_dot++ = '/'; ! 478: *cp_dotdot++ = *cp_dot++ = '.'; ! 479: *cp_dotdot++ = '.'; ! 480: *cp_dotdot = *cp_dot = '\0'; ! 481: ! 482: u.u_io.io_seg = IOSYS; ! 483: ! 484: ! 485: u.u_io.io_seg = IOUSR; ! 486: if ((pip = dmknod(path, mode)) == NULL) { ! 487: return; ! 488: } ! 489: u.u_io.io_seg = IOSYS; ! 490: /* Now we can switch our id to root. It allows to use existing ! 491: * functions. ! 492: */ ! 493: uid = u.u_uid; ! 494: u.u_uid = 0; ! 495: ulink(bufpath, bufdot); ! 496: if (u.u_error) { ! 497: error = u.u_error; ! 498: u.u_error = 0; ! 499: uunlink(bufpath); ! 500: u.u_error = 0; ! 501: u.u_io.io_seg = IOUSR; ! 502: u.u_uid = uid; ! 503: u.u_error = error; ! 504: return; ! 505: } ! 506: ulink(bufparent, bufdotdot); ! 507: if (u.u_error) { ! 508: error = u.u_error; ! 509: u.u_error = 0; ! 510: uunlink(bufdot); ! 511: printf("unlink %s errno is %d\n", bufdot, u.u_error); ! 512: u.u_error = 0; ! 513: uunlink(bufpath); ! 514: printf("unlink %s errno is %d\n", bufpath, u.u_error); ! 515: u.u_uid = uid; ! 516: u.u_io.io_seg = IOUSR; ! 517: u.u_error = error; ! 518: return; ! 519: } ! 520: u.u_io.io_seg = IOUSR; ! 521: return(0); ! 522: } ! 523: ! 524: /* ! 525: * Create a directory. ! 526: * We cannot use original ulink because it makes the directories only for ! 527: * superuser. ! 528: */ ! 529: INODE *dmknod(np, mode) ! 530: char *np; /* Direcotory name */ ! 531: int mode; ! 532: { ! 533: register INODE *ip, *pip; ! 534: register int type; ! 535: ! 536: type = (mode & ~IFMT); ! 537: type |= S_IFDIR; ! 538: ! 539: if (ftoi(np, 'c') != 0) ! 540: return NULL; ! 541: ! 542: if ((ip=u.u_cdiri) != NULL) { ! 543: SET_U_ERROR(EEXIST, "sys5: path already exist") ! 544: idetach(ip); ! 545: return NULL; ! 546: } ! 547: if ((ip=imake(type, (dev_t) 0)) != NULL) ! 548: idetach(ip); ! 549: pip = u.u_pdiri; /* grab ptr to parent inode */ ! 550: return pip; ! 551: } ! 552: ! 553: /* ! 554: * Get directory entry in file system independent format. ! 555: */ ! 556: ugetdents(fd, bp, n) ! 557: int fd; /* File descriptor to an open directory */ ! 558: char *bp; /* Buffer where entries should be read */ ! 559: unsigned n; /* Number of bytes to be read */ ! 560: { ! 561: struct direct r_dir; ! 562: unsigned bytes; /* Number of bytes */ ! 563: struct dirent sd; ! 564: ino_t inode; /* Inode number */ ! 565: unsigned short ofnm; /* Offset to file name in dirent */ ! 566: char *cw, ! 567: *cr; ! 568: int minbuf; /* Minimum possible size of the bp */ ! 569: int i, mod; ! 570: int entry; ! 571: char ends[3] = ""; ! 572: int total = 0; ! 573: ! 574: cw = &bp[0]; ! 575: ! 576: ofnm = sizeof(sd.d_ino) + sizeof(sd.d_off) + sizeof(sd.d_reclen); ! 577: ! 578: /* Find minimum possible size of bp. It should be enough to contain the ! 579: * header of dirent, file name + '\0', and be on a sizeof(long) ! 580: * boundary. ! 581: */ ! 582: entry = ofnm + DIRSIZ + 1; ! 583: mod = entry % sizeof(long); ! 584: minbuf = entry + (mod ? sizeof(long) - mod : 0); ! 585: ! 586: /* Is user buffer available? */ ! 587: if (!useracc(bp, n) || n < minbuf) { ! 588: u.u_error = EFAULT; ! 589: return(0); ! 590: } ! 591: ! 592: while(n - (cw - bp) >= minbuf) { ! 593: /* Read next entry from the directory. ! 594: * inode == 0 for rm(ed) entries ! 595: */ ! 596: do { ! 597: if ((bytes = dirio(fd, &r_dir, sizeof(struct direct), ! 598: &sd.d_off)) == 0) { ! 599: return(total); ! 600: } ! 601: inode = r_dir.d_ino; ! 602: } while (!inode); ! 603: ! 604: /* Find the size of file name */ ! 605: for (cr = r_dir.d_name, i = 0; *cr != '\0' && i < DIRSIZ; ! 606: i++, cr++) ! 607: ; ! 608: ! 609: /* Copy file name */ ! 610: if (!kucopy(r_dir.d_name, cw + ofnm, i)) ! 611: return(0); ! 612: /* Write '\0' */ ! 613: putubd(cw + ofnm + i++, '\0'); ! 614: /* Round up to long boundary */ ! 615: if (mod = (ofnm + i) % sizeof(long)) ! 616: if (!kucopy(ends, cw + ofnm + i, sizeof(long) - mod)) ! 617: return(0); ! 618: sd.d_ino = r_dir.d_ino; ! 619: sd.d_reclen = ofnm + i; /* Size of directory entry */ ! 620: if (mod) ! 621: sd.d_reclen += sizeof(long) - mod; ! 622: if (!kucopy(&sd, cw, ofnm)) ! 623: return(0); ! 624: total += sd.d_reclen; ! 625: cw += sd.d_reclen; ! 626: } ! 627: return(total); ! 628: } ! 629: ! 630: /* ! 631: * Read `n' bytes from the directory `fd' using the buffer `bp'. ! 632: */ ! 633: dirio(fd, bp, n, offset) ! 634: struct direct *bp; ! 635: unsigned n; ! 636: off_t *offset; ! 637: { ! 638: register FD *fdp; ! 639: register INODE *ip; ! 640: ! 641: /* Check file descriptor */ ! 642: if ((fdp = fdget(fd)) == NULL) ! 643: return (0); ! 644: if (((fdp->f_flag & IPR)) == 0) { ! 645: u.u_error = EBADF; ! 646: return (0); ! 647: } ! 648: ip = fdp->f_ip; ! 649: if ((ip->i_mode & IFMT) != IFDIR) { ! 650: u.u_error = EBADF; ! 651: return(0); ! 652: } ! 653: ! 654: ilock(ip); /* We do not want file changes during the read */ ! 655: ! 656: u.u_io.io_seek = fdp->f_seek; ! 657: u.u_io.io.vbase = (vaddr_t) bp; ! 658: u.u_io.io_ioc = n; ! 659: u.u_io.io_flag = (fdp->f_flag & IPNDLY) ? IONDLY : 0; ! 660: ! 661: iread(ip, &u.u_io); ! 662: iacc(ip); /* read - atime */ ! 663: ! 664: n -= u.u_io.io_ioc; ! 665: *offset = fdp->f_seek; ! 666: fdp->f_seek += n; ! 667: ! 668: iunlock(ip); ! 669: ! 670: return (n); ! 671: } ! 672: ! 673: /* ! 674: * Get file system information by file name. ! 675: */ ! 676: ustatfs(path, stfs, len, fstyp) ! 677: char *path; /* File name */ ! 678: struct statfs *stfs; /* Pointer to a user structure */ ! 679: int len; /* Size of the structure */ ! 680: int fstyp; /* File system type */ ! 681: { ! 682: struct filsys *statmount(); /* Get mp for mounted device */ ! 683: struct filsys *statunmount(); /* Get mp for unmounted device */ ! 684: struct filsys *sb; /* Pointer to superblock */ ! 685: int count = 0; /* Number of copied bytes */ ! 686: short systype = 1; /* System type */ ! 687: long bsize = BSIZE; /* Block size */ ! 688: long frsize = 0; /* Fragment size */ ! 689: ! 690: /* Check if stfs is an available user area. */ ! 691: if (!useracc((char *) stfs, len)) { ! 692: u.u_error = EFAULT; ! 693: return; ! 694: } ! 695: ! 696: /* Filesystem type is 1 for 512 bytes blocks. */ ! 697: count += sizeof(systype); ! 698: if (count > len) ! 699: return; ! 700: if (!kucopy(&(systype), &(stfs->f_fstyp), sizeof(systype))) ! 701: return; ! 702: ! 703: /* Block size */ ! 704: count += sizeof(bsize); ! 705: if (count > len) ! 706: return; ! 707: if (!kucopy(&(bsize), &(stfs->f_bsize), sizeof(bsize))) ! 708: return; ! 709: ! 710: /* Fragment size. */ ! 711: count += sizeof(int); ! 712: if (count > len) ! 713: return; ! 714: if (!kucopy(&(frsize), &(stfs->f_frsize), sizeof(frsize))) ! 715: return; ! 716: ! 717: if (!fstyp) { ! 718: if ((sb = statmount(-1, path)) == NULL) ! 719: return; ! 720: devinfo(sb, stfs, len, &count); ! 721: } else { ! 722: if ((sb = statunmount(-1, path)) == NULL) ! 723: return; ! 724: devinfo(sb, stfs, len, &count); ! 725: kfree(sb); ! 726: } ! 727: return; ! 728: } ! 729: ! 730: /* ! 731: * statmount - get superblock for mounted file system. ! 732: * fd - file descriptor or -1, path - file name or NULL. ! 733: */ ! 734: struct filsys *statmount(fd, path) ! 735: int fd; ! 736: char *path; ! 737: { ! 738: register INODE *ip; /* Structure inode */ ! 739: register FD *fdp; ! 740: register MOUNT *mp; /* Pointer to device */ ! 741: dev_t device; /* Mounted device */ ! 742: ! 743: /* Find the device */ ! 744: if (path != NULL) { /* Find ip by file name */ ! 745: if (ftoi(path, 'r') != 0) ! 746: return NULL; ! 747: ip = u.u_cdiri; ! 748: device = ip->i_dev; ! 749: idetach(ip); ! 750: } else { /* Find ip by file descriptor */ ! 751: if ((fdp = fdget(fd)) == NULL) ! 752: return NULL; ! 753: if (((fdp->f_flag & IPR)) == 0) { ! 754: u.u_error = EBADF; ! 755: return NULL; ! 756: } ! 757: ip = fdp->f_ip; ! 758: device = ip->i_dev; ! 759: } ! 760: /* Take mount filesystem, check if dev is mounted device */ ! 761: for (mp = mountp; mp != NULL; mp = mp->m_next) ! 762: if (mp->m_dev == device) ! 763: break; ! 764: if (mp == NULL) { ! 765: u.u_error = EINVAL; ! 766: return NULL; ! 767: } ! 768: return &mp->m_super; ! 769: } ! 770: ! 771: /* ! 772: * devinfo() write system information to user area ! 773: */ ! 774: devinfo(sb, stfs, len, count) ! 775: struct filsys *sb; /* File name */ ! 776: struct statfs *stfs; /* Pointer to a user structure */ ! 777: int len; /* Size of the structure */ ! 778: int *count; ! 779: { ! 780: long inode; ! 781: ! 782: /* Total number of blocks */ ! 783: *count += sizeof(sb->s_fsize); ! 784: if (*count > len) ! 785: return; ! 786: if (!kucopy(&(sb->s_fsize), &(stfs->f_blocks), ! 787: sizeof(sb->s_fsize))) ! 788: return; ! 789: ! 790: /* Count of free blocks */ ! 791: *count += sizeof(sb->s_tfree); ! 792: if (*count > len) ! 793: return; ! 794: if (!kucopy(&(sb->s_tfree), &(stfs->f_bfree), ! 795: sizeof(sb->s_tfree))) ! 796: return; ! 797: ! 798: /* Total number of file inodes */ ! 799: *count += sizeof(inode); ! 800: if (*count > len) ! 801: return; ! 802: inode = (long) (sb->s_isize - INODEI) * INOPB; ! 803: if (!kucopy(&inode, &(stfs->f_files), sizeof(inode))) ! 804: return; ! 805: ! 806: /* Number of free inodes */ ! 807: *count += sizeof(inode); ! 808: if (*count > len) ! 809: return; ! 810: inode = sb->s_tinode; ! 811: if (!kucopy(&inode, &(stfs->f_ffree), sizeof(inode))) ! 812: return; ! 813: ! 814: /* Volume name */ ! 815: *count += sizeof(sb->s_fname); ! 816: if (*count > len) ! 817: return; ! 818: if (!kucopy(sb->s_fname, stfs->f_fname, ! 819: sizeof(sb->s_fpack))) ! 820: return; ! 821: ! 822: /* Pack name */ ! 823: *count += sizeof(sb->s_fpack); ! 824: if (*count > len) ! 825: return; ! 826: if (!kucopy(sb->s_fpack, stfs->f_fpack, ! 827: sizeof(sb->s_fpack))) ! 828: return; ! 829: } ! 830: ! 831: /* ! 832: * statunmount - get superblock for unmounted file system. ! 833: * fd - file descriptor or -1, path - file name or NULL. ! 834: */ ! 835: struct filsys *statunmount(fd, path) ! 836: int fd; /* File descriptor */ ! 837: char *path; /* File name */ ! 838: { ! 839: register INODE *ip; ! 840: register MOUNT *mp; ! 841: register dev_t rdev; ! 842: FD *fdp; ! 843: int mode; ! 844: BUF *bp; ! 845: struct filsys *sb; ! 846: ! 847: /* Find the device */ ! 848: if (path != NULL) { /* Find ip by file name */ ! 849: if (ftoi(path, 'r') != 0) ! 850: return NULL; ! 851: ip = u.u_cdiri; ! 852: mode = ip->i_mode; ! 853: rdev = ip->i_a.i_rdev; ! 854: idetach(ip); ! 855: } else { /* Find ip by file descriptor */ ! 856: if ((fdp = fdget(fd)) == NULL) ! 857: return NULL; ! 858: if (((fdp->f_flag & IPR)) == 0) { ! 859: u.u_error = EBADF; ! 860: return NULL; ! 861: } ! 862: ip = fdp->f_ip; ! 863: ilock(ip); ! 864: mode = ip->i_mode; ! 865: rdev = ip->i_a.i_rdev; ! 866: iunlock(ip); ! 867: } ! 868: ! 869: /* Check for block special device */ ! 870: if ((mode & IFMT) != IFBLK) { ! 871: u.u_error = ENOTBLK; ! 872: return NULL; ! 873: } ! 874: ! 875: /* Check if device is mounted device */ ! 876: for (mp = mountp; mp != NULL; mp = mp->m_next) { ! 877: if (mp->m_dev == rdev) { ! 878: u.u_error = EBUSY; ! 879: return NULL; ! 880: } ! 881: } ! 882: dopen(rdev, IPR, DFBLK); ! 883: if (u.u_error) ! 884: return NULL; ! 885: ! 886: if ((bp = bread(rdev, (daddr_t) SUPERI, 1)) == NULL) { ! 887: dclose(rdev); ! 888: return NULL; ! 889: } ! 890: dclose(rdev); ! 891: ! 892: if ((sb = kalloc(sizeof(struct filsys))) == NULL) ! 893: return (NULL); ! 894: ! 895: kkcopy(bp->b_vaddr, sb, sizeof(struct filsys)); ! 896: brelease(bp); ! 897: cansuper(sb); /* canonicalize supperblock */ ! 898: if (tstf(sb) == 0) { /* check for consistency */ ! 899: kfree(sb); ! 900: u.u_error = EINVAL; ! 901: return(NULL); ! 902: } ! 903: return(sb); ! 904: } ! 905: ! 906: /* ! 907: * Get file system information by file descriptor ! 908: */ ! 909: ufstatfs(fildes, stfs, len, fstyp) ! 910: int fildes; /* File descriptor */ ! 911: struct statfs *stfs; /* Pointer to a user structure */ ! 912: int len; /* Size of the structure */ ! 913: int fstyp; /* File system type */ ! 914: { ! 915: struct filsys *statmount(); /* Get mp for mounted device */ ! 916: struct filsys *statunmount(); /* Get mp for unmounted device */ ! 917: struct filsys *sb; /* Pointer to superblock */ ! 918: int count = 0; /* Number of copied bytes */ ! 919: short systype = 1; /* System type */ ! 920: long bsize = BSIZE; /* Block size */ ! 921: long frsize = 0; /* Fragment size */ ! 922: ! 923: /* Check if stfs is an available user area. */ ! 924: if (!useracc((char *) stfs, len)) { ! 925: u.u_error = EFAULT; ! 926: return; ! 927: } ! 928: ! 929: /* Filesystem type is 1 for 512 bytes blocks. */ ! 930: count += sizeof(systype); ! 931: if (count > len) ! 932: return; ! 933: if (!kucopy(&(systype), &(stfs->f_fstyp), sizeof(systype))) ! 934: return; ! 935: ! 936: /* Block size */ ! 937: count += sizeof(bsize); ! 938: if (count > len) ! 939: return; ! 940: if (!kucopy(&(bsize), &(stfs->f_bsize), sizeof(bsize))) ! 941: return; ! 942: ! 943: /* Fragment size. */ ! 944: count += sizeof(int); ! 945: if (count > len) ! 946: return; ! 947: if (!kucopy(&(frsize), &(stfs->f_frsize), sizeof(frsize))) ! 948: return; ! 949: ! 950: if (!fstyp) { ! 951: if ((sb = statmount(fildes, NULL)) == NULL) ! 952: return; ! 953: devinfo(sb, stfs, len, &count); ! 954: } else { ! 955: if ((sb = statunmount(fildes, NULL)) == NULL) ! 956: return; ! 957: devinfo(sb, stfs, len, &count); ! 958: kfree(sb); ! 959: } ! 960: return; ! 961: } ! 962: ! 963: /* ! 964: * Check superblock for consistency. ! 965: */ ! 966: tstf(fp) ! 967: register struct filsys *fp; ! 968: { ! 969: register daddr_t *dp; ! 970: register ino_t *ip; ! 971: register ino_t maxinode; ! 972: ! 973: maxinode = (fp->s_isize - INODEI) * INOPB + 1; ! 974: if (fp->s_isize >= fp->s_fsize) ! 975: return (0); ! 976: if (fp->s_tfree < fp->s_nfree ! 977: || fp->s_tfree >= fp->s_fsize - fp->s_isize + 1) ! 978: return (0); ! 979: if (fp->s_tinode < fp->s_ninode ! 980: || fp->s_tinode >= maxinode-1) ! 981: return (0); ! 982: for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1) ! 983: if (*dp < fp->s_isize || *dp >= fp->s_fsize) ! 984: return (0); ! 985: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1) ! 986: if (*ip < 1 || *ip > maxinode) ! 987: return (0); ! 988: return (1); ! 989: } ! 990: ! 991: /* the following calls are not in the BCS */ ! 992: ! 993: uadmin() ! 994: { ! 995: u.u_error = EINVAL; ! 996: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.