mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add dup3(2).
This commit is contained in:
parent
9700623737
commit
b399ece14b
7 changed files with 63 additions and 6 deletions
|
@ -397,6 +397,7 @@ unistd/chroot.o \
|
||||||
unistd/close.o \
|
unistd/close.o \
|
||||||
unistd/confstr.o \
|
unistd/confstr.o \
|
||||||
unistd/dup2.o \
|
unistd/dup2.o \
|
||||||
|
unistd/dup3.o \
|
||||||
unistd/dup.o \
|
unistd/dup.o \
|
||||||
unistd/execle.o \
|
unistd/execle.o \
|
||||||
unistd/execl.o \
|
unistd/execl.o \
|
||||||
|
|
|
@ -298,6 +298,7 @@ int chroot(const char*);
|
||||||
int close(int);
|
int close(int);
|
||||||
size_t confstr(int, char*, size_t);
|
size_t confstr(int, char*, size_t);
|
||||||
int dup2(int, int);
|
int dup2(int, int);
|
||||||
|
int dup3(int, int, int);
|
||||||
int dup(int);
|
int dup(int);
|
||||||
void _exit(int) __attribute__ ((noreturn));
|
void _exit(int) __attribute__ ((noreturn));
|
||||||
int execl(const char*, const char*, ...);
|
int execl(const char*, const char*, ...);
|
||||||
|
|
34
libc/unistd/dup3.cpp
Normal file
34
libc/unistd/dup3.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
||||||
|
|
||||||
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
unistd/dup3.cpp
|
||||||
|
Duplicates a file descriptor.
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
DEFN_SYSCALL3(int, sys_dup3, SYSCALL_DUP3, int, int, int);
|
||||||
|
|
||||||
|
extern "C" int dup3(int oldfd, int newfd, int flags)
|
||||||
|
{
|
||||||
|
return sys_dup3(oldfd, newfd, flags);
|
||||||
|
}
|
|
@ -122,8 +122,10 @@ int DescriptorTable::Allocate(Ref<Descriptor> desc, int flags)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DescriptorTable::Copy(int from, int to)
|
int DescriptorTable::Copy(int from, int to, int flags)
|
||||||
{
|
{
|
||||||
|
if ( flags & ~__FD_ALLOWED_FLAGS )
|
||||||
|
return errno = EINVAL, -1;
|
||||||
ScopedLock lock(&dtablelock);
|
ScopedLock lock(&dtablelock);
|
||||||
if ( from < 0 || to < 0 )
|
if ( from < 0 || to < 0 )
|
||||||
return errno = EINVAL, -1;
|
return errno = EINVAL, -1;
|
||||||
|
@ -131,6 +133,8 @@ int DescriptorTable::Copy(int from, int to)
|
||||||
return errno = EBADF, -1;
|
return errno = EBADF, -1;
|
||||||
if ( !entries[from].desc )
|
if ( !entries[from].desc )
|
||||||
return errno = EBADF, -1;
|
return errno = EBADF, -1;
|
||||||
|
if ( from == to )
|
||||||
|
return errno = EINVAL, -1;
|
||||||
while ( !(to < numentries) )
|
while ( !(to < numentries) )
|
||||||
if ( !Enlargen(to+1) )
|
if ( !Enlargen(to+1) )
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -139,8 +143,8 @@ int DescriptorTable::Copy(int from, int to)
|
||||||
if ( entries[to].desc )
|
if ( entries[to].desc )
|
||||||
/* TODO: Should this be synced or otherwise properly closed? */{}
|
/* TODO: Should this be synced or otherwise properly closed? */{}
|
||||||
entries[to].desc = entries[from].desc;
|
entries[to].desc = entries[from].desc;
|
||||||
entries[to].flags = entries[from].flags;
|
|
||||||
}
|
}
|
||||||
|
entries[to].flags = flags;
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
Ref<DescriptorTable> Fork();
|
Ref<DescriptorTable> Fork();
|
||||||
Ref<Descriptor> Get(int index);
|
Ref<Descriptor> Get(int index);
|
||||||
int Allocate(Ref<Descriptor> desc, int flags);
|
int Allocate(Ref<Descriptor> desc, int flags);
|
||||||
int Copy(int from, int to);
|
int Copy(int from, int to, int flags);
|
||||||
void Free(int index);
|
void Free(int index);
|
||||||
Ref<Descriptor> FreeKeep(int index);
|
Ref<Descriptor> FreeKeep(int index);
|
||||||
void OnExecute();
|
void OnExecute();
|
||||||
|
|
|
@ -143,6 +143,7 @@
|
||||||
#define SYSCALL_GETPRIORITY 119
|
#define SYSCALL_GETPRIORITY 119
|
||||||
#define SYSCALL_SETPRIORITY 120
|
#define SYSCALL_SETPRIORITY 120
|
||||||
#define SYSCALL_PRLIMIT 121
|
#define SYSCALL_PRLIMIT 121
|
||||||
#define SYSCALL_MAX_NUM 122 /* index of highest constant + 1 */
|
#define SYSCALL_DUP3 122
|
||||||
|
#define SYSCALL_MAX_NUM 123 /* index of highest constant + 1 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -128,10 +128,25 @@ static int sys_dup(int fd)
|
||||||
return dtable->Allocate(desc, 0);
|
return dtable->Allocate(desc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sys_dup3(int oldfd, int newfd, int flags)
|
||||||
|
{
|
||||||
|
if ( flags & ~(O_CLOEXEC | O_CLOFORK) )
|
||||||
|
return errno = EINVAL, -1;
|
||||||
|
int fd_flags = 0;
|
||||||
|
flags |= flags & O_CLOEXEC ? FD_CLOEXEC : 0;
|
||||||
|
flags |= flags & O_CLOFORK ? FD_CLOFORK : 0;
|
||||||
|
Ref<DescriptorTable> dtable = CurrentProcess()->GetDTable();
|
||||||
|
return dtable->Copy(oldfd, newfd, fd_flags);
|
||||||
|
}
|
||||||
|
|
||||||
static int sys_dup2(int oldfd, int newfd)
|
static int sys_dup2(int oldfd, int newfd)
|
||||||
{
|
{
|
||||||
Ref<DescriptorTable> dtable = CurrentProcess()->GetDTable();
|
if ( oldfd < 0 || newfd < 0 )
|
||||||
return dtable->Copy(oldfd, newfd);
|
return errno = EINVAL, -1;
|
||||||
|
int ret = sys_dup3(oldfd, newfd, 0);
|
||||||
|
if ( ret < 0 && errno == EINVAL )
|
||||||
|
return errno = 0, newfd;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: If this function fails the file may still have been created. Does a
|
// TODO: If this function fails the file may still have been created. Does a
|
||||||
|
@ -949,6 +964,7 @@ void Init()
|
||||||
Syscall::Register(SYSCALL_CLOSE, (void*) sys_close);
|
Syscall::Register(SYSCALL_CLOSE, (void*) sys_close);
|
||||||
Syscall::Register(SYSCALL_CONNECT, (void*) sys_connect);
|
Syscall::Register(SYSCALL_CONNECT, (void*) sys_connect);
|
||||||
Syscall::Register(SYSCALL_DUP2, (void*) sys_dup2);
|
Syscall::Register(SYSCALL_DUP2, (void*) sys_dup2);
|
||||||
|
Syscall::Register(SYSCALL_DUP3, (void*) sys_dup3);
|
||||||
Syscall::Register(SYSCALL_DUP, (void*) sys_dup);
|
Syscall::Register(SYSCALL_DUP, (void*) sys_dup);
|
||||||
Syscall::Register(SYSCALL_FACCESSAT, (void*) sys_faccessat);
|
Syscall::Register(SYSCALL_FACCESSAT, (void*) sys_faccessat);
|
||||||
Syscall::Register(SYSCALL_FCHDIRAT, (void*) sys_fchdirat);
|
Syscall::Register(SYSCALL_FCHDIRAT, (void*) sys_fchdirat);
|
||||||
|
|
Loading…
Reference in a new issue