예제 #1
0
파일: thread.c 프로젝트: oscarlab/graphene
/* If *phdl is returned on success, the ref count is incremented */
static int parse_thread_fd (const char * name, const char ** rest,
                            struct shim_handle ** phdl)
{
    const char * next, * nextnext;
    int next_len;

    int pid = parse_thread_name(name, &next, &next_len, &nextnext);

    if (!pid)
        return pid;

    if (!next || !nextnext || memcmp(next, "fd", next_len))
        return -EINVAL;

    const char * p = nextnext;
    int fd = 0;

    for ( ; *p && *p != '/' ; p++) {
        if (*p < '0' || *p > '9')
            return -ENOENT;
        fd = fd * 10 + *p - '0';
        if (fd >= __rlim[RLIMIT_NOFILE].rlim_cur)
            return -ENOENT;
    }

    struct shim_thread * thread = lookup_thread(pid);

    if (!thread)
        return -ENOENT;

    struct shim_handle_map * handle_map = get_cur_handle_map(thread);

    lock(&handle_map->lock);

    if (fd >= handle_map->fd_top ||
        handle_map->map[fd] == NULL ||
        handle_map->map[fd]->handle == NULL) {
        unlock(&handle_map->lock);
        return -ENOENT;
    }

    if (phdl) {
        *phdl = handle_map->map[fd]->handle;
        get_handle(*phdl);
    }

    unlock(&handle_map->lock);

    if (rest)
        *rest = *p ? p + 1 : NULL;

    return 0;
}
예제 #2
0
struct shim_handle * get_fd_handle (FDTYPE fd, int * flags,
                                    struct shim_handle_map * map)
{
    if (!map)
        map = get_cur_handle_map(NULL);

    struct shim_handle * hdl = NULL;
    lock(map->lock);
    if ((hdl = __get_fd_handle(fd, flags, map)))
        get_handle(hdl);
    unlock(map->lock);
    return hdl;
}
예제 #3
0
int set_new_fd_handle (struct shim_handle * hdl, int flags,
                       struct shim_handle_map * handle_map)
{
    FDTYPE fd = 0;
    int new_size = 0;
    int ret = 0;

    if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
        return -EBADF;

    lock(handle_map->lock);

    if (!handle_map->map ||
        handle_map->fd_size < INIT_HANDLE_MAP_SIZE)
        new_size = INIT_HANDLE_MAP_SIZE;

    if (!handle_map->map)
        goto extend;

    if (handle_map->fd_top != FD_NULL)
        do {
            ++fd;
            if (fd == handle_map->fd_size) {
                new_size = handle_map->fd_size < new_size ? new_size :
                           handle_map->fd_size * 2;
extend:
                if (!__enlarge_handle_map(handle_map, new_size)) {
                    ret = -ENOMEM;
                    goto out;
                }
            }
        } while (handle_map->fd_top != FD_NULL &&
                 fd <= handle_map->fd_top &&
                 HANDLE_ALLOCATED(handle_map->map[fd]));

    if (handle_map->fd_top == FD_NULL ||
        fd > handle_map->fd_top)
        handle_map->fd_top = fd;

    ret = __set_new_fd_handle(&handle_map->map[fd], fd, hdl, flags);
    if (ret < 0) {
        if (fd == handle_map->fd_top)
            handle_map->fd_top = fd ? fd - 1 : FD_NULL;
    } else
        ret = fd;
out:
    unlock(handle_map->lock);
    return ret;
}
예제 #4
0
struct shim_handle * detach_fd_handle (FDTYPE fd, int * flags,
                                       struct shim_handle_map * handle_map)
{
    struct shim_handle * handle = NULL;

    if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
        return NULL;

    lock(handle_map->lock);

    if (fd < handle_map->fd_size)
        handle = __detach_fd_handle(handle_map->map[fd], flags,
                                    handle_map);

    unlock(handle_map->lock);
    return handle;
}
예제 #5
0
파일: thread.c 프로젝트: oscarlab/graphene
static int proc_list_thread_each_fd (const char * name,
                                     struct shim_dirent ** buf, int count)
{
    const char * next;
    int next_len;
    int pid = parse_thread_name(name, &next, &next_len, NULL);

    if (!pid)
        return pid;

    if (!next || memcmp(next, "fd", next_len))
        return -EINVAL;

    struct shim_thread * thread = lookup_thread(pid);
    if (!thread)
        return -ENOENT;

