From 6e6dafa23193171216254b7feb94372413dd3b52 Mon Sep 17 00:00:00 2001 From: wjhun <36206676+wjhun@users.noreply.github.com> Date: Fri, 1 Mar 2019 18:21:55 -0800 Subject: [PATCH] keep track of file (fdesc) types, properly fill stat st_mode --- src/net/netsyscall.c | 2 +- src/unix/pipe.c | 4 +-- src/unix/poll.c | 2 +- src/unix/syscall.c | 72 +++++++++++++++++++++++++++------------- src/unix/unix.c | 9 ++--- src/unix/unix_internal.h | 11 +++++- 6 files changed, 68 insertions(+), 32 deletions(-) diff --git a/src/net/netsyscall.c b/src/net/netsyscall.c index ce80f2241..7ef0ed202 100644 --- a/src/net/netsyscall.c +++ b/src/net/netsyscall.c @@ -515,7 +515,7 @@ static int allocate_sock(process p, int type, u32 flags, sock * rs) unix_cache_free(get_unix_heaps(), socket, s); return -EMFILE; } - fdesc_init(&s->f); + fdesc_init(&s->f, FDESC_TYPE_SOCKET); heap h = heap_general(get_kernel_heaps()); s->f.read = closure(h, socket_read, s); s->f.write = closure(h, socket_write, s); diff --git a/src/unix/pipe.c b/src/unix/pipe.c index 986ea7ce1..881dfdf8b 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -276,7 +276,7 @@ int do_pipe2(int fds[2], int flags) pipe_file reader = &pipe->files[PIPE_READ]; reader->fd = fds[PIPE_READ] = allocate_fd(pipe->p, reader); - fdesc_init(&reader->f); + fdesc_init(&reader->f, FDESC_TYPE_PIPE); reader->ns = allocate_notify_set(pipe->h); reader->bq = allocate_blockq(pipe->h, "pipe read", PIPE_BLOCKQ_LEN, 0); reader->f.read = closure(pipe->h, pipe_read, reader); @@ -284,7 +284,7 @@ int do_pipe2(int fds[2], int flags) reader->f.check = closure(pipe->h, pipe_read_check, reader); pipe_file writer = &pipe->files[PIPE_WRITE]; - fdesc_init(&writer->f); + fdesc_init(&writer->f, FDESC_TYPE_PIPE); writer->fd = fds[PIPE_WRITE] = allocate_fd(pipe->p, writer); writer->ns = allocate_notify_set(pipe->h); writer->bq = allocate_blockq(pipe->h, "pipe write", PIPE_BLOCKQ_LEN, 0); diff --git a/src/unix/poll.c b/src/unix/poll.c index 839084be4..b5b61df78 100644 --- a/src/unix/poll.c +++ b/src/unix/poll.c @@ -137,7 +137,7 @@ sysreturn epoll_create(u64 flags) rv = -EMFILE; goto out_cache_free; } - fdesc_init(&e->f); + fdesc_init(&e->f, FDESC_TYPE_EPOLL); e->f.close = closure(h, epoll_close, e); list_init(&e->blocked_head); e->events = allocate_vector(h, 8); diff --git a/src/unix/syscall.c b/src/unix/syscall.c index 76ba54347..af8669f5f 100644 --- a/src/unix/syscall.c +++ b/src/unix/syscall.c @@ -667,6 +667,16 @@ static boolean file_check(file f, fsfile fsf, u32 eventmask, u32 * last, event_h return true; } +static int file_type_from_tuple(tuple n) +{ + if (is_dir(n)) + return FDESC_TYPE_DIRECTORY; + else if (is_special(n)) + return FDESC_TYPE_SPECIAL; + else + return FDESC_TYPE_REGULAR; +} + sysreturn open_internal(tuple root, char *name, int flags, int mode) { heap h = heap_general(get_kernel_heaps()); @@ -692,9 +702,12 @@ sysreturn open_internal(tuple root, char *name, int flags, int mode) thread_log(current, "\"%s\" - not found", name); return set_syscall_error(current, ENOENT); } + u64 length = 0; fsfile fsf = 0; - if (!is_dir(n) && !is_special(n)) { + + int type = file_type_from_tuple(n); + if (type == FDESC_TYPE_REGULAR) { fsf = fsfile_from_node(current->p->fs, n); if (!fsf) { length = 0; @@ -702,19 +715,21 @@ sysreturn open_internal(tuple root, char *name, int flags, int mode) length = fsfile_get_length(fsf); } } - // might be functional, or be a directory + file f = unix_cache_alloc(uh, file); if (f == INVALID_ADDRESS) { thread_log(current, "failed to allocate struct file"); return set_syscall_error(current, ENOMEM); } + int fd = allocate_fd(current->p, f); if (fd == INVALID_PHYSICAL) { thread_log(current, "failed to allocate fd"); unix_cache_free(uh, file, f); return set_syscall_error(current, EMFILE); } - fdesc_init(&f->f); + + fdesc_init(&f->f, type); f->f.read = closure(h, file_read, f, fsf); f->f.write = closure(h, file_write, f, fsf); f->f.close = closure(h, file_close, f, fsf); @@ -1034,23 +1049,37 @@ sysreturn openat(int dirfd, char *name, int flags, int mode) return open_internal(f->n, name, flags, mode); } -static void fill_stat(tuple n, struct stat *s) +static void fill_stat(int type, tuple n, struct stat *s) { + switch (type) { + case FDESC_TYPE_REGULAR: + s->st_mode = S_IFREG | 0644; + break; + case FDESC_TYPE_DIRECTORY: + s->st_mode = S_IFDIR | 0777; + break; + case FDESC_TYPE_SPECIAL: + s->st_mode = S_IFCHR; /* assuming only character devs now */ + break; + case FDESC_TYPE_SOCKET: + s->st_mode = S_IFSOCK; + break; + case FDESC_TYPE_PIPE: + case FDESC_TYPE_STDIO: + s->st_mode = S_IFIFO; + break; + case FDESC_TYPE_EPOLL: + s->st_mode = S_IFCHR; /* XXX not clear - EBADF? */ + break; + } s->st_dev = 0; s->st_ino = u64_from_pointer(n); s->st_size = 0; - if (is_dir(n)) { - s->st_mode = S_IFDIR | 0777; - return; - } else if (!is_special(n)) { + if (type == FDESC_TYPE_REGULAR) { fsfile f = fsfile_from_node(current->p->fs, n); - if (!f) { - s->st_size = 0; - } else { + if (f) s->st_size = fsfile_get_length(f); - } } - s->st_mode = S_IFREG | 0644; /* TODO */ thread_log(current, "st_ino %P, st_mode %P, st_size %P", s->st_ino, s->st_mode, s->st_size); } @@ -1058,18 +1087,12 @@ static void fill_stat(tuple n, struct stat *s) static sysreturn fstat(int fd, struct stat *s) { thread_log(current, "fd %d, stat %p", fd, s); - file f = resolve_fd(current->p, fd); + fdesc f = resolve_fd(current->p, fd); zero(s, sizeof(struct stat)); - // take this from tuple space - if (fd == 0 || fd == 1 || fd == 2) { - s->st_mode = S_IFIFO; - return 0; - } - fill_stat(f->n, s); + fill_stat(f->type, ((file)f)->n, s); return 0; } - static sysreturn stat(char *name, struct stat *s) { thread_log(current, "name %s, stat %p", name, s); @@ -1078,7 +1101,8 @@ static sysreturn stat(char *name, struct stat *s) if (!(n = resolve_cstring(current->p->cwd, name))) { return set_syscall_error(current, ENOENT); } - fill_stat(n, s); + + fill_stat(file_type_from_tuple(n), n, s); return 0; } @@ -1103,7 +1127,8 @@ static sysreturn newfstatat(int dfd, char *name, struct stat *s, int flags) if (!(n = resolve_cstring(children, name))) { return set_syscall_error(current, ENOENT); } - fill_stat(n, s); + + fill_stat(file_type_from_tuple(n), n, s); return 0; } @@ -1212,6 +1237,7 @@ sysreturn readlinkat(int dirfd, const char *pathname, char *buf, u64 bufsiz) sysreturn close(int fd) { + thread_log(current, "close: fd %d", fd); fdesc f = resolve_fd(current->p, fd); deallocate_fd(current->p, fd); diff --git a/src/unix/unix.c b/src/unix/unix.c index 234a05fc1..917a7a74f 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -2,13 +2,14 @@ #include #include -void fdesc_init(fdesc f) +void fdesc_init(fdesc f, int type) { f->read = 0; f->write = 0; f->close = 0; f->check = 0; f->refcnt = 1; + f->type = type; f->flags = 0; } @@ -85,11 +86,11 @@ static boolean create_stdfiles(unix_heaps uh, process p) /* Writes to in, reads from out and err act as if handled by the out and in files respectively. */ - fdesc_init(&in->f); + fdesc_init(&in->f, FDESC_TYPE_STDIO); in->f.close = closure(h, std_close, in); - fdesc_init(&out->f); + fdesc_init(&out->f, FDESC_TYPE_STDIO); out->f.close = closure(h, std_close, out); - fdesc_init(&err->f); + fdesc_init(&err->f, FDESC_TYPE_STDIO); err->f.close = closure(h, std_close, err); in->f.write = out->f.write = err->f.write = closure(h, stdout); in->f.read = out->f.read = err->f.read = closure(h, dummy_read); diff --git a/src/unix/unix_internal.h b/src/unix/unix_internal.h index b336e6c37..e7027d697 100644 --- a/src/unix/unix_internal.h +++ b/src/unix/unix_internal.h @@ -104,11 +104,20 @@ typedef closure_type(io, sysreturn, void *, u64 length, u64 offset); #include +#define FDESC_TYPE_REGULAR 1 +#define FDESC_TYPE_DIRECTORY 2 +#define FDESC_TYPE_SPECIAL 3 +#define FDESC_TYPE_SOCKET 4 +#define FDESC_TYPE_PIPE 5 +#define FDESC_TYPE_STDIO 6 +#define FDESC_TYPE_EPOLL 7 + typedef struct fdesc { io read, write; closure_type(check, boolean, u32 eventmask, u32 * last, event_handler eh); closure_type(close, sysreturn); u64 refcnt; + int type; int flags; /* F_GETFD/F_SETFD flags */ } *fdesc; @@ -157,7 +166,7 @@ static inline kernel_heaps get_kernel_heaps() #define unix_cache_alloc(uh, c) ({ heap __c = uh->c ## _cache; allocate(__c, __c->pagesize); }) #define unix_cache_free(uh, c, p) ({ heap __c = uh->c ## _cache; deallocate(__c, p, __c->pagesize); }) -void fdesc_init(fdesc f); +void fdesc_init(fdesc f, int type); u64 allocate_fd(process p, void *f);