libc: Implement fcntl(F_DUPFD) and dup()

This commit is contained in:
apio 2022-10-15 11:16:34 +02:00
parent 36bb1cab5c
commit 1e86acd4c0
7 changed files with 53 additions and 2 deletions

View File

@ -141,5 +141,23 @@ int main()
printf("Press any key to restart.\n\n"); printf("Press any key to restart.\n\n");
int ferr = fileno(stderr);
int newerr = dup(ferr);
if (newerr < 0)
{
perror("dup");
return 1;
}
FILE* new_stderr = fdopen(newerr, "rw");
if (!new_stderr)
{
perror("fdopen");
return 1;
}
fprintf(new_stderr, "Bye!\n");
fclose(new_stderr);
return 0; return 0;
} }

View File

@ -20,7 +20,7 @@
#define FNCTL_DUPFD 0 #define FNCTL_DUPFD 0
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg) void sys_fcntl(Context* context, int fd, int command, [[maybe_unused]] uintptr_t arg)
{ {
if (fd >= TASK_MAX_FDS || fd < 0) if (fd >= TASK_MAX_FDS || fd < 0)
{ {
@ -34,7 +34,8 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
return; return;
} }
Descriptor& file = current_task->files[fd]; Descriptor& file = current_task->files[fd];
if (command == FNCTL_DUPFD) if (command == FNCTL_DUPFD) // FIXME: If arg is greater than 0, return the lowest numbered available file descriptor
// greater than or equal to arg.
{ {
int dupfd = current_task->alloc_fd(); int dupfd = current_task->alloc_fd();
if (dupfd < 0) if (dupfd < 0)

View File

@ -8,6 +8,9 @@
/* Open for reading and writing. */ /* Open for reading and writing. */
#define O_RDWR 3 #define O_RDWR 3
/* Duplicate a file descriptor. */
#define F_DUPFD 0
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -16,6 +19,9 @@ extern "C"
/* Opens the file specified by pathname. Returns a file descriptor on success, or -1 on error. */ /* Opens the file specified by pathname. Returns a file descriptor on success, or -1 on error. */
int open(const char* pathname, int flags); int open(const char* pathname, int flags);
/* Performs an operation on the file descriptor fd determined by cmd. */
int fcntl(int fd, int cmd, ...);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -15,6 +15,7 @@
#define SYS_close 11 #define SYS_close 11
#define SYS_seek 12 #define SYS_seek 12
#define SYS_exec 13 #define SYS_exec 13
#define SYS_fcntl 14
#ifndef __want_syscalls #ifndef __want_syscalls
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -45,6 +45,9 @@ extern "C"
/* Moves the read/write file offset for fd to offset, depending on whence. */ /* Moves the read/write file offset for fd to offset, depending on whence. */
off_t lseek(int fd, off_t offset, int whence); off_t lseek(int fd, off_t offset, int whence);
/* Returns a copy of the file descriptor fd. */
int dup(int fd);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,4 +1,5 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
@ -8,4 +9,18 @@ extern "C"
{ {
return (int)syscall(SYS_open, pathname, flags); return (int)syscall(SYS_open, pathname, flags);
} }
int fcntl(int fd, int cmd, ...)
{
va_list ap;
va_start(ap, cmd);
long result;
switch (cmd)
{
case F_DUPFD: result = syscall(SYS_fcntl, fd, cmd, va_arg(ap, int)); break;
default: result = syscall(SYS_fcntl, fd, cmd, 0); break;
}
va_end(ap);
return (int)result;
}
} }

View File

@ -1,4 +1,5 @@
#include <bits/error.h> #include <bits/error.h>
#include <fcntl.h>
#include <luna.h> #include <luna.h>
#include <luna/syscall.h> #include <luna/syscall.h>
#include <stdarg.h> #include <stdarg.h>
@ -45,6 +46,7 @@ extern "C"
result = __luna_syscall2(number, arg0, arg1); result = __luna_syscall2(number, arg0, arg1);
break; break;
} }
case SYS_fcntl:
case SYS_seek: case SYS_seek:
case SYS_write: case SYS_write:
case SYS_read: case SYS_read:
@ -101,4 +103,9 @@ extern "C"
syscall(SYS_exit, status); syscall(SYS_exit, status);
__builtin_unreachable(); __builtin_unreachable();
} }
int dup(int fd)
{
return fcntl(fd, F_DUPFD, 0);
}
} }