diff --git a/kernel/src/sys/open.cpp b/kernel/src/sys/open.cpp index c85dfdb9..930915e7 100644 --- a/kernel/src/sys/open.cpp +++ b/kernel/src/sys/open.cpp @@ -28,6 +28,12 @@ Result sys_openat(Registers*, SyscallArgs args) if ((flags & O_WRONLY) || (flags & O_CREAT)) return err(EINVAL); } + if (flags & O_TMPFILE) + { + if (!(flags & O_WRONLY)) return err(EINVAL); + if (flags & O_CREAT) return err(EINVAL); + } + int error; SharedPtr parent_inode; bool ok = current->resolve_atfile(dirfd, path, false, &parent_inode).try_set_value_or_error(inode, error); @@ -50,6 +56,14 @@ Result sys_openat(Registers*, SyscallArgs args) if ((flags & O_WRONLY) && !VFS::can_write(inode, current->auth)) return err(EACCES); } + if (flags & O_TMPFILE) + { + if (inode->type() != VFS::InodeType::Directory) return err(EINVAL); + inode = TRY(inode->fs().create_file_inode()); + inode->chmod(mode); + inode->chown(current->auth.euid, current->auth.egid); + } + if (inode->type() != VFS::InodeType::Directory && (flags & O_DIRECTORY)) return err(ENOTDIR); if ((flags & O_WRONLY) && (flags & O_TRUNC)) inode->truncate(0); diff --git a/libc/include/bits/open-flags.h b/libc/include/bits/open-flags.h index 58179a8c..e2d8b2ac 100644 --- a/libc/include/bits/open-flags.h +++ b/libc/include/bits/open-flags.h @@ -13,6 +13,7 @@ #define O_NONBLOCK 64 #define O_CLOEXEC 128 #define O_DIRECTORY 256 +#define O_TMPFILE 512 #define O_ACCMODE O_RDWR diff --git a/libc/include/stdio.h b/libc/include/stdio.h index 88e6f5fd..eb6abb83 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -91,7 +91,7 @@ extern "C" int getc(FILE* stream); /* Read a character from standard input. */ - int getchar(); + int getchar(void); /* Read a line from stream. */ char* fgets(char* buf, size_t size, FILE* stream); @@ -134,6 +134,9 @@ extern "C" /* Remove a file from the filesystem. */ int remove(const char* path); + /* Create a unique temporary file. */ + FILE* tmpfile(void); + #ifdef __cplusplus } #endif diff --git a/libc/src/stdio.cpp b/libc/src/stdio.cpp index 97cc3ad2..648d6c23 100644 --- a/libc/src/stdio.cpp +++ b/libc/src/stdio.cpp @@ -341,6 +341,17 @@ extern "C" // On Luna, unlink() allows removal of directories. return unlink(path); } + + FILE* tmpfile() + { + // FIXME: use /tmp as the directory when the tmpfs is mounted only there. + int fd = open("/", O_RDWR | O_TMPFILE, 0600); + if (fd < 0) return nullptr; + + FILE* f = fdopen(fd, "w+b"); + if (!f) close(fd); + return f; + } } void debug_log_impl(const char* format, va_list ap)