From 3cb7fdea950dd2d0377f0d9ad8a88fcb7c48b842 Mon Sep 17 00:00:00 2001 From: Jedidiah Barber Date: Wed, 14 Jul 2021 11:27:03 +1200 Subject: Initial mirror commit --- Platform/Unix/Directory.cpp | 62 +++++++ Platform/Unix/File.cpp | 348 ++++++++++++++++++++++++++++++++++++++ Platform/Unix/FilesystemPath.cpp | 96 +++++++++++ Platform/Unix/Mutex.cpp | 62 +++++++ Platform/Unix/Pipe.cpp | 65 +++++++ Platform/Unix/Pipe.h | 38 +++++ Platform/Unix/Poller.cpp | 57 +++++++ Platform/Unix/Poller.h | 33 ++++ Platform/Unix/Process.cpp | 202 ++++++++++++++++++++++ Platform/Unix/Process.h | 40 +++++ Platform/Unix/SyncEvent.cpp | 68 ++++++++ Platform/Unix/System.h | 12 ++ Platform/Unix/SystemException.cpp | 66 ++++++++ Platform/Unix/SystemInfo.cpp | 69 ++++++++ Platform/Unix/SystemLog.cpp | 27 +++ Platform/Unix/Thread.cpp | 54 ++++++ Platform/Unix/Time.cpp | 23 +++ 17 files changed, 1322 insertions(+) create mode 100644 Platform/Unix/Directory.cpp create mode 100644 Platform/Unix/File.cpp create mode 100644 Platform/Unix/FilesystemPath.cpp create mode 100644 Platform/Unix/Mutex.cpp create mode 100644 Platform/Unix/Pipe.cpp create mode 100644 Platform/Unix/Pipe.h create mode 100644 Platform/Unix/Poller.cpp create mode 100644 Platform/Unix/Poller.h create mode 100644 Platform/Unix/Process.cpp create mode 100644 Platform/Unix/Process.h create mode 100644 Platform/Unix/SyncEvent.cpp create mode 100644 Platform/Unix/System.h create mode 100644 Platform/Unix/SystemException.cpp create mode 100644 Platform/Unix/SystemInfo.cpp create mode 100644 Platform/Unix/SystemLog.cpp create mode 100644 Platform/Unix/Thread.cpp create mode 100644 Platform/Unix/Time.cpp (limited to 'Platform/Unix') 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 +#include +#include +#include +#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 (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 +#include +#include +#include + +#ifdef TC_LINUX +#include +#endif + +#ifdef TC_BSD +#include +#endif + +#ifdef TC_SOLARIS +#include +#include +#endif + +#include +#include +#include + +#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, §orSize) == -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 +#include + +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 +#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 +#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 +#include +#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 Poller::WaitForData (int timeOut) const + { + vector pfd (FileDescriptors.size()); + for (size_t i = 0; i < FileDescriptors.size(); i++) + { + pfd[i].fd = FileDescriptors[i]; + pfd[i].events = POLLIN; + } + + list 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 WaitForData (int timeOut = -1) const; + + protected: + vector 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 +#include +#include +#include +#include +#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 &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 (processName.c_str()); + + foreach (const string &arg, arguments) + { + args[argIndex++] = const_cast (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 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 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 deserializedObject; + Exception *deserializedException = nullptr; + + try + { + shared_ptr stream (new MemoryStream (ConstBufferPtr ((byte *) &exOutput[0], exOutput.size()))); + deserializedObject.reset (Serializable::DeserializeNew (stream)); + deserializedException = dynamic_cast (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 &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 +#include +#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) + { + Exception::Deserialize (stream); + Serializer sr (stream); + sr.Deserialize ("ErrorCode", ErrorCode); + } + + bool SystemException::IsError () const + { + return ErrorCode != 0; + } + + void SystemException::Serialize (shared_ptr 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 + +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 SystemInfo::GetVersion () + { + struct utsname unameData; + throw_sys_if (uname (&unameData) == -1); + + vector versionStrings = StringConverter::Split (unameData.release, "."); + vector 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 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 +#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 +#include +#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 +#include + +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; + } +} -- cgit