From 3bedf8846f4d7a5cb38276b274662d62a36dcd52 Mon Sep 17 00:00:00 2001 From: Martin Ebourne Date: Mon, 12 Dec 2005 20:50:00 +0000 Subject: Marged chris/win32/merge/07-win32-fixes at r210 to trunk --- lib/backupclient/BackupClientFileAttributes.cpp | 46 +- lib/backupclient/BackupClientFileAttributes.h | 2 +- lib/backupclient/BackupStoreFile.cpp | 4 +- lib/backupclient/BackupStoreFileDiff.cpp | 8 + lib/backupclient/BackupStoreObjectDump.cpp | 8 + lib/common/BoxPlatform.h | 45 +- lib/common/BoxPortsAndFiles.h | 9 +- lib/common/BoxTime.h | 4 +- lib/common/BoxTimeToText.cpp | 25 +- lib/common/BoxTimeToUnix.h | 4 + lib/common/CommonException.txt | 1 + lib/common/DebugPrintf.cpp | 6 + lib/common/FileStream.cpp | 116 ++- lib/common/FileStream.h | 28 +- lib/common/IOStream.cpp | 12 + lib/common/NamedLock.cpp | 2 +- lib/common/TemporaryDirectory.h | 34 +- lib/common/UnixUser.cpp | 3 + lib/common/WaitForEvent.h | 4 +- lib/server/Daemon.cpp | 21 +- lib/server/LocalProcessStream.cpp | 9 + lib/server/SSLLib.cpp | 2 + lib/server/ServerStream.h | 7 +- lib/server/Socket.cpp | 6 +- lib/server/Socket.h | 7 + lib/server/SocketListen.h | 21 +- lib/server/SocketStream.cpp | 24 +- lib/server/SocketStream.h | 10 +- lib/server/SocketStreamTLS.cpp | 12 +- lib/server/makeprotocol.pl | 6 +- lib/win32/WinNamedPipeStream.cpp | 301 ++++++++ lib/win32/WinNamedPipeStream.h | 60 ++ lib/win32/emu.cpp | 978 ++++++++++++++++++++++++ lib/win32/emu.h | 426 +++++++++++ 34 files changed, 2194 insertions(+), 57 deletions(-) create mode 100755 lib/win32/WinNamedPipeStream.cpp create mode 100755 lib/win32/WinNamedPipeStream.h create mode 100644 lib/win32/emu.cpp create mode 100644 lib/win32/emu.h (limited to 'lib') diff --git a/lib/backupclient/BackupClientFileAttributes.cpp b/lib/backupclient/BackupClientFileAttributes.cpp index adc3a91c..7b7cd216 100755 --- a/lib/backupclient/BackupClientFileAttributes.cpp +++ b/lib/backupclient/BackupClientFileAttributes.cpp @@ -287,7 +287,7 @@ bool BackupClientFileAttributes::Compare(const BackupClientFileAttributes &rAttr // // -------------------------------------------------------------------------- void BackupClientFileAttributes::ReadAttributes(const char *Filename, bool ZeroModificationTimes, box_time_t *pModTime, - box_time_t *pAttrModTime, int64_t *pFileSize, ino_t *pInodeNumber, bool *pHasMultipleLinks) + box_time_t *pAttrModTime, int64_t *pFileSize, InodeRefType *pInodeNumber, bool *pHasMultipleLinks) { StreamableMemBlock *pnewAttr = 0; try @@ -309,14 +309,46 @@ void BackupClientFileAttributes::ReadAttributes(const char *Filename, bool ZeroM FillAttributes(*pnewAttr, Filename, st, ZeroModificationTimes); +#ifndef WIN32 // Is it a link? if((st.st_mode & S_IFMT) == S_IFLNK) { FillAttributesLink(*pnewAttr, Filename, st); } +#endif FillExtendedAttr(*pnewAttr, Filename); +#ifdef WIN32 + //this is to catch those problems with invalid time stamps stored... + //need to find out the reason why - but also a catch as well. + + attr_StreamFormat *pattr = + (attr_StreamFormat*)pnewAttr->GetBuffer(); + ASSERT(pattr != 0); + + // __time64_t winTime = BoxTimeToSeconds( + // pnewAttr->ModificationTime); + + box_time_t bob = BoxTimeToSeconds(pattr->ModificationTime); + __time64_t winTime = bob; + if (_gmtime64(&winTime) == 0 ) + { + ::syslog(LOG_ERR, "Corrupt value in store " + "Modification Time in file %s", Filename); + pattr->ModificationTime = 0; + } + + bob = BoxTimeToSeconds(pattr->AttrModificationTime); + winTime = bob; + if (_gmtime64(&winTime) == 0 ) + { + ::syslog(LOG_ERR, "Corrupt value in store " + "Attr Modification Time in file %s", Filename); + pattr->AttrModificationTime = 0; + } +#endif + // Attributes ready. Encrypt into this block EncryptAttr(*pnewAttr); @@ -372,7 +404,7 @@ void BackupClientFileAttributes::FillAttributes(StreamableMemBlock &outputBlock, pattr->FileGenerationNumber = htonl(st.st_gen); #endif } - +#ifndef WIN32 // -------------------------------------------------------------------------- // // Function @@ -402,6 +434,7 @@ void BackupClientFileAttributes::FillAttributesLink(StreamableMemBlock &outputBl std::memcpy(buffer+oldSize, linkedTo, linkedToSize); buffer[oldSize+linkedToSize] = '\0'; } +#endif // -------------------------------------------------------------------------- // @@ -574,12 +607,18 @@ void BackupClientFileAttributes::WriteAttributes(const char *Filename) const THROW_EXCEPTION(BackupStoreException, AttributesNotLoaded); } +#ifdef WIN32 + ::syslog(LOG_WARNING, + "Cannot create symbolic links on Windows: %s", + Filename); +#else // Make a symlink, first deleting anything in the way ::unlink(Filename); if(::symlink((char*)(pattr + 1), Filename) != 0) { THROW_EXCEPTION(CommonException, OSFileError) } +#endif xattrOffset += std::strlen(reinterpret_cast(pattr+1))+1; } @@ -943,6 +982,3 @@ uint64_t BackupClientFileAttributes::GenerateAttributeHash(struct stat &st, cons uint64_t result = *((uint64_t *)(digest.DigestAsData())); return result; } - - - diff --git a/lib/backupclient/BackupClientFileAttributes.h b/lib/backupclient/BackupClientFileAttributes.h index 17124039..62ba2184 100755 --- a/lib/backupclient/BackupClientFileAttributes.h +++ b/lib/backupclient/BackupClientFileAttributes.h @@ -44,7 +44,7 @@ public: void ReadAttributes(const char *Filename, bool ZeroModificationTimes = false, box_time_t *pModTime = 0, box_time_t *pAttrModTime = 0, int64_t *pFileSize = 0, - ino_t *pInodeNumber = 0, bool *pHasMultipleLinks = 0); + InodeRefType *pInodeNumber = 0, bool *pHasMultipleLinks = 0); void WriteAttributes(const char *Filename) const; bool IsSymLink() const; diff --git a/lib/backupclient/BackupStoreFile.cpp b/lib/backupclient/BackupStoreFile.cpp index d31b53bb..28d88d27 100755 --- a/lib/backupclient/BackupStoreFile.cpp +++ b/lib/backupclient/BackupStoreFile.cpp @@ -15,7 +15,9 @@ #include #include #ifndef BOX_DISABLE_BACKWARDS_COMPATIBILITY_BACKUPSTOREFILE - #include + #ifndef WIN32 + #include + #endif #include #endif diff --git a/lib/backupclient/BackupStoreFileDiff.cpp b/lib/backupclient/BackupStoreFileDiff.cpp index 3699eb49..c1d0492d 100755 --- a/lib/backupclient/BackupStoreFileDiff.cpp +++ b/lib/backupclient/BackupStoreFileDiff.cpp @@ -12,7 +12,11 @@ #include #include #include +#ifdef WIN32 +#include +#else #include +#endif #include "BackupStoreFile.h" #include "BackupStoreFileWire.h" @@ -989,7 +993,11 @@ static void GenerateRecipe(BackupStoreFileEncodeStream::Recipe &rRecipe, BlocksA for(unsigned int e = 0; e < rRecipe.size(); ++e) { char b[64]; +#ifdef WIN32 + sprintf(b, "%8I64d", (int64_t)(rRecipe[e].mpStartBlock - pIndex)); +#else sprintf(b, "%8lld", (int64_t)(rRecipe[e].mpStartBlock - pIndex)); +#endif TRACE3("%8lld %s %8lld\n", rRecipe[e].mSpaceBefore, (rRecipe[e].mpStartBlock == 0)?" -":b, (int64_t)rRecipe[e].mBlocks); } } diff --git a/lib/backupclient/BackupStoreObjectDump.cpp b/lib/backupclient/BackupStoreObjectDump.cpp index 5f902831..8e6331c4 100644 --- a/lib/backupclient/BackupStoreObjectDump.cpp +++ b/lib/backupclient/BackupStoreObjectDump.cpp @@ -96,11 +96,19 @@ void BackupStoreDirectory::Dump(void *clibFileHandle, bool ToTrace) int depends_l = 0; if((*i)->GetDependsNewer() != 0) { +#ifdef WIN32 + depends_l += ::sprintf(depends + depends_l, " depNew(%I64x)", (*i)->GetDependsNewer()); +#else depends_l += ::sprintf(depends + depends_l, " depNew(%llx)", (*i)->GetDependsNewer()); +#endif } if((*i)->GetDependsOlder() != 0) { +#ifdef WIN32 + depends_l += ::sprintf(depends + depends_l, " depOld(%I64x)", (*i)->GetDependsOlder()); +#else depends_l += ::sprintf(depends + depends_l, " depOld(%llx)", (*i)->GetDependsOlder()); +#endif } // Output item diff --git a/lib/common/BoxPlatform.h b/lib/common/BoxPlatform.h index 6ddd1643..55065796 100755 --- a/lib/common/BoxPlatform.h +++ b/lib/common/BoxPlatform.h @@ -11,13 +11,24 @@ #ifndef BOXPLATFORM__H #define BOXPLATFORM__H +#ifdef WIN32 +#define DIRECTORY_SEPARATOR "\\" +#define DIRECTORY_SEPARATOR_ASCHAR '\\' +#else #define DIRECTORY_SEPARATOR "/" -#define DIRECTORY_SEPARATOR_ASCHAR '/' +#define DIRECTORY_SEPARATOR_ASCHAR '/' +#endif #define PLATFORM_DEV_NULL "/dev/null" #include "config.h" +#ifdef WIN32 + // need msvcrt version 6.1 or higher for _gmtime64() + // must define this before importing + #define __MSVCRT_VERSION__ 0x0601 +#endif + #ifdef HAVE_SYS_TYPES_H #include #endif @@ -51,6 +62,27 @@ #define STRUCTURE_PACKING_FOR_WIRE_USE_HEADERS #endif +#if defined WIN32 && !defined __MINGW32__ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + + typedef unsigned __int8 u_int8_t; + typedef unsigned __int16 u_int16_t; + typedef unsigned __int32 u_int32_t; + typedef unsigned __int64 u_int64_t; + + #define HAVE_UINT8_T + #define HAVE_UINT16_T + #define HAVE_UINT32_T + #define HAVE_UINT64_T + + typedef unsigned int uid_t; + typedef unsigned int gid_t; + typedef int pid_t; +#endif // WIN32 && !__MINGW32__ + // Define missing types #ifndef HAVE_UINT8_T typedef u_int8_t uint8_t; @@ -88,4 +120,15 @@ #define INFTIM -1 #endif +#ifdef WIN32 + typedef u_int64_t InodeRefType; +#else + typedef ino_t InodeRefType; +#endif + +#ifdef WIN32 + #define WIN32_LEAN_AND_MEAN + #include "emu.h" +#endif + #endif // BOXPLATFORM__H diff --git a/lib/common/BoxPortsAndFiles.h b/lib/common/BoxPortsAndFiles.h index 7788537e..562c6724 100755 --- a/lib/common/BoxPortsAndFiles.h +++ b/lib/common/BoxPortsAndFiles.h @@ -20,12 +20,17 @@ #define BOX_RAIDFILE_ROOT_BBSTORED "backup" // Backup client daemon +#ifdef WIN32 +#define BOX_FILE_BBACKUPD_DEFAULT_CONFIG "C:\\Program Files\\Box Backup\\bbackupd.conf" +#else #define BOX_FILE_BBACKUPD_DEFAULT_CONFIG "/etc/box/bbackupd.conf" +#endif - -// RaidFile conf location efault +// RaidFile conf location default #define BOX_FILE_RAIDFILE_DEFAULT_CONFIG "/etc/box/raidfile.conf" +// Default name of the named pipe +#define BOX_NAMED_PIPE_NAME L"\\\\.\\pipe\\boxbackup" #endif // BOXPORTSANDFILES__H diff --git a/lib/common/BoxTime.h b/lib/common/BoxTime.h index a7a25ac6..d166d6e7 100755 --- a/lib/common/BoxTime.h +++ b/lib/common/BoxTime.h @@ -31,11 +31,11 @@ inline box_time_t SecondsToBoxTime(uint64_t Seconds) { return ((box_time_t)Seconds * MICRO_SEC_IN_SEC_LL); } -inline int64_t BoxTimeToSeconds(box_time_t Time) +inline box_time_t BoxTimeToSeconds(box_time_t Time) { return Time / MICRO_SEC_IN_SEC_LL; } -inline int64_t BoxTimeToMilliSeconds(box_time_t Time) +inline box_time_t BoxTimeToMilliSeconds(box_time_t Time) { return Time / MILLI_SEC_IN_NANO_SEC_LL; } diff --git a/lib/common/BoxTimeToText.cpp b/lib/common/BoxTimeToText.cpp index 94b0d152..297d2100 100755 --- a/lib/common/BoxTimeToText.cpp +++ b/lib/common/BoxTimeToText.cpp @@ -27,14 +27,35 @@ // -------------------------------------------------------------------------- std::string BoxTimeToISO8601String(box_time_t Time) { +#ifdef WIN32 + struct tm *time; + box_time_t bob = BoxTimeToSeconds(Time); + + __time64_t winTime = bob; + + time = _gmtime64(&winTime); + char str[128]; // more than enough space + + if ( time == NULL ) + { + // ::sprintf(str, "%016I64x ", bob); + return std::string("unable to convert time"); + } + + sprintf(str, "%04d-%02d-%02dT%02d:%02d:%02d", time->tm_year + 1900, + time->tm_mon + 1, time->tm_mday, time->tm_hour, + time->tm_min, time->tm_sec); +#else // ! WIN32 time_t timeInSecs = (time_t)BoxTimeToSeconds(Time); struct tm time; gmtime_r(&timeInSecs, &time); char str[128]; // more than enough space sprintf(str, "%04d-%02d-%02dT%02d:%02d:%02d", time.tm_year + 1900, - time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec); - + time.tm_mon + 1, time.tm_mday, time.tm_hour, + time.tm_min, time.tm_sec); +#endif // WIN32 + return std::string(str); } diff --git a/lib/common/BoxTimeToUnix.h b/lib/common/BoxTimeToUnix.h index 17e57e27..f8a8797e 100755 --- a/lib/common/BoxTimeToUnix.h +++ b/lib/common/BoxTimeToUnix.h @@ -10,7 +10,11 @@ #ifndef FILEMODIFICATIONTIMETOTIMEVAL__H #define FILEMODIFICATIONTIMETOTIMEVAL__H +#ifdef WIN32 +#include +#else #include +#endif #include "BoxTime.h" diff --git a/lib/common/CommonException.txt b/lib/common/CommonException.txt index 3875ed71..f852b7d7 100644 --- a/lib/common/CommonException.txt +++ b/lib/common/CommonException.txt @@ -42,3 +42,4 @@ KEventErrorWait 34 KEventErrorRemove 35 KQueueNotSupportedOnThisPlatform 36 IOStreamGetLineNotEnoughDataToIgnore 37 Bad value passed to IOStreamGetLine::IgnoreBufferedData() +TempDirPathTooLong 38 Your temporary directory path is too long. Check the TMP and TEMP environment variables. diff --git a/lib/common/DebugPrintf.cpp b/lib/common/DebugPrintf.cpp index 02c25496..d07604b7 100755 --- a/lib/common/DebugPrintf.cpp +++ b/lib/common/DebugPrintf.cpp @@ -55,10 +55,16 @@ int BoxDebugTrace(const char *format, ...) // But tracing to syslog is independent of tracing being on or not if(BoxDebugTraceToSyslog) { +#ifdef WIN32 // Remove trailing '\n', if it's there + if(r > 0 && text[r-1] == '\n') + { + text[r-1] = '\0'; +#else if(r > 0 && text[r] == '\n') { text[r] = '\0'; +#endif --r; } // Log it diff --git a/lib/common/FileStream.cpp b/lib/common/FileStream.cpp index ca6894ae..9f5460bb 100755 --- a/lib/common/FileStream.cpp +++ b/lib/common/FileStream.cpp @@ -22,14 +22,25 @@ // // -------------------------------------------------------------------------- FileStream::FileStream(const char *Filename, int flags, int mode) +#ifdef WIN32 + : mOSFileHandle(::openfile(Filename, flags, mode)), +#else : mOSFileHandle(::open(Filename, flags, mode)), +#endif mIsEOF(false) { +#ifdef WIN32 + if(mOSFileHandle == 0) +#else if(mOSFileHandle < 0) +#endif { MEMLEAKFINDER_NOT_A_LEAK(this); THROW_EXCEPTION(CommonException, OSFileOpenError) } +#ifdef WIN32 + this->fileName = Filename; +#endif } @@ -41,7 +52,7 @@ FileStream::FileStream(const char *Filename, int flags, int mode) // Created: 2003/08/28 // // -------------------------------------------------------------------------- -FileStream::FileStream(int FileDescriptor) +FileStream::FileStream(tOSFileHandle FileDescriptor) : mOSFileHandle(FileDescriptor), mIsEOF(false) { @@ -52,7 +63,7 @@ FileStream::FileStream(int FileDescriptor) } } - +#if 0 // -------------------------------------------------------------------------- // // Function @@ -71,6 +82,7 @@ FileStream::FileStream(const FileStream &rToCopy) THROW_EXCEPTION(CommonException, OSFileOpenError) } } +#endif // 0 // -------------------------------------------------------------------------- // @@ -82,7 +94,7 @@ FileStream::FileStream(const FileStream &rToCopy) // -------------------------------------------------------------------------- FileStream::~FileStream() { - if(mOSFileHandle >= 0) + if(mOSFileHandle != INVALID_FILE) { Close(); } @@ -98,8 +110,33 @@ FileStream::~FileStream() // -------------------------------------------------------------------------- int FileStream::Read(void *pBuffer, int NBytes, int Timeout) { - if(mOSFileHandle == -1) {THROW_EXCEPTION(CommonException, FileClosed)} + if(mOSFileHandle == INVALID_FILE) + { + THROW_EXCEPTION(CommonException, FileClosed) + } + +#ifdef WIN32 + int r; + DWORD numBytesRead = 0; + BOOL valid = ReadFile( + this->mOSFileHandle, + pBuffer, + NBytes, + &numBytesRead, + NULL + ); + + if ( valid ) + { + r = numBytesRead; + } + else + { + r = -1; + } +#else int r = ::read(mOSFileHandle, pBuffer, NBytes); +#endif if(r == -1) { THROW_EXCEPTION(CommonException, OSFileReadError) @@ -143,11 +180,34 @@ IOStream::pos_type FileStream::BytesLeftToRead() // -------------------------------------------------------------------------- void FileStream::Write(const void *pBuffer, int NBytes) { - if(mOSFileHandle == -1) {THROW_EXCEPTION(CommonException, FileClosed)} + if(mOSFileHandle == INVALID_FILE) + { + THROW_EXCEPTION(CommonException, FileClosed) + } + +#ifdef WIN32 + DWORD numBytesWritten = 0; + BOOL res = WriteFile( + this->mOSFileHandle, + pBuffer, + NBytes, + &numBytesWritten, + NULL + ); + + if ( (res == 0) || (numBytesWritten != NBytes)) + { + DWORD err = GetLastError(); + THROW_EXCEPTION(CommonException, OSFileWriteError) + } + + +#else if(::write(mOSFileHandle, pBuffer, NBytes) != NBytes) { THROW_EXCEPTION(CommonException, OSFileWriteError) } +#endif } @@ -161,7 +221,21 @@ void FileStream::Write(const void *pBuffer, int NBytes) // -------------------------------------------------------------------------- IOStream::pos_type FileStream::GetPosition() const { - if(mOSFileHandle == -1) {THROW_EXCEPTION(CommonException, FileClosed)} + if(mOSFileHandle == INVALID_FILE) + { + THROW_EXCEPTION(CommonException, FileClosed) + } + +#ifdef WIN32 + LARGE_INTEGER conv; + + conv.HighPart = 0; + conv.LowPart = 0; + + conv.LowPart = SetFilePointer(this->mOSFileHandle, 0, &conv.HighPart, FILE_CURRENT); + + return (IOStream::pos_type)conv.QuadPart; +#else // ! WIN32 off_t p = ::lseek(mOSFileHandle, 0, SEEK_CUR); if(p == -1) { @@ -169,6 +243,7 @@ IOStream::pos_type FileStream::GetPosition() const } return (IOStream::pos_type)p; +#endif // WIN32 } @@ -182,12 +257,28 @@ IOStream::pos_type FileStream::GetPosition() const // -------------------------------------------------------------------------- void FileStream::Seek(IOStream::pos_type Offset, int SeekType) { - if(mOSFileHandle == -1) {THROW_EXCEPTION(CommonException, FileClosed)} + if(mOSFileHandle == INVALID_FILE) + { + THROW_EXCEPTION(CommonException, FileClosed) + } + +#ifdef WIN32 + LARGE_INTEGER conv; + + conv.QuadPart = Offset; + DWORD retVal = SetFilePointer(this->mOSFileHandle, conv.LowPart, &conv.HighPart, ConvertSeekTypeToOSWhence(SeekType)); + + if ( retVal == INVALID_SET_FILE_POINTER && (GetLastError() != NO_ERROR) ) + { + THROW_EXCEPTION(CommonException, OSFileError) + } +#else // ! WIN32 if(::lseek(mOSFileHandle, Offset, ConvertSeekTypeToOSWhence(SeekType)) == -1) { THROW_EXCEPTION(CommonException, OSFileError) } - +#endif // WIN32 + // Not end of file any more! mIsEOF = false; } @@ -207,12 +298,21 @@ void FileStream::Close() { THROW_EXCEPTION(CommonException, FileAlreadyClosed) } +#ifdef WIN32 + if(::CloseHandle(mOSFileHandle) == 0) + { + THROW_EXCEPTION(CommonException, OSFileCloseError) + } + mOSFileHandle = NULL; + mIsEOF = true; +#else if(::close(mOSFileHandle) != 0) { THROW_EXCEPTION(CommonException, OSFileCloseError) } mOSFileHandle = -1; mIsEOF = true; +#endif } diff --git a/lib/common/FileStream.h b/lib/common/FileStream.h index bb3cc459..7d677636 100755 --- a/lib/common/FileStream.h +++ b/lib/common/FileStream.h @@ -17,12 +17,26 @@ #include #include +#ifdef WIN32 + #define INVALID_FILE NULL + typedef HANDLE tOSFileHandle; +#else + #define INVALID_FILE -1 + typedef int tOSFileHandle; +#endif + class FileStream : public IOStream { public: - FileStream(const char *Filename, int flags = O_RDONLY, int mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)); - FileStream(int FileDescriptor); - FileStream(const FileStream &rToCopy); + FileStream(const char *Filename, +#ifdef WIN32 + int flags = (O_RDONLY | O_BINARY), +#else + int flags = O_RDONLY, +#endif + int mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)); + FileStream(tOSFileHandle FileDescriptor); + virtual ~FileStream(); virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite); @@ -36,8 +50,14 @@ public: virtual bool StreamClosed(); private: - int mOSFileHandle; + tOSFileHandle mOSFileHandle; bool mIsEOF; + FileStream(const FileStream &rToCopy) { /* do not call */ } + +#ifdef WIN32 + // for debugging.. + std::string fileName; +#endif }; diff --git a/lib/common/IOStream.cpp b/lib/common/IOStream.cpp index 024eefcc..3c7be561 100755 --- a/lib/common/IOStream.cpp +++ b/lib/common/IOStream.cpp @@ -105,6 +105,17 @@ int IOStream::ConvertSeekTypeToOSWhence(int SeekType) int ostype = SEEK_SET; switch(SeekType) { +#ifdef WIN32 + case SeekType_Absolute: + ostype = FILE_BEGIN; + break; + case SeekType_Relative: + ostype = FILE_CURRENT; + break; + case SeekType_End: + ostype = FILE_END; + break; +#else // ! WIN32 case SeekType_Absolute: ostype = SEEK_SET; break; @@ -114,6 +125,7 @@ int IOStream::ConvertSeekTypeToOSWhence(int SeekType) case SeekType_End: ostype = SEEK_END; break; +#endif // WIN32 default: THROW_EXCEPTION(CommonException, IOStreamBadSeekType) diff --git a/lib/common/NamedLock.cpp b/lib/common/NamedLock.cpp index b9aeb768..fc7b8309 100755 --- a/lib/common/NamedLock.cpp +++ b/lib/common/NamedLock.cpp @@ -105,7 +105,7 @@ bool NamedLock::TryAndGetLock(const char *Filename, int mode) THROW_EXCEPTION(CommonException, OSFileError) } } -#else +#elif HAVE_DECL_F_SETLK struct flock desc; desc.l_type = F_WRLCK; desc.l_whence = SEEK_SET; diff --git a/lib/common/TemporaryDirectory.h b/lib/common/TemporaryDirectory.h index e683863b..9d52ecd9 100755 --- a/lib/common/TemporaryDirectory.h +++ b/lib/common/TemporaryDirectory.h @@ -12,15 +12,35 @@ #include -#ifdef TEMP_DIRECTORY_NAME - // Prefix name with Box to avoid clashing with OS API names - inline std::string BoxGetTemporaryDirectoryName() +#ifdef WIN32 + #include +#endif + +// Prefix name with Box to avoid clashing with OS API names +std::string BoxGetTemporaryDirectoryName() +{ +#ifdef WIN32 + // http://msdn.microsoft.com/library/default.asp? + // url=/library/en-us/fileio/fs/creating_and_using_a_temporary_file.asp + + DWORD dwRetVal; + char lpPathBuffer[1024]; + DWORD dwBufSize = sizeof(lpPathBuffer); + + // Get the temp path. + dwRetVal = GetTempPath(dwBufSize, // length of the buffer + lpPathBuffer); // buffer for path + if (dwRetVal > dwBufSize) { - return std::string(TEMP_DIRECTORY_NAME); + THROW_EXCEPTION(CommonException, TempDirPathTooLong) } -#else - non-static temporary directory names not supported yet + + return std::string(lpPathBuffer); +#elif defined TEMP_DIRECTORY_NAME + return std::string(TEMP_DIRECTORY_NAME); +#else + #error non-static temporary directory names not supported yet #endif +} #endif // TEMPORARYDIRECTORY__H - diff --git a/lib/common/UnixUser.cpp b/lib/common/UnixUser.cpp index 7a60b263..8b85c3e1 100755 --- a/lib/common/UnixUser.cpp +++ b/lib/common/UnixUser.cpp @@ -9,7 +9,10 @@ #include "Box.h" +#ifndef WIN32 #include +#endif + #include #include "UnixUser.h" diff --git a/lib/common/WaitForEvent.h b/lib/common/WaitForEvent.h index 46f152c5..52a073e9 100644 --- a/lib/common/WaitForEvent.h +++ b/lib/common/WaitForEvent.h @@ -15,7 +15,9 @@ #include #else #include - #include + #ifndef WIN32 + #include + #endif #endif #include "CommonException.h" diff --git a/lib/server/Daemon.cpp b/lib/server/Daemon.cpp index ca2df62f..a4dfdaec 100755 --- a/lib/server/Daemon.cpp +++ b/lib/server/Daemon.cpp @@ -11,11 +11,14 @@ #include #include -#include #include #include #include +#ifndef WIN32 +#include +#endif + #include "Daemon.h" #include "Configuration.h" #include "ServerException.h" @@ -140,6 +143,7 @@ int Daemon::Main(const char *DefaultConfigFile, int argc, const char *argv[]) // Let the derived class have a go at setting up stuff in the initial process SetupInInitialProcess(); +#ifndef WIN32 // Set signal handler struct sigaction sa; sa.sa_handler = SignalHandler; @@ -219,12 +223,14 @@ int Daemon::Main(const char *DefaultConfigFile, int argc, const char *argv[]) break; } } +#endif // ! WIN32 // open the log ::openlog(DaemonName(), LOG_PID, LOG_LOCAL6); // Log the start message ::syslog(LOG_INFO, "Starting daemon (config: %s) (version " BOX_VERSION ")", configfile); +#ifndef WIN32 // Write PID to file char pid[32]; int pidsize = sprintf(pid, "%d", (int)getpid()); @@ -233,6 +239,7 @@ int Daemon::Main(const char *DefaultConfigFile, int argc, const char *argv[]) ::syslog(LOG_ERR, "can't write pid file"); THROW_EXCEPTION(ServerException, DaemoniseFailed) } +#endif // Set up memory leak reporting #ifdef BOX_MEMORY_LEAK_TESTING @@ -245,6 +252,7 @@ int Daemon::Main(const char *DefaultConfigFile, int argc, const char *argv[]) if(asDaemon) { +#ifndef WIN32 // Close standard streams ::close(0); ::close(1); @@ -265,8 +273,9 @@ int Daemon::Main(const char *DefaultConfigFile, int argc, const char *argv[]) { ::close(devnull); } - - // And definately don't try and send anything to those file descriptors +#endif // ! WIN32 + + // And definitely don't try and send anything to those file descriptors // -- this has in the past sent text to something which isn't expecting it. TRACE_TO_STDOUT(false); } @@ -357,6 +366,7 @@ int Daemon::Main(const char *DefaultConfigFile, int argc, const char *argv[]) // -------------------------------------------------------------------------- void Daemon::EnterChild() { +#ifndef WIN32 // Unset signal handlers struct sigaction sa; sa.sa_handler = SIG_DFL; @@ -364,6 +374,7 @@ void Daemon::EnterChild() sigemptyset(&sa.sa_mask); // macro ::sigaction(SIGHUP, &sa, NULL); ::sigaction(SIGTERM, &sa, NULL); +#endif } @@ -377,6 +388,7 @@ void Daemon::EnterChild() // -------------------------------------------------------------------------- void Daemon::SignalHandler(int sigraised) { +#ifndef WIN32 if(spDaemon != 0) { switch(sigraised) @@ -393,6 +405,7 @@ void Daemon::SignalHandler(int sigraised) break; } } +#endif } // -------------------------------------------------------------------------- @@ -534,5 +547,3 @@ void Daemon::SetProcessTitle(const char *format, ...) #endif // HAVE_SETPROCTITLE } - - diff --git a/lib/server/LocalProcessStream.cpp b/lib/server/LocalProcessStream.cpp index f2a97c56..0de7bef4 100644 --- a/lib/server/LocalProcessStream.cpp +++ b/lib/server/LocalProcessStream.cpp @@ -9,7 +9,9 @@ #include "Box.h" +#ifndef WIN32 #include +#endif #include #include "LocalProcessStream.h" @@ -36,6 +38,8 @@ std::auto_ptr LocalProcessStream(const char *CommandLine, pid_t &rPidO // Split up command std::vector command; SplitString(std::string(CommandLine), ' ', command); + +#ifndef WIN32 // Build arguments char *args[MAX_ARGUMENTS + 4]; { @@ -94,6 +98,11 @@ std::auto_ptr LocalProcessStream(const char *CommandLine, pid_t &rPidO // Return the stream object and PID rPidOut = pid; return stream; +#else // WIN32 + ::syslog(LOG_ERR, "vfork not implemented - LocalProcessStream.cpp"); + std::auto_ptr stream; + return stream; +#endif // ! WIN32 } diff --git a/lib/server/SSLLib.cpp b/lib/server/SSLLib.cpp index 9e98550a..2a5bdbde 100755 --- a/lib/server/SSLLib.cpp +++ b/lib/server/SSLLib.cpp @@ -14,7 +14,9 @@ #include #include +#ifndef WIN32 #include +#endif #include "SSLLib.h" #include "ServerException.h" diff --git a/lib/server/ServerStream.h b/lib/server/ServerStream.h index d087a321..8dafccae 100755 --- a/lib/server/ServerStream.h +++ b/lib/server/ServerStream.h @@ -10,10 +10,13 @@ #ifndef SERVERSTREAM__H #define SERVERSTREAM__H -#include #include #include -#include + +#ifndef WIN32 + #include + #include +#endif #include "Daemon.h" #include "SocketListen.h" diff --git a/lib/server/Socket.cpp b/lib/server/Socket.cpp index b2d32345..0343b8bf 100755 --- a/lib/server/Socket.cpp +++ b/lib/server/Socket.cpp @@ -11,11 +11,13 @@ #include #include +#ifndef WIN32 #include #include #include #include #include +#endif #include #include @@ -72,6 +74,7 @@ void Socket::NameLookupToSockAddr(SocketAllAddr &addr, int &sockDomain, int Type } break; +#ifndef WIN32 case TypeUNIX: sockDomain = AF_UNIX; { @@ -89,7 +92,8 @@ void Socket::NameLookupToSockAddr(SocketAllAddr &addr, int &sockDomain, int Type ::strcpy(addr.sa_unix.sun_path, Name); } break; - +#endif + default: THROW_EXCEPTION(CommonException, BadArguments) break; diff --git a/lib/server/Socket.h b/lib/server/Socket.h index 86a06097..057e4cad 100755 --- a/lib/server/Socket.h +++ b/lib/server/Socket.h @@ -10,16 +10,23 @@ #ifndef SOCKET__H #define SOCKET__H +#ifdef WIN32 +#include "emu.h" +typedef int socklen_t; +#else #include #include #include +#endif #include typedef union { struct sockaddr sa_generic; struct sockaddr_in sa_inet; +#ifndef WIN32 struct sockaddr_un sa_unix; +#endif } SocketAllAddr; // -------------------------------------------------------------------------- diff --git a/lib/server/SocketListen.h b/lib/server/SocketListen.h index 7042011c..d954339a 100755 --- a/lib/server/SocketListen.h +++ b/lib/server/SocketListen.h @@ -12,15 +12,20 @@ #include #include -#include -#include -#include -#include + #ifdef HAVE_KQUEUE #include #include #endif +#ifndef WIN32 + #include +#endif + +#include +#include +#include + #include "Socket.h" #include "ServerException.h" @@ -94,7 +99,11 @@ public: { if(mSocketHandle != -1) { +#ifdef WIN32 + if(::closesocket(mSocketHandle) == -1) +#else if(::close(mSocketHandle) == -1) +#endif { THROW_EXCEPTION(ServerException, SocketCloseError) } @@ -128,8 +137,12 @@ public: } // Set an option to allow reuse (useful for -HUP situations!) +#ifdef WIN32 + if(::setsockopt(mSocketHandle, SOL_SOCKET, SO_REUSEADDR, "", 0) == -1) +#else int option = true; if(::setsockopt(mSocketHandle, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) == -1) +#endif { THROW_EXCEPTION(ServerException, SocketOpenError) } diff --git a/lib/server/SocketStream.cpp b/lib/server/SocketStream.cpp index 53865ee3..6719fcde 100755 --- a/lib/server/SocketStream.cpp +++ b/lib/server/SocketStream.cpp @@ -11,9 +11,12 @@ #include #include -#include #include +#ifndef WIN32 +#include +#endif + #include "SocketStream.h" #include "ServerException.h" #include "CommonException.h" @@ -140,7 +143,11 @@ void SocketStream::Open(int Type, const char *Name, int Port) if(::connect(mSocketHandle, &addr.sa_generic, addrLen) == -1) { // Dispose of the socket +#ifdef WIN32 + ::closesocket(mSocketHandle); +#else ::close(mSocketHandle); +#endif mSocketHandle = -1; THROW_EXCEPTION(ConnectionException, Conn_SocketConnectError) } @@ -191,7 +198,11 @@ int SocketStream::Read(void *pBuffer, int NBytes, int Timeout) } } +#ifdef WIN32 + int r = ::recv(mSocketHandle, (char*)pBuffer, NBytes, 0); +#else int r = ::read(mSocketHandle, pBuffer, NBytes); +#endif if(r == -1) { if(errno == EINTR) @@ -236,7 +247,11 @@ void SocketStream::Write(const void *pBuffer, int NBytes) while(bytesLeft > 0) { // Try to send. +#ifdef WIN32 + int sent = ::send(mSocketHandle, buffer, bytesLeft, 0); +#else int sent = ::write(mSocketHandle, buffer, bytesLeft); +#endif if(sent == -1) { // Error. @@ -283,8 +298,11 @@ void SocketStream::Write(const void *pBuffer, int NBytes) void SocketStream::Close() { if(mSocketHandle == -1) {THROW_EXCEPTION(ServerException, BadSocketHandle)} - +#ifdef WIN32 + if(::closesocket(mSocketHandle) == -1) +#else if(::close(mSocketHandle) == -1) +#endif { THROW_EXCEPTION(ServerException, SocketCloseError) } @@ -354,7 +372,7 @@ bool SocketStream::StreamClosed() // Created: 2003/08/06 // // -------------------------------------------------------------------------- -int SocketStream::GetSocketHandle() +tOSSocketHandle SocketStream::GetSocketHandle() { if(mSocketHandle == -1) {THROW_EXCEPTION(ServerException, BadSocketHandle)} return mSocketHandle; diff --git a/lib/server/SocketStream.h b/lib/server/SocketStream.h index 9b16dbfc..5caaacfd 100755 --- a/lib/server/SocketStream.h +++ b/lib/server/SocketStream.h @@ -12,6 +12,12 @@ #include "IOStream.h" +#ifdef WIN32 + typedef SOCKET tOSSocketHandle; +#else + typedef int tOSSocketHandle; +#endif + // -------------------------------------------------------------------------- // // Class @@ -42,12 +48,12 @@ public: virtual bool GetPeerCredentials(uid_t &rUidOut, gid_t &rGidOut); protected: - int GetSocketHandle(); + tOSSocketHandle GetSocketHandle(); void MarkAsReadClosed() {mReadClosed = true;} void MarkAsWriteClosed() {mWriteClosed = true;} private: - int mSocketHandle; + tOSSocketHandle mSocketHandle; bool mReadClosed; bool mWriteClosed; }; diff --git a/lib/server/SocketStreamTLS.cpp b/lib/server/SocketStreamTLS.cpp index 7d82f82c..39e0ea6c 100755 --- a/lib/server/SocketStreamTLS.cpp +++ b/lib/server/SocketStreamTLS.cpp @@ -12,10 +12,13 @@ #define TLS_CLASS_IMPLEMENTATION_CPP #include #include -#include #include #include +#ifndef WIN32 +#include +#endif + #include "SocketStreamTLS.h" #include "SSLLib.h" #include "ServerException.h" @@ -120,7 +123,8 @@ void SocketStreamTLS::Handshake(const TLSContext &rContext, bool IsServer) SSLLib::LogError("Create socket bio"); THROW_EXCEPTION(ServerException, TLSAllocationFailed) } - int socket = GetSocketHandle(); + + tOSSocketHandle socket = GetSocketHandle(); BIO_set_fd(mpBIO, socket, BIO_NOCLOSE); // Then the SSL object @@ -131,6 +135,7 @@ void SocketStreamTLS::Handshake(const TLSContext &rContext, bool IsServer) THROW_EXCEPTION(ServerException, TLSAllocationFailed) } +#ifndef WIN32 // Make the socket non-blocking so timeouts on Read work // This is more portable than using ioctl with FIONBIO int statusFlags = 0; @@ -139,6 +144,7 @@ void SocketStreamTLS::Handshake(const TLSContext &rContext, bool IsServer) { THROW_EXCEPTION(ServerException, SocketSetNonBlockingFailed) } +#endif // FIXME: This is less portable than the above. However, it MAY be needed // for cygwin, which has/had bugs with fcntl @@ -464,5 +470,3 @@ std::string SocketStreamTLS::GetPeerCommonName() // Done. return std::string(commonName); } - - diff --git a/lib/server/makeprotocol.pl b/lib/server/makeprotocol.pl index 2a69c59c..71355e62 100755 --- a/lib/server/makeprotocol.pl +++ b/lib/server/makeprotocol.pl @@ -182,7 +182,11 @@ __E if($implement_syslog) { - print H qq~#include \n~; + print H < +#endif +EOF } diff --git a/lib/win32/WinNamedPipeStream.cpp b/lib/win32/WinNamedPipeStream.cpp new file mode 100755 index 00000000..17a2227b --- /dev/null +++ b/lib/win32/WinNamedPipeStream.cpp @@ -0,0 +1,301 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: WinNamedPipeStream.cpp +// Purpose: I/O stream interface for Win32 named pipes +// Created: 2005/12/07 +// +// -------------------------------------------------------------------------- + +#include "Box.h" + +#ifdef WIN32 + +#include +#include +#include +#include + +#include "WinNamedPipeStream.h" +#include "ServerException.h" +#include "CommonException.h" +#include "Socket.h" + +#include "MemLeakFindOn.h" + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::WinNamedPipeStream() +// Purpose: Constructor (create stream ready for Open() call) +// Created: 2005/12/07 +// +// -------------------------------------------------------------------------- +WinNamedPipeStream::WinNamedPipeStream() + : mSocketHandle(NULL), + mReadClosed(false), + mWriteClosed(false), + mIsServer(false), + mIsConnected(false) +{ +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::~WinNamedPipeStream() +// Purpose: Destructor, closes stream if open +// Created: 2005/12/07 +// +// -------------------------------------------------------------------------- +WinNamedPipeStream::~WinNamedPipeStream() +{ + if (mSocketHandle != NULL) + { + Close(); + } +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::Accept(const char* Name) +// Purpose: Creates a new named pipe with the given name, +// and wait for a connection on it +// Created: 2005/12/07 +// +// -------------------------------------------------------------------------- +void WinNamedPipeStream::Accept(const wchar_t* pName) +{ + if (mSocketHandle != NULL || mIsConnected) + { + THROW_EXCEPTION(ServerException, SocketAlreadyOpen) + } + + mSocketHandle = CreateNamedPipeW( + pName, // pipe name + PIPE_ACCESS_DUPLEX, // read/write access + PIPE_TYPE_MESSAGE | // message type pipe + PIPE_READMODE_MESSAGE | // message-read mode + PIPE_WAIT, // blocking mode + 1, // max. instances + 4096, // output buffer size + 4096, // input buffer size + NMPWAIT_USE_DEFAULT_WAIT, // client time-out + NULL); // default security attribute + + if (mSocketHandle == NULL) + { + ::syslog(LOG_ERR, "CreateNamedPipeW failed: %d", + GetLastError()); + THROW_EXCEPTION(ServerException, SocketOpenError) + } + + bool connected = ConnectNamedPipe(mSocketHandle, (LPOVERLAPPED) NULL); + + if (!connected) + { + ::syslog(LOG_ERR, "ConnectNamedPipe failed: %d", + GetLastError()); + CloseHandle(mSocketHandle); + mSocketHandle = NULL; + THROW_EXCEPTION(ServerException, SocketOpenError) + } + + mReadClosed = FALSE; + mWriteClosed = FALSE; + mIsServer = TRUE; // must flush and disconnect before closing + mIsConnected = TRUE; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::Connect(const char* Name) +// Purpose: Opens a connection to a listening named pipe +// Created: 2005/12/07 +// +// -------------------------------------------------------------------------- +void WinNamedPipeStream::Connect(const wchar_t* pName) +{ + if (mSocketHandle != NULL || mIsConnected) + { + THROW_EXCEPTION(ServerException, SocketAlreadyOpen) + } + + mSocketHandle = CreateFileW( + pName, // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, + 0, // default attributes + NULL); // no template file + + if (mSocketHandle == INVALID_HANDLE_VALUE) + { + ::syslog(LOG_ERR, "Failed to connect to server's named pipe: " + "error %d", GetLastError()); + THROW_EXCEPTION(ServerException, SocketOpenError) + } + + mReadClosed = FALSE; + mWriteClosed = FALSE; + mIsServer = FALSE; // just close the socket + mIsConnected = TRUE; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::Read(void *pBuffer, int NBytes) +// Purpose: Reads data from stream. Maybe returns less than asked for. +// Created: 2003/07/31 +// +// -------------------------------------------------------------------------- +int WinNamedPipeStream::Read(void *pBuffer, int NBytes, int Timeout) +{ + // TODO no support for timeouts yet + ASSERT(Timeout == IOStream::TimeOutInfinite) + + if (mSocketHandle == NULL || !mIsConnected) + { + THROW_EXCEPTION(ServerException, BadSocketHandle) + } + + DWORD NumBytesRead; + + bool Success = ReadFile( + mSocketHandle, // pipe handle + pBuffer, // buffer to receive reply + NBytes, // size of buffer + &NumBytesRead, // number of bytes read + NULL); // not overlapped + + if (!Success) + { + THROW_EXCEPTION(ConnectionException, Conn_SocketReadError) + } + + // Closed for reading at EOF? + if (NumBytesRead == 0) + { + mReadClosed = true; + } + + return NumBytesRead; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::Write(void *pBuffer, int NBytes) +// Purpose: Writes data, blocking until it's all done. +// Created: 2003/07/31 +// +// -------------------------------------------------------------------------- +void WinNamedPipeStream::Write(const void *pBuffer, int NBytes) +{ + if (mSocketHandle == NULL || !mIsConnected) + { + THROW_EXCEPTION(ServerException, BadSocketHandle) + } + + // Buffer in byte sized type. + ASSERT(sizeof(char) == 1); + const char *pByteBuffer = (char *)pBuffer; + + int NumBytesWrittenTotal = 0; + + while (NumBytesWrittenTotal < NBytes) + { + DWORD NumBytesWrittenThisTime = 0; + + bool Success = WriteFile( + mSocketHandle, // pipe handle + pByteBuffer + NumBytesWrittenTotal, // message + NBytes - NumBytesWrittenTotal, // message length + &NumBytesWrittenThisTime, // bytes written this time + NULL); // not overlapped + + if (!Success) + { + mWriteClosed = true; // assume can't write again + THROW_EXCEPTION(ConnectionException, + Conn_SocketWriteError) + } + + NumBytesWrittenTotal += NumBytesWrittenThisTime; + } +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::Close() +// Purpose: Closes connection to remote socket +// Created: 2003/07/31 +// +// -------------------------------------------------------------------------- +void WinNamedPipeStream::Close() +{ + if (mSocketHandle == NULL || !mIsConnected) + { + THROW_EXCEPTION(ServerException, BadSocketHandle) + } + + if (mIsServer) + { + if (!FlushFileBuffers(mSocketHandle)) + { + ::syslog(LOG_INFO, "FlushFileBuffers failed: %d", + GetLastError()); + } + + if (!DisconnectNamedPipe(mSocketHandle)) + { + ::syslog(LOG_ERR, "DisconnectNamedPipe failed: %d", + GetLastError()); + } + + mIsServer = false; + } + + if (!CloseHandle(mSocketHandle)) + { + ::syslog(LOG_ERR, "CloseHandle failed: %d", GetLastError()); + THROW_EXCEPTION(ServerException, SocketCloseError) + } + + mSocketHandle = NULL; + mIsConnected = FALSE; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::StreamDataLeft() +// Purpose: Still capable of reading data? +// Created: 2003/08/02 +// +// -------------------------------------------------------------------------- +bool WinNamedPipeStream::StreamDataLeft() +{ + return !mReadClosed; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: WinNamedPipeStream::StreamClosed() +// Purpose: Connection been closed? +// Created: 2003/08/02 +// +// -------------------------------------------------------------------------- +bool WinNamedPipeStream::StreamClosed() +{ + return mWriteClosed; +} + +#endif // WIN32 diff --git a/lib/win32/WinNamedPipeStream.h b/lib/win32/WinNamedPipeStream.h new file mode 100755 index 00000000..5a800371 --- /dev/null +++ b/lib/win32/WinNamedPipeStream.h @@ -0,0 +1,60 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: WinNamedPipeStream.h +// Purpose: I/O stream interface for Win32 named pipes +// Created: 2005/12/07 +// +// -------------------------------------------------------------------------- + +#if ! defined WINNAMEDPIPESTREAM__H && defined WIN32 +#define WINNAMEDPIPESTREAM__H + +#include "IOStream.h" + +// -------------------------------------------------------------------------- +// +// Class +// Name: WinNamedPipeStream +// Purpose: I/O stream interface for Win32 named pipes +// Created: 2003/07/31 +// +// -------------------------------------------------------------------------- +class WinNamedPipeStream : public IOStream +{ +public: + WinNamedPipeStream(); + ~WinNamedPipeStream(); + + // server side - create the named pipe and listen for connections + void Accept(const wchar_t* Name); + + // client side - connect to a waiting server + void Connect(const wchar_t* Name); + + // both sides + virtual int Read(void *pBuffer, int NBytes, + int Timeout = IOStream::TimeOutInfinite); + virtual void Write(const void *pBuffer, int NBytes); + virtual void Close(); + virtual bool StreamDataLeft(); + virtual bool StreamClosed(); + bool IsConnected() { return mIsConnected; } + +protected: + HANDLE GetSocketHandle(); + void MarkAsReadClosed() {mReadClosed = true;} + void MarkAsWriteClosed() {mWriteClosed = true;} + +private: + WinNamedPipeStream(const WinNamedPipeStream &rToCopy) + { /* do not call */ } + + HANDLE mSocketHandle; + bool mReadClosed; + bool mWriteClosed; + bool mIsServer; + bool mIsConnected; +}; + +#endif // WINNAMEDPIPESTREAM__H diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp new file mode 100644 index 00000000..29200313 --- /dev/null +++ b/lib/win32/emu.cpp @@ -0,0 +1,978 @@ +// Box Backup Win32 native port by Nick Knight + +// Need at least 0x0500 to use GetFileSizeEx on Cygwin/MinGW +#define WINVER 0x0500 + +#include "Box.h" + +#ifdef WIN32 + +// #include "emu.h" + +#include +#include +// #include +#include + +#include +#include + +//our implimentation for a timer +//based on a simple thread which sleeps for a +//period of time +static bool gFinishTimer; +static CRITICAL_SECTION gLock; + +typedef struct +{ + int countDown; + int interval; +} +tTimer; + +std::list gTimerList; +static void (__cdecl *gTimerFunc) (int) = NULL; + +int setitimer(int type , struct itimerval *timeout, int) +{ + if ( SIGVTALRM == type || ITIMER_VIRTUAL == type ) + { + EnterCriticalSection(&gLock); + // we only need seconds for the mo! + if (timeout->it_value.tv_sec == 0 && + timeout->it_value.tv_usec == 0) + { + gTimerList.clear(); + } + else + { + tTimer ourTimer; + ourTimer.countDown = timeout->it_value.tv_sec; + ourTimer.interval = timeout->it_interval.tv_sec; + gTimerList.push_back(ourTimer); + } + LeaveCriticalSection(&gLock); + } + + // indicate success + return 0; +} + +static unsigned int WINAPI RunTimer(LPVOID lpParameter) +{ + gFinishTimer = false; + + while (!gFinishTimer) + { + std::list::iterator it; + EnterCriticalSection(&gLock); + + for (it = gTimerList.begin(); it != gTimerList.end(); it++) + { + tTimer& rTimer(*it); + + rTimer.countDown --; + if (rTimer.countDown == 0) + { + if (gTimerFunc != NULL) + { + gTimerFunc(0); + } + if (rTimer.interval) + { + rTimer.countDown = rTimer.interval; + } + else + { + // mark for deletion + rTimer.countDown = -1; + } + } + } + + for (it = gTimerList.begin(); it != gTimerList.end(); it++) + { + tTimer& rTimer(*it); + + if (rTimer.countDown == -1) + { + gTimerList.erase(it); + //if we don't do this the search is on a corrupt list + it = gTimerList.begin(); + } + } + + LeaveCriticalSection(&gLock); + // we only need to have a 1 second resolution + Sleep(1000); + } + + return 0; +} + +int SetTimerHandler(void (__cdecl *func ) (int)) +{ + gTimerFunc = func; + return 0; +} + +void InitTimer(void) +{ + InitializeCriticalSection(&gLock); + + // create our thread + HANDLE ourThread = (HANDLE)_beginthreadex(NULL, 0, RunTimer, 0, + CREATE_SUSPENDED, NULL); + SetThreadPriority(ourThread, THREAD_PRIORITY_LOWEST); + ResumeThread(ourThread); +} + +void FiniTimer(void) +{ + gFinishTimer = true; + EnterCriticalSection(&gLock); + DeleteCriticalSection(&gLock); +} + +//Our constants we need to keep track of +//globals +struct passwd gTempPasswd; + +bool EnableBackupRights( void ) +{ + HANDLE hToken; + TOKEN_PRIVILEGES token_priv; + + //open current process to adjust privileges + if( !OpenProcessToken( GetCurrentProcess( ), + TOKEN_ADJUST_PRIVILEGES, + &hToken )) + { + printf( "Cannot open process token - err = %d\n", GetLastError( ) ); + return false; + } + + //let's build the token privilege struct - + //first, look up the LUID for the backup privilege + + if( !LookupPrivilegeValue( NULL, //this system + SE_BACKUP_NAME, //the name of the privilege + &( token_priv.Privileges[0].Luid )) ) //result + { + printf( "Cannot lookup backup privilege - err = %d\n", GetLastError( ) ); + return false; + } + + token_priv.PrivilegeCount = 1; + token_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + // now set the privilege + // because we're going exit right after dumping the streams, there isn't + // any need to save current state + + if( !AdjustTokenPrivileges( hToken, //our process token + false, //we're not disabling everything + &token_priv, //address of structure + sizeof( token_priv ), //size of structure + NULL, NULL )) //don't save current state + { + //this function is a little tricky - if we were adjusting + //more than one privilege, it could return success but not + //adjust them all - in the general case, you need to trap this + printf( "Could not enable backup privileges - err = %d\n", GetLastError( ) ); + return false; + + } + else + { + return true; + } +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: openfile +// Purpose: replacement for any open calls - handles unicode filenames - supplied in utf8 +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +HANDLE openfile(const char *filename, int flags, int mode) +{ + try{ + + wchar_t *buffer; + std::string fileN(filename); + + std::string tmpStr("\\\\?\\"); + //is the path relative or otherwise + if ( fileN[1] != ':' ) + { + //we need to get the current directory + char wd[PATH_MAX]; + if(::getcwd(wd, PATH_MAX) == 0) + { + return NULL; + } + tmpStr += wd; + if (tmpStr[tmpStr.length()] != '\\') + { + tmpStr += '\\'; + } + } + tmpStr += filename; + + int strlen = MultiByteToWideChar( + CP_UTF8, // code page + 0, // character-type options + tmpStr.c_str(), // string to map + (int)tmpStr.length(), // number of bytes in string + NULL, // wide-character buffer + 0 // size of buffer - work out how much space we need + ); + + buffer = new wchar_t[strlen+1]; + if ( buffer == NULL ) + { + return NULL; + } + + strlen = MultiByteToWideChar( + CP_UTF8, // code page + 0, // character-type options + tmpStr.c_str(), // string to map + (int)tmpStr.length(), // number of bytes in string + buffer, // wide-character buffer + strlen // size of buffer + ); + + if ( strlen == 0 ) + { + delete [] buffer; + return NULL; + } + + buffer[strlen] = L'\0'; + + //flags could be O_WRONLY | O_CREAT | O_RDONLY + DWORD createDisposition = OPEN_EXISTING; + DWORD shareMode = FILE_SHARE_READ; + DWORD accessRights = FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA; + + if ( flags & O_WRONLY ) + { + createDisposition = OPEN_EXISTING; + shareMode |= FILE_SHARE_READ ;//| FILE_SHARE_WRITE; + } + if ( flags & O_CREAT ) + { + createDisposition = OPEN_ALWAYS; + shareMode |= FILE_SHARE_READ ;//| FILE_SHARE_WRITE; + accessRights |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA | FILE_ALL_ACCESS; + } + if ( flags & O_TRUNC ) + { + createDisposition = OPEN_ALWAYS; + } + + HANDLE hdir = CreateFileW(buffer, + accessRights, + shareMode, + NULL, + createDisposition, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if ( hdir == INVALID_HANDLE_VALUE ) + { + // DWORD err = GetLastError(); + // syslog(EVENTLOG_WARNING_TYPE, "Couldn't open file %s, err %i\n", filename, err); + delete [] buffer; + return NULL; + } + + delete [] buffer; + return hdir; + + } + catch(...) + { + printf("Caught openfile:%s\r\n", filename); + } + return NULL; + +} + +// MinGW provides a getopt implementation +#ifndef __MINGW32__ +//works with getopt +char *optarg; +//optind looks like an index into the string - how far we have moved along +int optind = 1; +char nextchar = -1; +#endif + +// -------------------------------------------------------------------------- +// +// Function +// Name: ourfstat +// Purpose: replacement for fstat supply a windows handle +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +int ourfstat(HANDLE hdir, struct stat * st) +{ + ULARGE_INTEGER conv; + + if (hdir == INVALID_HANDLE_VALUE) + { + ::syslog(LOG_ERR, "Error: invalid file handle in ourfstat()"); + errno = EBADF; + return -1; + } + + BY_HANDLE_FILE_INFORMATION fi; + if (!GetFileInformationByHandle(hdir, &fi)) + { + ::syslog(LOG_WARNING, "Failed to read file information: " + "error %d", GetLastError()); + errno = EACCES; + return -1; + } + + // This next example is how we get our INODE (equivalent) information + conv.HighPart = fi.nFileIndexHigh; + conv.LowPart = fi.nFileIndexLow; + st->st_ino = conv.QuadPart; + + // get the time information + st->st_ctime = ConvertFileTimeToTime_t(&fi.ftCreationTime); + st->st_atime = ConvertFileTimeToTime_t(&fi.ftLastAccessTime); + st->st_mtime = ConvertFileTimeToTime_t(&fi.ftLastWriteTime); + + // size of the file + LARGE_INTEGER st_size; + if (!GetFileSizeEx(hdir, &st_size)) + { + ::syslog(LOG_WARNING, "Failed to get file size: error %d", + GetLastError()); + errno = EACCES; + return -1; + } + + conv.HighPart = st_size.HighPart; + conv.LowPart = st_size.LowPart; + st->st_size = conv.QuadPart; + + //the mode of the file + st->st_mode = 0; + //DWORD res = GetFileAttributes((LPCSTR)tmpStr.c_str()); + + if (INVALID_FILE_ATTRIBUTES != fi.dwFileAttributes) + { + if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + st->st_mode |= S_IFDIR; + } + else + { + st->st_mode |= S_IFREG; + } + } + else + { + ::syslog(LOG_WARNING, "Failed to get file attributes: " + "error %d", GetLastError()); + errno = EACCES; + return -1; + } + + return 0; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: OpenFileByNameUtf8 +// Purpose: Converts filename to Unicode and returns +// a handle to it. In case of error, sets errno, +// logs the error and returns NULL. +// Created: 10th December 2004 +// +// -------------------------------------------------------------------------- +HANDLE OpenFileByNameUtf8(const char* pName) +{ + //some string thing - required by ms to indicate long/unicode filename + std::string tmpStr("\\\\?\\"); + + // is the path relative or otherwise + std::string fileN(pName); + if (fileN[1] != ':') + { + // we need to get the current directory + char wd[PATH_MAX]; + if(::getcwd(wd, PATH_MAX) == 0) + { + ::syslog(LOG_WARNING, + "Failed to open '%s': path too long", pName); + errno = ENAMETOOLONG; + return NULL; + } + + tmpStr += wd; + if (tmpStr[tmpStr.length()] != '\\') + { + tmpStr += '\\'; + } + } + + tmpStr += fileN; + + int strlen = MultiByteToWideChar( + CP_UTF8, // code page + 0, // character-type options + tmpStr.c_str(), // string to map + (int)tmpStr.length(), // number of bytes in string + NULL, // wide-character buffer + 0 // size of buffer - work out + // how much space we need + ); + + wchar_t* buffer = new wchar_t[strlen+1]; + + if (buffer == NULL) + { + ::syslog(LOG_WARNING, + "Failed to open '%s': out of memory", pName); + errno = ENOMEM; + return NULL; + } + + strlen = MultiByteToWideChar( + CP_UTF8, // code page + 0, // character-type options + tmpStr.c_str(), // string to map + (int)tmpStr.length(), // number of bytes in string + buffer, // wide-character buffer + strlen // size of buffer + ); + + if (strlen == 0) + { + ::syslog(LOG_WARNING, + "Failed to open '%s': could not convert " + "file name to Unicode", pName); + errno = EACCES; + delete [] buffer; + return NULL; + } + + buffer[strlen] = L'\0'; + + HANDLE handle = CreateFileW(buffer, + FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA, + FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if (handle == INVALID_HANDLE_VALUE) + { + // if our open fails we should always be able to + // open in this mode - to get the inode information + // at least one process must have the file open - + // in this case someone else does. + handle = CreateFileW(buffer, + 0, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + } + + delete [] buffer; + + if (handle == INVALID_HANDLE_VALUE) + { + DWORD err = GetLastError(); + + if (err == ERROR_FILE_NOT_FOUND) + { + ::syslog(LOG_WARNING, + "Failed to open '%s': file not found", pName); + errno = ENOENT; + } + else + { + ::syslog(LOG_WARNING, + "Failed to open '%s': error %d", pName); + errno = EACCES; + } + + return NULL; + } + + return handle; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: ourstat +// Purpose: replacement for the lstat and stat functions, +// works with unicode filenames supplied in utf8 format +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +int ourstat(const char * pName, struct stat * st) +{ + // at the mo + st->st_uid = 0; + st->st_gid = 0; + st->st_nlink = 1; + + HANDLE handle = OpenFileByNameUtf8(pName); + + if (handle == NULL) + { + // errno already set and error logged by OpenFileByNameUtf8() + return -1; + } + + int retVal = ourfstat(handle, st); + if (retVal != 0) + { + // error logged, but without filename + ::syslog(LOG_WARNING, "Failed to get file information " + "for '%s'", pName); + } + + // close the handle + CloseHandle(handle); + + return retVal; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: statfs +// Purpose: returns the mount point of where a file is located - +// in this case the volume serial number +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +int statfs(const char * pName, struct statfs * s) +{ + HANDLE handle = OpenFileByNameUtf8(pName); + + if (handle == NULL) + { + // errno already set and error logged by OpenFileByNameUtf8() + return -1; + } + + BY_HANDLE_FILE_INFORMATION fi; + if (!GetFileInformationByHandle(handle, &fi)) + { + ::syslog(LOG_WARNING, "Failed to get file information " + "for '%s': error %d", pName, GetLastError()); + CloseHandle(handle); + errno = EACCES; + return -1; + } + + // convert volume serial number to a string + _ui64toa(fi.dwVolumeSerialNumber, s->f_mntonname + 1, 16); + + // pseudo unix mount point + s->f_mntonname[0] = DIRECTORY_SEPARATOR_ASCHAR; + + CloseHandle(handle); // close the handle + + return 0; +} + + + + + +// MinGW provides opendir(), etc. via +// MSVC does not provide these, so emulation is needed + +#ifndef __MINGW32__ +// -------------------------------------------------------------------------- +// +// Function +// Name: opendir +// Purpose: replacement for unix function, uses win32 findfirst routines +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +DIR *opendir(const char *name) +{ + try + { + DIR *dir = 0; + std::string dirName(name); + + //append a '\' win32 findfirst is sensitive to this + if ( dirName[dirName.size()] != '\\' || dirName[dirName.size()] != '/' ) + { + dirName += '\\'; + } + + //what is the search string? - everything + dirName += '*'; + + if(name && name[0]) + { + if ( ( dir = new DIR ) != 0 ) + { + //mbstowcs(dir->name, dirName.c_str(),100); + //wcscpy((wchar_t*)dir->name, (const wchar_t*)dirName.c_str()); + //mbstowcs(dir->name, dirName.c_str(), dirName.size()+1); + //wchar_t *buffer; + + int strlen = MultiByteToWideChar( + CP_UTF8, // code page + 0, // character-type options + dirName.c_str(), // string to map + (int)dirName.length(), // number of bytes in string + NULL, // wide-character buffer + 0 // size of buffer - work out how much space we need + ); + + dir->name = new wchar_t[strlen+1]; + + if (dir->name == NULL) + { + delete dir; + dir = 0; + errno = ENOMEM; + return NULL; + } + + strlen = MultiByteToWideChar( + CP_UTF8, // code page + 0, // character-type options + dirName.c_str(), // string to map + (int)dirName.length(), // number of bytes in string + dir->name, // wide-character buffer + strlen // size of buffer + ); + + if (strlen == 0) + { + delete dir->name; + delete dir; + dir = 0; + errno = ENOMEM; + return NULL; + } + + dir->name[strlen] = L'\0'; + + + dir->fd = _wfindfirst( + (const wchar_t*)dir->name, + &dir->info); + + if (dir->fd != -1) + { + dir->result.d_name = 0; + } + else // go back + { + delete [] dir->name; + delete dir; + dir = 0; + } + } + else // backwards again + { + delete dir; + dir = 0; + errno = ENOMEM; + } + } + else + { + errno = EINVAL; + } + + return dir; + + } + catch(...) + { + printf("Caught opendir"); + } + + return NULL; +} + +//this kinda makes it not thread friendly! +//but I don't think it needs to be. +char tempbuff[MAX_PATH]; +// -------------------------------------------------------------------------- +// +// Function +// Name: readdir +// Purpose: as function above +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +struct dirent *readdir(DIR *dp) +{ + try + { + struct dirent *den = NULL; + + if (dp && dp->fd != -1) + { + if (!dp->result.d_name || + _wfindnext(dp->fd, &dp->info) != -1) + { + den = &dp->result; + std::wstring input(dp->info.name); + memset(tempbuff, 0, sizeof(tempbuff)); + WideCharToMultiByte(CP_UTF8, 0, dp->info.name, + -1, &tempbuff[0], sizeof (tempbuff), + NULL, NULL); + //den->d_name = (char *)dp->info.name; + den->d_name = &tempbuff[0]; + } + } + else + { + errno = EBADF; + } + return den; + } + catch (...) + { + printf("Caught readdir"); + } + return NULL; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: closedir +// Purpose: as function above +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +int closedir(DIR *dp) +{ + try + { + int finres = -1; + if (dp) + { + if(dp->fd != -1) + { + finres = _findclose(dp->fd); + } + + delete [] dp->name; + delete dp; + } + + if (finres == -1) // errors go to EBADF + { + errno = EBADF; + } + + return finres; + } + catch (...) + { + printf("Caught closedir"); + } + return -1; +} +#endif // !__MINGW32__ + +// -------------------------------------------------------------------------- +// +// Function +// Name: poll +// Purpose: a weak implimentation (just enough for box) +// of the unix poll for winsock2 +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +int poll (struct pollfd *ufds, unsigned long nfds, int timeout) +{ + try + { + fd_set readfd; + fd_set writefd; + + readfd.fd_count = 0; + writefd.fd_count = 0; + + struct pollfd *ufdsTmp = ufds; + + timeval timOut; + timeval *tmpptr; + + if (timeout == INFTIM) + tmpptr = NULL; + else + tmpptr = &timOut; + + timOut.tv_sec = timeout / 1000; + timOut.tv_usec = timeout * 1000; + + if (ufds->events & POLLIN) + { + for (unsigned long i = 0; i < nfds; i++) + { + readfd.fd_array[i] = ufdsTmp->fd; + readfd.fd_count++; + } + } + + if (ufds->events & POLLOUT) + { + for (unsigned long i = 0; i < nfds; i++) + { + + writefd.fd_array[i]=ufdsTmp->fd; + writefd.fd_count++; + } + } + + int noffds = select(0, &readfd, &writefd, 0, tmpptr); + + if (noffds == SOCKET_ERROR) + { + // int errval = WSAGetLastError(); + + ufdsTmp = ufds; + for (unsigned long i = 0; i < nfds; i++) + { + ufdsTmp->revents = POLLERR; + ufdsTmp++; + } + return (-1); + } + + return noffds; + } + catch (...) + { + printf("Caught poll"); + } + + return -1; +} + +HANDLE gSyslogH = 0; + +void syslog(int loglevel, const char *frmt, ...) +{ + DWORD errinfo; + char* buffer; + std::string sixfour(frmt); + + switch (loglevel) + { + case LOG_INFO: + errinfo = EVENTLOG_INFORMATION_TYPE; + break; + case LOG_ERR: + errinfo = EVENTLOG_ERROR_TYPE; + break; + case LOG_WARNING: + errinfo = EVENTLOG_WARNING_TYPE; + break; + default: + errinfo = EVENTLOG_WARNING_TYPE; + break; + } + + + //taken from MSDN + try + { + + + int sixfourpos; + while ( ( sixfourpos = sixfour.find("%ll")) != -1 ) + { + //maintain portability - change the 64 bit formater... + std::string temp = sixfour.substr(0,sixfourpos); + temp += "%I64"; + temp += sixfour.substr(sixfourpos+3, sixfour.length()); + sixfour = temp; + } + + //printf("parsed string is:%s\r\n", sixfour.c_str()); + + va_list args; + va_start(args, frmt); + +#ifdef __MINGW32__ + // no _vscprintf, use a fixed size buffer + buffer = new char[1024]; + int len = 1023; +#else + int len = _vscprintf( sixfour.c_str(), args ); + ASSERT(len > 0) + + len = len + 1; + char* buffer = new char[len]; +#endif + + ASSERT(buffer) + memset(buffer, 0, len); + + int len2 = vsnprintf(buffer, len, sixfour.c_str(), args); + ASSERT(len2 <= len); + + va_end(args); + } + catch (...) + { + printf("Caught syslog: %s", sixfour.c_str()); + return; + } + + try + { + + if (!ReportEvent(gSyslogH, // event log handle + errinfo, // event type + 0, // category zero + MSG_ERR_EXIST, // event identifier - + // we will call them all the same + NULL, // no user security identifier + 1, // one substitution string + 0, // no data + (LPCSTR*)&buffer, // pointer to string array + NULL)) // pointer to data + + { + DWORD err = GetLastError(); + printf("Unable to send message to Event Log " + "(error %i):\r\n", err); + } + + printf("%s\r\n", buffer); + + if (buffer) delete [] buffer; + } + catch (...) + { + printf("Caught syslog ReportEvent"); + } +} + +#endif // WIN32 diff --git a/lib/win32/emu.h b/lib/win32/emu.h new file mode 100644 index 00000000..5b506206 --- /dev/null +++ b/lib/win32/emu.h @@ -0,0 +1,426 @@ +// emulates unix syscalls to win32 functions + +#if ! defined EMU_INCLUDE && defined WIN32 +#define EMU_INCLUDE + +#define _STAT_DEFINED +#define _INO_T_DEFINED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +//#include + +#include + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + + +//signal in unix SIGVTALRM does not exist in win32 - but looking at the +#define SIGVTALRM 254 +#define SIGALRM SIGVTALRM +#define ITIMER_VIRTUAL 0 + +int setitimer(int type , struct itimerval *timeout, int); +void InitTimer(void); +void FiniTimer(void); + +inline int geteuid(void) +{ + //lets pretend to be root! + return 0; +} + +struct passwd { + char *pw_name; + char *pw_passwd; + uid_t pw_uid; + gid_t pw_gid; + time_t pw_change; + char *pw_class; + char *pw_gecos; + char *pw_dir; + char *pw_shell; + time_t pw_expire; +}; + +extern passwd gTempPasswd; +inline struct passwd * getpwnam(const char * name) +{ + //for the mo pretend to be root + gTempPasswd.pw_uid = 0; + gTempPasswd.pw_gid = 0; + + return &gTempPasswd; +} + +#define S_IRWXG 1 +#define S_IRWXO 2 +#define S_ISUID 4 +#define S_ISGID 8 +#define S_ISVTX 16 + +#ifndef __MINGW32__ + //not sure if these are correct + //S_IWRITE - writing permitted + //_S_IREAD - reading permitted + //_S_IREAD | _S_IWRITE - + #define S_IRUSR S_IWRITE + #define S_IWUSR S_IREAD + #define S_IRWXU (S_IREAD|S_IWRITE|S_IEXEC) + + #define S_ISREG(x) (S_IFREG & x) + #define S_ISDIR(x) (S_IFDIR & x) +#endif + +inline int utimes(const char * Filename, timeval[]) +{ + //again I am guessing this is quite important to + //be functioning, as large restores would be a problem + + //indicate success + return 0; +} +inline int chown(const char * Filename, u_int32_t uid, u_int32_t gid) +{ + //important - this needs implementing + //If a large restore is required then + //it needs to restore files AND permissions + //reference AdjustTokenPrivileges + //GetAccountSid + //InitializeSecurityDescriptor + //SetSecurityDescriptorOwner + //The next function looks like the guy to use... + //SetFileSecurity + + //indicate success + return 0; +} + +inline int chmod(const char * Filename, int uid) +{ + //indicate sucsess + return 0; +} + +//I do not perceive a need to change the user or group on a backup client +//at any rate the owner of a service can be set in the service settings +inline int setegid(int) +{ + return true; +} +inline int seteuid(int) +{ + return true; +} +inline int setgid(int) +{ + return true; +} +inline int setuid(int) +{ + return true; +} +inline int getgid(void) +{ + return 0; +} +inline int getuid(void) +{ + return 0; +} + +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif + +// MinGW provides a getopt implementation +#ifndef __MINGW32__ + +//this will need to be implimented if we see fit that command line +//options are going to be used! (probably then:) +//where the calling function looks for the parsed parameter +extern char *optarg; +//optind looks like an index into the string - how far we have moved along +extern int optind; +extern char nextchar; + +inline int getopt(int count, char * const * args, char * tolookfor) +{ + if ( optind >= count ) return -1; + + std::string str((const char *)args[optind]); + std::string interestin(tolookfor); + int opttolookfor = 0; + int index = -1; + //just initialize the string - just in case it is used. + //optarg[0] = 0; + std::string opt; + + if ( count == 0 ) return -1; + + do + { + if ( index != -1 ) + { + str = str.substr(index+1, str.size()); + } + + index = str.find('-'); + + if ( index == -1 ) return -1; + + opt = str[1]; + + optind ++; + str = args[optind]; + } + while ( ( opttolookfor = interestin.find(opt)) == -1 ); + + if ( interestin[opttolookfor+1] == ':' ) + { + + //strcpy(optarg, str.c_str()); + optarg = args[optind]; + optind ++; + } + + //indicate we have finished + return opt[0]; +} +#endif // !__MINGW32__ + +#define timespec timeval + +//not available in win32 +struct itimerval +{ + timeval it_interval; + timeval it_value; +}; + +//win32 deals in usec not nsec - so need to ensure this follows through +#define tv_nsec tv_usec + +#ifndef __MINGW32__ + typedef unsigned __int64 u_int64_t; + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int32 u_int32_t; + typedef __int32 int32_t; + typedef unsigned __int16 uint16_t; + typedef __int16 int16_t; + typedef unsigned __int8 uint8_t; + typedef __int8 int8_t; + + typedef int socklen_t; +#endif + +// I (re-)defined here for the moment; has to be removed later !!! +#ifndef BOX_VERSION +#define BOX_VERSION "0.09hWin32" +#endif + +#define S_IRGRP S_IWRITE +#define S_IWGRP S_IREAD +#define S_IROTH S_IWRITE | S_IREAD +#define S_IWOTH S_IREAD | S_IREAD + +//again need to verify these +#define S_IFLNK 1 + +#define S_ISLNK(x) ( false ) + +// nasty implementation to get working - TODO get the win32 equiv +#ifdef _DEBUG +#define getpid() 1 +#endif + +#define vsnprintf _vsnprintf + +#ifndef __MINGW32__ +typedef unsigned int mode_t; +#endif + +inline int mkdir(const char *pathname, mode_t mode) +{ + return mkdir(pathname); +} + +#ifdef __MINGW32__ + #include +#else + inline int strcasecmp(const char *s1, const char *s2) + { + return _stricmp(s1,s2); + } + + struct dirent + { + char *d_name; + }; + + struct DIR + { + intptr_t fd; // filedescriptor + // struct _finddata_t info; + struct _wfinddata_t info; + // struct _finddata_t info; + struct dirent result; // d_name (first time null) + wchar_t *name; // null-terminated byte string + }; + + DIR *opendir(const char *name); + struct dirent *readdir(DIR *dp); + int closedir(DIR *dp); +#endif + +HANDLE openfile(const char *filename, int flags, int mode); + +#define LOG_INFO 6 +#define LOG_WARNING 4 +#define LOG_ERR 3 +#define LOG_PID 0 +#define LOG_LOCAL6 0 + +extern HANDLE gSyslogH; +void MyReportEvent(LPCTSTR *szMsg, DWORD errinfo); +inline void openlog(const char * daemonName, int, int) +{ + gSyslogH = RegisterEventSource( + NULL, // uses local computer + daemonName); // source name + if (gSyslogH == NULL) + { + } +} + +inline void closelog(void) +{ + DeregisterEventSource(gSyslogH); +} + +void syslog(int loglevel, const char *fmt, ...); + +#ifndef __MINGW32__ +#define strtoll _strtoi64 +#endif + +inline unsigned int sleep(unsigned int secs) +{ + Sleep(secs*1000); + return(ERROR_SUCCESS); +} + +#define INFTIM -1 +#define POLLIN 0x1 +#define POLLERR 0x8 +#define POLLOUT 0x4 + +#define SHUT_RDWR SD_BOTH +#define SHUT_RD SD_RECEIVE +#define SHUT_WR SD_SEND + +struct pollfd +{ + SOCKET fd; + short int events; + short int revents; +}; + +inline int ioctl(SOCKET sock, int flag, int * something) +{ + //indicate success + return 0; +} + +inline int waitpid(pid_t pid, int *status, int) +{ + return 0; +} + +//this shouldn't be needed. +struct statfs +{ + TCHAR f_mntonname[MAX_PATH]; +}; + +// I think this should get us going +// Although there is a warning about +// mount points in win32 can now exists - which means inode number can be +// duplicated, so potential of a problem - perhaps this needs to be +// implemented with a little more thought... TODO + +struct stat { + //_dev_t st_dev; + u_int64_t st_ino; + DWORD st_mode; + short st_nlink; + short st_uid; + short st_gid; + //_dev_t st_rdev; + u_int64_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; + +#ifndef __MINGW32__ +typedef u_int64_t _ino_t; +#endif + +int ourstat(const char * name, struct stat * st); +int ourfstat(HANDLE file, struct stat * st); +int statfs(const char * name, struct statfs * s); + +//need this for converstions +inline time_t ConvertFileTimeToTime_t(FILETIME *fileTime) +{ + SYSTEMTIME stUTC; + struct tm timeinfo; + + // Convert the last-write time to local time. + FileTimeToSystemTime(fileTime, &stUTC); + // SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); + + timeinfo.tm_sec = stUTC.wSecond; + timeinfo.tm_min = stUTC.wMinute; + timeinfo.tm_hour = stUTC.wHour; + timeinfo.tm_mday = stUTC.wDay; + timeinfo.tm_wday = stUTC.wDayOfWeek; + timeinfo.tm_mon = stUTC.wMonth - 1; + // timeinfo.tm_yday = ...; + timeinfo.tm_year = stUTC.wYear - 1900; + + time_t retVal = mktime(&timeinfo); + return retVal; +} + +#define stat(x,y) ourstat(x,y) +#define fstat(x,y) ourfstat(x,y) +#define lstat(x,y) ourstat(x,y) + +int poll (struct pollfd *ufds, unsigned long nfds, int timeout); +bool EnableBackupRights( void ); + +// +// MessageId: MSG_ERR_EXIST +// MessageText: +// Box Backup. +// +#define MSG_ERR_EXIST ((DWORD)0xC0000004L) + +#endif // !EMU_INCLUDE && WIN32 -- cgit v1.2.3