[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / prex / usr / server / fs / vfs

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