summaryrefslogtreecommitdiff
path: root/Platform/Unix
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/Unix')
-rw-r--r--Platform/Unix/Directory.cpp62
-rw-r--r--Platform/Unix/File.cpp348
-rw-r--r--Platform/Unix/FilesystemPath.cpp96
-rw-r--r--Platform/Unix/Mutex.cpp62
-rw-r--r--Platform/Unix/Pipe.cpp65
-rw-r--r--Platform/Unix/Pipe.h38
-rw-r--r--Platform/Unix/Poller.cpp57
-rw-r--r--Platform/Unix/Poller.h33
-rw-r--r--Platform/Unix/Process.cpp202
-rw-r--r--Platform/Unix/Process.h40
-rw-r--r--Platform/Unix/SyncEvent.cpp68
-rw-r--r--Platform/Unix/System.h12
-rw-r--r--Platform/Unix/SystemException.cpp66
-rw-r--r--Platform/Unix/SystemInfo.cpp69
-rw-r--r--Platform/Unix/SystemLog.cpp27
-rw-r--r--Platform/Unix/Thread.cpp54
-rw-r--r--Platform/Unix/Time.cpp23
17 files changed, 1322 insertions, 0 deletions
diff --git a/Platform/Unix/Directory.cpp b/Platform/Unix/Directory.cpp
new file mode 100644
index 0000000..0a0088a
--- /dev/null
+++ b/Platform/Unix/Directory.cpp
@@ -0,0 +1,62 @@
+/*
+ Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include "System.h"
+#include "Platform/Directory.h"
+#include "Platform/Finally.h"
+#include "Platform/SystemException.h"
+
+namespace TrueCrypt
+{
+ static Mutex ReadDirMutex; // readdir_r() may be unsafe on some systems
+
+ void Directory::Create (const DirectoryPath &path)
+ {
+ string p = path;
+ throw_sys_sub_if (mkdir (p.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) == -1, p);
+ }
+
+ DirectoryPath Directory::AppendSeparator (const DirectoryPath &path)
+ {
+ wstring p (path);
+
+ if (p.find_last_of (L'/') + 1 != p.size())
+ return p + L'/';
+
+ return p;
+ }
+
+ FilePathList Directory::GetFilePaths (const DirectoryPath &path, bool regularFilesOnly)
+ {
+ DIR *dir = opendir (string (path).c_str());
+ throw_sys_sub_if (!dir, wstring (path));
+ finally_do_arg (DIR*, dir, { closedir (finally_arg); });
+
+ ScopeLock lock (ReadDirMutex);
+
+ FilePathList files;
+ struct dirent *dirEntry;
+ errno = 0;
+ while ((dirEntry = readdir (dir)) != nullptr)
+ {
+ shared_ptr <FilePath> filePath (new FilePath (string (AppendSeparator (path)) + string (dirEntry->d_name)));
+
+ if (!regularFilesOnly || filePath->IsFile())
+ files.push_back (filePath);
+
+ errno = 0;
+ }
+
+ throw_sys_sub_if (errno != 0, wstring (path));
+ return files;
+ }
+}
diff --git a/Platform/Unix/File.cpp b/Platform/Unix/File.cpp
new file mode 100644
index 0000000..d69cb1d
--- /dev/null
+++ b/Platform/Unix/File.cpp
@@ -0,0 +1,348 @@
+/*
+ Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <utime.h>
+
+#ifdef TC_LINUX
+#include <sys/mount.h>
+#endif
+
+#ifdef TC_BSD
+#include <sys/disk.h>
+#endif
+
+#ifdef TC_SOLARIS
+#include <stropts.h>
+#include <sys/dkio.h>
+#endif
+
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "Platform/File.h"
+#include "Platform/TextReader.h"
+
+namespace TrueCrypt
+{
+#if 0
+# define TC_TRACE_FILE_OPERATIONS
+
+ static void TraceFileOperation (int fileHandle, FilePath filePath, bool write, uint64 length, int64 position = -1)
+ {
+ string path = filePath;
+ if (path.empty() || path.find ("truecrypt_aux_mnt") != string::npos)
+ return;
+
+ stringstream s;
+ s << path << ": " << (write ? "W " : "R ") << (position == -1 ? lseek (fileHandle, 0, SEEK_CUR) : position) << " (" << length << ")";
+ SystemLog::WriteError (s.str());
+ }
+#endif
+
+ void File::Close ()
+ {
+ if_debug (ValidateState());
+
+ if (!SharedHandle)
+ {
+ close (FileHandle);
+ FileIsOpen = false;
+
+ if ((mFileOpenFlags & File::PreserveTimestamps) && Path.IsFile())
+ {
+ struct utimbuf u;
+ u.actime = AccTime;
+ u.modtime = ModTime;
+
+ try
+ {
+ throw_sys_sub_if (utime (string (Path).c_str(), &u) == -1, wstring (Path));
+ }
+ catch (...) // Suppress errors to allow using read-only files
+ {
+#ifdef DEBUG
+ throw;
+#endif
+ }
+ }
+ }
+ }
+
+ void File::Delete ()
+ {
+ Close();
+ Path.Delete();
+ }
+
+
+ void File::Flush () const
+ {
+ if_debug (ValidateState());
+ throw_sys_sub_if (fsync (FileHandle) != 0, wstring (Path));
+ }
+
+ uint32 File::GetDeviceSectorSize () const
+ {
+ if (Path.IsDevice())
+ {
+#ifdef TC_LINUX
+ int blockSize;
+ throw_sys_sub_if (ioctl (FileHandle, BLKSSZGET, &blockSize) == -1, wstring (Path));
+ return blockSize;
+
+#elif defined (TC_MACOSX)
+ uint32 blockSize;
+ throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path));
+ return blockSize;
+
+#elif defined (TC_FREEBSD)
+ u_int sectorSize;
+ throw_sys_sub_if (ioctl (FileHandle, DIOCGSECTORSIZE, &sectorSize) == -1, wstring (Path));
+ return (uint32) sectorSize;
+
+#elif defined (TC_SOLARIS)
+ struct dk_minfo mediaInfo;
+ throw_sys_sub_if (ioctl (FileHandle, DKIOCGMEDIAINFO, &mediaInfo) == -1, wstring (Path));
+ return mediaInfo.dki_lbsize;
+
+#else
+# error GetDeviceSectorSize()
+#endif
+ }
+ else
+ throw ParameterIncorrect (SRC_POS);
+ }
+
+ uint64 File::GetPartitionDeviceStartOffset () const
+ {
+#ifdef TC_LINUX
+
+ // HDIO_GETGEO ioctl is limited by the size of long
+ TextReader tr ("/sys/block/" + string (Path.ToHostDriveOfPartition().ToBaseName()) + "/" + string (Path.ToBaseName()) + "/start");
+
+ string line;
+ tr.ReadLine (line);
+ return StringConverter::ToUInt64 (line) * GetDeviceSectorSize();
+
+#elif defined (TC_MACOSX)
+
+#ifndef DKIOCGETBASE
+# define DKIOCGETBASE _IOR('d', 73, uint64)
+#endif
+ uint64 offset;
+ throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBASE, &offset) == -1, wstring (Path));
+ return offset;
+
+#elif defined (TC_SOLARIS)
+
+ struct extpart_info partInfo;
+ throw_sys_sub_if (ioctl (FileHandle, DKIOCEXTPARTINFO, &partInfo) == -1, wstring (Path));
+ return partInfo.p_start * GetDeviceSectorSize();
+
+#else
+ throw NotImplemented (SRC_POS);
+#endif
+ }
+
+ uint64 File::Length () const
+ {
+ if_debug (ValidateState());
+
+ // BSD does not support seeking to the end of a device
+#ifdef TC_BSD
+ if (Path.IsBlockDevice() || Path.IsCharacterDevice())
+ {
+# ifdef TC_MACOSX
+ uint32 blockSize;
+ uint64 blockCount;
+ throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path));
+ throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKCOUNT, &blockCount) == -1, wstring (Path));
+ return blockCount * blockSize;
+# else
+ uint64 mediaSize;
+ throw_sys_sub_if (ioctl (FileHandle, DIOCGMEDIASIZE, &mediaSize) == -1, wstring (Path));
+ return mediaSize;
+# endif
+ }
+#endif
+ off_t current = lseek (FileHandle, 0, SEEK_CUR);
+ throw_sys_sub_if (current == -1, wstring (Path));
+ SeekEnd (0);
+ uint64 length = lseek (FileHandle, 0, SEEK_CUR);
+ SeekAt (current);
+ return length;
+ }
+
+ void File::Open (const FilePath &path, FileOpenMode mode, FileShareMode shareMode, FileOpenFlags flags)
+ {
+#ifdef TC_LINUX
+ int sysFlags = O_LARGEFILE;
+#else
+ int sysFlags = 0;
+#endif
+
+ switch (mode)
+ {
+ case CreateReadWrite:
+ sysFlags |= O_CREAT | O_TRUNC | O_RDWR;
+ break;
+
+ case CreateWrite:
+ sysFlags |= O_CREAT | O_TRUNC | O_WRONLY;
+ break;
+
+ case OpenRead:
+ sysFlags |= O_RDONLY;
+ break;
+
+ case OpenWrite:
+ sysFlags |= O_WRONLY;
+ break;
+
+ case OpenReadWrite:
+ sysFlags |= O_RDWR;
+ break;
+
+ default:
+ throw ParameterIncorrect (SRC_POS);
+ }
+
+ if ((flags & File::PreserveTimestamps) && path.IsFile())
+ {
+ struct stat statData;
+ throw_sys_sub_if (stat (string (path).c_str(), &statData) == -1, wstring (path));
+ AccTime = statData.st_atime;
+ ModTime = statData.st_mtime;
+ }
+
+ FileHandle = open (string (path).c_str(), sysFlags, S_IRUSR | S_IWUSR);
+ throw_sys_sub_if (FileHandle == -1, wstring (path));
+
+#if 0 // File locking is disabled to avoid remote filesystem locking issues
+ try
+ {
+ struct flock fl;
+ memset (&fl, 0, sizeof (fl));
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+
+ switch (shareMode)
+ {
+ case ShareNone:
+ fl.l_type = F_WRLCK;
+ if (fcntl (FileHandle, F_SETLK, &fl) == -1)
+ throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path));
+ break;
+
+ case ShareRead:
+ fl.l_type = F_RDLCK;
+ if (fcntl (FileHandle, F_SETLK, &fl) == -1)
+ throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path));
+ break;
+
+ case ShareReadWrite:
+ fl.l_type = (mode == OpenRead ? F_RDLCK : F_WRLCK);
+ if (fcntl (FileHandle, F_GETLK, &fl) != -1 && fl.l_type != F_UNLCK)
+ {
+ errno = EAGAIN;
+ throw SystemException (SRC_POS, wstring (path));
+ }
+ break;
+
+ case ShareReadWriteIgnoreLock:
+ break;
+
+ default:
+ throw ParameterIncorrect (SRC_POS);
+ }
+ }
+ catch (...)
+ {
+ close (FileHandle);
+ throw;
+ }
+#endif // 0
+
+ Path = path;
+ mFileOpenFlags = flags;
+ FileIsOpen = true;
+ }
+
+ uint64 File::Read (const BufferPtr &buffer) const
+ {
+ if_debug (ValidateState());
+
+#ifdef TC_TRACE_FILE_OPERATIONS
+ TraceFileOperation (FileHandle, Path, false, buffer.Size());
+#endif
+ ssize_t bytesRead = read (FileHandle, buffer, buffer.Size());
+ throw_sys_sub_if (bytesRead == -1, wstring (Path));
+
+ return bytesRead;
+ }
+
+ uint64 File::ReadAt (const BufferPtr &buffer, uint64 position) const
+ {
+ if_debug (ValidateState());
+
+#ifdef TC_TRACE_FILE_OPERATIONS
+ TraceFileOperation (FileHandle, Path, false, buffer.Size(), position);
+#endif
+ ssize_t bytesRead = pread (FileHandle, buffer, buffer.Size(), position);
+ throw_sys_sub_if (bytesRead == -1, wstring (Path));
+
+ return bytesRead;
+ }
+
+ void File::SeekAt (uint64 position) const
+ {
+ if_debug (ValidateState());
+ throw_sys_sub_if (lseek (FileHandle, position, SEEK_SET) == -1, wstring (Path));
+ }
+
+ void File::SeekEnd (int offset) const
+ {
+ if_debug (ValidateState());
+
+ // BSD does not support seeking to the end of a device
+#ifdef TC_BSD
+ if (Path.IsBlockDevice() || Path.IsCharacterDevice())
+ {
+ SeekAt (Length() + offset);
+ return;
+ }
+#endif
+
+ throw_sys_sub_if (lseek (FileHandle, offset, SEEK_END) == -1, wstring (Path));
+ }
+
+ void File::Write (const ConstBufferPtr &buffer) const
+ {
+ if_debug (ValidateState());
+
+#ifdef TC_TRACE_FILE_OPERATIONS
+ TraceFileOperation (FileHandle, Path, true, buffer.Size());
+#endif
+ throw_sys_sub_if (write (FileHandle, buffer, buffer.Size()) != (ssize_t) buffer.Size(), wstring (Path));
+ }
+
+ void File::WriteAt (const ConstBufferPtr &buffer, uint64 position) const
+ {
+ if_debug (ValidateState());
+
+#ifdef TC_TRACE_FILE_OPERATIONS
+ TraceFileOperation (FileHandle, Path, true, buffer.Size(), position);
+#endif
+ throw_sys_sub_if (pwrite (FileHandle, buffer, buffer.Size(), position) != (ssize_t) buffer.Size(), wstring (Path));
+ }
+}
diff --git a/Platform/Unix/FilesystemPath.cpp b/Platform/Unix/FilesystemPath.cpp
new file mode 100644
index 0000000..ef52fe8
--- /dev/null
+++ b/Platform/Unix/FilesystemPath.cpp
@@ -0,0 +1,96 @@
+/*
+ Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include "Platform/FilesystemPath.h"
+#include "Platform/SystemException.h"
+#include "Platform/StringConverter.h"
+#include <stdio.h>
+#include <sys/stat.h>
+
+namespace TrueCrypt
+{
+ void FilesystemPath::Delete () const
+ {
+ throw_sys_sub_if (remove (string (*this).c_str()) == -1, Path);
+ }
+
+ UserId FilesystemPath::GetOwner () const
+ {
+ struct stat statData;
+ throw_sys_if (stat (StringConverter::ToSingle (Path).c_str(), &statData) == -1);
+
+ UserId owner;
+ owner.SystemId = statData.st_uid;
+ return owner;
+ }
+
+ FilesystemPathType::Enum FilesystemPath::GetType () const
+ {
+ // Strip trailing directory separator
+ wstring path = Path;
+ size_t pos = path.find_last_not_of (L'/');
+ if (path.size() > 2 && pos != path.size() - 1)
+ path = path.substr (0, pos + 1);
+
+ struct stat statData;
+ throw_sys_sub_if (stat (StringConverter::ToSingle (path).c_str(), &statData) != 0, Path);
+
+ if (S_ISREG (statData.st_mode)) return FilesystemPathType::File;
+ if (S_ISDIR (statData.st_mode)) return FilesystemPathType::Directory;
+ if (S_ISCHR (statData.st_mode)) return FilesystemPathType::CharacterDevice;
+ if (S_ISBLK (statData.st_mode)) return FilesystemPathType::BlockDevice;
+ if (S_ISLNK (statData.st_mode)) return FilesystemPathType::SymbolickLink;
+
+ return FilesystemPathType::Unknown;
+ }
+
+ FilesystemPath FilesystemPath::ToBaseName () const
+ {
+ wstring path = Path;
+ size_t pos = path.find_last_of (L'/');
+
+ if (pos == string::npos)
+ return Path;
+
+ return Path.substr (pos + 1);
+ }
+
+ FilesystemPath FilesystemPath::ToHostDriveOfPartition () const
+ {
+ DevicePath path;
+
+#ifdef TC_LINUX
+
+ path = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path));
+
+#elif defined (TC_MACOSX)
+
+ string pathStr = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path));
+ path = pathStr.substr (0, pathStr.size() - 1);
+
+#elif defined (TC_FREEBSD)
+
+ string pathStr = StringConverter::ToSingle (Path);
+ size_t p = pathStr.rfind ("s");
+ if (p == string::npos)
+ throw PartitionDeviceRequired (SRC_POS);
+ path = pathStr.substr (0, p);
+
+#elif defined (TC_SOLARIS)
+
+ path = StringConverter::StripTrailingNumber (StringConverter::ToSingle (Path)) + "0";
+
+#else
+ throw NotImplemented (SRC_POS);
+#endif
+ if (!path.IsDevice())
+ throw PartitionDeviceRequired (SRC_POS);
+
+ return path;
+ }
+}
diff --git a/Platform/Unix/Mutex.cpp b/Platform/Unix/Mutex.cpp
new file mode 100644
index 0000000..aae5d78
--- /dev/null
+++ b/Platform/Unix/Mutex.cpp
@@ -0,0 +1,62 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <pthread.h>
+#include "Platform/Mutex.h"
+#include "Platform/SystemException.h"
+
+namespace TrueCrypt
+{
+ Mutex::Mutex ()
+ {
+ pthread_mutexattr_t attributes;
+
+ int status = pthread_mutexattr_init (&attributes);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+
+ status = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+
+ status = pthread_mutex_init (&SystemMutex, &attributes);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+
+ Initialized = true;
+ }
+
+ Mutex::~Mutex ()
+ {
+ Initialized = false;
+#ifdef DEBUG
+ int status =
+#endif
+ pthread_mutex_destroy (&SystemMutex);
+
+#ifdef DEBUG
+ if (status != 0)
+ SystemLog::WriteException (SystemException (SRC_POS, status));
+#endif
+ }
+
+ void Mutex::Lock ()
+ {
+ assert (Initialized);
+ int status = pthread_mutex_lock (&SystemMutex);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+ }
+
+ void Mutex::Unlock ()
+ {
+ int status = pthread_mutex_unlock (&SystemMutex);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+ }
+}
diff --git a/Platform/Unix/Pipe.cpp b/Platform/Unix/Pipe.cpp
new file mode 100644
index 0000000..d346540
--- /dev/null
+++ b/Platform/Unix/Pipe.cpp
@@ -0,0 +1,65 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <unistd.h>
+#include "Pipe.h"
+#include "Platform/SystemException.h"
+
+namespace TrueCrypt
+{
+ Pipe::Pipe ()
+ {
+ int fd[2];
+ throw_sys_if (pipe (fd) == -1);
+ ReadFileDescriptor = fd[0];
+ WriteFileDescriptor = fd[1];
+ }
+
+ Pipe::~Pipe ()
+ {
+ try
+ {
+ Close();
+ }
+ catch (...) { }
+ }
+
+ void Pipe::Close ()
+ {
+ if (ReadFileDescriptor != -1)
+ close (ReadFileDescriptor);
+ if (WriteFileDescriptor != -1)
+ close (WriteFileDescriptor);
+ }
+
+ int Pipe::GetReadFD ()
+ {
+ assert (ReadFileDescriptor != -1);
+
+ if (WriteFileDescriptor != -1)
+ {
+ close (WriteFileDescriptor);
+ WriteFileDescriptor = -1;
+ }
+
+ return ReadFileDescriptor;
+ }
+
+ int Pipe::GetWriteFD ()
+ {
+ assert (WriteFileDescriptor != -1);
+
+ if (ReadFileDescriptor != -1)
+ {
+ close (ReadFileDescriptor);
+ ReadFileDescriptor = -1;
+ }
+
+ return WriteFileDescriptor;
+ }
+}
diff --git a/Platform/Unix/Pipe.h b/Platform/Unix/Pipe.h
new file mode 100644
index 0000000..9aa5bf9
--- /dev/null
+++ b/Platform/Unix/Pipe.h
@@ -0,0 +1,38 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#ifndef TC_HEADER_Platform_Unix_Pipe
+#define TC_HEADER_Platform_Unix_Pipe
+
+#include "Platform/PlatformBase.h"
+
+namespace TrueCrypt
+{
+ class Pipe
+ {
+ public:
+ Pipe ();
+ virtual ~Pipe ();
+
+ void Close ();
+ int GetReadFD ();
+ int GetWriteFD ();
+ int PeekReadFD () const { return ReadFileDescriptor; }
+ int PeekWriteFD () const { return WriteFileDescriptor; }
+
+ protected:
+ int ReadFileDescriptor;
+ int WriteFileDescriptor;
+
+ private:
+ Pipe (const Pipe &);
+ Pipe &operator= (const Pipe &);
+ };
+}
+
+#endif // TC_HEADER_Platform_Unix_Pipe
diff --git a/Platform/Unix/Poller.cpp b/Platform/Unix/Poller.cpp
new file mode 100644
index 0000000..3950eab
--- /dev/null
+++ b/Platform/Unix/Poller.cpp
@@ -0,0 +1,57 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <poll.h>
+#include <unistd.h>
+#include "Poller.h"
+#include "Platform/SystemException.h"
+
+namespace TrueCrypt
+{
+ Poller::Poller (int fileDescriptor1, int fileDescriptor2, int fileDescriptor3, int fileDescriptor4)
+ {
+ FileDescriptors.push_back (fileDescriptor1);
+
+ if (fileDescriptor2 != -1)
+ FileDescriptors.push_back (fileDescriptor2);
+
+ if (fileDescriptor3 != -1)
+ FileDescriptors.push_back (fileDescriptor3);
+
+ if (fileDescriptor4 != -1)
+ FileDescriptors.push_back (fileDescriptor4);
+ }
+
+ list <int> Poller::WaitForData (int timeOut) const
+ {
+ vector <pollfd> pfd (FileDescriptors.size());
+ for (size_t i = 0; i < FileDescriptors.size(); i++)
+ {
+ pfd[i].fd = FileDescriptors[i];
+ pfd[i].events = POLLIN;
+ }
+
+ list <int> descList;
+
+ int pollRes = poll (&pfd[0], pfd.size(), timeOut);
+
+ if (pollRes == 0 && timeOut != -1)
+ throw TimeOut (SRC_POS);
+
+ if (pollRes > 0)
+ {
+ for (size_t i = 0; i < pfd.size(); i++)
+ {
+ if (pfd[i].revents & POLLIN)
+ descList.push_back (pfd[i].fd);
+ }
+ }
+
+ return descList;
+ }
+}
diff --git a/Platform/Unix/Poller.h b/Platform/Unix/Poller.h
new file mode 100644
index 0000000..131e469
--- /dev/null
+++ b/Platform/Unix/Poller.h
@@ -0,0 +1,33 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#ifndef TC_HEADER_Platform_Unix_Poller
+#define TC_HEADER_Platform_Unix_Poller
+
+#include "Platform/PlatformBase.h"
+
+namespace TrueCrypt
+{
+ class Poller
+ {
+ public:
+ Poller (int fileDescriptor1, int fileDescriptor2 = -1, int fileDescriptor3 = -1, int fileDescriptor4 = -1);
+ virtual ~Poller () { }
+
+ list <int> WaitForData (int timeOut = -1) const;
+
+ protected:
+ vector <int> FileDescriptors;
+
+ private:
+ Poller (const Poller &);
+ Poller &operator= (const Poller &);
+ };
+}
+
+#endif // TC_HEADER_Platform_Unix_Poller
diff --git a/Platform/Unix/Process.cpp b/Platform/Unix/Process.cpp
new file mode 100644
index 0000000..d99dff8
--- /dev/null
+++ b/Platform/Unix/Process.cpp
@@ -0,0 +1,202 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include "Process.h"
+#include "Platform/Exception.h"
+#include "Platform/FileStream.h"
+#include "Platform/ForEach.h"
+#include "Platform/MemoryStream.h"
+#include "Platform/SystemException.h"
+#include "Platform/StringConverter.h"
+#include "Platform/Unix/Pipe.h"
+#include "Platform/Unix/Poller.h"
+
+namespace TrueCrypt
+{
+ string Process::Execute (const string &processName, const list <string> &arguments, int timeOut, ProcessExecFunctor *execFunctor, const Buffer *inputData)
+ {
+ char *args[32];
+ if (array_capacity (args) <= arguments.size())
+ throw ParameterTooLarge (SRC_POS);
+
+#if 0
+ stringstream dbg;
+ dbg << "exec " << processName;
+ foreach (const string &at, arguments)
+ dbg << " " << at;
+ trace_msg (dbg.str());
+#endif
+
+ Pipe inPipe, outPipe, errPipe, exceptionPipe;
+
+ int forkedPid = fork();
+ throw_sys_if (forkedPid == -1);
+
+ if (forkedPid == 0)
+ {
+ try
+ {
+ try
+ {
+ int argIndex = 0;
+ if (!execFunctor)
+ args[argIndex++] = const_cast <char*> (processName.c_str());
+
+ foreach (const string &arg, arguments)
+ {
+ args[argIndex++] = const_cast <char*> (arg.c_str());
+ }
+ args[argIndex] = nullptr;
+
+ if (inputData)
+ {
+ throw_sys_if (dup2 (inPipe.GetReadFD(), STDIN_FILENO) == -1);
+ }
+ else
+ {
+ inPipe.Close();
+ int nullDev = open ("/dev/null", 0);
+ throw_sys_sub_if (nullDev == -1, "/dev/null");
+ throw_sys_if (dup2 (nullDev, STDIN_FILENO) == -1);
+ }
+
+ throw_sys_if (dup2 (outPipe.GetWriteFD(), STDOUT_FILENO) == -1);
+ throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1);
+ exceptionPipe.GetWriteFD();
+
+ if (execFunctor)
+ {
+ (*execFunctor)(argIndex, args);
+ }
+ else
+ {
+ execvp (args[0], args);
+ throw SystemException (SRC_POS, args[0]);
+ }
+ }
+ catch (Exception &)
+ {
+ throw;
+ }
+ catch (exception &e)
+ {
+ throw ExternalException (SRC_POS, StringConverter::ToExceptionString (e));
+ }
+ catch (...)
+ {
+ throw UnknownException (SRC_POS);
+ }
+ }
+ catch (Exception &e)
+ {
+ try
+ {
+ shared_ptr <Stream> outputStream (new FileStream (exceptionPipe.GetWriteFD()));
+ e.Serialize (outputStream);
+ }
+ catch (...) { }
+ }
+
+ _exit (1);
+ }
+
+ throw_sys_if (fcntl (outPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
+ throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
+ throw_sys_if (fcntl (exceptionPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
+
+ vector <char> buffer (4096), stdOutput (4096), errOutput (4096), exOutput (4096);
+ buffer.clear ();
+ stdOutput.clear ();
+ errOutput.clear ();
+ exOutput.clear ();
+
+ Poller poller (outPipe.GetReadFD(), errPipe.GetReadFD(), exceptionPipe.GetReadFD());
+ int status, waitRes;
+
+ if (inputData)
+ throw_sys_if (write (inPipe.GetWriteFD(), inputData->Ptr(), inputData->Size()) == -1 && errno != EPIPE);
+
+ inPipe.Close();
+
+ int timeTaken = 0;
+ do
+ {
+ const int pollTimeout = 200;
+ try
+ {
+ ssize_t bytesRead = 0;
+ foreach (int fd, poller.WaitForData (pollTimeout))
+ {
+ bytesRead = read (fd, &buffer[0], buffer.capacity());
+ if (bytesRead > 0)
+ {
+ if (fd == outPipe.GetReadFD())
+ stdOutput.insert (stdOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
+ else if (fd == errPipe.GetReadFD())
+ errOutput.insert (errOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
+ else if (fd == exceptionPipe.GetReadFD())
+ exOutput.insert (exOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
+ }
+ }
+
+ if (bytesRead == 0)
+ {
+ waitRes = waitpid (forkedPid, &status, 0);
+ break;
+ }
+ }
+ catch (TimeOut&)
+ {
+ timeTaken += pollTimeout;
+ if (timeOut >= 0 && timeTaken >= timeOut)
+ throw;
+ }
+ } while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0);
+ throw_sys_if (waitRes == -1);
+
+ if (!exOutput.empty())
+ {
+ auto_ptr <Serializable> deserializedObject;
+ Exception *deserializedException = nullptr;
+
+ try
+ {
+ shared_ptr <Stream> stream (new MemoryStream (ConstBufferPtr ((byte *) &exOutput[0], exOutput.size())));
+ deserializedObject.reset (Serializable::DeserializeNew (stream));
+ deserializedException = dynamic_cast <Exception*> (deserializedObject.get());
+ }
+ catch (...) { }
+
+ if (deserializedException)
+ deserializedException->Throw();
+ }
+
+ int exitCode = (WIFEXITED (status) ? WEXITSTATUS (status) : 1);
+ if (exitCode != 0)
+ {
+ string strErrOutput;
+
+ if (!errOutput.empty())
+ strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end());
+
+ throw ExecutedProcessFailed (SRC_POS, processName, exitCode, strErrOutput);
+ }
+
+ string strOutput;
+
+ if (!stdOutput.empty())
+ strOutput.insert (strOutput.begin(), stdOutput.begin(), stdOutput.end());
+
+ return strOutput;
+ }
+}
diff --git a/Platform/Unix/Process.h b/Platform/Unix/Process.h
new file mode 100644
index 0000000..dd878dd
--- /dev/null
+++ b/Platform/Unix/Process.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#ifndef TC_HEADER_Platform_Unix_Process
+#define TC_HEADER_Platform_Unix_Process
+
+#include "Platform/PlatformBase.h"
+#include "Platform/Buffer.h"
+#include "Platform/Functor.h"
+
+namespace TrueCrypt
+{
+ struct ProcessExecFunctor
+ {
+ virtual ~ProcessExecFunctor () { }
+ virtual void operator() (int argc, char *argv[]) = 0;
+ };
+
+ class Process
+ {
+ public:
+ Process ();
+ virtual ~Process ();
+
+ static string Execute (const string &processName, const list <string> &arguments, int timeOut = -1, ProcessExecFunctor *execFunctor = nullptr, const Buffer *inputData = nullptr);
+
+ protected:
+
+ private:
+ Process (const Process &);
+ Process &operator= (const Process &);
+ };
+}
+
+#endif // TC_HEADER_Platform_Unix_Process
diff --git a/Platform/Unix/SyncEvent.cpp b/Platform/Unix/SyncEvent.cpp
new file mode 100644
index 0000000..fbf8300
--- /dev/null
+++ b/Platform/Unix/SyncEvent.cpp
@@ -0,0 +1,68 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include "Platform/Exception.h"
+#include "Platform/SyncEvent.h"
+#include "Platform/SystemException.h"
+
+namespace TrueCrypt
+{
+ SyncEvent::SyncEvent ()
+ {
+ int status = pthread_cond_init (&SystemSyncEvent, nullptr);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+
+ Signaled = false;
+ Initialized = true;
+ }
+
+ SyncEvent::~SyncEvent ()
+ {
+#ifdef DEBUG
+ int status =
+#endif
+ pthread_cond_destroy (&SystemSyncEvent);
+
+#ifdef DEBUG
+ if (status != 0)
+ SystemLog::WriteException (SystemException (SRC_POS, status));
+#endif
+
+ Initialized = false;
+ }
+
+ void SyncEvent::Signal ()
+ {
+ assert (Initialized);
+
+ ScopeLock lock (EventMutex);
+
+ Signaled = true;
+
+ int status = pthread_cond_signal (&SystemSyncEvent);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+ }
+
+ void SyncEvent::Wait ()
+ {
+ assert (Initialized);
+
+ ScopeLock lock (EventMutex);
+
+ while (!Signaled)
+ {
+ int status = pthread_cond_wait (&SystemSyncEvent, EventMutex.GetSystemHandle());
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+ }
+
+ Signaled = false;
+ }
+}
diff --git a/Platform/Unix/System.h b/Platform/Unix/System.h
new file mode 100644
index 0000000..63d565b
--- /dev/null
+++ b/Platform/Unix/System.h
@@ -0,0 +1,12 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#ifndef TC_HEADER_Platform_Unix_System
+#define TC_HEADER_Platform_Unix_System
+
+#endif // TC_HEADER_Platform_Unix_System
diff --git a/Platform/Unix/SystemException.cpp b/Platform/Unix/SystemException.cpp
new file mode 100644
index 0000000..b29c9b5
--- /dev/null
+++ b/Platform/Unix/SystemException.cpp
@@ -0,0 +1,66 @@
+/*
+ Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <errno.h>
+#include <string.h>
+#include "Platform/SerializerFactory.h"
+#include "Platform/SystemException.h"
+#include "Platform/StringConverter.h"
+
+namespace TrueCrypt
+{
+ SystemException::SystemException ()
+ : ErrorCode (errno)
+ {
+ }
+
+ SystemException::SystemException (const string &message)
+ : Exception (message), ErrorCode (errno)
+ {
+ }
+
+ SystemException::SystemException (const string &message, const string &subject)
+ : Exception (message, StringConverter::ToWide (subject)), ErrorCode (errno)
+ {
+ }
+
+ SystemException::SystemException (const string &message, const wstring &subject)
+ : Exception (message, subject), ErrorCode (errno)
+ {
+ }
+
+ void SystemException::Deserialize (shared_ptr <Stream> stream)
+ {
+ Exception::Deserialize (stream);
+ Serializer sr (stream);
+ sr.Deserialize ("ErrorCode", ErrorCode);
+ }
+
+ bool SystemException::IsError () const
+ {
+ return ErrorCode != 0;
+ }
+
+ void SystemException::Serialize (shared_ptr <Stream> stream) const
+ {
+ Exception::Serialize (stream);
+ Serializer sr (stream);
+ sr.Serialize ("ErrorCode", ErrorCode);
+ }
+
+ wstring SystemException::SystemText () const
+ {
+ return StringConverter::ToWide (strerror ((int) ErrorCode));
+ }
+
+#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
+#undef TC_EXCEPTION_NODECL
+#define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
+
+ TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SystemException);
+}
diff --git a/Platform/Unix/SystemInfo.cpp b/Platform/Unix/SystemInfo.cpp
new file mode 100644
index 0000000..d0ea6e6
--- /dev/null
+++ b/Platform/Unix/SystemInfo.cpp
@@ -0,0 +1,69 @@
+/*
+ Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include "Platform/SystemException.h"
+#include "Platform/SystemInfo.h"
+#include <sys/utsname.h>
+
+namespace TrueCrypt
+{
+ wstring SystemInfo::GetPlatformName ()
+ {
+#ifdef TC_LINUX
+ return L"Linux";
+#elif defined (TC_MACOSX)
+ return L"Mac OS X";
+#elif defined (TC_FREEBSD)
+ return L"FreeBSD";
+#elif defined (TC_SOLARIS)
+ return L"Solaris";
+#else
+# error GetPlatformName() undefined
+#endif
+
+ }
+
+ vector <int> SystemInfo::GetVersion ()
+ {
+ struct utsname unameData;
+ throw_sys_if (uname (&unameData) == -1);
+
+ vector <string> versionStrings = StringConverter::Split (unameData.release, ".");
+ vector <int> version;
+
+ for (size_t i = 0; i < versionStrings.size(); ++i)
+ {
+ string s = versionStrings[i];
+
+ size_t p = s.find_first_not_of ("0123456789");
+ if (p != string::npos)
+ s = s.substr (0, p);
+
+ if (s.empty())
+ break;
+
+ version.push_back (StringConverter::ToUInt32 (s));
+ }
+
+ return version;
+ }
+
+ bool SystemInfo::IsVersionAtLeast (int versionNumber1, int versionNumber2, int versionNumber3)
+ {
+ vector <int> osVersionNumbers = GetVersion();
+
+ if (osVersionNumbers.size() < 2)
+ throw ParameterIncorrect (SRC_POS);
+
+ if (osVersionNumbers.size() < 3)
+ osVersionNumbers[2] = 0;
+
+ return (osVersionNumbers[0] * 10000000 + osVersionNumbers[1] * 10000 + osVersionNumbers[2]) >=
+ (versionNumber1 * 10000000 + versionNumber2 * 10000 + versionNumber3);
+ }
+}
diff --git a/Platform/Unix/SystemLog.cpp b/Platform/Unix/SystemLog.cpp
new file mode 100644
index 0000000..eea94e0
--- /dev/null
+++ b/Platform/Unix/SystemLog.cpp
@@ -0,0 +1,27 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <syslog.h>
+#include "Platform/SystemLog.h"
+
+namespace TrueCrypt
+{
+ void SystemLog::WriteDebug (const string &debugMessage)
+ {
+ openlog ("truecrypt", LOG_PID, LOG_USER);
+ syslog (LOG_DEBUG, "%s", debugMessage.c_str());
+ closelog();
+ }
+
+ void SystemLog::WriteError (const string &errorMessage)
+ {
+ openlog ("truecrypt", LOG_PID, LOG_USER);
+ syslog (LOG_ERR, "%s", errorMessage.c_str());
+ closelog();
+ }
+}
diff --git a/Platform/Unix/Thread.cpp b/Platform/Unix/Thread.cpp
new file mode 100644
index 0000000..7afe683
--- /dev/null
+++ b/Platform/Unix/Thread.cpp
@@ -0,0 +1,54 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include <pthread.h>
+#include <unistd.h>
+#include "Platform/SystemException.h"
+#include "Platform/Thread.h"
+#include "Platform/SystemLog.h"
+
+namespace TrueCrypt
+{
+ void Thread::Join () const
+ {
+ int status = pthread_join (SystemHandle, nullptr);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+ }
+
+ void Thread::Start (ThreadProcPtr threadProc, void *parameter)
+ {
+ pthread_attr_t attr;
+ size_t stackSize = 0;
+ int status;
+
+ status = pthread_attr_init (&attr);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+
+ status = pthread_attr_getstacksize (&attr, &stackSize);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+
+ if (stackSize < MinThreadStackSize)
+ {
+ status = pthread_attr_setstacksize (&attr, MinThreadStackSize);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+ }
+
+ status = pthread_create (&SystemHandle, nullptr, threadProc, parameter);
+ if (status != 0)
+ throw SystemException (SRC_POS, status);
+ }
+
+ void Thread::Sleep (uint32 milliSeconds)
+ {
+ ::usleep (milliSeconds * 1000);
+ }
+}
diff --git a/Platform/Unix/Time.cpp b/Platform/Unix/Time.cpp
new file mode 100644
index 0000000..01313d5
--- /dev/null
+++ b/Platform/Unix/Time.cpp
@@ -0,0 +1,23 @@
+/*
+ Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include "Platform/Time.h"
+#include <sys/time.h>
+#include <time.h>
+
+namespace TrueCrypt
+{
+ uint64 Time::GetCurrent ()
+ {
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+
+ // Unix time => Windows file time
+ return ((uint64) tv.tv_sec + 134774LL * 24 * 3600) * 1000LL * 1000 * 10;
+ }
+}