diff --git a/sortix/descriptors.cpp b/sortix/descriptors.cpp index 8c3b787f..2360a820 100644 --- a/sortix/descriptors.cpp +++ b/sortix/descriptors.cpp @@ -1,6 +1,6 @@ -/****************************************************************************** +/******************************************************************************* - COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2012. This file is part of Sortix. @@ -14,18 +14,19 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Sortix. If not, see . + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . descriptors.cpp Handles file descriptors, socket descriptors, and whatnot for each process. -******************************************************************************/ +*******************************************************************************/ #include "platform.h" #include #include "descriptors.h" #include "device.h" +#include using namespace Maxsi; @@ -33,7 +34,7 @@ namespace Sortix { // When in doubt use brute-force. This class could easily be optimized. - Device* const reserveddevideptr = (Device*) 0x1UL; + Device* const RESERVED_DEVICE = (Device*) 0x1UL; DescriptorTable::DescriptorTable() { @@ -50,9 +51,10 @@ namespace Sortix { for ( int i = 0; i < numdevices; i++ ) { - if ( devices[i] == NULL || devices[i] == reserveddevideptr ) { continue; } + Device* dev = devices[i].dev; + if ( !dev || dev == RESERVED_DEVICE ) { continue; } - devices[i]->Unref(); + dev->Unref(); } delete[] devices; @@ -64,10 +66,11 @@ namespace Sortix { for ( int i = 0; i < numdevices; i++ ) { - if ( devices[i] == NULL ) + if ( !devices[i].dev ) { object->Refer(); - devices[i] = object; + devices[i].dev = object; + devices[i].flags = 0; return i; } } @@ -75,15 +78,16 @@ namespace Sortix int newlistlength = numdevices*2; if ( newlistlength == 0 ) { newlistlength = 8; } - Device** newlist = new Device*[newlistlength]; + DescriptorEntry* newlist = new DescriptorEntry[newlistlength]; if ( newlist == NULL ) { return -1; } if ( devices != NULL ) { - Memory::Copy(newlist, devices, sizeof(Device*) * numdevices); + Memory::Copy(newlist, devices, sizeof(*devices) * numdevices); } - Memory::Set(newlist + numdevices, 0, sizeof(Device*) * (newlistlength-numdevices)); + size_t numpadded = newlistlength-numdevices; + Memory::Set(newlist + numdevices, 0, sizeof(*devices) * numpadded); delete[] devices; @@ -96,50 +100,77 @@ namespace Sortix void DescriptorTable::Free(int index) { ASSERT(index < numdevices); - ASSERT(devices[index] != NULL); + ASSERT(devices[index].dev); - if ( devices[index] != reserveddevideptr ) + if ( devices[index].dev != RESERVED_DEVICE ) { - devices[index]->Unref(); + devices[index].dev->Unref(); } - devices[index] = NULL; + devices[index].dev = NULL; + devices[index].flags = 0; } int DescriptorTable::Reserve() { - return Allocate(reserveddevideptr); + return Allocate(RESERVED_DEVICE); } void DescriptorTable::UseReservation(int index, Device* object) { ASSERT(index < index); - ASSERT(devices[index] != NULL); - ASSERT(devices[index] == reserveddevideptr); + ASSERT(devices[index].dev != NULL); + ASSERT(devices[index].dev == RESERVED_DEVICE); object->Refer(); - devices[index] = object; + devices[index].dev = object; + devices[index].flags = 0; } bool DescriptorTable::Fork(DescriptorTable* forkinto) { - Device** newlist = new Device*[numdevices]; - if ( newlist == NULL ) { return false; } + DescriptorEntry* newlist = new DescriptorEntry[numdevices]; + if ( !newlist ) { return false; } for ( int i = 0; i < numdevices; i++ ) { - // TODO: Possibly deal with a potential O_CLOFORK! - newlist[i] = devices[i]; - if ( !devices[i] ) { continue; } - if ( devices[i] == reserveddevideptr ) { continue; } - newlist[i]->Refer(); + Device* dev = devices[i].dev; + int flags = devices[i].flags; + if ( flags & FD_CLOFORK ) { dev = NULL; flags = 0; } + newlist[i].dev = dev; + newlist[i].flags = flags; + if ( !dev || dev == RESERVED_DEVICE ) { continue; } + newlist[i].dev->Refer(); } - ASSERT(forkinto->devices == NULL); + ASSERT(!forkinto->devices); forkinto->devices = newlist; forkinto->numdevices = numdevices; return true; } + + void DescriptorTable::OnExecute() + { + for ( int i = 0; i < numdevices; i++ ) + { + if ( devices[i].flags & FD_CLOEXEC ) { Free(i); } + } + } + + void DescriptorTable::SetFlags(int index, int flags) + { + ASSERT(0 <= index && index < numdevices); + ASSERT(devices[index].dev); + devices[index].flags = flags; + } + + int DescriptorTable::GetFlags(int index) + { + ASSERT(0 <= index && index < numdevices); + ASSERT(devices[index].dev); + return devices[index].flags; + } } + diff --git a/sortix/descriptors.h b/sortix/descriptors.h index 91d93cd0..086d35db 100644 --- a/sortix/descriptors.h +++ b/sortix/descriptors.h @@ -1,6 +1,6 @@ -/****************************************************************************** +/******************************************************************************* - COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2012. This file is part of Sortix. @@ -14,13 +14,13 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Sortix. If not, see . + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . descriptors.h Handles file descriptors, socket descriptors, and whatnot for each process. -******************************************************************************/ +*******************************************************************************/ #ifndef SORTIX_DESCRIPTORS_H #define SORTIX_DESCRIPTORS_H @@ -29,6 +29,12 @@ namespace Sortix { class Device; + struct DescriptorEntry + { + Device* dev; + int flags; + }; + class DescriptorTable { public: @@ -37,7 +43,7 @@ namespace Sortix private: int numdevices; - Device** devices; + DescriptorEntry* devices; public: int Allocate(Device* object); @@ -45,14 +51,17 @@ namespace Sortix void Free(int index); void UseReservation(int index, Device* object); bool Fork(DescriptorTable* forkinto); + void OnExecute(); void Reset(); + void SetFlags(int index, int flags); + int GetFlags(int index); public: inline Device* Get(int index) { if ( !devices ) { return NULL; } if ( index < 0 || numdevices <= index ) { return NULL; } - return devices[index]; + return devices[index].dev; } }; diff --git a/sortix/fcntl.h b/sortix/fcntl.h index 56d798e6..b615196f 100644 --- a/sortix/fcntl.h +++ b/sortix/fcntl.h @@ -41,6 +41,10 @@ __BEGIN_DECLS #define O_DIRECTORY (1<<6) #define O_EXCL (1<<7) #define O_TRUNC (1<<8) +#define O_CLOFORK (1<<9) + +#define FD_CLOEXEC (1<<0) +#define FD_CLOFORK (1<<1) __END_DECLS diff --git a/sortix/filesystem.cpp b/sortix/filesystem.cpp index 6a35f764..d148b786 100644 --- a/sortix/filesystem.cpp +++ b/sortix/filesystem.cpp @@ -31,6 +31,7 @@ #include "filesystem.h" #include "directory.h" #include "mount.h" +#include using namespace Maxsi; @@ -75,6 +76,10 @@ namespace Sortix if ( !dev ) { return -1; /* TODO: errno */ } int fd = process->descriptors.Allocate(dev); if ( fd < 0 ) { dev->Unref(); } + int fdflags = 0; + if ( flags & O_CLOEXEC ) { fdflags |= FD_CLOEXEC; } + if ( flags & O_CLOFORK ) { fdflags |= FD_CLOFORK; } + process->descriptors.SetFlags(fd, fdflags); return fd; } diff --git a/sortix/process.cpp b/sortix/process.cpp index 2e2d08cc..9e38956b 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -288,6 +288,8 @@ namespace Sortix ExecuteCPU(argc, stackargv, stackpos, entry, regs); + descriptors.OnExecute(); + return 0; }