diff --git a/libc/Makefile b/libc/Makefile
index 69161d14..895aa547 100644
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -172,6 +172,7 @@ canonicalize_file_name.o \
chdir.o \
chmod.o \
chown.o \
+chroot.o \
close.o \
confstr.o \
$(CPUDIR)/calltrace.o \
@@ -204,6 +205,8 @@ fchmodat.o \
fchmod.o \
fchownat.o \
fchown.o \
+fchrootat.o \
+fchroot.o \
fcloseall.o \
fcntl.o \
fddir-sortix.o \
diff --git a/libc/chroot.cpp b/libc/chroot.cpp
new file mode 100644
index 00000000..98230afc
--- /dev/null
+++ b/libc/chroot.cpp
@@ -0,0 +1,31 @@
+/*******************************************************************************
+
+ 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 .
+
+ chroot.cpp
+ Changes the root directory.
+
+*******************************************************************************/
+
+#include
+#include
+
+extern "C" int chroot(const char* path)
+{
+ return fchrootat(AT_FDCWD, path);
+}
diff --git a/libc/fchroot.cpp b/libc/fchroot.cpp
new file mode 100644
index 00000000..d463168e
--- /dev/null
+++ b/libc/fchroot.cpp
@@ -0,0 +1,33 @@
+/*******************************************************************************
+
+ 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 .
+
+ fchroot.cpp
+ Changes the root directory.
+
+*******************************************************************************/
+
+#include
+#include
+
+DEFN_SYSCALL1(int, sys_fchroot, SYSCALL_FCHROOT, int);
+
+extern "C" int fchroot(int fd)
+{
+ return sys_fchroot(fd);
+}
diff --git a/libc/fchrootat.cpp b/libc/fchrootat.cpp
new file mode 100644
index 00000000..bd24c588
--- /dev/null
+++ b/libc/fchrootat.cpp
@@ -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 .
+
+ fchrootat.cpp
+ Changes the root directory.
+
+*******************************************************************************/
+
+#include
+
+#include
+
+DEFN_SYSCALL2(int, sys_fchrootat, SYSCALL_FCHROOTAT, int, const char*);
+
+extern "C" int fchrootat(int dirfd, const char* path)
+{
+ return sys_fchrootat(dirfd, path);
+}
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index b9aa7016..3dcdd5bd 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -302,6 +302,7 @@ int access(const char*, int);
unsigned alarm(unsigned);
int chdir(const char*);
int chown(const char*, uid_t, gid_t);
+int chroot(const char*);
int close(int);
size_t confstr(int, char*, size_t);
int dup2(int, int);
@@ -319,6 +320,8 @@ int fchdir(int);
int fchdirat(int, const char*);
int fchown(int, uid_t, gid_t);
int fchownat(int, const char*, uid_t, gid_t, int);
+int fchroot(int);
+int fchrootat(int, const char*);
int fsync(int);
int ftruncate(int, off_t);
char* getcwd(char*, size_t);
diff --git a/sortix/include/sortix/kernel/process.h b/sortix/include/sortix/kernel/process.h
index 91d0837f..e74fc5f8 100644
--- a/sortix/include/sortix/kernel/process.h
+++ b/sortix/include/sortix/kernel/process.h
@@ -120,6 +120,7 @@ public:
Ref GetDescriptor(int fd);
// TODO: This should be removed, don't call it.
Ref Open(ioctx_t* ctx, const char* path, int flags, mode_t mode = 0);
+ void SetRoot(Ref newroot);
void SetCWD(Ref newcwd);
private:
diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h
index fce88e59..0bff873b 100644
--- a/sortix/include/sortix/syscallnum.h
+++ b/sortix/include/sortix/syscallnum.h
@@ -130,6 +130,8 @@
#define SYSCALL_TIMENS 106
#define SYSCALL_UMASK 107
#define SYSCALL_FCHDIRAT 108
-#define SYSCALL_MAX_NUM 109 /* index of highest constant + 1 */
+#define SYSCALL_FCHROOT 109
+#define SYSCALL_FCHROOTAT 110
+#define SYSCALL_MAX_NUM 111 /* index of highest constant + 1 */
#endif
diff --git a/sortix/io.cpp b/sortix/io.cpp
index ecb71b7b..34f3fbba 100644
--- a/sortix/io.cpp
+++ b/sortix/io.cpp
@@ -390,6 +390,35 @@ static int sys_chdir(const char* path)
return sys_fchdirat(AT_FDCWD, path);
}
+static int sys_fchroot(int fd)
+{
+ Process* process = CurrentProcess();
+ Ref desc = process->GetDescriptor(fd);
+ if ( !desc )
+ return -1;
+ if ( !S_ISDIR(desc->type) )
+ return errno = ENOTDIR, -1;
+ process->SetRoot(desc);
+ return 0;
+}
+
+static int sys_fchrootat(int dirfd, const char* path)
+{
+ char* pathcopy = GetStringFromUser(path);
+ if ( !pathcopy )
+ return -1;
+ ioctx_t ctx; SetupUserIOCtx(&ctx);
+ const char* relpath = pathcopy;
+ Ref from = PrepareLookup(&relpath, dirfd);
+ Ref desc = from->open(&ctx, relpath, O_READ | O_DIRECTORY);
+ from.Reset();
+ delete[] pathcopy;
+ if ( !desc )
+ return -1;
+ CurrentProcess()->SetRoot(desc);
+ return 0;
+}
+
static int sys_fchown(int fd, uid_t owner, gid_t group)
{
Ref desc = CurrentProcess()->GetDescriptor(fd);
@@ -876,6 +905,8 @@ void Init()
Syscall::Register(SYSCALL_FCHMOD, (void*) sys_fchmod);
Syscall::Register(SYSCALL_FCHOWNAT, (void*) sys_fchownat);
Syscall::Register(SYSCALL_FCHOWN, (void*) sys_fchown);
+ Syscall::Register(SYSCALL_FCHROOTAT, (void*) sys_fchrootat);
+ Syscall::Register(SYSCALL_FCHROOT, (void*) sys_fchroot);
Syscall::Register(SYSCALL_FCNTL, (void*) sys_fcntl);
Syscall::Register(SYSCALL_FSTATAT, (void*) sys_fstatat);
Syscall::Register(SYSCALL_FSTAT, (void*) sys_fstat);
diff --git a/sortix/process.cpp b/sortix/process.cpp
index 941c0a55..c9fff14f 100644
--- a/sortix/process.cpp
+++ b/sortix/process.cpp
@@ -546,6 +546,13 @@ namespace Sortix
return cwd;
}
+ void Process::SetRoot(Ref newroot)
+ {
+ ScopedLock lock(&ptrlock);
+ assert(newroot);
+ root = newroot;
+ }
+
void Process::SetCWD(Ref newcwd)
{
ScopedLock lock(&ptrlock);