Annotation of prex/usr/server/fs/vfs/main.c, Revision 1.1
1.1 ! nbrk 1: /*
! 2: * Copyright (c) 2005-2007, Kohsuke Ohtani
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: * 3. Neither the name of the author nor the names of any co-contributors
! 14: * may be used to endorse or promote products derived from this software
! 15: * without specific prior written permission.
! 16: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 27: * SUCH DAMAGE.
! 28: */
! 29:
! 30: /*
! 31: * main.c - File system server
! 32: */
! 33:
! 34: /*
! 35: * All file systems work as a sub-modules under VFS (Virtual File System).
! 36: * The routines in this file have the responsible to the following jobs.
! 37: *
! 38: * - Interpret the IPC message and pass the request into VFS routines.
! 39: * - Validate the some of passed arguments in the message.
! 40: * - Mapping of the task ID and cwd/file pointers.
! 41: *
! 42: * Note: All path string is translated to the full path before passing
! 43: * it to the sys_* routines.
! 44: */
! 45:
! 46: #include <prex/prex.h>
! 47: #include <prex/capability.h>
! 48: #include <server/fs.h>
! 49: #include <server/proc.h>
! 50: #include <server/stdmsg.h>
! 51: #include <server/object.h>
! 52: #include <sys/list.h>
! 53: #include <sys/stat.h>
! 54: #include <sys/vnode.h>
! 55: #include <sys/mount.h>
! 56: #include <sys/buf.h>
! 57: #include <sys/file.h>
! 58:
! 59: #include <limits.h>
! 60: #include <unistd.h>
! 61: #include <stdio.h>
! 62: #include <stdlib.h>
! 63: #include <string.h>
! 64: #include <errno.h>
! 65: #include <fcntl.h>
! 66: #include <signal.h>
! 67:
! 68: #include "vfs.h"
! 69:
! 70: #ifdef DEBUG_VFS
! 71: int vfs_debug = 0;
! 72: #endif
! 73: /*
! 74: * Message mapping
! 75: */
! 76: struct msg_map {
! 77: int code;
! 78: int (*func)(struct task *, struct msg *);
! 79: };
! 80:
! 81: #define MSGMAP(code, fn) {code, (int (*)(struct task *, struct msg *))fn}
! 82:
! 83: /* object for file service */
! 84: static object_t fs_obj;
! 85:
! 86:
! 87: static int
! 88: fs_mount(struct task *t, struct mount_msg *msg)
! 89: {
! 90: int err;
! 91:
! 92: /* Check mount capability. */
! 93: if ((t->cap & CAP_ADMIN) == 0)
! 94: return EPERM;
! 95:
! 96: err = sys_mount(msg->dev, msg->dir, msg->fs, msg->flags,
! 97: (void *)msg->data);
! 98: if (err)
! 99: dprintf("VFS: mount failed! fs=%s\n", msg->fs);
! 100: return err;
! 101: }
! 102:
! 103: static int
! 104: fs_umount(struct task *t, struct path_msg *msg)
! 105: {
! 106:
! 107: /* Check mount capability. */
! 108: if ((t->cap & CAP_ADMIN) == 0)
! 109: return EPERM;
! 110: return sys_umount(msg->path);
! 111: }
! 112:
! 113: static int
! 114: fs_sync(struct task *t, struct msg *msg)
! 115: {
! 116:
! 117: return sys_sync();
! 118: }
! 119:
! 120: static int
! 121: fs_open(struct task *t, struct open_msg *msg)
! 122: {
! 123: char path[PATH_MAX];
! 124: file_t fp;
! 125: int fd, err;
! 126: mode_t mode;
! 127:
! 128: /* Find empty slot for file descriptor. */
! 129: if ((fd = task_newfd(t)) == -1)
! 130: return EMFILE;
! 131:
! 132: /*
! 133: * Check the capability of caller task.
! 134: */
! 135: mode = msg->mode;
! 136: if ((mode & 0111) && (t->cap & CAP_EXEC) == 0)
! 137: return EACCES;
! 138: if ((mode & 0222) && (t->cap & CAP_FS_WRITE) == 0)
! 139: return EACCES;
! 140: if ((mode & 0444) && (t->cap & CAP_FS_READ) == 0)
! 141: return EACCES;
! 142:
! 143: if ((err = task_conv(t, msg->path, path)) != 0)
! 144: return err;
! 145: if ((err = sys_open(path, msg->flags, mode, &fp)) != 0)
! 146: return err;
! 147:
! 148: t->file[fd] = fp;
! 149: t->nopens++;
! 150: msg->fd = fd;
! 151: return 0;
! 152: }
! 153:
! 154: static int
! 155: fs_close(struct task *t, struct msg *msg)
! 156: {
! 157: file_t fp;
! 158: int fd, err;
! 159:
! 160: fd = msg->data[0];
! 161: if (fd >= OPEN_MAX)
! 162: return EBADF;
! 163:
! 164: fp = t->file[fd];
! 165: if (fp == NULL)
! 166: return EBADF;
! 167:
! 168: if ((err = sys_close(fp)) != 0)
! 169: return err;
! 170:
! 171: t->file[fd] = NULL;
! 172: t->nopens--;
! 173: return 0;
! 174: }
! 175:
! 176: static int
! 177: fs_mknod(struct task *t, struct open_msg *msg)
! 178: {
! 179: char path[PATH_MAX];
! 180: int err;
! 181:
! 182: if ((t->cap & CAP_FS_WRITE) == 0)
! 183: return EACCES;
! 184: if ((err = task_conv(t, msg->path, path)) != 0)
! 185: return err;
! 186: return sys_mknod(path, msg->mode);
! 187: }
! 188:
! 189: static int
! 190: fs_lseek(struct task *t, struct msg *msg)
! 191: {
! 192: file_t fp;
! 193: off_t offset, org;
! 194: int err, type;
! 195:
! 196: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 197: return EBADF;
! 198: offset = (off_t)msg->data[1];
! 199: type = msg->data[2];
! 200: err = sys_lseek(fp, offset, type, &org);
! 201: msg->data[0] = (int)org;
! 202: return err;
! 203: }
! 204:
! 205: static int
! 206: fs_read(struct task *t, struct io_msg *msg)
! 207: {
! 208: file_t fp;
! 209: void *buf;
! 210: size_t size, bytes;
! 211: int err;
! 212:
! 213: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 214: return EBADF;
! 215: size = msg->size;
! 216: if ((err = vm_map(msg->hdr.task, msg->buf, size, &buf)) != 0)
! 217: return EFAULT;
! 218: err = sys_read(fp, buf, size, &bytes);
! 219: msg->size = bytes;
! 220: vm_free(task_self(), buf);
! 221: return err;
! 222: }
! 223:
! 224: static int
! 225: fs_write(struct task *t, struct io_msg *msg)
! 226: {
! 227: file_t fp;
! 228: void *buf;
! 229: size_t size, bytes;
! 230: int err;
! 231:
! 232: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 233: return EBADF;
! 234: size = msg->size;
! 235: if ((err = vm_map(msg->hdr.task, msg->buf, size, &buf)) != 0)
! 236: return EFAULT;
! 237: err = sys_write(fp, buf, size, &bytes);
! 238: msg->size = bytes;
! 239: vm_free(task_self(), buf);
! 240: return err;
! 241: }
! 242:
! 243: static int
! 244: fs_ioctl(struct task *t, struct ioctl_msg *msg)
! 245: {
! 246: file_t fp;
! 247:
! 248: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 249: return EBADF;
! 250: return sys_ioctl(fp, msg->request, msg->buf);
! 251: }
! 252:
! 253: static int
! 254: fs_fsync(struct task *t, struct msg *msg)
! 255: {
! 256: file_t fp;
! 257:
! 258: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 259: return EBADF;
! 260: return sys_fsync(fp);
! 261: }
! 262:
! 263: static int
! 264: fs_fstat(struct task *t, struct stat_msg *msg)
! 265: {
! 266: file_t fp;
! 267: struct stat *st;
! 268:
! 269: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 270: return EBADF;
! 271: st = &msg->st;
! 272: return sys_fstat(fp, st);
! 273: }
! 274:
! 275: static int
! 276: fs_opendir(struct task *t, struct open_msg *msg)
! 277: {
! 278: char path[PATH_MAX];
! 279: file_t fp;
! 280: int fd, err;
! 281:
! 282: /* Find empty slot for file descriptor. */
! 283: if ((fd = task_newfd(t)) == -1)
! 284: return EMFILE;
! 285:
! 286: /* Get the mounted file system and node */
! 287: if ((err = task_conv(t, msg->path, path)) != 0)
! 288: return err;
! 289: if ((err = sys_opendir(path, &fp)) != 0)
! 290: return err;
! 291: t->file[fd] = fp;
! 292: msg->fd = fd;
! 293: return 0;
! 294: }
! 295:
! 296: static int
! 297: fs_closedir(struct task *t, struct msg *msg)
! 298: {
! 299: file_t fp;
! 300: int fd, err;
! 301:
! 302: fd = msg->data[0];
! 303: if (fd >= OPEN_MAX)
! 304: return EBADF;
! 305: fp = t->file[fd];
! 306: if (fp == NULL)
! 307: return EBADF;
! 308: if ((err = sys_closedir(fp)) != 0)
! 309: return err;
! 310: t->file[fd] = NULL;
! 311: return 0;
! 312: }
! 313:
! 314: static int
! 315: fs_readdir(struct task *t, struct dir_msg *msg)
! 316: {
! 317: file_t fp;
! 318:
! 319: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 320: return EBADF;
! 321: return sys_readdir(fp, &msg->dirent);
! 322: }
! 323:
! 324: static int
! 325: fs_rewinddir(struct task *t, struct msg *msg)
! 326: {
! 327: file_t fp;
! 328:
! 329: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 330: return EBADF;
! 331: return sys_rewinddir(fp);
! 332: }
! 333:
! 334: static int
! 335: fs_seekdir(struct task *t, struct msg *msg)
! 336: {
! 337: file_t fp;
! 338: long loc;
! 339:
! 340: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 341: return EBADF;
! 342: loc = msg->data[1];
! 343: return sys_seekdir(fp, loc);
! 344: }
! 345:
! 346: static int
! 347: fs_telldir(struct task *t, struct msg *msg)
! 348: {
! 349: file_t fp;
! 350: long loc;
! 351: int err;
! 352:
! 353: if ((fp = task_getfp(t, msg->data[0])) == NULL)
! 354: return EBADF;
! 355: loc = msg->data[1];
! 356: if ((err = sys_telldir(fp, &loc)) != 0)
! 357: return err;
! 358: msg->data[0] = loc;
! 359: return 0;
! 360: }
! 361:
! 362: static int
! 363: fs_mkdir(struct task *t, struct open_msg *msg)
! 364: {
! 365: char path[PATH_MAX];
! 366: int err;
! 367:
! 368: if ((t->cap & CAP_FS_WRITE) == 0)
! 369: return EACCES;
! 370: if ((err = task_conv(t, msg->path, path)) != 0)
! 371: return err;
! 372: return sys_mkdir(path, msg->mode);
! 373: }
! 374:
! 375: static int
! 376: fs_rmdir(struct task *t, struct path_msg *msg)
! 377: {
! 378: char path[PATH_MAX];
! 379: int err;
! 380:
! 381: if ((t->cap & CAP_FS_WRITE) == 0)
! 382: return EACCES;
! 383: if (msg->path == NULL)
! 384: return ENOENT;
! 385: if ((err = task_conv(t, msg->path, path)) != 0)
! 386: return err;
! 387: return sys_rmdir(path);
! 388: }
! 389:
! 390: static int
! 391: fs_rename(struct task *t, struct path_msg *msg)
! 392: {
! 393: char src[PATH_MAX];
! 394: char dest[PATH_MAX];
! 395: int err;
! 396:
! 397: if ((t->cap & CAP_FS_WRITE) == 0)
! 398: return EACCES;
! 399: if (msg->path == NULL || msg->path2 == NULL)
! 400: return ENOENT;
! 401: if ((err = task_conv(t, msg->path, src)) != 0)
! 402: return err;
! 403: if ((err = task_conv(t, msg->path2, dest)) != 0)
! 404: return err;
! 405: return sys_rename(src, dest);
! 406: }
! 407:
! 408: static int
! 409: fs_chdir(struct task *t, struct path_msg *msg)
! 410: {
! 411: char path[PATH_MAX];
! 412: file_t fp;
! 413: int err;
! 414:
! 415: if (msg->path == NULL)
! 416: return ENOENT;
! 417: if ((err = task_conv(t, msg->path, path)) != 0)
! 418: return err;
! 419: /* Check if directory exits */
! 420: if ((err = sys_opendir(path, &fp)) != 0)
! 421: return err;
! 422: if (t->cwdfp)
! 423: sys_closedir(t->cwdfp);
! 424: t->cwdfp = fp;
! 425: strcpy(t->cwd, path);
! 426: return 0;
! 427: }
! 428:
! 429: static int
! 430: fs_link(struct task *t, struct msg *msg)
! 431: {
! 432: /* XXX */
! 433: return EPERM;
! 434: }
! 435:
! 436: static int
! 437: fs_unlink(struct task *t, struct path_msg *msg)
! 438: {
! 439: char path[PATH_MAX];
! 440:
! 441: if ((t->cap & CAP_FS_WRITE) == 0)
! 442: return EACCES;
! 443: if (msg->path == NULL)
! 444: return ENOENT;
! 445: task_conv(t, msg->path, path);
! 446: return sys_unlink(path);
! 447: }
! 448:
! 449: static int
! 450: fs_stat(struct task *t, struct stat_msg *msg)
! 451: {
! 452: char path[PATH_MAX];
! 453: struct stat *st;
! 454: int err;
! 455:
! 456: task_conv(t, msg->path, path);
! 457: st = &msg->st;
! 458: err = sys_stat(path, st);
! 459: return err;
! 460: }
! 461:
! 462: static int
! 463: fs_getcwd(struct task *t, struct path_msg *msg)
! 464: {
! 465:
! 466: strcpy(msg->path, t->cwd);
! 467: return 0;
! 468: }
! 469:
! 470: /*
! 471: * Duplicate a file descriptor.
! 472: */
! 473: static int
! 474: fs_dup(struct task *t, struct msg *msg)
! 475: {
! 476: file_t fp;
! 477: int old_fd, new_fd;
! 478:
! 479: old_fd = msg->data[0];
! 480: if (old_fd >= OPEN_MAX)
! 481: return EBADF;
! 482: fp = t->file[old_fd];
! 483: if (fp == NULL)
! 484: return EBADF;
! 485:
! 486: /* Find smallest empty slot as new fd. */
! 487: if ((new_fd = task_newfd(t)) == -1)
! 488: return EMFILE;
! 489:
! 490: t->file[new_fd] = fp;
! 491:
! 492: /* Increment file reference */
! 493: vref(fp->f_vnode);
! 494: fp->f_count++;
! 495:
! 496: msg->data[0] = new_fd;
! 497: return 0;
! 498: }
! 499:
! 500: /*
! 501: * Duplicate a file descriptor to a particular value.
! 502: */
! 503: static int
! 504: fs_dup2(struct task *t, struct msg *msg)
! 505: {
! 506: file_t fp, org;
! 507: int old_fd, new_fd;
! 508: int err;
! 509:
! 510: old_fd = msg->data[0];
! 511: new_fd = msg->data[1];
! 512: if (old_fd >= OPEN_MAX || new_fd >= OPEN_MAX)
! 513: return EBADF;
! 514: fp = t->file[old_fd];
! 515: if (fp == NULL)
! 516: return EBADF;
! 517: org = t->file[new_fd];
! 518: if (org != NULL) {
! 519: /* Close previous file if it's opened. */
! 520: err = sys_close(org);
! 521: }
! 522: t->file[new_fd] = fp;
! 523: msg->data[0] = new_fd;
! 524: return 0;
! 525: }
! 526:
! 527: /*
! 528: * The file control system call.
! 529: */
! 530: static int
! 531: fs_fcntl(struct task *t, struct fcntl_msg *msg)
! 532: {
! 533: file_t fp;
! 534: int arg, new_fd;
! 535:
! 536: if ((fp = task_getfp(t, msg->fd)) == NULL)
! 537: return EBADF;
! 538:
! 539: arg = msg->arg;
! 540: switch (msg->cmd) {
! 541: case F_DUPFD:
! 542: if (arg >= OPEN_MAX)
! 543: return EINVAL;
! 544:
! 545: /* Find smallest empty slot as new fd. */
! 546: if ((new_fd = task_newfd(t)) == -1)
! 547: return EMFILE;
! 548: t->file[new_fd] = fp;
! 549: break;
! 550: case F_GETFD:
! 551: msg->arg = fp->f_flags & FD_CLOEXEC;
! 552: break;
! 553: case F_SETFD:
! 554: fp->f_flags = (fp->f_flags & ~FD_CLOEXEC) |
! 555: (msg->arg & FD_CLOEXEC);
! 556: break;
! 557: case F_GETFL:
! 558: break;
! 559: case F_SETFL:
! 560: break;
! 561: default:
! 562: break;
! 563: }
! 564: return 0;
! 565: }
! 566:
! 567: /*
! 568: * Check permission for file access
! 569: */
! 570: static int
! 571: fs_access(struct task *t, struct path_msg *msg)
! 572: {
! 573: char path[PATH_MAX];
! 574: int mode, err;
! 575:
! 576: mode = msg->data[0];
! 577:
! 578: /*
! 579: * Check file permission.
! 580: */
! 581: task_conv(t, msg->path, path);
! 582: if ((err = sys_access(path, mode)) != 0)
! 583: return err;
! 584:
! 585: /*
! 586: * Check task permission.
! 587: */
! 588: err = EACCES;
! 589: if ((mode & X_OK) && (t->cap & CAP_EXEC) == 0)
! 590: goto out;
! 591: if ((mode & W_OK) && (t->cap & CAP_FS_WRITE) == 0)
! 592: goto out;
! 593: if ((mode & R_OK) && (t->cap & CAP_FS_READ) == 0)
! 594: goto out;
! 595: err = 0;
! 596: out:
! 597: return err;
! 598: }
! 599:
! 600: /*
! 601: * Copy parent's cwd & file/directory descriptor to child's.
! 602: */
! 603: static int
! 604: fs_fork(struct task *t, struct msg *msg)
! 605: {
! 606: struct task *newtask;
! 607: file_t fp;
! 608: int err, i;
! 609:
! 610: DPRINTF(VFSDB_CORE, ("fs_fork\n"));
! 611:
! 612: if ((err = task_alloc((task_t)msg->data[0], &newtask)) != 0)
! 613: return err;
! 614:
! 615: /*
! 616: * Copy task related data
! 617: */
! 618: newtask->cwdfp = t->cwdfp;
! 619: strcpy(newtask->cwd, t->cwd);
! 620: for (i = 0; i < OPEN_MAX; i++) {
! 621: fp = t->file[i];
! 622: newtask->file[i] = fp;
! 623: /*
! 624: * Increment file reference if it's
! 625: * already opened.
! 626: */
! 627: if (fp != NULL) {
! 628: vref(fp->f_vnode);
! 629: fp->f_count++;
! 630: }
! 631: }
! 632: if (newtask->cwdfp)
! 633: newtask->cwdfp->f_count++;
! 634: /* Increment cwd's reference count */
! 635: if (newtask->cwdfp)
! 636: vref(newtask->cwdfp->f_vnode);
! 637: return 0;
! 638: }
! 639:
! 640: /*
! 641: * fs_exec() is called for POSIX exec().
! 642: * It closes all directory stream.
! 643: * File descriptor which is marked close-on-exec are also closed.
! 644: */
! 645: static int
! 646: fs_exec(struct task *t, struct msg *msg)
! 647: {
! 648: task_t old_id, new_id;
! 649: struct task *target;
! 650: file_t fp;
! 651: int fd;
! 652:
! 653: old_id = (task_t)msg->data[0];
! 654: new_id = (task_t)msg->data[1];
! 655:
! 656: if (!(target = task_lookup(old_id)))
! 657: return EINVAL;
! 658:
! 659: /* Update task id in the task. */
! 660: task_update(target, new_id);
! 661:
! 662: /* Close all directory descriptor */
! 663: for (fd = 0; fd < OPEN_MAX; fd++) {
! 664: fp = target->file[fd];
! 665: if (fp) {
! 666: if (fp->f_vnode->v_type == VDIR) {
! 667: sys_close(fp);
! 668: target->file[fd] = NULL;
! 669: }
! 670:
! 671: /* XXX: need to check close-on-exec flag */
! 672: }
! 673: }
! 674: task_unlock(target);
! 675: return 0;
! 676: }
! 677:
! 678: /*
! 679: * fs_exit() cleans up data for task's termination.
! 680: */
! 681: static int
! 682: fs_exit(struct task *t, struct msg *msg)
! 683: {
! 684: file_t fp;
! 685: int fd;
! 686:
! 687: /*
! 688: * Close all files opened by task.
! 689: */
! 690: for (fd = 0; fd < OPEN_MAX; fd++) {
! 691: fp = t->file[fd];
! 692: if (fp != NULL)
! 693: sys_close(fp);
! 694: }
! 695: if (t->cwdfp)
! 696: sys_close(t->cwdfp);
! 697: task_free(t);
! 698: return 0;
! 699: }
! 700:
! 701: /*
! 702: * fs_register() is called by boot tasks.
! 703: * This can be called even when no fs is mounted.
! 704: */
! 705: static int
! 706: fs_register(struct task *t, struct msg *msg)
! 707: {
! 708: struct task *tmp;
! 709: cap_t cap;
! 710: int err;
! 711:
! 712: DPRINTF(VFSDB_CORE, ("fs_register\n"));
! 713:
! 714: if (task_getcap(msg->hdr.task, &cap))
! 715: return EINVAL;
! 716: if ((cap & CAP_ADMIN) == 0)
! 717: return EPERM;
! 718:
! 719: err = task_alloc(msg->hdr.task, &tmp);
! 720: return err;
! 721: }
! 722:
! 723: static int
! 724: fs_pipe(struct task *t, struct msg *msg)
! 725: {
! 726: #ifdef CONFIG_FIFOFS
! 727: char path[PATH_MAX];
! 728: file_t rfp, wfp;
! 729: int err, rfd, wfd;
! 730:
! 731: DPRINTF(VFSDB_CORE, ("fs_pipe\n"));
! 732:
! 733: if ((rfd = task_newfd(t)) == -1)
! 734: return EMFILE;
! 735: t->file[rfd] = (file_t)1; /* temp */
! 736:
! 737: if ((wfd = task_newfd(t)) == -1) {
! 738: t->file[rfd] = NULL;
! 739: return EMFILE;
! 740: }
! 741: sprintf(path, "/fifo/%x-%d", (u_int)t->task, rfd);
! 742:
! 743: if ((err = sys_mknod(path, S_IFIFO)) != 0)
! 744: goto out;
! 745: if ((err = sys_open(path, O_RDONLY | O_NONBLOCK, 0, &rfp)) != 0) {
! 746: goto out;
! 747: }
! 748: if ((err = sys_open(path, O_WRONLY | O_NONBLOCK, 0, &wfp)) != 0) {
! 749: goto out;
! 750: }
! 751: t->file[rfd] = rfp;
! 752: t->file[wfd] = wfp;
! 753: t->nopens += 2;
! 754: msg->data[0] = rfd;
! 755: msg->data[1] = wfd;
! 756: return 0;
! 757: out:
! 758: t->file[rfd] = NULL;
! 759: t->file[wfd] = NULL;
! 760: return err;
! 761: #else
! 762: return ENOSYS;
! 763: #endif
! 764: }
! 765:
! 766: /*
! 767: * Prepare for shutdown
! 768: */
! 769: static int
! 770: fs_shutdown(struct task *t, struct msg *msg)
! 771: {
! 772:
! 773: sys_sync();
! 774: return 0;
! 775: }
! 776:
! 777: /*
! 778: * Dump internal data.
! 779: */
! 780: static int
! 781: fs_debug(struct task *t, struct msg *msg)
! 782: {
! 783:
! 784: #ifdef DEBUG
! 785: dprintf("<File System Server>\n");
! 786: task_dump();
! 787: vnode_dump();
! 788: mount_dump();
! 789: #endif
! 790: return 0;
! 791: }
! 792:
! 793: /*
! 794: * Register to process server if it is loaded.
! 795: */
! 796: static void
! 797: process_init(void)
! 798: {
! 799: int i, err = 0;
! 800: object_t obj = 0;
! 801: struct msg m;
! 802:
! 803: /*
! 804: * Wait for server loading. timeout is 1 sec.
! 805: */
! 806: for (i = 0; i < 100; i++) {
! 807: err = object_lookup(OBJNAME_PROC, &obj);
! 808: if (err == 0)
! 809: break;
! 810:
! 811: /* Wait 10msec */
! 812: timer_sleep(10, 0);
! 813: thread_yield();
! 814: }
! 815: if (obj == 0)
! 816: return;
! 817:
! 818: /*
! 819: * Notify to process server.
! 820: */
! 821: m.hdr.code = PS_REGISTER;
! 822: msg_send(obj, &m, sizeof(m));
! 823: }
! 824:
! 825: static void
! 826: fs_init(void)
! 827: {
! 828: const struct vfssw *fs;
! 829: struct msg msg;
! 830:
! 831: process_init();
! 832:
! 833: /*
! 834: * Initialize VFS core.
! 835: */
! 836: task_init();
! 837: bio_init();
! 838: vnode_init();
! 839:
! 840: /*
! 841: * Initialize each file system.
! 842: */
! 843: for (fs = vfssw_table; fs->vs_name; fs++) {
! 844: DPRINTF(VFSDB_CORE, ("VFS: Initializing %s\n",
! 845: fs->vs_name));
! 846: fs->vs_init();
! 847: }
! 848:
! 849: /*
! 850: * Create task data for ourselves.
! 851: */
! 852: msg.hdr.task = task_self();
! 853: fs_register(NULL, &msg);
! 854: }
! 855:
! 856: /*
! 857: * Run specified routine as a thread.
! 858: */
! 859: static int
! 860: thread_run(void (*entry)(void))
! 861: {
! 862: task_t self;
! 863: thread_t th;
! 864: void *stack, *sp;
! 865: int err;
! 866:
! 867: self = task_self();
! 868: if ((err = thread_create(self, &th)) != 0)
! 869: return err;
! 870: if ((err = vm_allocate(self, &stack, USTACK_SIZE, 1)) != 0)
! 871: return err;
! 872:
! 873: sp = (void *)((u_long)stack + USTACK_SIZE - sizeof(u_long) * 3);
! 874: if ((err = thread_load(th, entry, sp)) != 0)
! 875: return err;
! 876: if ((err = thread_setprio(th, PRIO_FS)) != 0)
! 877: return err;
! 878:
! 879: return thread_resume(th);
! 880: }
! 881:
! 882: /*
! 883: * Message mapping
! 884: */
! 885: static const struct msg_map fsmsg_map[] = {
! 886: MSGMAP( STD_DEBUG, fs_debug ),
! 887: MSGMAP( STD_SHUTDOWN, fs_shutdown ),
! 888: MSGMAP( FS_MOUNT, fs_mount ),
! 889: MSGMAP( FS_UMOUNT, fs_umount ),
! 890: MSGMAP( FS_SYNC, fs_sync ),
! 891: MSGMAP( FS_OPEN, fs_open ),
! 892: MSGMAP( FS_CLOSE, fs_close ),
! 893: MSGMAP( FS_MKNOD, fs_mknod ),
! 894: MSGMAP( FS_LSEEK, fs_lseek ),
! 895: MSGMAP( FS_READ, fs_read ),
! 896: MSGMAP( FS_WRITE, fs_write ),
! 897: MSGMAP( FS_IOCTL, fs_ioctl ),
! 898: MSGMAP( FS_FSYNC, fs_fsync ),
! 899: MSGMAP( FS_FSTAT, fs_fstat ),
! 900: MSGMAP( FS_OPENDIR, fs_opendir ),
! 901: MSGMAP( FS_CLOSEDIR, fs_closedir ),
! 902: MSGMAP( FS_READDIR, fs_readdir ),
! 903: MSGMAP( FS_REWINDDIR, fs_rewinddir ),
! 904: MSGMAP( FS_SEEKDIR, fs_seekdir ),
! 905: MSGMAP( FS_TELLDIR, fs_telldir ),
! 906: MSGMAP( FS_MKDIR, fs_mkdir ),
! 907: MSGMAP( FS_RMDIR, fs_rmdir ),
! 908: MSGMAP( FS_RENAME, fs_rename ),
! 909: MSGMAP( FS_CHDIR, fs_chdir ),
! 910: MSGMAP( FS_LINK, fs_link ),
! 911: MSGMAP( FS_UNLINK, fs_unlink ),
! 912: MSGMAP( FS_STAT, fs_stat ),
! 913: MSGMAP( FS_GETCWD, fs_getcwd ),
! 914: MSGMAP( FS_DUP, fs_dup ),
! 915: MSGMAP( FS_DUP2, fs_dup2 ),
! 916: MSGMAP( FS_FCNTL, fs_fcntl ),
! 917: MSGMAP( FS_ACCESS, fs_access ),
! 918: MSGMAP( FS_FORK, fs_fork ),
! 919: MSGMAP( FS_EXEC, fs_exec ),
! 920: MSGMAP( FS_EXIT, fs_exit ),
! 921: MSGMAP( FS_REGISTER, fs_register ),
! 922: MSGMAP( FS_PIPE, fs_pipe ),
! 923: MSGMAP( 0, NULL ),
! 924: };
! 925:
! 926: /*
! 927: * File system thread.
! 928: */
! 929: static void
! 930: fs_thread(void)
! 931: {
! 932: struct msg *msg;
! 933: const struct msg_map *map;
! 934: struct task *t;
! 935: int err;
! 936:
! 937: msg = (struct msg *)malloc(MAX_FSMSG);
! 938:
! 939: /*
! 940: * Message loop
! 941: */
! 942: for (;;) {
! 943: /*
! 944: * Wait for an incoming request.
! 945: */
! 946: if ((err = msg_receive(fs_obj, msg, MAX_FSMSG)) != 0)
! 947: continue;
! 948:
! 949: err = EINVAL;
! 950: map = &fsmsg_map[0];
! 951: while (map->code != 0) {
! 952: if (map->code == msg->hdr.code) {
! 953: if (map->code == FS_REGISTER) {
! 954: err = fs_register(NULL, msg);
! 955: break;
! 956: }
! 957: /* Lookup and lock task */
! 958: t = task_lookup(msg->hdr.task);
! 959: if (t == NULL)
! 960: break;
! 961:
! 962: /* Get the capability list of caller task. */
! 963: if (task_getcap(msg->hdr.task, &t->cap))
! 964: break;
! 965:
! 966: /* Dispatch request */
! 967: err = (*map->func)(t, msg);
! 968: if (map->code != FS_EXIT)
! 969: task_unlock(t);
! 970: break;
! 971: }
! 972: map++;
! 973: }
! 974: #ifdef DEBUG_VFS
! 975: if (err)
! 976: dprintf("VFS: task=%x code=%x error=%d\n",
! 977: msg->hdr.task, map->code, err);
! 978: #endif
! 979: /*
! 980: * Reply to the client.
! 981: */
! 982: msg->hdr.status = err;
! 983: msg_reply(fs_obj, msg, MAX_FSMSG);
! 984: }
! 985: }
! 986:
! 987: /*
! 988: * Main routine for file system service
! 989: */
! 990: int
! 991: main(int argc, char *argv[])
! 992: {
! 993: int i;
! 994:
! 995: sys_log("Starting File System Server\n");
! 996:
! 997: /*
! 998: * Boost current priority.
! 999: */
! 1000: thread_setprio(thread_self(), PRIO_FS);
! 1001:
! 1002: /*
! 1003: * Initialize file systems.
! 1004: */
! 1005: fs_init();
! 1006:
! 1007: /*
! 1008: * Create an object to expose our service.
! 1009: */
! 1010: if (object_create(OBJNAME_FS, &fs_obj))
! 1011: sys_panic("VFS: fail to create object");
! 1012:
! 1013: /*
! 1014: * Create new server threads.
! 1015: */
! 1016: #ifdef DEBUG_VFS
! 1017: dprintf("VFS: Number of fs threads: %d\n", CONFIG_FS_THREADS);
! 1018: #endif
! 1019: i = CONFIG_FS_THREADS;
! 1020: while (--i > 0) {
! 1021: if (thread_run(fs_thread))
! 1022: goto err;
! 1023: }
! 1024: fs_thread();
! 1025: exit(0);
! 1026: err:
! 1027: sys_panic("VFS: failed to create thread");
! 1028: return 0;
! 1029: }
CVSweb