    struct shim_handle_map * handle_map = get_cur_handle_map(thread);
    int err = 0, bytes = 0;
    struct shim_dirent * dirent = *buf, ** last = NULL;

    lock(&handle_map->lock);

    for (int i = 0 ; i < handle_map->fd_size ; i++)
        if (handle_map->map[i] &&
            handle_map->map[i]->handle) {
            int d = i, l = 0;
            for ( ; d ; d /= 10, l++);
            l = l ? : 1;

            bytes += sizeof(struct shim_dirent) + l + 1;
            if (bytes > count) {
                err = -ENOMEM;
                break;
            }

            dirent->next = (void *) (dirent + 1) + l + 1;
            dirent->ino = 1;
            dirent->type = LINUX_DT_LNK;
            dirent->name[0] = '0';
            dirent->name[l--] = 0;
            for (d = i ; d ; d /= 10)
                dirent->name[l--] = '0' + d % 10;
            last = &dirent->next;
            dirent = dirent->next;
        }
예제 #6
0
int set_new_fd_handle_by_fd (FDTYPE fd, struct shim_handle * hdl, int flags,
                             struct shim_handle_map * handle_map)
{
    int new_size = 0;
    int ret = 0;

    if (!handle_map && !(handle_map = get_cur_handle_map(NULL)))
        return -EBADF;

    lock(handle_map->lock);

    if (!handle_map->map ||
        handle_map->fd_size < INIT_HANDLE_MAP_SIZE)
        new_size = INIT_HANDLE_MAP_SIZE;

    if (!handle_map->map)
        goto extend;

    if (fd >= handle_map->fd_size) {
        new_size = handle_map->fd_size < new_size ? new_size :
                   handle_map->fd_size;
extend:
        while (new_size <= fd)
            new_size *= 2;

        if (!__enlarge_handle_map(handle_map, new_size)) {
            ret = -ENOMEM;
            goto out;
        }
    }

    if (handle_map->fd_top != FD_NULL &&
        fd <= handle_map->fd_top &&
        HANDLE_ALLOCATED(handle_map->map[fd])) {
        ret = -EBADF;
        goto out;
    }

    if (handle_map->fd_top == FD_NULL ||
        fd > handle_map->fd_top)
        handle_map->fd_top = fd;

    struct shim_fd_handle * new_handle = handle_map->map[fd];

    if (!new_handle) {
        new_handle = malloc(sizeof(struct shim_fd_handle));
        if (!new_handle) {
            ret = -ENOMEM;
            goto out;
        }
        handle_map->map[fd] = new_handle;
    }

    ret = __set_new_fd_handle(&handle_map->map[fd], fd, hdl, flags);
    if (ret < 0) {
        if (fd == handle_map->fd_top)
            handle_map->fd_top = fd ? fd - 1 : FD_NULL;
    } else
        ret = fd;
out:
    unlock(handle_map->lock);
    return fd;
}
예제 #7
0
int init_important_handles (void)
{
    struct shim_thread * thread = get_cur_thread();

    if (thread->handle_map)
        goto done;

    struct shim_handle_map * handle_map = get_cur_handle_map(thread);

    if (!handle_map) {
        handle_map = get_new_handle_map(INIT_HANDLE_MAP_SIZE);
        if (!handle_map)
            return -ENOMEM;

        set_handle_map(thread, handle_map);
    }

    lock(handle_map->lock);

    if (handle_map->fd_size < 3) {
        if (!__enlarge_handle_map(handle_map, INIT_HANDLE_MAP_SIZE)) {
            unlock(handle_map->lock);
            return -ENOMEM;
        }
    }

    struct shim_handle * hdl = NULL;
    int ret;

    for (int fd = 0 ; fd < 3 ; fd++)
        if (!HANDLE_ALLOCATED(handle_map->map[fd])) {
            if (!hdl) {
                hdl = get_new_handle();
                if (!hdl)
                    return -ENOMEM;

                if ((ret = init_tty_handle(hdl, fd)) < 0) {
                    put_handle(hdl);
                    return ret;
                }
            } else {
                get_handle(hdl);
            }

            __set_new_fd_handle(&handle_map->map[fd], fd, hdl, 0);
            put_handle(hdl);
            if (fd != 1)
                hdl = NULL;
        } else {
            if (fd == 1)
                hdl = handle_map->map[fd]->handle;
        }

    if (handle_map->fd_top == FD_NULL || handle_map->fd_top < 2)
        handle_map->fd_top = 2;

    unlock(handle_map->lock);

done:
    init_exec_handle(thread);
    return 0;
}