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/win32/WinNamedPipeStream.cpp | 301 ++++++++++++ lib/win32/WinNamedPipeStream.h | 60 +++ lib/win32/emu.cpp | 978 +++++++++++++++++++++++++++++++++++++++ lib/win32/emu.h | 426 +++++++++++++++++ 4 files changed, 1765 insertions(+) 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/win32') 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 From 8b99bea2180508f1a8720074fa043828583ce98b Mon Sep 17 00:00:00 2001 From: Martin Ebourne Date: Mon, 12 Dec 2005 21:03:38 +0000 Subject: Fixing up svn:executable properties. You may need a new checkout to see this. --- lib/win32/WinNamedPipeStream.cpp | 0 lib/win32/WinNamedPipeStream.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 lib/win32/WinNamedPipeStream.cpp mode change 100755 => 100644 lib/win32/WinNamedPipeStream.h (limited to 'lib/win32') diff --git a/lib/win32/WinNamedPipeStream.cpp b/lib/win32/WinNamedPipeStream.cpp old mode 100755 new mode 100644 diff --git a/lib/win32/WinNamedPipeStream.h b/lib/win32/WinNamedPipeStream.h old mode 100755 new mode 100644 -- cgit v1.2.3 From a2b798939612ef6b40f67e8da36e9a532c869b47 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 28 Jan 2006 13:12:58 +0000 Subject: * infrastructure/makeparcels.pl - Use the target platform's name, rather than the build platform, in the generated package file names (useful for cross-compiling) * lib/win32/emu.cpp - Don't log a warning when statting a file that doesn't exist, as bbackupquery does this to verify that the target does not exist before restoring * lib/backupclient/BackupClientFileAttributes.cpp - Fixed a missing endian conversion that was causing file timestamps to appear to be invalid, generating warnings about every file on the server, on Win32 * parcels.txt - Include a couple of DLL files in the package on MinGW, which are needed to run the compiled binaries * bin/bbackupquery/BackupQueries.cpp - Fixed usage text for the "get" command --- lib/win32/emu.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 29200313..17ac698f 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -500,8 +500,6 @@ HANDLE OpenFileByNameUtf8(const char* pName) if (err == ERROR_FILE_NOT_FOUND) { - ::syslog(LOG_WARNING, - "Failed to open '%s': file not found", pName); errno = ENOENT; } else -- cgit v1.2.3 From 830aa82e44381c85d8486e46de7ae0e26830457e Mon Sep 17 00:00:00 2001 From: Ben Summers Date: Mon, 13 Feb 2006 13:30:21 +0000 Subject: Merge chris/win32/vc2005-compile-fixes @ r455, add infrastructure/msvc to distribution --- lib/win32/WinNamedPipeStream.cpp | 43 +- lib/win32/config.h.win32 | 396 +++++++++++++++++ lib/win32/emu.cpp | 913 +++++++++++++++++++++++++-------------- lib/win32/emu.h | 196 ++++++--- 4 files changed, 1131 insertions(+), 417 deletions(-) create mode 100644 lib/win32/config.h.win32 (limited to 'lib/win32') diff --git a/lib/win32/WinNamedPipeStream.cpp b/lib/win32/WinNamedPipeStream.cpp index 17a2227b..c5b7eaa5 100644 --- a/lib/win32/WinNamedPipeStream.cpp +++ b/lib/win32/WinNamedPipeStream.cpp @@ -11,7 +11,10 @@ #ifdef WIN32 -#include +#ifdef HAVE_UNISTD_H + #include +#endif + #include #include #include @@ -97,15 +100,14 @@ void WinNamedPipeStream::Accept(const wchar_t* pName) { ::syslog(LOG_ERR, "ConnectNamedPipe failed: %d", GetLastError()); - CloseHandle(mSocketHandle); - mSocketHandle = NULL; + Close(); THROW_EXCEPTION(ServerException, SocketOpenError) } - mReadClosed = FALSE; - mWriteClosed = FALSE; - mIsServer = TRUE; // must flush and disconnect before closing - mIsConnected = TRUE; + mReadClosed = false; + mWriteClosed = false; + mIsServer = true; // must flush and disconnect before closing + mIsConnected = true; } // -------------------------------------------------------------------------- @@ -140,10 +142,10 @@ void WinNamedPipeStream::Connect(const wchar_t* pName) THROW_EXCEPTION(ServerException, SocketOpenError) } - mReadClosed = FALSE; - mWriteClosed = FALSE; - mIsServer = FALSE; // just close the socket - mIsConnected = TRUE; + mReadClosed = false; + mWriteClosed = false; + mIsServer = false; // just close the socket + mIsConnected = true; } // -------------------------------------------------------------------------- @@ -240,7 +242,14 @@ void WinNamedPipeStream::Write(const void *pBuffer, int NBytes) // -------------------------------------------------------------------------- void WinNamedPipeStream::Close() { - if (mSocketHandle == NULL || !mIsConnected) + if (mSocketHandle == NULL && mIsConnected) + { + fprintf(stderr, "Inconsistent connected state\n"); + ::syslog(LOG_ERR, "Inconsistent connected state"); + mIsConnected = false; + } + + if (mSocketHandle == NULL) { THROW_EXCEPTION(ServerException, BadSocketHandle) } @@ -262,14 +271,16 @@ void WinNamedPipeStream::Close() mIsServer = false; } - if (!CloseHandle(mSocketHandle)) + bool result = CloseHandle(mSocketHandle); + + mSocketHandle = NULL; + mIsConnected = false; + + if (!result) { ::syslog(LOG_ERR, "CloseHandle failed: %d", GetLastError()); THROW_EXCEPTION(ServerException, SocketCloseError) } - - mSocketHandle = NULL; - mIsConnected = FALSE; } // -------------------------------------------------------------------------- diff --git a/lib/win32/config.h.win32 b/lib/win32/config.h.win32 new file mode 100644 index 00000000..42298545 --- /dev/null +++ b/lib/win32/config.h.win32 @@ -0,0 +1,396 @@ +/* lib/common/BoxConfig.h. Generated by configure. */ +/* lib/common/BoxConfig.h.in. Generated from configure.ac by autoheader. */ +/* Hacked by hand to work for MSVC by Chris Wilson */ + +/* Define to major version for BDB_VERSION */ +/* #undef BDB_VERSION_MAJOR */ + +/* Define to minor version for BDB_VERSION */ +/* #undef BDB_VERSION_MINOR */ + +/* Define to point version for BDB_VERSION */ +/* #undef BDB_VERSION_POINT */ + +/* Name of the 64 bit endian swapping function */ +/* #undef BSWAP64 */ + +/* Define to 1 if the `closedir' function returns void instead of `int'. */ +#define CLOSEDIR_VOID 1 + +/* Define to 1 if non-aligned int16 access will fail */ +/* #undef HAVE_ALIGNED_ONLY_INT16 */ + +/* Define to 1 if non-aligned int32 access will fail */ +/* #undef HAVE_ALIGNED_ONLY_INT32 */ + +/* Define to 1 if non-aligned int64 access will fail */ +/* #undef HAVE_ALIGNED_ONLY_INT64 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_BYTEORDER_H */ + +/* Define to 1 if BSWAP64 is defined to the name of a valid 64 bit endian + swapping function */ +/* #undef HAVE_BSWAP64 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DB_H */ + +/* Define to 1 if you have the declaration of `F_SETLK', and to 0 if you + don't. */ +#define HAVE_DECL_F_SETLK 0 + +/* Define to 1 if you have the declaration of `INFTIM', and to 0 if you don't. + */ +#define HAVE_DECL_INFTIM 0 + +/* Define to 1 if you have the declaration of `O_EXLOCK', and to 0 if you + don't. */ +#define HAVE_DECL_O_EXLOCK 0 + +/* Define to 1 if you have the declaration of `SO_PEERCRED', and to 0 if you + don't. */ +#define HAVE_DECL_SO_PEERCRED 0 + +/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if + you don't. */ +#define HAVE_DECL_XATTR_NOFOLLOW 0 + +/* Define to 1 if #define of pragmas works */ +/* #undef HAVE_DEFINE_PRAGMA */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_DIRENT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_EDITLINE_READLINE_H */ + +/* define if the compiler supports exceptions */ +#define HAVE_EXCEPTIONS + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_EXECINFO_H */ + +/* Define to 1 if you have the `flock' function. */ +/* #undef HAVE_FLOCK */ + +/* Define to 1 if you have the `getmntent' function. */ +/* #undef HAVE_GETMNTENT */ + +/* Define to 1 if you have the `getpeereid' function. */ +/* #undef HAVE_GETPEEREID */ + +/* Define to 1 if you have the `getpid' function. */ +#define HAVE_GETPID 1 + +/* Define to 1 if you have the `getxattr' function. */ +/* #undef HAVE_GETXATTR */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_HISTORY_H */ + +/* Define to 1 if you have the header file. */ +// #define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `kqueue' function. */ +/* #undef HAVE_KQUEUE */ + +/* Define to 1 if you have the `lchown' function. */ +/* #undef HAVE_LCHOWN */ + +/* Define to 1 if you have the `lgetxattr' function. */ +/* #undef HAVE_LGETXATTR */ + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#define HAVE_LIBCRYPTO 1 + +/* Define if you have a readline compatible library */ +/* #undef HAVE_LIBREADLINE */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#define HAVE_LIBSSL 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#define HAVE_LIBZ 1 + +/* Define to 1 if you have the `listxattr' function. */ +/* #undef HAVE_LISTXATTR */ + +/* Define to 1 if you have the `llistxattr' function. */ +/* #undef HAVE_LLISTXATTR */ + +/* Define to 1 if syscall lseek requires a dummy middle parameter */ +/* #undef HAVE_LSEEK_DUMMY_PARAM */ + +/* Define to 1 if you have the `lsetxattr' function. */ +/* #undef HAVE_LSETXATTR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MNTENT_H */ + +/* Define to 1 if this platform supports mounts */ +/* #undef HAVE_MOUNTS */ + +/* define if the compiler implements namespaces */ +#define HAVE_NAMESPACES + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IN_H */ + +/* Define to 1 if SSL is pre-0.9.7 */ +/* #undef HAVE_OLD_SSL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PROCESS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 (and set RANDOM_DEVICE) if a random device is available */ +/* #undef HAVE_RANDOM_DEVICE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_READLINE_H */ + +/* Define if your readline library has add_history */ +/* #undef HAVE_READLINE_HISTORY */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_READLINE_HISTORY_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_READLINE_READLINE_H */ + +/* Define to 1 if you have the header file. */ +// #define HAVE_REGEX_H 1 + +/* Define to 1 if you have the `setproctitle' function. */ +/* #undef HAVE_SETPROCTITLE */ + +/* Define to 1 if you have the `setxattr' function. */ +/* #undef HAVE_SETXATTR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if SSL is available */ +#define HAVE_SSL 1 + +/* Define to 1 if you have the `statfs' function. */ +/* #undef HAVE_STATFS */ + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +/* #undef HAVE_STAT_EMPTY_STRING_BUG */ + +/* Define to 1 if stdbool.h conforms to C99. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +// #define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if `d_type' is member of `struct dirent'. */ +/* #undef HAVE_STRUCT_DIRENT_D_TYPE */ + +/* Define to 1 if `mnt_dir' is member of `struct mntent'. */ +/* #undef HAVE_STRUCT_MNTENT_MNT_DIR */ + +/* Define to 1 if `mnt_mountp' is member of `struct mnttab'. */ +/* #undef HAVE_STRUCT_MNTTAB_MNT_MOUNTP */ + +/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */ +/* #undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + +/* Define to 1 if `f_mntonname' is member of `struct statfs'. */ +/* #undef HAVE_STRUCT_STATFS_F_MNTONNAME */ + +/* Define to 1 if `st_flags' is member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_FLAGS */ + +/* Define to 1 if `st_mtimespec' is member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC */ + +/* Define to 1 if you have the `syscall' function. */ +/* #undef HAVE_SYSCALL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYSLOG_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_ENDIAN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MNTTAB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MOUNT_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +// #define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SYSCALL_H */ + +/* Define to 1 if you have the header file. */ +// #define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_WAIT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_XATTR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define HAVE_UINT16_T 1 + +/* Define to 1 if the system has the type `uint32_t'. */ +#define HAVE_UINT32_T 1 + +/* Define to 1 if the system has the type `uint64_t'. */ +#define HAVE_UINT64_T 1 + +/* Define to 1 if the system has the type `uint8_t'. */ +#define HAVE_UINT8_T 1 + +/* Define to 1 if you have the header file. */ +// #define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the type `u_int16_t'. */ +/* #undef HAVE_U_INT16_T */ + +/* Define to 1 if the system has the type `u_int32_t'. */ +/* #undef HAVE_U_INT32_T */ + +/* Define to 1 if the system has the type `u_int64_t'. */ +/* #undef HAVE_U_INT64_T */ + +/* Define to 1 if the system has the type `u_int8_t'. */ +/* #undef HAVE_U_INT8_T */ + +/* Define to 1 if struct dirent.d_type is valid */ +/* #undef HAVE_VALID_DIRENT_D_TYPE */ + +/* Define to 1 if the system has the type `_Bool'. */ +/* #undef HAVE__BOOL */ + +/* Define to 1 if you have the `__syscall' function. */ +/* #undef HAVE___SYSCALL */ + +/* Define to 1 if __syscall is available but needs a definition */ +/* #undef HAVE___SYSCALL_NEED_DEFN */ + +/* max value of long long calculated by configure */ +/* #undef LLONG_MAX */ + +/* min value of long long calculated by configure */ +/* #undef LLONG_MIN */ + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "box@fluffy.co.uk" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Box Backup" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Box Backup 0.09" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "box-backup" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.09" + +/* Define to the filename of the random device (and set HAVE_RANDOM_DEVICE) */ +/* #undef RANDOM_DEVICE */ + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* TMP directory name */ +#define TEMP_DIRECTORY_NAME "/tmp" + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if __USE_MALLOC is required work around STL memory leaks */ +/* #undef __USE_MALLOC */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `int' if doesn't define. */ +#define gid_t int + +/* Define to `int' if does not define. */ +/* #undef mode_t */ + +/* Define to `long' if does not define. */ +/* #undef off_t */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if doesn't define. */ +#define uid_t int diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 17ac698f..00d43122 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -12,14 +12,20 @@ #include #include // #include -#include + +#ifdef HAVE_UNISTD_H + #include +#endif +#ifdef HAVE_PROCESS_H + #include +#endif #include #include -//our implimentation for a timer -//based on a simple thread which sleeps for a -//period of time +// our implementation for a timer, based on a +// simple thread which sleeps for a period of time + static bool gFinishTimer; static CRITICAL_SECTION gLock; @@ -28,14 +34,14 @@ typedef struct int countDown; int interval; } -tTimer; +Timer_t; -std::list gTimerList; +std::list gTimerList; static void (__cdecl *gTimerFunc) (int) = NULL; -int setitimer(int type , struct itimerval *timeout, int) +int setitimer(int type, struct itimerval *timeout, void *arg) { - if ( SIGVTALRM == type || ITIMER_VIRTUAL == type ) + if (ITIMER_VIRTUAL == type) { EnterCriticalSection(&gLock); // we only need seconds for the mo! @@ -46,7 +52,7 @@ int setitimer(int type , struct itimerval *timeout, int) } else { - tTimer ourTimer; + Timer_t ourTimer; ourTimer.countDown = timeout->it_value.tv_sec; ourTimer.interval = timeout->it_interval.tv_sec; gTimerList.push_back(ourTimer); @@ -64,12 +70,12 @@ static unsigned int WINAPI RunTimer(LPVOID lpParameter) while (!gFinishTimer) { - std::list::iterator it; + std::list::iterator it; EnterCriticalSection(&gLock); for (it = gTimerList.begin(); it != gTimerList.end(); it++) { - tTimer& rTimer(*it); + Timer_t& rTimer(*it); rTimer.countDown --; if (rTimer.countDown == 0) @@ -92,13 +98,18 @@ static unsigned int WINAPI RunTimer(LPVOID lpParameter) for (it = gTimerList.begin(); it != gTimerList.end(); it++) { - tTimer& rTimer(*it); + Timer_t& rTimer(*it); if (rTimer.countDown == -1) { gTimerList.erase(it); - //if we don't do this the search is on a corrupt list + + // the iterator is now invalid, so restart search it = gTimerList.begin(); + + // if the list is now empty, don't try to increment + // the iterator again + if (it == gTimerList.end()) break; } } @@ -148,7 +159,8 @@ bool EnableBackupRights( void ) TOKEN_ADJUST_PRIVILEGES, &hToken )) { - printf( "Cannot open process token - err = %d\n", GetLastError( ) ); + printf( "Cannot open process token: error %d\n", + (int)GetLastError() ); return false; } @@ -159,7 +171,8 @@ bool EnableBackupRights( void ) SE_BACKUP_NAME, //the name of the privilege &( token_priv.Privileges[0].Luid )) ) //result { - printf( "Cannot lookup backup privilege - err = %d\n", GetLastError( ) ); + printf( "Cannot lookup backup privilege: error %d\n", + (int)GetLastError( ) ); return false; } @@ -179,7 +192,8 @@ bool EnableBackupRights( void ) //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( ) ); + printf( "Could not enable backup privileges: error %d\n", + (int)GetLastError( ) ); return false; } @@ -192,115 +206,342 @@ bool EnableBackupRights( void ) // -------------------------------------------------------------------------- // // Function -// Name: openfile -// Purpose: replacement for any open calls - handles unicode filenames - supplied in utf8 -// Created: 25th October 2004 +// Name: ConvertToWideString +// Purpose: Converts a string from specified codepage to +// a wide string (WCHAR*). Returns a buffer which +// MUST be freed by the caller with delete[]. +// In case of fire, logs the error and returns NULL. +// Created: 4th February 2006 // // -------------------------------------------------------------------------- -HANDLE openfile(const char *filename, int flags, int mode) +WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) { - try{ + int len = MultiByteToWideChar + ( + codepage, // source code page + 0, // character-type options + pString, // string to map + -1, // number of bytes in string - auto detect + NULL, // wide-character buffer + 0 // size of buffer - work out + // how much space we need + ); + + if (len == 0) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "error %d", GetLastError()); + errno = EINVAL; + return NULL; + } - wchar_t *buffer; - std::string fileN(filename); + WCHAR* buffer = new WCHAR[len]; - 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; - } + if (buffer == NULL) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "out of memory"); + 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 - ); + len = MultiByteToWideChar + ( + codepage, // source code page + 0, // character-type options + pString, // string to map + -1, // number of bytes in string - auto detect + buffer, // wide-character buffer + len // size of buffer + ); + + if (len == 0) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "error %i", GetLastError()); + errno = EACCES; + delete [] buffer; + return NULL; + } - if ( strlen == 0 ) - { - delete [] buffer; - return NULL; - } + return buffer; +} - buffer[strlen] = L'\0'; +// -------------------------------------------------------------------------- +// +// Function +// Name: ConvertUtf8ToWideString +// Purpose: Converts a string from UTF-8 to a wide string. +// Returns a buffer which MUST be freed by the caller +// with delete[]. +// In case of fire, logs the error and returns NULL. +// Created: 4th February 2006 +// +// -------------------------------------------------------------------------- +WCHAR* ConvertUtf8ToWideString(const char* pString) +{ + return ConvertToWideString(pString, CP_UTF8); +} - //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; +// -------------------------------------------------------------------------- +// +// Function +// Name: ConvertFromWideString +// Purpose: Converts a wide string to a narrow string in the +// specified code page. Returns a buffer which MUST +// be freed by the caller with delete[]. +// In case of fire, logs the error and returns NULL. +// Created: 4th February 2006 +// +// -------------------------------------------------------------------------- +char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) +{ + int len = WideCharToMultiByte + ( + codepage, // destination code page + 0, // character-type options + pString, // string to map + -1, // number of bytes in string - auto detect + NULL, // output buffer + 0, // size of buffer - work out + // how much space we need + NULL, // replace unknown chars with system default + NULL // don't tell us when that happened + ); + + if (len == 0) + { + ::syslog(LOG_WARNING, + "Failed to convert wide string to narrow: " + "error %d", GetLastError()); + errno = EINVAL; + return NULL; + } - if ( flags & O_WRONLY ) - { - createDisposition = OPEN_EXISTING; - shareMode |= FILE_SHARE_READ ;//| FILE_SHARE_WRITE; - } - if ( flags & O_CREAT ) + char* buffer = new char[len]; + + if (buffer == NULL) + { + ::syslog(LOG_WARNING, + "Failed to convert wide string to narrow: " + "out of memory"); + errno = ENOMEM; + return NULL; + } + + len = WideCharToMultiByte + ( + codepage, // source code page + 0, // character-type options + pString, // string to map + -1, // number of bytes in string - auto detect + buffer, // output buffer + len, // size of buffer + NULL, // replace unknown chars with system default + NULL // don't tell us when that happened + ); + + if (len == 0) + { + ::syslog(LOG_WARNING, + "Failed to convert wide string to narrow: " + "error %i", GetLastError()); + errno = EACCES; + delete [] buffer; + return NULL; + } + + return buffer; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: ConvertUtf8ToConsole +// Purpose: Converts a string from UTF-8 to the console +// code page. On success, replaces contents of rDest +// and returns true. In case of fire, logs the error +// and returns false. +// Created: 4th February 2006 +// +// -------------------------------------------------------------------------- +bool ConvertUtf8ToConsole(const char* pString, std::string& rDest) +{ + WCHAR* pWide = ConvertToWideString(pString, CP_UTF8); + if (pWide == NULL) + { + return false; + } + + char* pConsole = ConvertFromWideString(pWide, GetConsoleOutputCP()); + delete [] pWide; + + if (!pConsole) + { + return false; + } + + rDest = pConsole; + delete [] pConsole; + + return true; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: ConvertConsoleToUtf8 +// Purpose: Converts a string from the console code page +// to UTF-8. On success, replaces contents of rDest +// and returns true. In case of fire, logs the error +// and returns false. +// Created: 4th February 2006 +// +// -------------------------------------------------------------------------- +bool ConvertConsoleToUtf8(const char* pString, std::string& rDest) +{ + WCHAR* pWide = ConvertToWideString(pString, GetConsoleCP()); + if (pWide == NULL) + { + return false; + } + + char* pConsole = ConvertFromWideString(pWide, CP_UTF8); + delete [] pWide; + + if (!pConsole) + { + return false; + } + + rDest = pConsole; + delete [] pConsole; + + return true; +} + + +// -------------------------------------------------------------------------- +// +// Function +// Name: ConvertPathToAbsoluteUnicode +// Purpose: Converts relative paths to absolute (with unicode marker) +// Created: 4th February 2006 +// +// -------------------------------------------------------------------------- +std::string ConvertPathToAbsoluteUnicode(const char *pFileName) +{ + std::string tmpStr("\\\\?\\"); + + // Is the path relative or absolute? + // Absolute paths on Windows are always a drive letter + // followed by ':' + + if (pFileName[1] != ':') + { + // Must be relative. We need to get the + // current directory to make it absolute. + + char wd[PATH_MAX]; + if (::getcwd(wd, PATH_MAX) == 0) { - createDisposition = OPEN_ALWAYS; - shareMode |= FILE_SHARE_READ ;//| FILE_SHARE_WRITE; - accessRights |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA | FILE_ALL_ACCESS; + ::syslog(LOG_WARNING, + "Failed to open '%s': path too long", + pFileName); + errno = ENAMETOOLONG; + tmpStr = ""; + return tmpStr; } - if ( flags & O_TRUNC ) + + tmpStr += wd; + if (tmpStr[tmpStr.length()] != '\\') { - createDisposition = OPEN_ALWAYS; + tmpStr += '\\'; } + } + + tmpStr += pFileName; + return tmpStr; +} - 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; - } +// -------------------------------------------------------------------------- +// +// Function +// Name: openfile +// Purpose: replacement for any open calls - handles unicode filenames - supplied in utf8 +// Created: 25th October 2004 +// +// -------------------------------------------------------------------------- +HANDLE openfile(const char *pFileName, int flags, int mode) +{ + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); + + if (AbsPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return NULL; + } + + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); + // We are responsible for freeing pBuffer + + if (pBuffer == NULL) + { + // error already logged by ConvertUtf8ToWideString() + return NULL; + } - delete [] buffer; - return hdir; + // 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) + { + shareMode = FILE_SHARE_WRITE; } - catch(...) + if (flags & O_RDWR) { - printf("Caught openfile:%s\r\n", filename); + shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + } + if (flags & O_CREAT) + { + createDisposition = OPEN_ALWAYS; + shareMode |= FILE_SHARE_WRITE; + accessRights |= FILE_WRITE_ATTRIBUTES + | FILE_WRITE_DATA | FILE_WRITE_EA + | FILE_ALL_ACCESS; + } + if (flags & O_TRUNC) + { + createDisposition = CREATE_ALWAYS; + } + if (flags & O_EXCL) + { + shareMode = 0; + } + + HANDLE hdir = CreateFileW(pBuffer, + accessRights, + shareMode, + NULL, + createDisposition, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + delete [] pBuffer; + + if (hdir == INVALID_HANDLE_VALUE) + { + ::syslog(LOG_WARNING, "Failed to open file %s: " + "error %i", pFileName, GetLastError()); + return NULL; } - return NULL; + return hdir; } // MinGW provides a getopt implementation @@ -315,18 +556,18 @@ char nextchar = -1; // -------------------------------------------------------------------------- // // Function -// Name: ourfstat +// Name: emu_fstat // Purpose: replacement for fstat supply a windows handle // Created: 25th October 2004 // // -------------------------------------------------------------------------- -int ourfstat(HANDLE hdir, struct stat * st) +int emu_fstat(HANDLE hdir, struct stat * st) { ULARGE_INTEGER conv; if (hdir == INVALID_HANDLE_VALUE) { - ::syslog(LOG_ERR, "Error: invalid file handle in ourfstat()"); + ::syslog(LOG_ERR, "Error: invalid file handle in emu_fstat()"); errno = EBADF; return -1; } @@ -343,7 +584,7 @@ int ourfstat(HANDLE hdir, struct stat * st) // This next example is how we get our INODE (equivalent) information conv.HighPart = fi.nFileIndexHigh; conv.LowPart = fi.nFileIndexLow; - st->st_ino = conv.QuadPart; + st->st_ino = (_ino_t)conv.QuadPart; // get the time information st->st_ctime = ConvertFileTimeToTime_t(&fi.ftCreationTime); @@ -362,7 +603,7 @@ int ourfstat(HANDLE hdir, struct stat * st) conv.HighPart = st_size.HighPart; conv.LowPart = st_size.LowPart; - st->st_size = conv.QuadPart; + st->st_size = (_off_t)conv.QuadPart; //the mode of the file st->st_mode = 0; @@ -400,76 +641,26 @@ int ourfstat(HANDLE hdir, struct stat * st) // Created: 10th December 2004 // // -------------------------------------------------------------------------- -HANDLE OpenFileByNameUtf8(const char* pName) +HANDLE OpenFileByNameUtf8(const char* pFileName) { - //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) + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); + + if (AbsPathWithUnicode.size() == 0) { - ::syslog(LOG_WARNING, - "Failed to open '%s': out of memory", pName); - errno = ENOMEM; + // error already logged by ConvertPathToAbsoluteUnicode() 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) + + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); + // We are responsible for freeing pBuffer + + if (pBuffer == NULL) { - ::syslog(LOG_WARNING, - "Failed to open '%s': could not convert " - "file name to Unicode", pName); - errno = EACCES; - delete [] buffer; + // error already logged by ConvertUtf8ToWideString() return NULL; } - buffer[strlen] = L'\0'; - - HANDLE handle = CreateFileW(buffer, + HANDLE handle = CreateFileW(pBuffer, FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, @@ -483,7 +674,7 @@ HANDLE OpenFileByNameUtf8(const char* pName) // 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, + handle = CreateFileW(pBuffer, 0, FILE_SHARE_READ, NULL, @@ -492,7 +683,7 @@ HANDLE OpenFileByNameUtf8(const char* pName) NULL); } - delete [] buffer; + delete [] pBuffer; if (handle == INVALID_HANDLE_VALUE) { @@ -505,7 +696,7 @@ HANDLE OpenFileByNameUtf8(const char* pName) else { ::syslog(LOG_WARNING, - "Failed to open '%s': error %d", pName); + "Failed to open '%s': error %d", pFileName, err); errno = EACCES; } @@ -518,13 +709,13 @@ HANDLE OpenFileByNameUtf8(const char* pName) // -------------------------------------------------------------------------- // // Function -// Name: ourstat +// Name: emu_stat // 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) +int emu_stat(const char * pName, struct stat * st) { // at the mo st->st_uid = 0; @@ -539,7 +730,7 @@ int ourstat(const char * pName, struct stat * st) return -1; } - int retVal = ourfstat(handle, st); + int retVal = emu_fstat(handle, st); if (retVal != 0) { // error logged, but without filename @@ -593,14 +784,6 @@ int statfs(const char * pName, struct statfs * s) return 0; } - - - - -// MinGW provides opendir(), etc. via -// MSVC does not provide these, so emulation is needed - -#ifndef __MINGW32__ // -------------------------------------------------------------------------- // // Function @@ -611,110 +794,56 @@ int statfs(const char * pName, struct statfs * s) // -------------------------------------------------------------------------- DIR *opendir(const char *name) { - try + if (!name || !name[0]) { - 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 - ); + errno = EINVAL; + return NULL; + } + + std::string dirName(name); - if (strlen == 0) - { - delete dir->name; - delete dir; - dir = 0; - errno = ENOMEM; - return NULL; - } + //append a '\' win32 findfirst is sensitive to this + if ( dirName[dirName.size()] != '\\' || dirName[dirName.size()] != '/' ) + { + dirName += '\\'; + } - dir->name[strlen] = L'\0'; + // what is the search string? - everything + dirName += '*'; - - dir->fd = _wfindfirst( - (const wchar_t*)dir->name, - &dir->info); + DIR *pDir = new DIR; + if (pDir == NULL) + { + errno = ENOMEM; + return NULL; + } - 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; - } + pDir->name = ConvertUtf8ToWideString(dirName.c_str()); + // We are responsible for freeing dir->name + + if (pDir->name == NULL) + { + delete pDir; + return NULL; + } - return dir; + pDir->fd = _wfindfirst((const wchar_t*)pDir->name, &(pDir->info)); - } - catch(...) + if (pDir->fd == -1) { - printf("Caught opendir"); + delete [] pDir->name; + delete pDir; + return NULL; } - - return NULL; + + pDir->result.d_name = 0; + return pDir; } -//this kinda makes it not thread friendly! -//but I don't think it needs to be. +// this kinda makes it not thread friendly! +// but I don't think it needs to be. char tempbuff[MAX_PATH]; + // -------------------------------------------------------------------------- // // Function @@ -794,7 +923,6 @@ int closedir(DIR *dp) } return -1; } -#endif // !__MINGW32__ // -------------------------------------------------------------------------- // @@ -873,11 +1001,12 @@ int poll (struct pollfd *ufds, unsigned long nfds, int timeout) } HANDLE gSyslogH = 0; +static bool sHaveWarnedEventLogFull = false; void syslog(int loglevel, const char *frmt, ...) { - DWORD errinfo; - char* buffer; + WORD errinfo; + char buffer[1024]; std::string sixfour(frmt); switch (loglevel) @@ -896,81 +1025,203 @@ void syslog(int loglevel, const char *frmt, ...) break; } - - //taken from MSDN - try + // taken from MSDN + int sixfourpos; + while ( (sixfourpos = (int)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); + + int len = vsnprintf(buffer, sizeof(buffer)-1, sixfour.c_str(), args); + ASSERT(len < sizeof(buffer)) + buffer[sizeof(buffer)-1] = 0; + + va_end(args); + + LPCSTR strings[] = { buffer, NULL }; + 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 + strings, // pointer to string array + NULL)) // pointer to data - int sixfourpos; - while ( ( sixfourpos = sixfour.find("%ll")) != -1 ) + { + DWORD err = GetLastError(); + if (err == ERROR_LOG_FILE_FULL) + { + if (!sHaveWarnedEventLogFull) + { + printf("Unable to send message to Event Log " + "(Event Log is full):\r\n"); + sHaveWarnedEventLogFull = TRUE; + } + } + else { - //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("Unable to send message to Event Log: " + "error %i:\r\n", (int)err); } + } + else + { + sHaveWarnedEventLogFull = false; + } - //printf("parsed string is:%s\r\n", sixfour.c_str()); + printf("%s\r\n", buffer); +} - va_list args; - va_start(args, frmt); +int emu_chdir(const char* pDirName) +{ + WCHAR* pBuffer = ConvertUtf8ToWideString(pDirName); + if (!pBuffer) return -1; + int result = SetCurrentDirectoryW(pBuffer); + delete [] pBuffer; + if (result != 0) return 0; + errno = EACCES; + return -1; +} -#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) +char* emu_getcwd(char* pBuffer, int BufSize) +{ + DWORD len = GetCurrentDirectoryW(0, NULL); + if (len == 0) + { + errno = EINVAL; + return NULL; + } - len = len + 1; - char* buffer = new char[len]; -#endif + if (len > BufSize) + { + errno = ENAMETOOLONG; + return NULL; + } - ASSERT(buffer) - memset(buffer, 0, len); + WCHAR* pWide = new WCHAR [len]; + if (!pWide) + { + errno = ENOMEM; + return NULL; + } - int len2 = vsnprintf(buffer, len, sixfour.c_str(), args); - ASSERT(len2 <= len); + DWORD result = GetCurrentDirectoryW(len, pWide); + if (result <= 0 || result >= len) + { + errno = EACCES; + return NULL; + } + + char* pUtf8 = ConvertFromWideString(pWide, CP_UTF8); + delete [] pWide; - va_end(args); + if (!pUtf8) + { + return NULL; } - catch (...) + + strncpy(pBuffer, pUtf8, BufSize - 1); + pBuffer[BufSize - 1] = 0; + delete [] pUtf8; + + return pBuffer; +} + +int emu_mkdir(const char* pPathName) +{ + WCHAR* pBuffer = ConvertToWideString(pPathName, CP_UTF8); + if (!pBuffer) { - printf("Caught syslog: %s", sixfour.c_str()); - return; + return -1; } - try + BOOL result = CreateDirectoryW(pBuffer, NULL); + delete [] pBuffer; + + if (!result) { + errno = EACCES; + return -1; + } - 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 + return 0; +} - { - DWORD err = GetLastError(); - printf("Unable to send message to Event Log " - "(error %i):\r\n", err); - } +int emu_unlink(const char* pFileName) +{ + WCHAR* pBuffer = ConvertToWideString(pFileName, CP_UTF8); + if (!pBuffer) + { + return -1; + } - printf("%s\r\n", buffer); + BOOL result = DeleteFileW(pBuffer); + delete [] pBuffer; - if (buffer) delete [] buffer; + if (!result) + { + errno = EACCES; + return -1; } - catch (...) + + return 0; +} + +int console_read(char* pBuffer, size_t BufferSize) +{ + HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); + + if (hConsole == INVALID_HANDLE_VALUE) { - printf("Caught syslog ReportEvent"); + ::fprintf(stderr, "Failed to get a handle on standard input: " + "error %d\n", GetLastError()); + return -1; } + + int WideSize = BufferSize / 5; + WCHAR* pWideBuffer = new WCHAR [WideSize]; + + if (!pWideBuffer) + { + ::perror("Failed to allocate wide character buffer"); + return -1; + } + + DWORD numCharsRead = 0; + + if (!ReadConsoleW( + hConsole, + pWideBuffer, + WideSize - 1, + &numCharsRead, + NULL // reserved + )) + { + ::fprintf(stderr, "Failed to read from console: error %d\n", + GetLastError()); + return -1; + } + + pWideBuffer[numCharsRead] = 0; + + char* pUtf8 = ConvertFromWideString(pWideBuffer, GetConsoleCP()); + strncpy(pBuffer, pUtf8, BufferSize); + delete [] pUtf8; + + return strlen(pBuffer); } #endif // WIN32 diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 5b506206..ce0c884f 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -3,7 +3,6 @@ #if ! defined EMU_INCLUDE && defined WIN32 #define EMU_INCLUDE -#define _STAT_DEFINED #define _INO_T_DEFINED #include @@ -17,9 +16,6 @@ #include #include #include -//#include -//#include -//#include #include @@ -27,13 +23,21 @@ ( *(_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); +#ifdef _MSC_VER +// Microsoft decided to deprecate the standard POSIX functions. Great! +#define open(file,flags,mode) _open(file,flags,mode) +#define close(fd) _close(fd) +#define dup(fd) _dup(fd) +#define read(fd,buf,count) _read(fd,buf,count) +#define write(fd,buf,count) _write(fd,buf,count) +#define lseek(fd,off,whence) _lseek(fd,off,whence) +#define fileno(struct_file) _fileno(struct_file) +#endif + +int SetTimerHandler(void (__cdecl *func ) (int)); +int setitimer(int type, struct itimerval *timeout, void *arg); void InitTimer(void); void FiniTimer(void); @@ -109,11 +113,43 @@ inline int chown(const char * Filename, u_int32_t uid, u_int32_t gid) return 0; } -inline int chmod(const char * Filename, int uid) -{ - //indicate sucsess - return 0; -} +int emu_chdir (const char* pDirName); +int emu_unlink(const char* pFileName); +char* emu_getcwd(char* pBuffer, int BufSize); + +#ifdef _MSC_VER + inline int emu_chmod(const char * Filename, int mode) + { + // indicate success + return 0; + } + + #define chmod(file, mode) emu_chmod(file, mode) + #define chdir(directory) emu_chdir(directory) + #define unlink(file) emu_unlink(file) + #define getcwd(buffer, size) emu_getcwd(buffer, size) +#else + inline int chmod(const char * Filename, int mode) + { + // indicate success + return 0; + } + + inline int chdir(const char* pDirName) + { + return emu_chdir(pDirName); + } + + inline char* getcwd(char* pBuffer, int BufSize) + { + return emu_getcwd(pBuffer, BufSize); + } + + inline int unlink(const char* pFileName) + { + return emu_unlink(pFileName); + } +#endif //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 @@ -149,55 +185,56 @@ inline int getuid(void) // 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 +// this will need to be implemented 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 + +// 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) +inline int getopt(int count, char * const * args, const char * tolookfor) { - if ( optind >= count ) return -1; + 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; + // just initialize the string - just in case it is used. + // optarg[0] = 0; std::string opt; - if ( count == 0 ) return -1; + if (count == 0) return -1; do { - if ( index != -1 ) + if (index != -1) { str = str.substr(index+1, str.size()); } - index = str.find('-'); + index = (int)str.find('-'); - if ( index == -1 ) return -1; + if (index == -1) return -1; opt = str[1]; optind ++; str = args[optind]; } - while ( ( opttolookfor = interestin.find(opt)) == -1 ); + while ((opttolookfor = (int)interestin.find(opt)) == -1); - if ( interestin[opttolookfor+1] == ':' ) + if (interestin[opttolookfor+1] == ':') { - //strcpy(optarg, str.c_str()); + // strcpy(optarg, str.c_str()); optarg = args[optind]; optind ++; } - //indicate we have finished + // indicate we have finished return opt[0]; } #endif // !__MINGW32__ @@ -244,49 +281,44 @@ struct itimerval #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) +int emu_mkdir(const char* pPathName); + +inline int mkdir(const char *pPathName, mode_t mode) { - return mkdir(pathname); + return emu_mkdir(pPathName); } -#ifdef __MINGW32__ - #include -#else - inline int strcasecmp(const char *s1, const char *s2) - { - return _stricmp(s1,s2); - } +#ifndef __MINGW32__ +inline int strcasecmp(const char *s1, const char *s2) +{ + return _stricmp(s1,s2); +} +#endif - struct dirent - { - char *d_name; - }; +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 +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); HANDLE openfile(const char *filename, int flags, int mode); @@ -358,6 +390,7 @@ struct statfs TCHAR f_mntonname[MAX_PATH]; }; +#if 0 // 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 @@ -381,9 +414,10 @@ struct stat { #ifndef __MINGW32__ typedef u_int64_t _ino_t; #endif +#endif -int ourstat(const char * name, struct stat * st); -int ourfstat(HANDLE file, struct stat * st); +int emu_stat(const char * name, struct stat * st); +int emu_fstat(HANDLE file, struct stat * st); int statfs(const char * name, struct statfs * s); //need this for converstions @@ -395,7 +429,8 @@ inline time_t ConvertFileTimeToTime_t(FILETIME *fileTime) // Convert the last-write time to local time. FileTimeToSystemTime(fileTime, &stUTC); // SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); - + + memset(&timeinfo, 0, sizeof(timeinfo)); timeinfo.tm_sec = stUTC.wSecond; timeinfo.tm_min = stUTC.wMinute; timeinfo.tm_hour = stUTC.wHour; @@ -405,17 +440,35 @@ inline time_t ConvertFileTimeToTime_t(FILETIME *fileTime) // timeinfo.tm_yday = ...; timeinfo.tm_year = stUTC.wYear - 1900; - time_t retVal = mktime(&timeinfo); + time_t retVal = mktime(&timeinfo) - _timezone; return retVal; } -#define stat(x,y) ourstat(x,y) -#define fstat(x,y) ourfstat(x,y) -#define lstat(x,y) ourstat(x,y) +#ifdef _MSC_VER + #define stat(filename, struct) emu_stat (filename, struct) + #define lstat(filename, struct) emu_stat (filename, struct) + #define fstat(handle, struct) emu_fstat(handle, struct) +#else + inline int stat(const char* filename, struct stat* stat) + { + return emu_stat(filename, stat); + } + inline int lstat(const char* filename, struct stat* stat) + { + return emu_stat(filename, stat); + } + inline int fstat(HANDLE handle, struct stat* stat) + { + return emu_fstat(handle, stat); + } +#endif -int poll (struct pollfd *ufds, unsigned long nfds, int timeout); +int poll(struct pollfd *ufds, unsigned long nfds, int timeout); bool EnableBackupRights( void ); +bool ConvertUtf8ToConsole(const char* pString, std::string& rDest); +bool ConvertConsoleToUtf8(const char* pString, std::string& rDest); + // // MessageId: MSG_ERR_EXIST // MessageText: @@ -423,4 +476,7 @@ bool EnableBackupRights( void ); // #define MSG_ERR_EXIST ((DWORD)0xC0000004L) +// replacement for _cgetws which requires a relatively recent C runtime lib +int console_read(char* pBuffer, size_t BufferSize); + #endif // !EMU_INCLUDE && WIN32 -- cgit v1.2.3 From e8da7ced76a7412b3aa09a9361dbdcf9aefe37d6 Mon Sep 17 00:00:00 2001 From: Ben Summers Date: Tue, 14 Feb 2006 09:19:40 +0000 Subject: Zero any unused fields in struct stat, to avoid spurious checksum mismatches that waste bandwidth and slow down backups (committing on behalf of chris) --- lib/win32/emu.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 00d43122..b9cefba8 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -581,6 +581,8 @@ int emu_fstat(HANDLE hdir, struct stat * st) return -1; } + memset(st, 0, sizeof(*st)); + // This next example is how we get our INODE (equivalent) information conv.HighPart = fi.nFileIndexHigh; conv.LowPart = fi.nFileIndexLow; -- cgit v1.2.3 From 659492827b96812173e79a97f5fd89d005c4aaeb Mon Sep 17 00:00:00 2001 From: Ben Summers Date: Mon, 19 Jun 2006 14:12:32 +0000 Subject: Apply patch from Stuart Hickinbottom to fix complication problems with gcc 4.1.1 where configure didn't detect LLONG_MAX properly. Fix by removing configure check completely, and using STL interface. --- lib/win32/config.h.win32 | 6 ------ 1 file changed, 6 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/config.h.win32 b/lib/win32/config.h.win32 index 42298545..edc44a75 100644 --- a/lib/win32/config.h.win32 +++ b/lib/win32/config.h.win32 @@ -318,12 +318,6 @@ /* Define to 1 if __syscall is available but needs a definition */ /* #undef HAVE___SYSCALL_NEED_DEFN */ -/* max value of long long calculated by configure */ -/* #undef LLONG_MAX */ - -/* min value of long long calculated by configure */ -/* #undef LLONG_MIN */ - /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ /* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */ -- cgit v1.2.3 From d36cf5c650533abc3d940dde160ee1a0c529876d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 9 Aug 2006 18:36:54 +0000 Subject: * lib/win32/WinNamedPipeStream.h * lib/win32/WinNamedPipeStream.cpp * lib/server/WinNamedPipeStream.h * lib/server/WinNamedPipeStream.cpp - Moved WinNamedPipeStream class from lib/win32 to lib/server, to resolve circular dependency between lib/common and lib/win32. --- lib/win32/WinNamedPipeStream.cpp | 312 --------------------------------------- lib/win32/WinNamedPipeStream.h | 60 -------- 2 files changed, 372 deletions(-) delete mode 100644 lib/win32/WinNamedPipeStream.cpp delete mode 100644 lib/win32/WinNamedPipeStream.h (limited to 'lib/win32') diff --git a/lib/win32/WinNamedPipeStream.cpp b/lib/win32/WinNamedPipeStream.cpp deleted file mode 100644 index c5b7eaa5..00000000 --- a/lib/win32/WinNamedPipeStream.cpp +++ /dev/null @@ -1,312 +0,0 @@ -// -------------------------------------------------------------------------- -// -// File -// Name: WinNamedPipeStream.cpp -// Purpose: I/O stream interface for Win32 named pipes -// Created: 2005/12/07 -// -// -------------------------------------------------------------------------- - -#include "Box.h" - -#ifdef WIN32 - -#ifdef HAVE_UNISTD_H - #include -#endif - -#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()); - Close(); - 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) - { - fprintf(stderr, "Inconsistent connected state\n"); - ::syslog(LOG_ERR, "Inconsistent connected state"); - mIsConnected = false; - } - - if (mSocketHandle == NULL) - { - 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; - } - - bool result = CloseHandle(mSocketHandle); - - mSocketHandle = NULL; - mIsConnected = false; - - if (!result) - { - ::syslog(LOG_ERR, "CloseHandle failed: %d", GetLastError()); - THROW_EXCEPTION(ServerException, SocketCloseError) - } -} - -// -------------------------------------------------------------------------- -// -// 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 deleted file mode 100644 index 5a800371..00000000 --- a/lib/win32/WinNamedPipeStream.h +++ /dev/null @@ -1,60 +0,0 @@ -// -------------------------------------------------------------------------- -// -// 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 -- cgit v1.2.3 From 364ec72789db5a33c5ff35f0774a29348304d868 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 2 Sep 2006 11:32:38 +0000 Subject: (refs #3) Reorganise typedefs for clarity --- lib/win32/emu.h | 68 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 22 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index ce0c884f..5d67264a 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -3,7 +3,48 @@ #if ! defined EMU_INCLUDE && defined WIN32 #define EMU_INCLUDE -#define _INO_T_DEFINED +// basic types, may be required by other headers since we +// don't include sys/types.h + +#ifdef __MINGW32__ + #include + typedef uint32_t u_int32_t; +#else // MSVC + typedef __int64 int64_t; + typedef __int32 int32_t; + typedef __int16 int16_t; + typedef __int8 int8_t; + + typedef unsigned __int64 u_int64_t; + typedef unsigned __int32 u_int32_t; + + typedef unsigned __int64 uint64_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int8 uint8_t; +#endif + +// emulated types, present on MinGW but not MSVC or vice versa + +#ifdef _MSC_VER + typedef unsigned int mode_t; + typedef unsigned int pid_t; + + // must define _INO_T_DEFINED before including + // to replace it with our own. + typedef u_int64_t _ino_t; + #define _INO_T_DEFINED +#endif + +// set up to include the necessary parts of Windows headers + +#define WIN32_LEAN_AND_MEAN + +#ifndef __MSVCRT_VERSION__ +#define __MSVCRT_VERSION__ 0x0601 +#endif + +// Windows headers #include #include @@ -19,6 +60,8 @@ #include +// emulated functions + #define gmtime_r( _clock, _result ) \ ( *(_result) = *gmtime( (_clock) ), \ (_result) ) @@ -50,8 +93,8 @@ inline int geteuid(void) struct passwd { char *pw_name; char *pw_passwd; - uid_t pw_uid; - gid_t pw_gid; + int pw_uid; + int pw_gid; time_t pw_change; char *pw_class; char *pw_gecos; @@ -252,17 +295,6 @@ struct itimerval #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 @@ -283,10 +315,6 @@ struct itimerval #define vsnprintf _vsnprintf -#ifndef __MINGW32__ -typedef unsigned int mode_t; -#endif - int emu_mkdir(const char* pPathName); inline int mkdir(const char *pPathName, mode_t mode) @@ -410,10 +438,6 @@ struct stat { time_t st_mtime; time_t st_ctime; }; - -#ifndef __MINGW32__ -typedef u_int64_t _ino_t; -#endif #endif int emu_stat(const char * name, struct stat * st); -- cgit v1.2.3 From 26bff57d54830e2d2c7cf1416cc66a7787d41640 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 2 Sep 2006 11:39:39 +0000 Subject: (refs #3) Remove dependency on Box.h and hence on lib/common --- lib/win32/emu.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index b9cefba8..927eefb0 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -3,15 +3,13 @@ // Need at least 0x0500 to use GetFileSizeEx on Cygwin/MinGW #define WINVER 0x0500 -#include "Box.h" +#include "emu.h" #ifdef WIN32 -// #include "emu.h" - -#include +#include #include -// #include +#include #ifdef HAVE_UNISTD_H #include -- cgit v1.2.3 From 29e9ec5e4f13ab0f191016cdba5182a2374449c2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 2 Sep 2006 11:41:44 +0000 Subject: (refs #3) Add message definitions and resource files --- lib/win32/messages.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/win32/messages.mc | 22 ++++++++++++++++++++ lib/win32/messages.rc | 2 ++ 3 files changed, 81 insertions(+) create mode 100755 lib/win32/messages.h create mode 100644 lib/win32/messages.mc create mode 100755 lib/win32/messages.rc (limited to 'lib/win32') diff --git a/lib/win32/messages.h b/lib/win32/messages.h new file mode 100755 index 00000000..6959591b --- /dev/null +++ b/lib/win32/messages.h @@ -0,0 +1,57 @@ + // Message source file, to be compiled to a resource file with + // Microsoft Message Compiler (MC), to an object file with a Resource + // Compiler, and linked into the application. + + // The main reason for this file is to work around Windows' stupid + // messages in the Event Log, which say: + + // The description for Event ID ( 4 ) in Source ( Box Backup (bbackupd) ) + // cannot be found. The local computer may not have the necessary + // registry information or message DLL files to display messages from a + // remote computer. The following information is part of the event: + // Message definitions follow +// +// Values are 32 bit values layed out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// + + +// +// Define the severity codes +// + + +// +// MessageId: MSG_ERR +// +// MessageText: +// +// %1 +// +#define MSG_ERR ((DWORD)0x40000001L) + diff --git a/lib/win32/messages.mc b/lib/win32/messages.mc new file mode 100644 index 00000000..75f17b0f --- /dev/null +++ b/lib/win32/messages.mc @@ -0,0 +1,22 @@ +; // Message source file, to be compiled to a resource file with +; // Microsoft Message Compiler (MC), to an object file with a Resource +; // Compiler, and linked into the application. +; +; // The main reason for this file is to work around Windows' stupid +; // messages in the Event Log, which say: +; +; // The description for Event ID ( 4 ) in Source ( Box Backup (bbackupd) ) +; // cannot be found. The local computer may not have the necessary +; // registry information or message DLL files to display messages from a +; // remote computer. The following information is part of the event: + +MessageIdTypedef = DWORD + +; // Message definitions follow + +MessageId = 0x1 +Severity = Informational +SymbolicName = MSG_ERR +Language = English +%1 +. diff --git a/lib/win32/messages.rc b/lib/win32/messages.rc new file mode 100755 index 00000000..116522b7 --- /dev/null +++ b/lib/win32/messages.rc @@ -0,0 +1,2 @@ +LANGUAGE 0x9,0x1 +1 11 MSG00001.bin -- cgit v1.2.3 From affb37c9860c4575f2580c49ee3d274dad9e4c8e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 2 Sep 2006 11:44:24 +0000 Subject: (refs #3) Include message resource definitions --- lib/win32/emu.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 927eefb0..0fbbe047 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -21,6 +21,10 @@ #include #include +// message resource definitions for syslog() + +#include "messages.h" + // our implementation for a timer, based on a // simple thread which sleeps for a period of time -- cgit v1.2.3 From 241e62376bc3c4dac114d25915e42eb2ab4159b0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 2 Sep 2006 11:45:11 +0000 Subject: (refs #3) Add BSD-licensed getopt.h to replace our own version --- lib/win32/getopt.h | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100755 lib/win32/getopt.h (limited to 'lib/win32') diff --git a/lib/win32/getopt.h b/lib/win32/getopt.h new file mode 100755 index 00000000..7c290343 --- /dev/null +++ b/lib/win32/getopt.h @@ -0,0 +1,98 @@ +/* $OpenBSD: getopt.h,v 1.1 2002/12/03 20:24:29 millert Exp $ */ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +// copied from: http://www.la.utexas.edu/lab/software/devtool/gnu/libtool/C_header_files.html + +/* __BEGIN_DECLS should be used at the beginning of your declarations, + so that C++ compilers don't mangle their names. Use __END_DECLS at + the end of C declarations. */ +#undef __BEGIN_DECLS +#undef __END_DECLS +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS /* empty */ +# define __END_DECLS /* empty */ +#endif + +/* + * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +__BEGIN_DECLS +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); +#ifndef _GETOPT_DEFINED_ +#define _GETOPT_DEFINED_ +int getopt(int, char * const *, const char *); +int getsubopt(char **, char * const *, char **); + +extern char *optarg; /* getopt(3) external variables */ +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; +extern char *suboptarg; /* getsubopt(3) external variable */ +#endif +__END_DECLS + +#endif /* !_GETOPT_H_ */ -- cgit v1.2.3 From 309f2d0428db81ea8bf9762e276de2458ce1d125 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 2 Sep 2006 11:50:26 +0000 Subject: (refs #3) Use our own ConvertUtf8ToWideString for simplicity --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 0fbbe047..fa853f14 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -372,7 +372,7 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) // -------------------------------------------------------------------------- bool ConvertUtf8ToConsole(const char* pString, std::string& rDest) { - WCHAR* pWide = ConvertToWideString(pString, CP_UTF8); + WCHAR* pWide = ConvertUtf8ToWideString(pString); if (pWide == NULL) { return false; -- cgit v1.2.3 From 054f818ce7f7d9e274da16b5ab6956792fa1b986 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 22:54:58 +0000 Subject: (refs #3) Convert UNIX to native paths --- lib/win32/emu.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index fa853f14..37699bb1 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -436,13 +436,26 @@ bool ConvertConsoleToUtf8(const char* pString, std::string& rDest) // -------------------------------------------------------------------------- std::string ConvertPathToAbsoluteUnicode(const char *pFileName) { + std::string filename; + for (int i = 0; pFileName[i] != 0; i++) + { + if (pFileName[i] == '/') + { + filename += '\\'; + } + else + { + filename += pFileName[i]; + } + } + std::string tmpStr("\\\\?\\"); // Is the path relative or absolute? // Absolute paths on Windows are always a drive letter // followed by ':' - if (pFileName[1] != ':') + if (filename.length() >= 2 && filename[1] != ':') { // Must be relative. We need to get the // current directory to make it absolute. @@ -465,7 +478,7 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) } } - tmpStr += pFileName; + tmpStr += filename; return tmpStr; } -- cgit v1.2.3 From 4434ff992787675604d9868d555887579d07fc52 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:35:48 +0000 Subject: (refs #3) Return INVALID_HANDLE_VALUE instead of NULL from openfile() on failure --- lib/win32/emu.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 37699bb1..f13fb899 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -486,18 +486,20 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) // // Function // Name: openfile -// Purpose: replacement for any open calls - handles unicode filenames - supplied in utf8 +// Purpose: replacement for any open calls - handles unicode +// filenames - supplied in utf8 // Created: 25th October 2004 // // -------------------------------------------------------------------------- HANDLE openfile(const char *pFileName, int flags, int mode) { - std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); + std::string AbsPathWithUnicode = + ConvertPathToAbsoluteUnicode(pFileName); if (AbsPathWithUnicode.size() == 0) { // error already logged by ConvertPathToAbsoluteUnicode() - return NULL; + return INVALID_HANDLE_VALUE; } WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); @@ -506,7 +508,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode) if (pBuffer == NULL) { // error already logged by ConvertUtf8ToWideString() - return NULL; + return INVALID_HANDLE_VALUE; } // flags could be O_WRONLY | O_CREAT | O_RDONLY @@ -553,7 +555,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode) { ::syslog(LOG_WARNING, "Failed to open file %s: " "error %i", pFileName, GetLastError()); - return NULL; + return INVALID_HANDLE_VALUE; } return hdir; -- cgit v1.2.3 From 7904931e8026a5e43bcfcdc75adb5688766b67eb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:41:31 +0000 Subject: (refs #3) Improved handling of UNIX flags to openfile(), allows multiple opens --- lib/win32/emu.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index f13fb899..3285f90c 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -518,19 +518,19 @@ HANDLE openfile(const char *pFileName, int flags, int mode) if (flags & O_WRONLY) { + accessRights = FILE_WRITE_DATA; shareMode = FILE_SHARE_WRITE; } - if (flags & O_RDWR) + else if (flags & (O_RDWR | O_CREAT)) { - shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + accessRights |= FILE_WRITE_ATTRIBUTES + | FILE_WRITE_DATA | FILE_WRITE_EA; + shareMode |= FILE_SHARE_WRITE; } + if (flags & O_CREAT) { createDisposition = OPEN_ALWAYS; - shareMode |= FILE_SHARE_WRITE; - accessRights |= FILE_WRITE_ATTRIBUTES - | FILE_WRITE_DATA | FILE_WRITE_EA - | FILE_ALL_ACCESS; } if (flags & O_TRUNC) { -- cgit v1.2.3 From 33c64c6247b677f6233d4c529ee162f34d1535fc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:46:11 +0000 Subject: (refs #3) Improved error handling in emu_fstat --- lib/win32/emu.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 3285f90c..41361409 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -580,8 +580,6 @@ char nextchar = -1; // -------------------------------------------------------------------------- int emu_fstat(HANDLE hdir, struct stat * st) { - ULARGE_INTEGER conv; - if (hdir == INVALID_HANDLE_VALUE) { ::syslog(LOG_ERR, "Error: invalid file handle in emu_fstat()"); @@ -598,9 +596,18 @@ int emu_fstat(HANDLE hdir, struct stat * st) return -1; } + if (INVALID_FILE_ATTRIBUTES == fi.dwFileAttributes) + { + ::syslog(LOG_WARNING, "Failed to get file attributes: " + "error %d", GetLastError()); + errno = EACCES; + return -1; + } + memset(st, 0, sizeof(*st)); - // This next example is how we get our INODE (equivalent) information + // This is how we get our INODE (equivalent) information + ULARGE_INTEGER conv; conv.HighPart = fi.nFileIndexHigh; conv.LowPart = fi.nFileIndexLow; st->st_ino = (_ino_t)conv.QuadPart; -- cgit v1.2.3 From a64a6f4c9c71dfe925bf5492c6e6aa828611fba0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:48:34 +0000 Subject: (refs #3) Always fill in st_uid, st_gid and st_nlink Return zero size for directories Improved emulation of Unix file modes (helps when restoring Windows files on Unix) --- lib/win32/emu.cpp | 66 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 26 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 41361409..c0bdd609 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -617,41 +617,55 @@ int emu_fstat(HANDLE hdir, struct stat * st) 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)) + if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - ::syslog(LOG_WARNING, "Failed to get file size: error %d", - GetLastError()); - errno = EACCES; - return -1; + st->st_size = 0; } + else + { + // size of the file + LARGE_INTEGER st_size; + memset(&st_size, 0, sizeof(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 = (_off_t)conv.QuadPart; + conv.HighPart = st_size.HighPart; + conv.LowPart = st_size.LowPart; + st->st_size = (_off_t)conv.QuadPart; + } - //the mode of the file - st->st_mode = 0; - //DWORD res = GetFileAttributes((LPCSTR)tmpStr.c_str()); + // at the mo + st->st_uid = 0; + st->st_gid = 0; + st->st_nlink = 1; - if (INVALID_FILE_ATTRIBUTES != fi.dwFileAttributes) + // the mode of the file + // mode zero will make it impossible to restore on Unix + // (no access to anybody, including the owner). + // we'll fake a sensible mode: + // all objects get user read (0400) + // if it's a directory it gets user execute (0100) + // if it's not read-only it gets user write (0200) + st->st_mode = S_IREAD; + + if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - st->st_mode |= S_IFDIR; - } - else - { - st->st_mode |= S_IFREG; - } + st->st_mode |= S_IFDIR | S_IEXEC; } else { - ::syslog(LOG_WARNING, "Failed to get file attributes: " - "error %d", GetLastError()); - errno = EACCES; - return -1; + st->st_mode |= S_IFREG; + } + + if (!(fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + { + st->st_mode |= S_IWRITE; } return 0; -- cgit v1.2.3 From a1ccaaebe529e4c054812c13394b597974c58123 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:51:22 +0000 Subject: (refs #3) Pass requested open flags to OpenFileByNameUtf8 --- lib/win32/emu.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index c0bdd609..0239724c 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -681,9 +681,10 @@ int emu_fstat(HANDLE hdir, struct stat * st) // Created: 10th December 2004 // // -------------------------------------------------------------------------- -HANDLE OpenFileByNameUtf8(const char* pFileName) +HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) { - std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); + std::string AbsPathWithUnicode = + ConvertPathToAbsoluteUnicode(pFileName); if (AbsPathWithUnicode.size() == 0) { @@ -701,7 +702,7 @@ HANDLE OpenFileByNameUtf8(const char* pFileName) } HANDLE handle = CreateFileW(pBuffer, - FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA, + flags, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, @@ -757,12 +758,8 @@ HANDLE OpenFileByNameUtf8(const char* pFileName) // -------------------------------------------------------------------------- int emu_stat(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); + HANDLE handle = OpenFileByNameUtf8(pName, + FILE_READ_ATTRIBUTES | FILE_READ_EA); if (handle == NULL) { @@ -795,7 +792,8 @@ int emu_stat(const char * pName, struct stat * st) // -------------------------------------------------------------------------- int statfs(const char * pName, struct statfs * s) { - HANDLE handle = OpenFileByNameUtf8(pName); + HANDLE handle = OpenFileByNameUtf8(pName, + FILE_READ_ATTRIBUTES | FILE_READ_EA); if (handle == NULL) { -- cgit v1.2.3 From f2a0eaaedd261b287c11ca29661490c15ef57e72 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:52:19 +0000 Subject: (refs #3) Request READ_CONTROL when standard open fails, rather than no flags --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 0239724c..809cfa0e 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -716,7 +716,7 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) // at least one process must have the file open - // in this case someone else does. handle = CreateFileW(pBuffer, - 0, + READ_CONTROL, FILE_SHARE_READ, NULL, OPEN_EXISTING, -- cgit v1.2.3 From 3a073296c1630000907ba6385da0e93006adc891 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:53:13 +0000 Subject: (refs #3) Treat PATH_NOT_FOUND just like FILE_NOT_FOUND in Unix land (errno = ENOENT) --- lib/win32/emu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 809cfa0e..e54b2d72 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -730,7 +730,8 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) { DWORD err = GetLastError(); - if (err == ERROR_FILE_NOT_FOUND) + if (err == ERROR_FILE_NOT_FOUND || + err == ERROR_PATH_NOT_FOUND) { errno = ENOENT; } -- cgit v1.2.3 From 83bf070fb425f75bdb85b58dc810791736369814 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:55:55 +0000 Subject: (refs #3) Added emulated utimes, chmod, readv and writev Added useful utility functions ConvertFileTimeToTime_t and ConvertTime_tToFileTime --- lib/win32/emu.cpp | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index e54b2d72..d681335a 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -823,6 +823,115 @@ int statfs(const char * pName, struct statfs * s) return 0; } +// -------------------------------------------------------------------------- +// +// Function +// Name: emu_utimes +// Purpose: replacement for the POSIX utimes() function, +// works with unicode filenames supplied in utf8 format, +// sets creation time instead of last access time. +// Created: 25th July 2006 +// +// -------------------------------------------------------------------------- +int emu_utimes(const char * pName, const struct timeval times[]) +{ + FILETIME creationTime; + if (!ConvertTime_tToFileTime(times[0].tv_sec, &creationTime)) + { + errno = EINVAL; + return -1; + } + + FILETIME modificationTime; + if (!ConvertTime_tToFileTime(times[1].tv_sec, &modificationTime)) + { + errno = EINVAL; + return -1; + } + + HANDLE handle = OpenFileByNameUtf8(pName, FILE_WRITE_ATTRIBUTES); + + if (handle == NULL) + { + // errno already set and error logged by OpenFileByNameUtf8() + return -1; + } + + if (!SetFileTime(handle, &creationTime, NULL, &modificationTime)) + { + ::syslog(LOG_ERR, "Failed to set times on '%s': error %d", + pName, GetLastError()); + CloseHandle(handle); + return 1; + } + + CloseHandle(handle); + return 0; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: emu_chmod +// Purpose: replacement for the POSIX chmod function, +// works with unicode filenames supplied in utf8 format +// Created: 26th July 2006 +// +// -------------------------------------------------------------------------- +int emu_chmod(const char * pName, mode_t mode) +{ + std::string AbsPathWithUnicode = + ConvertPathToAbsoluteUnicode(pName); + + if (AbsPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); + // We are responsible for freeing pBuffer + + if (pBuffer == NULL) + { + // error already logged by ConvertUtf8ToWideString() + free(pBuffer); + return -1; + } + + DWORD attribs = GetFileAttributesW(pBuffer); + if (attribs == INVALID_FILE_ATTRIBUTES) + { + ::syslog(LOG_ERR, "Failed to get file attributes of '%s': " + "error %d", pName, GetLastError()); + errno = EACCES; + free(pBuffer); + return -1; + } + + if (mode & S_IWRITE) + { + attribs &= ~FILE_ATTRIBUTE_READONLY; + } + else + { + attribs |= FILE_ATTRIBUTE_READONLY; + } + + if (!SetFileAttributesW(pBuffer, attribs)) + { + ::syslog(LOG_ERR, "Failed to set file attributes of '%s': " + "error %d", pName, GetLastError()); + errno = EACCES; + free(pBuffer); + return -1; + } + + free(pBuffer); + return 0; +} + + // -------------------------------------------------------------------------- // // Function @@ -1263,4 +1372,96 @@ int console_read(char* pBuffer, size_t BufferSize) return strlen(pBuffer); } +int readv (int filedes, const struct iovec *vector, size_t count) +{ + int bytes = 0; + + for (size_t i = 0; i < count; i++) + { + int result = read(filedes, vector[i].iov_base, + vector[i].iov_len); + if (result < 0) + { + return result; + } + bytes += result; + } + + return bytes; +} + +int writev(int filedes, const struct iovec *vector, size_t count) +{ + int bytes = 0; + + for (size_t i = 0; i < count; i++) + { + int result = write(filedes, vector[i].iov_base, + vector[i].iov_len); + if (result < 0) + { + return result; + } + bytes += result; + } + + return bytes; +} + +// need this for conversions +time_t ConvertFileTimeToTime_t(FILETIME *fileTime) +{ + SYSTEMTIME stUTC; + struct tm timeinfo; + + // Convert the last-write time to local time. + FileTimeToSystemTime(fileTime, &stUTC); + + memset(&timeinfo, 0, sizeof(timeinfo)); + 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) - _timezone; + return retVal; +} + +bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo) +{ + time_t adjusted = from + _timezone; + struct tm *time_breakdown = gmtime(&adjusted); + if (time_breakdown == NULL) + { + ::syslog(LOG_ERR, "Error: failed to convert time format: " + "%d is not a valid time\n", from); + return false; + } + + SYSTEMTIME stUTC; + stUTC.wSecond = time_breakdown->tm_sec; + stUTC.wMinute = time_breakdown->tm_min; + stUTC.wHour = time_breakdown->tm_hour; + stUTC.wDay = time_breakdown->tm_mday; + stUTC.wDayOfWeek = time_breakdown->tm_wday; + stUTC.wMonth = time_breakdown->tm_mon + 1; + stUTC.wYear = time_breakdown->tm_year + 1900; + stUTC.wMilliseconds = 0; + + // Convert the last-write time to local time. + if (!SystemTimeToFileTime(&stUTC, pTo)) + { + syslog(LOG_ERR, "Failed to convert between time formats: " + "error %d", GetLastError()); + return false; + } + + return true; +} + + #endif // WIN32 -- cgit v1.2.3 From 078175bdc74e4a571e30474189063af1ff48dacb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:57:08 +0000 Subject: (refs #3) Removed last vestiges of old getopt() --- lib/win32/emu.cpp | 9 --------- 1 file changed, 9 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index d681335a..1dbd98a7 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -561,15 +561,6 @@ HANDLE openfile(const char *pFileName, int flags, int mode) return hdir; } -// 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 -- cgit v1.2.3 From abd90648a83b3884039bbd813c92341807c090c8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Sep 2006 23:58:43 +0000 Subject: (refs #3) Improved poll() emulation to handle multiple fds --- lib/win32/emu.cpp | 58 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 19 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 1dbd98a7..ed89816e 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1079,10 +1079,10 @@ int poll (struct pollfd *ufds, unsigned long nfds, int timeout) fd_set readfd; fd_set writefd; - readfd.fd_count = 0; - writefd.fd_count = 0; + FD_ZERO(&readfd); + FD_ZERO(&writefd); - struct pollfd *ufdsTmp = ufds; + // struct pollfd *ufdsTmp = ufds; timeval timOut; timeval *tmpptr; @@ -1095,41 +1095,61 @@ int poll (struct pollfd *ufds, unsigned long nfds, int timeout) timOut.tv_sec = timeout / 1000; timOut.tv_usec = timeout * 1000; - if (ufds->events & POLLIN) + for (unsigned long i = 0; i < nfds; i++) { - for (unsigned long i = 0; i < nfds; i++) + struct pollfd* ufd = &(ufds[i]); + + if (ufd->events & POLLIN) { - readfd.fd_array[i] = ufdsTmp->fd; - readfd.fd_count++; + FD_SET(ufd->fd, &readfd); } - } - if (ufds->events & POLLOUT) - { - for (unsigned long i = 0; i < nfds; i++) + if (ufd->events & POLLOUT) { + FD_SET(ufd->fd, &writefd); + } - writefd.fd_array[i]=ufdsTmp->fd; - writefd.fd_count++; + if (ufd->events & ~(POLLIN | POLLOUT)) + { + printf("Unsupported poll bits %d", + ufd->events); + return -1; } } - int noffds = select(0, &readfd, &writefd, 0, tmpptr); + int nready = select(0, &readfd, &writefd, 0, tmpptr); - if (noffds == SOCKET_ERROR) + if (nready == SOCKET_ERROR) { // int errval = WSAGetLastError(); - ufdsTmp = ufds; + struct pollfd* pufd = ufds; for (unsigned long i = 0; i < nfds; i++) { - ufdsTmp->revents = POLLERR; - ufdsTmp++; + pufd->revents = POLLERR; + pufd++; } return (-1); } + else if (nready > 0) + { + for (unsigned long i = 0; i < nfds; i++) + { + struct pollfd *ufd = &(ufds[i]); + + if (FD_ISSET(ufd->fd, &readfd)) + { + ufd->revents |= POLLIN; + } + + if (FD_ISSET(ufd->fd, &writefd)) + { + ufd->revents |= POLLOUT; + } + } + } - return noffds; + return nready; } catch (...) { -- cgit v1.2.3 From b8f9eeceb44b72bbab18ebd0644e1b6cabe624da Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Sep 2006 00:02:12 +0000 Subject: (refs #3) Fixed looking up message source in syslog() Flush stdout after writing to it Allow syslog() to log to console even when openlog() has not been called --- lib/win32/emu.cpp | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++- lib/win32/emu.h | 29 ++-------- 2 files changed, 163 insertions(+), 28 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index ed89816e..dc17c1df 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1159,9 +1159,147 @@ int poll (struct pollfd *ufds, unsigned long nfds, int timeout) return -1; } -HANDLE gSyslogH = 0; +// copied from MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/eventlog/base/adding_a_source_to_the_registry.asp + +BOOL AddEventSource +( + LPTSTR pszSrcName, // event source name + DWORD dwNum // number of categories +) +{ + // Work out the executable file name, to register ourselves + // as the event source + + char cmd[MAX_PATH]; + if (GetModuleFileName(NULL, cmd, sizeof(cmd)-1) == 0) + { + ::syslog(LOG_ERR, "Failed to get the program file name: " + "error %d", GetLastError()); + return FALSE; + } + cmd[sizeof(cmd)-1] = 0; + std::string exepath(cmd); + + // Create the event source as a subkey of the log. + + std::string regkey("SYSTEM\\CurrentControlSet\\Services\\EventLog\\" + "Application\\"); + regkey += pszSrcName; + + HKEY hk; + DWORD dwDisp; + + if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, regkey.c_str(), + 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_WRITE, NULL, &hk, &dwDisp)) + { + ::syslog(LOG_ERR, "Failed to create the registry key: " + "error %d", GetLastError()); + return FALSE; + } + + // Set the name of the message file. + + if (RegSetValueEx(hk, // subkey handle + "EventMessageFile", // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE) exepath.c_str(), // pointer to value data + (DWORD) (exepath.size()))) // data size + { + ::syslog(LOG_ERR, "Failed to set the event message file: " + "error %d", GetLastError()); + RegCloseKey(hk); + return FALSE; + } + + // Set the supported event types. + + DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | + EVENTLOG_INFORMATION_TYPE; + + if (RegSetValueEx(hk, // subkey handle + "TypesSupported", // value name + 0, // must be zero + REG_DWORD, // value type + (LPBYTE) &dwData, // pointer to value data + sizeof(DWORD))) // length of value data + { + ::syslog(LOG_ERR, "Failed to set the supported types: " + "error %d", GetLastError()); + RegCloseKey(hk); + return FALSE; + } + + // Set the category message file and number of categories. + + if (RegSetValueEx(hk, // subkey handle + "CategoryMessageFile", // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE) exepath.c_str(), // pointer to value data + (DWORD) (exepath.size()))) // data size + { + ::syslog(LOG_ERR, "Failed to set the category message file: " + "error %d", GetLastError()); + RegCloseKey(hk); + return FALSE; + } + + if (RegSetValueEx(hk, // subkey handle + "CategoryCount", // value name + 0, // must be zero + REG_DWORD, // value type + (LPBYTE) &dwNum, // pointer to value data + sizeof(DWORD))) // length of value data + { + ::syslog(LOG_ERR, "Failed to set the category count: " + "error %d", GetLastError()); + RegCloseKey(hk); + return FALSE; + } + + RegCloseKey(hk); + return TRUE; +} + +static HANDLE gSyslogH = 0; static bool sHaveWarnedEventLogFull = false; +void openlog(const char * daemonName, int, int) +{ + // register a default event source, so that we can + // log errors with the process of adding or registering our own. + gSyslogH = RegisterEventSource( + NULL, // uses local computer + daemonName); // source name + if (gSyslogH == NULL) + { + } + + if (!AddEventSource("Box Backup", 0)) + { + ::syslog(LOG_ERR, "Failed to add our own event source"); + return; + } + + HANDLE newSyslogH = RegisterEventSource(NULL, "Box Backup"); + if (newSyslogH == NULL) + { + ::syslog(LOG_ERR, "Failed to register our own event source: " + "error %d", GetLastError()); + return; + } + + DeregisterEventSource(gSyslogH); + gSyslogH = newSyslogH; +} + +void closelog(void) +{ + DeregisterEventSource(gSyslogH); +} + void syslog(int loglevel, const char *frmt, ...) { WORD errinfo; @@ -1201,17 +1339,32 @@ void syslog(int loglevel, const char *frmt, ...) va_start(args, frmt); int len = vsnprintf(buffer, sizeof(buffer)-1, sixfour.c_str(), args); - ASSERT(len < sizeof(buffer)) + assert(len >= 0); + if (len < 0) + { + printf("%s\r\n", buffer); + fflush(stdout); + return; + } + + assert((size_t)len < sizeof(buffer)); buffer[sizeof(buffer)-1] = 0; va_end(args); LPCSTR strings[] = { buffer, NULL }; + if (gSyslogH == 0) + { + printf("%s\r\n", buffer); + fflush(stdout); + return; + } + if (!ReportEvent(gSyslogH, // event log handle errinfo, // event type 0, // category zero - MSG_ERR_EXIST, // event identifier - + MSG_ERR, // event identifier - // we will call them all the same NULL, // no user security identifier 1, // one substitution string @@ -1227,6 +1380,7 @@ void syslog(int loglevel, const char *frmt, ...) { printf("Unable to send message to Event Log " "(Event Log is full):\r\n"); + fflush(stdout); sHaveWarnedEventLogFull = TRUE; } } @@ -1234,6 +1388,7 @@ void syslog(int loglevel, const char *frmt, ...) { printf("Unable to send message to Event Log: " "error %i:\r\n", (int)err); + fflush(stdout); } } else @@ -1242,6 +1397,7 @@ void syslog(int loglevel, const char *frmt, ...) } printf("%s\r\n", buffer); + fflush(stdout); } int emu_chdir(const char* pDirName) diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 5d67264a..2c4e1550 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -354,26 +354,12 @@ HANDLE openfile(const char *filename, int flags, int mode); #define LOG_WARNING 4 #define LOG_ERR 3 #define LOG_PID 0 +#define LOG_LOCAL5 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, ...); +void openlog (const char * daemonName, int, int); +void closelog(void); +void syslog (int loglevel, const char *fmt, ...); #ifndef __MINGW32__ #define strtoll _strtoi64 @@ -493,13 +479,6 @@ bool EnableBackupRights( void ); bool ConvertUtf8ToConsole(const char* pString, std::string& rDest); bool ConvertConsoleToUtf8(const char* pString, std::string& rDest); -// -// MessageId: MSG_ERR_EXIST -// MessageText: -// Box Backup. -// -#define MSG_ERR_EXIST ((DWORD)0xC0000004L) - // replacement for _cgetws which requires a relatively recent C runtime lib int console_read(char* pBuffer, size_t BufferSize); -- cgit v1.2.3 From 3f9f0196e6d437f225cfb14bce8b9b424def09ab Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Sep 2006 00:03:28 +0000 Subject: (refs #3) Emulated chdir, mkdir and unlink should handle file names in UTF-8 as well --- lib/win32/emu.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index dc17c1df..423b3632 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1402,7 +1402,16 @@ void syslog(int loglevel, const char *frmt, ...) int emu_chdir(const char* pDirName) { - WCHAR* pBuffer = ConvertUtf8ToWideString(pDirName); + std::string AbsPathWithUnicode = + ConvertPathToAbsoluteUnicode(pDirName); + + if (AbsPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); if (!pBuffer) return -1; int result = SetCurrentDirectoryW(pBuffer); delete [] pBuffer; @@ -1420,7 +1429,7 @@ char* emu_getcwd(char* pBuffer, int BufSize) return NULL; } - if (len > BufSize) + if ((int)len > BufSize) { errno = ENAMETOOLONG; return NULL; @@ -1457,7 +1466,16 @@ char* emu_getcwd(char* pBuffer, int BufSize) int emu_mkdir(const char* pPathName) { - WCHAR* pBuffer = ConvertToWideString(pPathName, CP_UTF8); + std::string AbsPathWithUnicode = + ConvertPathToAbsoluteUnicode(pPathName); + + if (AbsPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); if (!pBuffer) { return -1; @@ -1477,18 +1495,45 @@ int emu_mkdir(const char* pPathName) int emu_unlink(const char* pFileName) { - WCHAR* pBuffer = ConvertToWideString(pFileName, CP_UTF8); + std::string AbsPathWithUnicode = + ConvertPathToAbsoluteUnicode(pFileName); + + if (AbsPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); if (!pBuffer) { return -1; } BOOL result = DeleteFileW(pBuffer); + DWORD err = GetLastError(); delete [] pBuffer; if (!result) { - errno = EACCES; + if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + { + errno = ENOENT; + } + else if (err == ERROR_SHARING_VIOLATION) + { + errno = EBUSY; + } + else if (err == ERROR_ACCESS_DENIED) + { + errno = EACCES; + } + else + { + ::syslog(LOG_WARNING, "Failed to delete file " + "'%s': error %d", pFileName, (int)err); + errno = ENOSYS; + } return -1; } -- cgit v1.2.3 From 98009bbda2550b7e6aa28fd53f3daaa14d6cd577 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Sep 2006 00:05:08 +0000 Subject: (refs #3) Emulate readdir's d_type field --- lib/win32/emu.cpp | 10 +++++++++- lib/win32/emu.h | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 423b3632..109e54f6 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1002,7 +1002,7 @@ struct dirent *readdir(DIR *dp) if (!dp->result.d_name || _wfindnext(dp->fd, &dp->info) != -1) { - den = &dp->result; + den = &dp->result; std::wstring input(dp->info.name); memset(tempbuff, 0, sizeof(tempbuff)); WideCharToMultiByte(CP_UTF8, 0, dp->info.name, @@ -1010,6 +1010,14 @@ struct dirent *readdir(DIR *dp) NULL, NULL); //den->d_name = (char *)dp->info.name; den->d_name = &tempbuff[0]; + if (dp->info.attrib & FILE_ATTRIBUTE_DIRECTORY) + { + den->d_type = S_IFDIR; + } + else + { + den->d_type = S_IFREG; + } } } else diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 2c4e1550..69daaa67 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -329,9 +329,14 @@ inline int strcasecmp(const char *s1, const char *s2) } #endif +#ifdef _DIRENT_H_ +#error You must not include MinGW's dirent.h! +#endif + struct dirent { char *d_name; + unsigned long d_type; }; struct DIR -- cgit v1.2.3 From cfbb24dbc08bcb0e506922d826808549fd107181 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Sep 2006 00:06:56 +0000 Subject: (refs #3) Remove more vestiges of old getopt --- lib/win32/emu.h | 54 +----------------------------------------------------- 1 file changed, 1 insertion(+), 53 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 69daaa67..a861d3b9 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -227,59 +227,7 @@ inline int getuid(void) // MinGW provides a getopt implementation #ifndef __MINGW32__ - -// this will need to be implemented 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, const 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 = (int)str.find('-'); - - if (index == -1) return -1; - - opt = str[1]; - - optind ++; - str = args[optind]; - } - while ((opttolookfor = (int)interestin.find(opt)) == -1); - - if (interestin[opttolookfor+1] == ':') - { - - // strcpy(optarg, str.c_str()); - optarg = args[optind]; - optind ++; - } - - // indicate we have finished - return opt[0]; -} +#include "getopt.h" #endif // !__MINGW32__ #define timespec timeval -- cgit v1.2.3 From 502fa3141e5330a0e2e91ff4d7258f3f3c0fcaa6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Sep 2006 00:08:36 +0000 Subject: (refs #3) Added prototypes for new emulated functions emu_utimes, readv and writev --- lib/win32/emu.h | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index a861d3b9..2e9f8cd0 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -132,14 +132,6 @@ inline struct passwd * getpwnam(const char * name) #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 @@ -159,23 +151,20 @@ inline int chown(const char * Filename, u_int32_t uid, u_int32_t gid) int emu_chdir (const char* pDirName); int emu_unlink(const char* pFileName); char* emu_getcwd(char* pBuffer, int BufSize); +int emu_utimes(const char* pName, const struct timeval[]); +int emu_chmod (const char* pName, mode_t mode); -#ifdef _MSC_VER - inline int emu_chmod(const char * Filename, int mode) - { - // indicate success - return 0; - } +#define utimes(buffer, times) emu_utimes(buffer, times) - #define chmod(file, mode) emu_chmod(file, mode) - #define chdir(directory) emu_chdir(directory) - #define unlink(file) emu_unlink(file) - #define getcwd(buffer, size) emu_getcwd(buffer, size) +#ifdef _MSC_VER + #define chmod(file, mode) emu_chmod(file, mode) + #define chdir(directory) emu_chdir(directory) + #define unlink(file) emu_unlink(file) + #define getcwd(buffer, size) emu_getcwd(buffer, size) #else - inline int chmod(const char * Filename, int mode) + inline int chmod(const char * pName, mode_t mode) { - // indicate success - return 0; + return emu_chmod(pName, mode); } inline int chdir(const char* pDirName) @@ -435,4 +424,12 @@ bool ConvertConsoleToUtf8(const char* pString, std::string& rDest); // replacement for _cgetws which requires a relatively recent C runtime lib int console_read(char* pBuffer, size_t BufferSize); +struct iovec { + void *iov_base; /* Starting address */ + size_t iov_len; /* Number of bytes */ +}; + +int readv (int filedes, const struct iovec *vector, size_t count); +int writev(int filedes, const struct iovec *vector, size_t count); + #endif // !EMU_INCLUDE && WIN32 -- cgit v1.2.3 From 012c1b4c977bc94d4f8859c04890223f48881463 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Sep 2006 00:09:26 +0000 Subject: (refs #3) Remove inline ConvertFileTimeToTime_t, add prototypes for new versions in emu.cpp --- lib/win32/emu.h | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 2e9f8cd0..54280769 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -372,29 +372,9 @@ int emu_stat(const char * name, struct stat * st); int emu_fstat(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); - - memset(&timeinfo, 0, sizeof(timeinfo)); - 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) - _timezone; - return retVal; -} +// need this for conversions +time_t ConvertFileTimeToTime_t(FILETIME *fileTime); +bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo); #ifdef _MSC_VER #define stat(filename, struct) emu_stat (filename, struct) -- cgit v1.2.3 From 38429ae610b92e83cc0febb232eaa5149a0bd494 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Sep 2006 00:10:38 +0000 Subject: (refs #3) Changed WideSize from int to size_t Don't allow space for null terminator that will not be added --- lib/win32/emu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 109e54f6..91684f1c 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1559,7 +1559,7 @@ int console_read(char* pBuffer, size_t BufferSize) return -1; } - int WideSize = BufferSize / 5; + size_t WideSize = BufferSize / 5; WCHAR* pWideBuffer = new WCHAR [WideSize]; if (!pWideBuffer) @@ -1573,7 +1573,7 @@ int console_read(char* pBuffer, size_t BufferSize) if (!ReadConsoleW( hConsole, pWideBuffer, - WideSize - 1, + WideSize, // will not be null terminated by ReadConsole &numCharsRead, NULL // reserved )) -- cgit v1.2.3 From 9635631135e1f0df36a0b038f047384dd9d8c8c0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 13 Oct 2006 23:03:23 +0000 Subject: * Added support for Win32 temporary files * Added InvisibleTempFileStream class and unit tests for it * Use InvisibleTempFileStream instead of FileStream for temporary files (refs #3) --- lib/win32/emu.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 91684f1c..6ce1790c 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -521,7 +521,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode) accessRights = FILE_WRITE_DATA; shareMode = FILE_SHARE_WRITE; } - else if (flags & (O_RDWR | O_CREAT)) + else if (flags & O_RDWR) { accessRights |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA; @@ -541,12 +541,19 @@ HANDLE openfile(const char *pFileName, int flags, int mode) shareMode = 0; } + DWORD winFlags = FILE_FLAG_BACKUP_SEMANTICS; + if (flags & O_TEMPORARY) + { + winFlags |= FILE_FLAG_DELETE_ON_CLOSE; + shareMode |= FILE_SHARE_DELETE; + } + HANDLE hdir = CreateFileW(pBuffer, accessRights, shareMode, NULL, createDisposition, - FILE_FLAG_BACKUP_SEMANTICS, + winFlags, NULL); delete [] pBuffer; -- cgit v1.2.3 From 9a1c50ad833480750f82168a0bea138c461ec8b6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 15 Oct 2006 19:20:49 +0000 Subject: Compile fix (refs #3) --- lib/win32/emu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 54280769..d898968a 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -267,7 +267,7 @@ inline int strcasecmp(const char *s1, const char *s2) #endif #ifdef _DIRENT_H_ -#error You must not include MinGW's dirent.h! +#error You must not include the MinGW dirent.h! #endif struct dirent -- cgit v1.2.3 From da8282e7a87b67c1585ce9b81199d7966d8481c9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Oct 2006 22:50:57 +0000 Subject: Rename config.h.win32 to the new name, which will be auto-included by another change (refs #3) --- lib/win32/config.h.win32 | 390 ----------------------------------------------- 1 file changed, 390 deletions(-) delete mode 100644 lib/win32/config.h.win32 (limited to 'lib/win32') diff --git a/lib/win32/config.h.win32 b/lib/win32/config.h.win32 deleted file mode 100644 index edc44a75..00000000 --- a/lib/win32/config.h.win32 +++ /dev/null @@ -1,390 +0,0 @@ -/* lib/common/BoxConfig.h. Generated by configure. */ -/* lib/common/BoxConfig.h.in. Generated from configure.ac by autoheader. */ -/* Hacked by hand to work for MSVC by Chris Wilson */ - -/* Define to major version for BDB_VERSION */ -/* #undef BDB_VERSION_MAJOR */ - -/* Define to minor version for BDB_VERSION */ -/* #undef BDB_VERSION_MINOR */ - -/* Define to point version for BDB_VERSION */ -/* #undef BDB_VERSION_POINT */ - -/* Name of the 64 bit endian swapping function */ -/* #undef BSWAP64 */ - -/* Define to 1 if the `closedir' function returns void instead of `int'. */ -#define CLOSEDIR_VOID 1 - -/* Define to 1 if non-aligned int16 access will fail */ -/* #undef HAVE_ALIGNED_ONLY_INT16 */ - -/* Define to 1 if non-aligned int32 access will fail */ -/* #undef HAVE_ALIGNED_ONLY_INT32 */ - -/* Define to 1 if non-aligned int64 access will fail */ -/* #undef HAVE_ALIGNED_ONLY_INT64 */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_BYTEORDER_H */ - -/* Define to 1 if BSWAP64 is defined to the name of a valid 64 bit endian - swapping function */ -/* #undef HAVE_BSWAP64 */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DB_H */ - -/* Define to 1 if you have the declaration of `F_SETLK', and to 0 if you - don't. */ -#define HAVE_DECL_F_SETLK 0 - -/* Define to 1 if you have the declaration of `INFTIM', and to 0 if you don't. - */ -#define HAVE_DECL_INFTIM 0 - -/* Define to 1 if you have the declaration of `O_EXLOCK', and to 0 if you - don't. */ -#define HAVE_DECL_O_EXLOCK 0 - -/* Define to 1 if you have the declaration of `SO_PEERCRED', and to 0 if you - don't. */ -#define HAVE_DECL_SO_PEERCRED 0 - -/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if - you don't. */ -#define HAVE_DECL_XATTR_NOFOLLOW 0 - -/* Define to 1 if #define of pragmas works */ -/* #undef HAVE_DEFINE_PRAGMA */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_DIRENT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_EDITLINE_READLINE_H */ - -/* define if the compiler supports exceptions */ -#define HAVE_EXCEPTIONS - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_EXECINFO_H */ - -/* Define to 1 if you have the `flock' function. */ -/* #undef HAVE_FLOCK */ - -/* Define to 1 if you have the `getmntent' function. */ -/* #undef HAVE_GETMNTENT */ - -/* Define to 1 if you have the `getpeereid' function. */ -/* #undef HAVE_GETPEEREID */ - -/* Define to 1 if you have the `getpid' function. */ -#define HAVE_GETPID 1 - -/* Define to 1 if you have the `getxattr' function. */ -/* #undef HAVE_GETXATTR */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_HISTORY_H */ - -/* Define to 1 if you have the header file. */ -// #define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `kqueue' function. */ -/* #undef HAVE_KQUEUE */ - -/* Define to 1 if you have the `lchown' function. */ -/* #undef HAVE_LCHOWN */ - -/* Define to 1 if you have the `lgetxattr' function. */ -/* #undef HAVE_LGETXATTR */ - -/* Define to 1 if you have the `crypto' library (-lcrypto). */ -#define HAVE_LIBCRYPTO 1 - -/* Define if you have a readline compatible library */ -/* #undef HAVE_LIBREADLINE */ - -/* Define to 1 if you have the `ssl' library (-lssl). */ -#define HAVE_LIBSSL 1 - -/* Define to 1 if you have the `z' library (-lz). */ -#define HAVE_LIBZ 1 - -/* Define to 1 if you have the `listxattr' function. */ -/* #undef HAVE_LISTXATTR */ - -/* Define to 1 if you have the `llistxattr' function. */ -/* #undef HAVE_LLISTXATTR */ - -/* Define to 1 if syscall lseek requires a dummy middle parameter */ -/* #undef HAVE_LSEEK_DUMMY_PARAM */ - -/* Define to 1 if you have the `lsetxattr' function. */ -/* #undef HAVE_LSETXATTR */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MNTENT_H */ - -/* Define to 1 if this platform supports mounts */ -/* #undef HAVE_MOUNTS */ - -/* define if the compiler implements namespaces */ -#define HAVE_NAMESPACES - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_IN_H */ - -/* Define to 1 if SSL is pre-0.9.7 */ -/* #undef HAVE_OLD_SSL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_OPENSSL_SSL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_PROCESS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PWD_H */ - -/* Define to 1 (and set RANDOM_DEVICE) if a random device is available */ -/* #undef HAVE_RANDOM_DEVICE */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_H */ - -/* Define if your readline library has add_history */ -/* #undef HAVE_READLINE_HISTORY */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_HISTORY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_READLINE_H */ - -/* Define to 1 if you have the header file. */ -// #define HAVE_REGEX_H 1 - -/* Define to 1 if you have the `setproctitle' function. */ -/* #undef HAVE_SETPROCTITLE */ - -/* Define to 1 if you have the `setxattr' function. */ -/* #undef HAVE_SETXATTR */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if SSL is available */ -#define HAVE_SSL 1 - -/* Define to 1 if you have the `statfs' function. */ -/* #undef HAVE_STATFS */ - -/* Define to 1 if `stat' has the bug that it succeeds when given the - zero-length file name argument. */ -/* #undef HAVE_STAT_EMPTY_STRING_BUG */ - -/* Define to 1 if stdbool.h conforms to C99. */ -#define HAVE_STDBOOL_H 1 - -/* Define to 1 if you have the header file. */ -// #define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if `d_type' is member of `struct dirent'. */ -/* #undef HAVE_STRUCT_DIRENT_D_TYPE */ - -/* Define to 1 if `mnt_dir' is member of `struct mntent'. */ -/* #undef HAVE_STRUCT_MNTENT_MNT_DIR */ - -/* Define to 1 if `mnt_mountp' is member of `struct mnttab'. */ -/* #undef HAVE_STRUCT_MNTTAB_MNT_MOUNTP */ - -/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */ -/* #undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - -/* Define to 1 if `f_mntonname' is member of `struct statfs'. */ -/* #undef HAVE_STRUCT_STATFS_F_MNTONNAME */ - -/* Define to 1 if `st_flags' is member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_FLAGS */ - -/* Define to 1 if `st_mtimespec' is member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_MTIMESPEC */ - -/* Define to 1 if you have the `syscall' function. */ -/* #undef HAVE_SYSCALL */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYSLOG_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_ENDIAN_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MNTTAB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MOUNT_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the header file. */ -// #define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SYSCALL_H */ - -/* Define to 1 if you have the header file. */ -// #define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_WAIT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_XATTR_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_TIME_H 1 - -/* Define to 1 if the system has the type `uint16_t'. */ -#define HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define HAVE_UINT8_T 1 - -/* Define to 1 if you have the header file. */ -// #define HAVE_UNISTD_H 1 - -/* Define to 1 if the system has the type `u_int16_t'. */ -/* #undef HAVE_U_INT16_T */ - -/* Define to 1 if the system has the type `u_int32_t'. */ -/* #undef HAVE_U_INT32_T */ - -/* Define to 1 if the system has the type `u_int64_t'. */ -/* #undef HAVE_U_INT64_T */ - -/* Define to 1 if the system has the type `u_int8_t'. */ -/* #undef HAVE_U_INT8_T */ - -/* Define to 1 if struct dirent.d_type is valid */ -/* #undef HAVE_VALID_DIRENT_D_TYPE */ - -/* Define to 1 if the system has the type `_Bool'. */ -/* #undef HAVE__BOOL */ - -/* Define to 1 if you have the `__syscall' function. */ -/* #undef HAVE___SYSCALL */ - -/* Define to 1 if __syscall is available but needs a definition */ -/* #undef HAVE___SYSCALL_NEED_DEFN */ - -/* Define to 1 if `lstat' dereferences a symlink specified with a trailing - slash. */ -/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "box@fluffy.co.uk" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "Box Backup" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "Box Backup 0.09" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "box-backup" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "0.09" - -/* Define to the filename of the random device (and set HAVE_RANDOM_DEVICE) */ -/* #undef RANDOM_DEVICE */ - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* TMP directory name */ -#define TEMP_DIRECTORY_NAME "/tmp" - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your declares `struct tm'. */ -/* #undef TM_IN_SYS_TIME */ - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to 1 if __USE_MALLOC is required work around STL memory leaks */ -/* #undef __USE_MALLOC */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `int' if doesn't define. */ -#define gid_t int - -/* Define to `int' if does not define. */ -/* #undef mode_t */ - -/* Define to `long' if does not define. */ -/* #undef off_t */ - -/* Define to `int' if does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned' if does not define. */ -/* #undef size_t */ - -/* Define to `int' if doesn't define. */ -#define uid_t int -- cgit v1.2.3 From 45a95c864a32098eb9ac73b9c5fec1fa25061f3d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 6 Nov 2006 20:45:32 +0000 Subject: Protect against double initialisation of win32 timers --- lib/win32/emu.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 6ce1790c..205ada9b 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -28,6 +28,7 @@ // our implementation for a timer, based on a // simple thread which sleeps for a period of time +static bool gTimerInitialised = false; static bool gFinishTimer; static CRITICAL_SECTION gLock; @@ -43,6 +44,8 @@ static void (__cdecl *gTimerFunc) (int) = NULL; int setitimer(int type, struct itimerval *timeout, void *arg) { + ASSERT(gTimerInitialised); + if (ITIMER_VIRTUAL == type) { EnterCriticalSection(&gLock); @@ -131,20 +134,25 @@ int SetTimerHandler(void (__cdecl *func ) (int)) void InitTimer(void) { + ASSERT(!gTimerInitialised); InitializeCriticalSection(&gLock); - + // create our thread HANDLE ourThread = (HANDLE)_beginthreadex(NULL, 0, RunTimer, 0, CREATE_SUSPENDED, NULL); SetThreadPriority(ourThread, THREAD_PRIORITY_LOWEST); ResumeThread(ourThread); + + gTimerInitialised = true; } void FiniTimer(void) { + ASSERT(gTimerInitialised); gFinishTimer = true; EnterCriticalSection(&gLock); DeleteCriticalSection(&gLock); + gTimerInitialised = false; } //Our constants we need to keep track of -- cgit v1.2.3 From 1e14bb0876a81f4168ea028dddd53e8a81c1c727 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 16 Dec 2006 16:15:07 +0000 Subject: Added implementation of getopt from BSD (refs #3) (check license!) --- lib/win32/getopt_long.cxx | 547 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 547 insertions(+) create mode 100755 lib/win32/getopt_long.cxx (limited to 'lib/win32') diff --git a/lib/win32/getopt_long.cxx b/lib/win32/getopt_long.cxx new file mode 100755 index 00000000..c6800426 --- /dev/null +++ b/lib/win32/getopt_long.cxx @@ -0,0 +1,547 @@ +/* $OpenBSD: getopt_long.c,v 1.20 2005/10/25 15:49:37 jmc Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ +// Adapted for Box Backup by Chris Wilson + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Box.h" + +#include +#include +#include +#include + +#ifdef _MSC_VER +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ +#endif + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#endif + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static void warnx(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + const char * oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; + if (*options == '+' || *options == '-') + options++; + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + optchar == (int)'-' && *place != '\0' || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + /* XXX: disable test for :: if PC? (GNU doesn't) */ + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } else if (!(flags & FLAG_PERMUTE)) { + /* + * If permutation is disabled, we can accept an + * optional arg separated by whitespace so long + * as it does not start with a dash (-). + */ + if (optind + 1 < nargc && *nargv[optind + 1] != '-') + optarg = nargv[++optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* REPLACE_GETOPT */ + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} + -- cgit v1.2.3 From b8e98d8ef95d57d81535e6c6e5dcbd411990669a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 15 Jan 2007 21:38:53 +0000 Subject: Detect reparse points and change the device number (refs #3) --- lib/win32/emu.cpp | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 205ada9b..da4ecb2a 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -46,24 +46,21 @@ int setitimer(int type, struct itimerval *timeout, void *arg) { ASSERT(gTimerInitialised); - if (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) { - 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 - { - Timer_t ourTimer; - ourTimer.countDown = timeout->it_value.tv_sec; - ourTimer.interval = timeout->it_interval.tv_sec; - gTimerList.push_back(ourTimer); - } - LeaveCriticalSection(&gLock); + gTimerList.clear(); + } + else + { + Timer_t 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; @@ -674,6 +671,22 @@ int emu_fstat(HANDLE hdir, struct stat * st) st->st_mode |= S_IWRITE; } + // st_dev is nroammly zero, regardless of the drive letter, + // since backup locations can't normally span drives. However, + // a reparse point does allow all kinds of weird stuff to happen. + // We set st_dev to 1 for a reparse point, so that Box will detect + // a change of device number (from 0) and refuse to recurse down + // the reparse point (which could lead to havoc). + + if (fi.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + { + st->st_dev = 1; + } + else + { + st->st_dev = 0; + } + return 0; } -- cgit v1.2.3 From 07be2b3a2181d97c393d79f731e3d564733d58bd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:06:13 +0000 Subject: Always include process.h, as we don't know whether it was detected or not (we don't have access to lib/common/BoxConfig.h in lib/win32) (refs #3) --- lib/win32/emu.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index da4ecb2a..16c4a2ef 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -9,14 +9,12 @@ #include #include +#include #include #ifdef HAVE_UNISTD_H #include #endif -#ifdef HAVE_PROCESS_H - #include -#endif #include #include -- cgit v1.2.3 From a0a9f969a6831739e9a9dc325b5d2e4048635bd7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:12:01 +0000 Subject: Our timer code only supports ITIMER_REAL (refs #3) --- lib/win32/emu.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 16c4a2ef..7ee2b5a1 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -44,7 +44,14 @@ int setitimer(int type, struct itimerval *timeout, void *arg) { ASSERT(gTimerInitialised); + if (ITIMER_REAL != type) + { + errno = ENOSYS; + return -1; + } + EnterCriticalSection(&gLock); + // we only need seconds for the mo! if (timeout->it_value.tv_sec == 0 && timeout->it_value.tv_usec == 0) @@ -58,6 +65,7 @@ int setitimer(int type, struct itimerval *timeout, void *arg) ourTimer.interval = timeout->it_interval.tv_sec; gTimerList.push_back(ourTimer); } + LeaveCriticalSection(&gLock); // indicate success -- cgit v1.2.3 From a9c4ae701ac2e2a5d5d62d82be4059e96fb6cb64 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:15:03 +0000 Subject: We can't use lib/common here, so we don't have ASSERT() (refs #3) --- lib/win32/emu.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 7ee2b5a1..cfe73ddd 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -42,7 +42,7 @@ static void (__cdecl *gTimerFunc) (int) = NULL; int setitimer(int type, struct itimerval *timeout, void *arg) { - ASSERT(gTimerInitialised); + assert(gTimerInitialised); if (ITIMER_REAL != type) { @@ -137,7 +137,8 @@ int SetTimerHandler(void (__cdecl *func ) (int)) void InitTimer(void) { - ASSERT(!gTimerInitialised); + assert(!gTimerInitialised); + InitializeCriticalSection(&gLock); // create our thread @@ -151,7 +152,7 @@ void InitTimer(void) void FiniTimer(void) { - ASSERT(gTimerInitialised); + assert(gTimerInitialised); gFinishTimer = true; EnterCriticalSection(&gLock); DeleteCriticalSection(&gLock); -- cgit v1.2.3 From dd1026364150b2b80194015aa5ffafdd86b50fdb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:20:40 +0000 Subject: Expanded character set conversion API to allow arbitrary conversions (needed to handle command lines with international encodings) (refs #3, merges [1038]) --- lib/win32/emu.cpp | 62 ++++++++++++++++++++++--------------------------------- lib/win32/emu.h | 8 ++++++- 2 files changed, 32 insertions(+), 38 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index cfe73ddd..7e6cbcd0 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -374,23 +374,25 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) // -------------------------------------------------------------------------- // // Function -// Name: ConvertUtf8ToConsole -// Purpose: Converts a string from UTF-8 to the console -// code page. On success, replaces contents of rDest -// and returns true. In case of fire, logs the error -// and returns false. -// Created: 4th February 2006 +// Name: ConvertEncoding(const std::string&, int, +// std::string&, int) +// Purpose: Converts a string from one code page to another. +// On success, replaces contents of rDest and returns +// true. In case of fire, logs the error and returns +// false. +// Created: 15th October 2006 // // -------------------------------------------------------------------------- -bool ConvertUtf8ToConsole(const char* pString, std::string& rDest) +bool ConvertEncoding(const std::string& rSource, int sourceCodePage, + std::string& rDest, int destCodePage) { - WCHAR* pWide = ConvertUtf8ToWideString(pString); + WCHAR* pWide = ConvertToWideString(rSource.c_str(), sourceCodePage); if (pWide == NULL) { return false; } - char* pConsole = ConvertFromWideString(pWide, GetConsoleOutputCP()); + char* pConsole = ConvertFromWideString(pWide, destCodePage); delete [] pWide; if (!pConsole) @@ -404,39 +406,25 @@ bool ConvertUtf8ToConsole(const char* pString, std::string& rDest) return true; } -// -------------------------------------------------------------------------- -// -// Function -// Name: ConvertConsoleToUtf8 -// Purpose: Converts a string from the console code page -// to UTF-8. On success, replaces contents of rDest -// and returns true. In case of fire, logs the error -// and returns false. -// Created: 4th February 2006 -// -// -------------------------------------------------------------------------- -bool ConvertConsoleToUtf8(const char* pString, std::string& rDest) +bool ConvertToUtf8(const char* pString, std::string& rDest, int sourceCodePage) { - WCHAR* pWide = ConvertToWideString(pString, GetConsoleCP()); - if (pWide == NULL) - { - return false; - } - - char* pConsole = ConvertFromWideString(pWide, CP_UTF8); - delete [] pWide; - - if (!pConsole) - { - return false; - } + return ConvertEncoding(pString, sourceCodePage, rDest, CP_UTF8); +} - rDest = pConsole; - delete [] pConsole; +bool ConvertFromUtf8(const char* pString, std::string& rDest, int destCodePage) +{ + return ConvertEncoding(pString, CP_UTF8, rDest, destCodePage); +} - return true; +bool ConvertConsoleToUtf8(const char* pString, std::string& rDest) +{ + return ConvertEncoding(pString, GetConsoleCP(), rDest, CP_UTF8); } +bool ConvertUtf8ToConsole(const char* pString, std::string& rDest) +{ + return ConvertEncoding(pString, CP_UTF8, rDest, GetConsoleOutputCP()); +} // -------------------------------------------------------------------------- // diff --git a/lib/win32/emu.h b/lib/win32/emu.h index d898968a..5b3e2280 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -254,7 +254,7 @@ struct itimerval int emu_mkdir(const char* pPathName); -inline int mkdir(const char *pPathName, mode_t mode) +inline int mkdir(const char *pPathName, mode_t mode = 0) { return emu_mkdir(pPathName); } @@ -398,6 +398,12 @@ bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo); int poll(struct pollfd *ufds, unsigned long nfds, int timeout); bool EnableBackupRights( void ); +bool ConvertEncoding (const std::string& rSource, int sourceCodePage, + std::string& rDest, int destCodePage); +bool ConvertToUtf8 (const std::string& rSource, std::string& rDest, + int sourceCodePage); +bool ConvertFromUtf8 (const std::string& rSource, std::string& rDest, + int destCodePage); bool ConvertUtf8ToConsole(const char* pString, std::string& rDest); bool ConvertConsoleToUtf8(const char* pString, std::string& rDest); -- cgit v1.2.3 From f54474874ae06d72963d560cd17b1fe0f0c82106 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:27:31 +0000 Subject: Print localised error messages rather than error codes for all errors (refs #3, merges [1046]) --- lib/win32/emu.cpp | 100 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 35 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 7e6cbcd0..0a7b8ed6 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -482,6 +482,32 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) return tmpStr; } +std::string GetErrorMessage(DWORD errorCode) +{ + char* pMsgBuf = NULL; + + DWORD chars = FormatMessage + ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char *)(&pMsgBuf), + 0, NULL + ); + + if (chars == 0 || pMsgBuf == NULL) + { + return std::string("failed to get error message"); + } + + std::string out(pMsgBuf); + LocalFree(pMsgBuf); + + return out; +} + // -------------------------------------------------------------------------- // // Function @@ -560,8 +586,9 @@ HANDLE openfile(const char *pFileName, int flags, int mode) if (hdir == INVALID_HANDLE_VALUE) { - ::syslog(LOG_WARNING, "Failed to open file %s: " - "error %i", pFileName, GetLastError()); + ::syslog(LOG_WARNING, "Failed to open file '%s': " + "%s", pFileName, + GetErrorMessage(GetLastError()).c_str()); return INVALID_HANDLE_VALUE; } @@ -589,7 +616,7 @@ int emu_fstat(HANDLE hdir, struct stat * st) if (!GetFileInformationByHandle(hdir, &fi)) { ::syslog(LOG_WARNING, "Failed to read file information: " - "error %d", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); errno = EACCES; return -1; } @@ -597,7 +624,7 @@ int emu_fstat(HANDLE hdir, struct stat * st) if (INVALID_FILE_ATTRIBUTES == fi.dwFileAttributes) { ::syslog(LOG_WARNING, "Failed to get file attributes: " - "error %d", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); errno = EACCES; return -1; } @@ -628,7 +655,7 @@ int emu_fstat(HANDLE hdir, struct stat * st) if (!GetFileSizeEx(hdir, &st_size)) { ::syslog(LOG_WARNING, "Failed to get file size: " - "error %d", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); errno = EACCES; return -1; } @@ -751,8 +778,9 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) } else { - ::syslog(LOG_WARNING, - "Failed to open '%s': error %d", pFileName, err); + ::syslog(LOG_WARNING, "Failed to open '%s': " + "%s", pFileName, + GetErrorMessage(err).c_str()); errno = EACCES; } @@ -820,7 +848,8 @@ int statfs(const char * pName, struct statfs * s) if (!GetFileInformationByHandle(handle, &fi)) { ::syslog(LOG_WARNING, "Failed to get file information " - "for '%s': error %d", pName, GetLastError()); + "for '%s': %s", pName, + GetErrorMessage(GetLastError()).c_str()); CloseHandle(handle); errno = EACCES; return -1; @@ -873,8 +902,8 @@ int emu_utimes(const char * pName, const struct timeval times[]) if (!SetFileTime(handle, &creationTime, NULL, &modificationTime)) { - ::syslog(LOG_ERR, "Failed to set times on '%s': error %d", - pName, GetLastError()); + ::syslog(LOG_ERR, "Failed to set times on '%s': %s", pName, + GetErrorMessage(GetLastError()).c_str()); CloseHandle(handle); return 1; } @@ -916,8 +945,8 @@ int emu_chmod(const char * pName, mode_t mode) DWORD attribs = GetFileAttributesW(pBuffer); if (attribs == INVALID_FILE_ATTRIBUTES) { - ::syslog(LOG_ERR, "Failed to get file attributes of '%s': " - "error %d", pName, GetLastError()); + ::syslog(LOG_ERR, "Failed to get file attributes of '%s': %s", + pName, GetErrorMessage(GetLastError()).c_str()); errno = EACCES; free(pBuffer); return -1; @@ -934,8 +963,8 @@ int emu_chmod(const char * pName, mode_t mode) if (!SetFileAttributesW(pBuffer, attribs)) { - ::syslog(LOG_ERR, "Failed to set file attributes of '%s': " - "error %d", pName, GetLastError()); + ::syslog(LOG_ERR, "Failed to set file attributes of '%s': %s", + pName, GetErrorMessage(GetLastError()).c_str()); errno = EACCES; free(pBuffer); return -1; @@ -1204,8 +1233,8 @@ BOOL AddEventSource char cmd[MAX_PATH]; if (GetModuleFileName(NULL, cmd, sizeof(cmd)-1) == 0) { - ::syslog(LOG_ERR, "Failed to get the program file name: " - "error %d", GetLastError()); + ::syslog(LOG_ERR, "Failed to get the program file name: %s", + GetErrorMessage(GetLastError()).c_str()); return FALSE; } cmd[sizeof(cmd)-1] = 0; @@ -1224,8 +1253,8 @@ BOOL AddEventSource 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hk, &dwDisp)) { - ::syslog(LOG_ERR, "Failed to create the registry key: " - "error %d", GetLastError()); + ::syslog(LOG_ERR, "Failed to create the registry key: %s", + GetErrorMessage(GetLastError()).c_str()); return FALSE; } @@ -1238,8 +1267,8 @@ BOOL AddEventSource (LPBYTE) exepath.c_str(), // pointer to value data (DWORD) (exepath.size()))) // data size { - ::syslog(LOG_ERR, "Failed to set the event message file: " - "error %d", GetLastError()); + ::syslog(LOG_ERR, "Failed to set the event message file: %s", + GetErrorMessage(GetLastError()).c_str()); RegCloseKey(hk); return FALSE; } @@ -1256,8 +1285,8 @@ BOOL AddEventSource (LPBYTE) &dwData, // pointer to value data sizeof(DWORD))) // length of value data { - ::syslog(LOG_ERR, "Failed to set the supported types: " - "error %d", GetLastError()); + ::syslog(LOG_ERR, "Failed to set the supported types: %s", + GetErrorMessage(GetLastError()).c_str()); RegCloseKey(hk); return FALSE; } @@ -1272,7 +1301,7 @@ BOOL AddEventSource (DWORD) (exepath.size()))) // data size { ::syslog(LOG_ERR, "Failed to set the category message file: " - "error %d", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); RegCloseKey(hk); return FALSE; } @@ -1284,8 +1313,8 @@ BOOL AddEventSource (LPBYTE) &dwNum, // pointer to value data sizeof(DWORD))) // length of value data { - ::syslog(LOG_ERR, "Failed to set the category count: " - "error %d", GetLastError()); + ::syslog(LOG_ERR, "Failed to set the category count: %s", + GetErrorMessage(GetLastError()).c_str()); RegCloseKey(hk); return FALSE; } @@ -1318,7 +1347,7 @@ void openlog(const char * daemonName, int, int) if (newSyslogH == NULL) { ::syslog(LOG_ERR, "Failed to register our own event source: " - "error %d", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); return; } @@ -1417,8 +1446,8 @@ void syslog(int loglevel, const char *frmt, ...) } else { - printf("Unable to send message to Event Log: " - "error %i:\r\n", (int)err); + printf("Unable to send message to Event Log: %s:\r\n", + GetErrorMessage(err).c_str()); fflush(stdout); } } @@ -1562,7 +1591,8 @@ int emu_unlink(const char* pFileName) else { ::syslog(LOG_WARNING, "Failed to delete file " - "'%s': error %d", pFileName, (int)err); + "'%s': %s", pFileName, + GetErrorMessage(err).c_str()); errno = ENOSYS; } return -1; @@ -1578,7 +1608,7 @@ int console_read(char* pBuffer, size_t BufferSize) if (hConsole == INVALID_HANDLE_VALUE) { ::fprintf(stderr, "Failed to get a handle on standard input: " - "error %d\n", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); return -1; } @@ -1601,8 +1631,8 @@ int console_read(char* pBuffer, size_t BufferSize) NULL // reserved )) { - ::fprintf(stderr, "Failed to read from console: error %d\n", - GetLastError()); + ::fprintf(stderr, "Failed to read from console: %s\n", + GetErrorMessage(GetLastError()).c_str()); return -1; } @@ -1698,13 +1728,13 @@ bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo) // Convert the last-write time to local time. if (!SystemTimeToFileTime(&stUTC, pTo)) { - syslog(LOG_ERR, "Failed to convert between time formats: " - "error %d", GetLastError()); + syslog(LOG_ERR, "Failed to convert between time formats: %s", + GetErrorMessage(GetLastError()).c_str()); return false; } return true; } - #endif // WIN32 + -- cgit v1.2.3 From a936147b531d87060e61dec21342d32d05d2f0a0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:29:31 +0000 Subject: Improve GetErrorMessage() by including the error number/code in the message (helps debugging on foreign langauge versions of Windows) (refs #3, merges [1364]) --- lib/win32/emu.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 0a7b8ed6..b201a9e0 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -18,6 +18,7 @@ #include #include +#include // message resource definitions for syslog() @@ -502,10 +503,11 @@ std::string GetErrorMessage(DWORD errorCode) return std::string("failed to get error message"); } - std::string out(pMsgBuf); + std::ostringstream line; + line << pMsgBuf << " (" << errorCode << ")"; LocalFree(pMsgBuf); - return out; + return line.str(); } // -------------------------------------------------------------------------- -- cgit v1.2.3 From a67d2d4364280ffa21f8054afde91af027f4214b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:32:44 +0000 Subject: Fix handling of O_EXCL to behave just like Unix, not abused to lock files. Add a new constant which specifies that files are to be locked open. (refs #3, merges [1288]) --- lib/win32/emu.cpp | 18 ++++++++++++------ lib/win32/emu.h | 3 +++ 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index b201a9e0..3de83517 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -541,30 +541,37 @@ HANDLE openfile(const char *pFileName, int flags, int mode) // 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; + DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE + | FILE_SHARE_DELETE; + DWORD accessRights = FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY + | FILE_READ_EA; if (flags & O_WRONLY) { accessRights = FILE_WRITE_DATA; - shareMode = FILE_SHARE_WRITE; } else if (flags & O_RDWR) { accessRights |= FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA; - shareMode |= FILE_SHARE_WRITE; } if (flags & O_CREAT) { createDisposition = OPEN_ALWAYS; } + if (flags & O_TRUNC) { createDisposition = CREATE_ALWAYS; } - if (flags & O_EXCL) + + if ((flags & O_CREAT) && (flags & O_EXCL)) + { + createDisposition = CREATE_NEW; + } + + if (flags & O_LOCK) { shareMode = 0; } @@ -573,7 +580,6 @@ HANDLE openfile(const char *pFileName, int flags, int mode) if (flags & O_TEMPORARY) { winFlags |= FILE_FLAG_DELETE_ON_CLOSE; - shareMode |= FILE_SHARE_DELETE; } HANDLE hdir = CreateFileW(pBuffer, diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 5b3e2280..0612e441 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -290,6 +290,9 @@ DIR *opendir(const char *name); struct dirent *readdir(DIR *dp); int closedir(DIR *dp); +// local constant to open file exclusively without shared access +#define O_LOCK 0x10000 + HANDLE openfile(const char *filename, int flags, int mode); #define LOG_INFO 6 -- cgit v1.2.3 From be2a8857bf807f347f3b6a1bf68ee672c0963963 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:36:54 +0000 Subject: We don't have access to DIRECTORY_SEPARATOR_ASCHAR in lib/win32 (refs #3, merges [1362]) --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 3de83517..a9390e90 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -867,7 +867,7 @@ int statfs(const char * pName, struct statfs * s) _ui64toa(fi.dwVolumeSerialNumber, s->f_mntonname + 1, 16); // pseudo unix mount point - s->f_mntonname[0] = DIRECTORY_SEPARATOR_ASCHAR; + s->f_mntonname[0] = '\\'; CloseHandle(handle); // close the handle -- cgit v1.2.3 From fc15dd1a4f59addd990c3f86f32b80b3376be8f7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:37:30 +0000 Subject: Typo fix (refs #3) --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index a9390e90..c03e491a 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -701,7 +701,7 @@ int emu_fstat(HANDLE hdir, struct stat * st) st->st_mode |= S_IWRITE; } - // st_dev is nroammly zero, regardless of the drive letter, + // st_dev is normally zero, regardless of the drive letter, // since backup locations can't normally span drives. However, // a reparse point does allow all kinds of weird stuff to happen. // We set st_dev to 1 for a reparse point, so that Box will detect -- cgit v1.2.3 From 3b161e80a045f1ebb11e196b7f514b96c302b746 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:38:48 +0000 Subject: Fix two memory leaks and one buffer overflow in codepage conversion code. (refs #3, merges [1340]) --- lib/win32/emu.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index c03e491a..112b1c9f 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -978,7 +978,7 @@ int emu_chmod(const char * pName, mode_t mode) return -1; } - free(pBuffer); + delete [] pBuffer; return 0; } @@ -1621,7 +1621,7 @@ int console_read(char* pBuffer, size_t BufferSize) } size_t WideSize = BufferSize / 5; - WCHAR* pWideBuffer = new WCHAR [WideSize]; + WCHAR* pWideBuffer = new WCHAR [WideSize + 1]; if (!pWideBuffer) { @@ -1647,6 +1647,8 @@ int console_read(char* pBuffer, size_t BufferSize) pWideBuffer[numCharsRead] = 0; char* pUtf8 = ConvertFromWideString(pWideBuffer, GetConsoleCP()); + delete [] pWideBuffer; + strncpy(pBuffer, pUtf8, BufferSize); delete [] pUtf8; -- cgit v1.2.3 From 28195d8d1da7a34fbff4c9d217f6333c5472ed7c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 17:50:33 +0000 Subject: First attempt to achieve a more logical order in this chaos: reordered all typedefs to be clearer and more readable (refs #3, merges [766]) --- lib/win32/emu.h | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 0612e441..206e1f70 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -6,27 +6,24 @@ // basic types, may be required by other headers since we // don't include sys/types.h -#ifdef __MINGW32__ - #include - typedef uint32_t u_int32_t; -#else // MSVC - typedef __int64 int64_t; - typedef __int32 int32_t; - typedef __int16 int16_t; - typedef __int8 int8_t; - +#ifndef __MINGW32__ typedef unsigned __int64 u_int64_t; - typedef unsigned __int32 u_int32_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; #endif // emulated types, present on MinGW but not MSVC or vice versa -#ifdef _MSC_VER +#ifdef __MINGW32__ + typedef uint32_t u_int32_t; +#else typedef unsigned int mode_t; typedef unsigned int pid_t; -- cgit v1.2.3 From cb0dae3a34f9409780905c075e82b46ed18576c0 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 18:01:07 +0000 Subject: Added d_type member to struct dirent, initialise with S_IFDIR or S_IFREG MinGW compile fix (refs #3, merges [775]) --- lib/win32/emu.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 206e1f70..25bff02c 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -6,7 +6,9 @@ // basic types, may be required by other headers since we // don't include sys/types.h -#ifndef __MINGW32__ +#ifdef __MINGW32__ + #include +#else // MSVC typedef unsigned __int64 u_int64_t; typedef unsigned __int64 uint64_t; typedef __int64 int64_t; -- cgit v1.2.3 From 1013fe643a8a3ada3049b011ba8363ab73caeeab Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 18:52:15 +0000 Subject: Compile fix for [1397] (refs #3) --- lib/win32/emu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 25bff02c..ca461c95 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -65,7 +65,7 @@ ( *(_result) = *gmtime( (_clock) ), \ (_result) ) -#define ITIMER_VIRTUAL 0 +#define ITIMER_REAL 0 #ifdef _MSC_VER // Microsoft decided to deprecate the standard POSIX functions. Great! -- cgit v1.2.3 From 13d90d5a6f528952c7574e8e2529732fcc6ab044 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 18:57:00 +0000 Subject: Use #defines to replace POSIX functions with emulated ones on MinGW, like we do on MSVC. This allows us to #undef them when we really need to use the original platform function (if available). Disable emulated fstat() in raidfile (and use the platform one) by undefining fstat, since it doesn't use the other emulated file handling functions, or need Unicode support, and it can't take a filehandle returned by open() (only openfile()). (refs #3, merges [1045]) --- lib/win32/emu.h | 84 ++++++++++++++------------------------------------------- 1 file changed, 20 insertions(+), 64 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index ca461c95..7ce4b831 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -147,41 +147,6 @@ inline int chown(const char * Filename, u_int32_t uid, u_int32_t gid) return 0; } -int emu_chdir (const char* pDirName); -int emu_unlink(const char* pFileName); -char* emu_getcwd(char* pBuffer, int BufSize); -int emu_utimes(const char* pName, const struct timeval[]); -int emu_chmod (const char* pName, mode_t mode); - -#define utimes(buffer, times) emu_utimes(buffer, times) - -#ifdef _MSC_VER - #define chmod(file, mode) emu_chmod(file, mode) - #define chdir(directory) emu_chdir(directory) - #define unlink(file) emu_unlink(file) - #define getcwd(buffer, size) emu_getcwd(buffer, size) -#else - inline int chmod(const char * pName, mode_t mode) - { - return emu_chmod(pName, mode); - } - - inline int chdir(const char* pDirName) - { - return emu_chdir(pDirName); - } - - inline char* getcwd(char* pBuffer, int BufSize) - { - return emu_getcwd(pBuffer, BufSize); - } - - inline int unlink(const char* pFileName) - { - return emu_unlink(pFileName); - } -#endif - //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) @@ -251,13 +216,6 @@ struct itimerval #define vsnprintf _vsnprintf -int emu_mkdir(const char* pPathName); - -inline int mkdir(const char *pPathName, mode_t mode = 0) -{ - return emu_mkdir(pPathName); -} - #ifndef __MINGW32__ inline int strcasecmp(const char *s1, const char *s2) { @@ -370,32 +328,30 @@ struct stat { }; #endif -int emu_stat(const char * name, struct stat * st); -int emu_fstat(HANDLE file, struct stat * st); -int statfs(const char * name, struct statfs * s); - // need this for conversions time_t ConvertFileTimeToTime_t(FILETIME *fileTime); bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo); -#ifdef _MSC_VER - #define stat(filename, struct) emu_stat (filename, struct) - #define lstat(filename, struct) emu_stat (filename, struct) - #define fstat(handle, struct) emu_fstat(handle, struct) -#else - inline int stat(const char* filename, struct stat* stat) - { - return emu_stat(filename, stat); - } - inline int lstat(const char* filename, struct stat* stat) - { - return emu_stat(filename, stat); - } - inline int fstat(HANDLE handle, struct stat* stat) - { - return emu_fstat(handle, stat); - } -#endif +int emu_chdir (const char* pDirName); +int emu_mkdir (const char* pPathName); +int emu_unlink (const char* pFileName); +int emu_fstat (HANDLE file, struct stat* st); +int emu_stat (const char* pName, struct stat* st); +int emu_utimes (const char* pName, const struct timeval[]); +int emu_chmod (const char* pName, mode_t mode); +char* emu_getcwd (char* pBuffer, int BufSize); + +#define chdir(directory) emu_chdir (directory) +#define mkdir(path, mode) emu_mkdir (path) +#define unlink(file) emu_unlink (file) +#define stat(filename, struct) emu_stat (filename, struct) +#define lstat(filename, struct) emu_stat (filename, struct) +#define fstat(handle, struct) emu_fstat (handle, struct) +#define utimes(buffer, times) emu_utimes (buffer, times) +#define chmod(file, mode) emu_chmod (file, mode) +#define getcwd(buffer, size) emu_getcwd (buffer, size) + +int statfs(const char * name, struct statfs * s); int poll(struct pollfd *ufds, unsigned long nfds, int timeout); bool EnableBackupRights( void ); -- cgit v1.2.3 From 8ef165b887dfb88514e4d00a07fa4e3d0c53fbc1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 19:01:11 +0000 Subject: Remove #define BOX_VERSION since we now get it from BoxVersion.h via BoxPlatform.h when building with MSVC, and from the Makefiles when building with MinGW. (refs #3, merges part of [634]) --- lib/win32/emu.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 7ce4b831..c8e15f3c 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -199,11 +199,6 @@ struct itimerval 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 -- cgit v1.2.3 From 40d737e975070ba43d15866b1b24e6e2d0922984 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 19:05:52 +0000 Subject: Reorder for clarity Expose GetErrorMessage() Improve comments (refs #3, merges [1365]) --- lib/win32/emu.h | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index c8e15f3c..f8bccb02 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -321,7 +321,7 @@ struct stat { time_t st_mtime; time_t st_ctime; }; -#endif +#endif // 0 // need this for conversions time_t ConvertFileTimeToTime_t(FILETIME *fileTime); @@ -349,6 +349,19 @@ char* emu_getcwd (char* pBuffer, int BufSize); int statfs(const char * name, struct statfs * s); int poll(struct pollfd *ufds, unsigned long nfds, int timeout); + +struct iovec { + void *iov_base; /* Starting address */ + size_t iov_len; /* Number of bytes */ +}; + +int readv (int filedes, const struct iovec *vector, size_t count); +int writev(int filedes, const struct iovec *vector, size_t count); + +// The following functions are not emulations, but utilities for other +// parts of the code where Windows API is used or windows-specific stuff +// is needed, like codepage conversion. + bool EnableBackupRights( void ); bool ConvertEncoding (const std::string& rSource, int sourceCodePage, @@ -360,15 +373,12 @@ bool ConvertFromUtf8 (const std::string& rSource, std::string& rDest, bool ConvertUtf8ToConsole(const char* pString, std::string& rDest); bool ConvertConsoleToUtf8(const char* pString, std::string& rDest); -// replacement for _cgetws which requires a relatively recent C runtime lib -int console_read(char* pBuffer, size_t BufferSize); - -struct iovec { - void *iov_base; /* Starting address */ - size_t iov_len; /* Number of bytes */ -}; +// GetErrorMessage() returns a system error message, like strerror() +// but for Windows error codes. +std::string GetErrorMessage(DWORD errorCode); -int readv (int filedes, const struct iovec *vector, size_t count); -int writev(int filedes, const struct iovec *vector, size_t count); +// console_read() is a replacement for _cgetws which requires a +// relatively recent C runtime lib +int console_read(char* pBuffer, size_t BufferSize); #endif // !EMU_INCLUDE && WIN32 -- cgit v1.2.3 From 0beaa1cd614b55d27a409cd7727a793b0757cfdf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 19:09:09 +0000 Subject: Add new syslog level emulations (refs #3, merges remainder of [1299]) --- lib/win32/emu.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index f8bccb02..fc88737d 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -247,9 +247,12 @@ int closedir(DIR *dp); HANDLE openfile(const char *filename, int flags, int mode); +#define LOG_DEBUG LOG_INFO #define LOG_INFO 6 +#define LOG_NOTICE LOG_INFO #define LOG_WARNING 4 #define LOG_ERR 3 +#define LOG_CRIT LOG_ERR #define LOG_PID 0 #define LOG_LOCAL5 0 #define LOG_LOCAL6 0 -- cgit v1.2.3 From 50f4c4a76a07ce1d34c4e50094d570a5087084cb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 10 Mar 2007 19:12:57 +0000 Subject: Group remaining set*id() and get*id() functions. Improve comments about why they are being retained. (refs #3, related to [634]) --- lib/win32/emu.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index fc88737d..a4af6e64 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -83,12 +83,6 @@ int setitimer(int type, struct itimerval *timeout, void *arg); 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; @@ -147,8 +141,9 @@ inline int chown(const char * Filename, u_int32_t uid, u_int32_t gid) 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 +// Windows and Unix owners and groups are pretty fundamentally different. +// Ben prefers that we kludge here rather than litter the code with #ifdefs. +// Pretend to be root, and pretend that set...() operations succeed. inline int setegid(int) { return true; @@ -173,6 +168,10 @@ inline int getuid(void) { return 0; } +inline int geteuid(void) +{ + return 0; +} #ifndef PATH_MAX #define PATH_MAX MAX_PATH -- cgit v1.2.3 From 198d823a23f6fbece6a4792c6d7f7f787555ae1e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 24 Mar 2007 22:53:45 +0000 Subject: Add emulated rename() with path conversion. (refs #3, merges [1436] and [1438]) --- lib/win32/emu.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/win32/emu.h | 2 ++ 2 files changed, 68 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 112b1c9f..0aedffc7 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1609,6 +1609,72 @@ int emu_unlink(const char* pFileName) return 0; } +int emu_rename(const char* pOldFileName, const char* pNewFileName) +{ + std::string OldPathWithUnicode = + ConvertPathToAbsoluteUnicode(pOldFileName); + + if (OldPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + WCHAR* pOldBuffer = ConvertUtf8ToWideString(OldPathWithUnicode.c_str()); + if (!pOldBuffer) + { + return -1; + } + + std::string NewPathWithUnicode = + ConvertPathToAbsoluteUnicode(pNewFileName); + + if (NewPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + delete [] pOldBuffer; + return -1; + } + + WCHAR* pNewBuffer = ConvertUtf8ToWideString(NewPathWithUnicode.c_str()); + if (!pNewBuffer) + { + delete [] pOldBuffer; + return -1; + } + + BOOL result = MoveFileW(pOldBuffer, pNewBuffer); + DWORD err = GetLastError(); + delete [] pOldBuffer; + delete [] pNewBuffer; + + if (!result) + { + if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + { + errno = ENOENT; + } + else if (err == ERROR_SHARING_VIOLATION) + { + errno = EBUSY; + } + else if (err == ERROR_ACCESS_DENIED) + { + errno = EACCES; + } + else + { + ::syslog(LOG_WARNING, "Failed to rename file " + "'%s' to '%s': %s", pOldFileName, pNewFileName, + GetErrorMessage(err).c_str()); + errno = ENOSYS; + } + return -1; + } + + return 0; +} + int console_read(char* pBuffer, size_t BufferSize) { HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); diff --git a/lib/win32/emu.h b/lib/win32/emu.h index a4af6e64..ec6c0918 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -337,6 +337,7 @@ int emu_stat (const char* pName, struct stat* st); int emu_utimes (const char* pName, const struct timeval[]); int emu_chmod (const char* pName, mode_t mode); char* emu_getcwd (char* pBuffer, int BufSize); +int emu_rename (const char* pOldName, const char* pNewName); #define chdir(directory) emu_chdir (directory) #define mkdir(path, mode) emu_mkdir (path) @@ -347,6 +348,7 @@ char* emu_getcwd (char* pBuffer, int BufSize); #define utimes(buffer, times) emu_utimes (buffer, times) #define chmod(file, mode) emu_chmod (file, mode) #define getcwd(buffer, size) emu_getcwd (buffer, size) +#define rename(oldname, newname) emu_rename (oldname, newname) int statfs(const char * name, struct statfs * s); -- cgit v1.2.3 From bdb64683f2bb8279c91770869370a0717bb45098 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 24 Mar 2007 22:54:30 +0000 Subject: Initialise logging framework and set our program name to Box Backup (bbstored) (refs #3, merges [1462]) --- lib/win32/emu.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 0aedffc7..818c6a6b 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1345,13 +1345,17 @@ void openlog(const char * daemonName, int, int) { } - if (!AddEventSource("Box Backup", 0)) + char* name = strdup(daemonName); + BOOL success = AddEventSource(name, 0); + free(name); + + if (!success) { ::syslog(LOG_ERR, "Failed to add our own event source"); return; } - HANDLE newSyslogH = RegisterEventSource(NULL, "Box Backup"); + HANDLE newSyslogH = RegisterEventSource(NULL, daemonName); if (newSyslogH == NULL) { ::syslog(LOG_ERR, "Failed to register our own event source: " -- cgit v1.2.3 From a5d88b13e3358afeeaf77242d6a8a47c098a5d01 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 24 Mar 2007 23:52:52 +0000 Subject: Added precompiled output from message compiler, for those who don't have it, e.g. using MinGW instead of MSVC. (refs #3, merges [526]) --- lib/win32/MSG00001.bin | Bin 0 -> 32 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 lib/win32/MSG00001.bin (limited to 'lib/win32') diff --git a/lib/win32/MSG00001.bin b/lib/win32/MSG00001.bin new file mode 100755 index 00000000..b4377b85 Binary files /dev/null and b/lib/win32/MSG00001.bin differ -- cgit v1.2.3 From 5f500e07ceaf3e2cb67b6809d266af281e809b99 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 28 Apr 2007 21:26:41 +0000 Subject: Fix rare memory leak. (refs #3, merges part of [1514]) --- lib/win32/emu.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 818c6a6b..7f665629 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1518,6 +1518,7 @@ char* emu_getcwd(char* pBuffer, int BufSize) if (result <= 0 || result >= len) { errno = EACCES; + delete [] pWide; return NULL; } -- cgit v1.2.3 From 8da5d31e2f3a22a52b6228a289efe9c7b1d9f6c7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 9 May 2007 10:49:50 +0000 Subject: Fix emulated chdir to work with relative paths and with bbackupquery's "sh" command (which doesn't like UNC paths). Fix error messages by removing surplus newline kindly added by Windows. (refs #3, merges [1514] and [1569]) --- lib/win32/emu.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 7f665629..0077166f 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -503,6 +503,10 @@ std::string GetErrorMessage(DWORD errorCode) return std::string("failed to get error message"); } + // remove embedded newline + pMsgBuf[chars - 1] = 0; + pMsgBuf[chars - 2] = 0; + std::ostringstream line; line << pMsgBuf << " (" << errorCode << ")"; LocalFree(pMsgBuf); @@ -1474,6 +1478,7 @@ void syslog(int loglevel, const char *frmt, ...) int emu_chdir(const char* pDirName) { + /* std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pDirName); @@ -1484,11 +1489,19 @@ int emu_chdir(const char* pDirName) } WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str()); + */ + + WCHAR* pBuffer = ConvertUtf8ToWideString(pDirName); if (!pBuffer) return -1; + int result = SetCurrentDirectoryW(pBuffer); delete [] pBuffer; + if (result != 0) return 0; + errno = EACCES; + fprintf(stderr, "Failed to change directory to '%s': %s\n", + pDirName, GetErrorMessage(GetLastError()).c_str()); return -1; } -- cgit v1.2.3 From ee62a6ec511a7699e276aae63927a3fa1ce6df2e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 26 Jul 2007 20:50:46 +0000 Subject: Add more debugging checks and messages for location setup error reported by Pete Jalajas (http://lists.warhead.org.uk/pipermail/boxbackup/2007-July/003668.html) --- lib/win32/emu.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 0077166f..d69d8197 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -390,6 +390,10 @@ bool ConvertEncoding(const std::string& rSource, int sourceCodePage, WCHAR* pWide = ConvertToWideString(rSource.c_str(), sourceCodePage); if (pWide == NULL) { + ::syslog(LOG_ERR, "Failed to convert string '%s' from " + "current code page %d to wide string: %s", + rSource.c_str(), sourceCodePage, + GetErrorMessage(GetLastError()).c_str()); return false; } @@ -398,6 +402,7 @@ bool ConvertEncoding(const std::string& rSource, int sourceCodePage, if (!pConsole) { + // Error should have been logged by ConvertFromWideString return false; } -- cgit v1.2.3 From a436702cdf84264e1176548a4dd0f78f8eeb123a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 26 Jul 2007 21:58:40 +0000 Subject: Fix restoring to top-level directories (e.g. c:\test) (refs #3, merges [1661]) --- lib/win32/emu.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index d69d8197..4224d62e 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -460,23 +460,28 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) // Is the path relative or absolute? // Absolute paths on Windows are always a drive letter // followed by ':' + + char wd[PATH_MAX]; + if (::getcwd(wd, PATH_MAX) == 0) + { + ::syslog(LOG_WARNING, + "Failed to open '%s': path too long", + pFileName); + errno = ENAMETOOLONG; + tmpStr = ""; + return tmpStr; + } - if (filename.length() >= 2 && filename[1] != ':') + if (filename.length() >= 1 && filename[0] == '\\') + { + // root directory of current drive. + tmpStr = wd; + tmpStr.resize(2); // drive letter and colon + } + else if (filename.length() >= 2 && filename[1] != ':') { // Must be relative. We need to get the // current directory to make it absolute. - - char wd[PATH_MAX]; - if (::getcwd(wd, PATH_MAX) == 0) - { - ::syslog(LOG_WARNING, - "Failed to open '%s': path too long", - pFileName); - errno = ENAMETOOLONG; - tmpStr = ""; - return tmpStr; - } - tmpStr += wd; if (tmpStr[tmpStr.length()] != '\\') { -- cgit v1.2.3 From 4a3627d5b883c0f66c9f2b770a427c18df51203f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 26 Jul 2007 22:04:53 +0000 Subject: Disable some warnings under MSVC to reduce build noise, thanks Gary! (refs #3, merges [1676]) --- lib/win32/emu.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index ec6c0918..1f078c14 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -385,4 +385,16 @@ std::string GetErrorMessage(DWORD errorCode); // relatively recent C runtime lib int console_read(char* pBuffer, size_t BufferSize); +#ifdef _MSC_VER + /* disable certain compiler warnings to be able to actually see the show-stopper ones */ + #pragma warning(disable:4101) // unreferenced local variable + #pragma warning(disable:4244) // conversion, possible loss of data + #pragma warning(disable:4267) // conversion, possible loss of data + #pragma warning(disable:4311) // pointer truncation + #pragma warning(disable:4700) // uninitialized local variable used (hmmmmm...) + #pragma warning(disable:4805) // unsafe mix of type and type 'bool' in operation + #pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning) + #pragma warning(disable:4996) // POSIX name for this item is deprecated +#endif // _MSC_VER + #endif // !EMU_INCLUDE && WIN32 -- cgit v1.2.3 From 498e58eb188d98c6ec78e57cdc5f0c211f1f4dcf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 26 Jul 2007 22:11:03 +0000 Subject: Make Configuration take a std::string filename instead of a char array, in C++ style. Add a function to get default config file paths at runtime, dependent on the location of the executable being run. Pass the config file name directly to Daemon::Main, instead of faking argv. No default raid file path at compile time on Windows, depends on executable location when run. Determine RaidFile path at runtime if not supplied in config file on Windows. Don't define default locations for config files at compile time on Windows, provide macros to determine them at runtime instead. Make FileHandleGuard take a std::string instead of a char array, C++ style. Determine config file location at runtime instead of hard-coding on Windows. Thanks to Paul MacKenzie, Per Thomsen, Pete Jalajas, Stuart Sanders, Dave Bamford and Gary for pushing me to do this. (fixes #12) Determine config file path at runtime. Call Daemon::Main with config file name instead of building fake argv. (refs #3, merges [1684] [1685] [1686] [1687] [1688] [1689] [1690] [1691] [1692]) --- lib/win32/emu.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++------------- lib/win32/emu.h | 4 ++++ 2 files changed, 58 insertions(+), 16 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 4224d62e..1a6b0e79 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -218,6 +218,44 @@ bool EnableBackupRights( void ) } } +// forward declaration +char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage); + +// -------------------------------------------------------------------------- +// +// Function +// Name: GetDefaultConfigFilePath(std::string name) +// Purpose: Calculates the default configuration file name, +// by using the directory location of the currently +// executing program, and appending the provided name. +// In case of fire, returns an empty string. +// Created: 26th May 2007 +// +// -------------------------------------------------------------------------- +std::string GetDefaultConfigFilePath(const std::string& rName) +{ + WCHAR exePathWide[MAX_PATH]; + GetModuleFileNameW(NULL, exePathWide, MAX_PATH-1); + + char* exePathUtf8 = ConvertFromWideString(exePathWide, CP_UTF8); + if (exePathUtf8 == NULL) + { + return ""; + } + + std::string configfile = exePathUtf8; + delete [] exePathUtf8; + + // make the default config file name, + // based on the program path + configfile = configfile.substr(0, + configfile.rfind('\\')); + configfile += "\\"; + configfile += rName; + + return configfile; +} + // -------------------------------------------------------------------------- // // Function @@ -1252,15 +1290,15 @@ BOOL AddEventSource // Work out the executable file name, to register ourselves // as the event source - char cmd[MAX_PATH]; - if (GetModuleFileName(NULL, cmd, sizeof(cmd)-1) == 0) + WCHAR cmd[MAX_PATH]; + DWORD len = GetModuleFileNameW(NULL, cmd, MAX_PATH); + + if (len == 0) { ::syslog(LOG_ERR, "Failed to get the program file name: %s", GetErrorMessage(GetLastError()).c_str()); return FALSE; } - cmd[sizeof(cmd)-1] = 0; - std::string exepath(cmd); // Create the event source as a subkey of the log. @@ -1282,12 +1320,12 @@ BOOL AddEventSource // Set the name of the message file. - if (RegSetValueEx(hk, // subkey handle - "EventMessageFile", // value name - 0, // must be zero - REG_EXPAND_SZ, // value type - (LPBYTE) exepath.c_str(), // pointer to value data - (DWORD) (exepath.size()))) // data size + if (RegSetValueExW(hk, // subkey handle + L"EventMessageFile", // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE)cmd, // pointer to value data + len*sizeof(WCHAR))) // data size { ::syslog(LOG_ERR, "Failed to set the event message file: %s", GetErrorMessage(GetLastError()).c_str()); @@ -1315,12 +1353,12 @@ BOOL AddEventSource // Set the category message file and number of categories. - if (RegSetValueEx(hk, // subkey handle - "CategoryMessageFile", // value name - 0, // must be zero - REG_EXPAND_SZ, // value type - (LPBYTE) exepath.c_str(), // pointer to value data - (DWORD) (exepath.size()))) // data size + if (RegSetValueExW(hk, // subkey handle + L"CategoryMessageFile", // value name + 0, // must be zero + REG_EXPAND_SZ, // value type + (LPBYTE)cmd, // pointer to value data + len*sizeof(WCHAR))) // data size { ::syslog(LOG_ERR, "Failed to set the category message file: " "%s", GetErrorMessage(GetLastError()).c_str()); diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 1f078c14..8ab74130 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -377,6 +377,10 @@ bool ConvertFromUtf8 (const std::string& rSource, std::string& rDest, bool ConvertUtf8ToConsole(const char* pString, std::string& rDest); bool ConvertConsoleToUtf8(const char* pString, std::string& rDest); +// Utility function which returns a default config file name, +// based on the path of the current executable. +std::string GetDefaultConfigFilePath(const std::string& rName); + // GetErrorMessage() returns a system error message, like strerror() // but for Windows error codes. std::string GetErrorMessage(DWORD errorCode); -- cgit v1.2.3 From 6ecbbd73e47eb14d144925421294702eff8370ff Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Sep 2007 21:55:53 +0000 Subject: No need to print syslog() messages any more, now that we have a logging framework. (merges [1814]) --- lib/win32/emu.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 1a6b0e79..071dc788 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -509,8 +509,16 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) tmpStr = ""; return tmpStr; } - - if (filename.length() >= 1 && filename[0] == '\\') + + if (filename.length() > 2 && filename[0] == '\\' && + filename[1] == '\\') + { + tmpStr += "UNC\\"; + filename.replace(0, 2, ""); + // \\?\UNC\\ + // see http://msdn2.microsoft.com/en-us/library/aa365247.aspx + } + else if (filename.length() >= 1 && filename[0] == '\\') { // root directory of current drive. tmpStr = wd; @@ -1520,8 +1528,8 @@ void syslog(int loglevel, const char *frmt, ...) sHaveWarnedEventLogFull = false; } - printf("%s\r\n", buffer); - fflush(stdout); + // printf("%s\r\n", buffer); + // fflush(stdout); } int emu_chdir(const char* pDirName) -- cgit v1.2.3 From 4b5b0815af4f478c18ee6681fe013f5213c727de Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 17 Oct 2007 12:51:40 +0000 Subject: Fix compilation on MinGW. Not yet actually used on MinGW due to the file extension, but it might be soon, if the default implementation doesn't do what I want. (merges [1848]) --- lib/win32/getopt_long.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/getopt_long.cxx b/lib/win32/getopt_long.cxx index c6800426..a24930aa 100755 --- a/lib/win32/getopt_long.cxx +++ b/lib/win32/getopt_long.cxx @@ -57,14 +57,17 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "Box.h" +// #include "Box.h" #include #include #include +#include #include -#ifdef _MSC_VER +#include "getopt.h" + +#if defined _MSC_VER || defined __MINGW32__ #define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ #endif -- cgit v1.2.3 From 859c7b360481f12628cc085c1ecbd9bfa77aff7d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 5 Apr 2008 00:50:13 +0000 Subject: Close process token in EnableBackupRights(), thanks Charles! Improve error messages in EnableBackupRights() when failing to enable the backup privilege. Use file size returned by GetFileInformationByHandle in emu_fstat instead of calling GetFileSizeEx(), thanks Charles! Merges [1939]. --- lib/win32/emu.cpp | 60 +++++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 071dc788..961dff70 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -164,30 +164,31 @@ void FiniTimer(void) //globals struct passwd gTempPasswd; -bool EnableBackupRights( void ) +bool EnableBackupRights() { HANDLE hToken; TOKEN_PRIVILEGES token_priv; //open current process to adjust privileges - if( !OpenProcessToken( GetCurrentProcess( ), - TOKEN_ADJUST_PRIVILEGES, - &hToken )) + if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, + &hToken)) { - printf( "Cannot open process token: error %d\n", - (int)GetLastError() ); + ::syslog(LOG_ERR, "Failed to open process token: %s", + GetErrorMessage(GetLastError()).c_str()); return false; } //let's build the token privilege struct - //first, look up the LUID for the backup privilege - if( !LookupPrivilegeValue( NULL, //this system + if (!LookupPrivilegeValue( + NULL, //this system SE_BACKUP_NAME, //the name of the privilege - &( token_priv.Privileges[0].Luid )) ) //result + &( token_priv.Privileges[0].Luid ))) //result { - printf( "Cannot lookup backup privilege: error %d\n", - (int)GetLastError( ) ); + ::syslog(LOG_ERR, "Failed to lookup backup privilege: %s", + GetErrorMessage(GetLastError()).c_str()); + CloseHandle(hToken); return false; } @@ -198,24 +199,25 @@ bool EnableBackupRights( void ) // 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 + 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 + 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: error %d\n", - (int)GetLastError( ) ); + ::syslog(LOG_ERR, "Failed to enable backup privilege: %s", + GetErrorMessage(GetLastError()).c_str()); + CloseHandle(hToken); return false; } - else - { - return true; - } + + CloseHandle(hToken); + return true; } // forward declaration @@ -702,7 +704,7 @@ int emu_fstat(HANDLE hdir, struct stat * st) // This is how we get our INODE (equivalent) information ULARGE_INTEGER conv; conv.HighPart = fi.nFileIndexHigh; - conv.LowPart = fi.nFileIndexLow; + conv.LowPart = fi.nFileIndexLow; st->st_ino = (_ino_t)conv.QuadPart; // get the time information @@ -716,20 +718,8 @@ int emu_fstat(HANDLE hdir, struct stat * st) } else { - // size of the file - LARGE_INTEGER st_size; - memset(&st_size, 0, sizeof(st_size)); - - if (!GetFileSizeEx(hdir, &st_size)) - { - ::syslog(LOG_WARNING, "Failed to get file size: " - "%s", GetErrorMessage(GetLastError()).c_str()); - errno = EACCES; - return -1; - } - - conv.HighPart = st_size.HighPart; - conv.LowPart = st_size.LowPart; + conv.HighPart = fi.nFileSizeHigh; + conv.LowPart = fi.nFileSizeLow; st->st_size = (_off_t)conv.QuadPart; } @@ -1078,7 +1068,7 @@ DIR *opendir(const char *name) } pDir->name = ConvertUtf8ToWideString(dirName.c_str()); - // We are responsible for freeing dir->name + // We are responsible for freeing dir->name with delete[] if (pDir->name == NULL) { -- cgit v1.2.3 From b159c3ce4cbc940c844753c9eee8d4b7fb76652b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 5 Apr 2008 00:51:48 +0000 Subject: Convert UTF-8 to Unicode for logging in Windows Event Log, so that international paths and filenames are displayed correctly. (merges [1942]) --- lib/win32/emu.cpp | 87 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 27 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 961dff70..05b83812 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -269,7 +269,8 @@ std::string GetDefaultConfigFilePath(const std::string& rName) // Created: 4th February 2006 // // -------------------------------------------------------------------------- -WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) +WCHAR* ConvertToWideString(const char* pString, unsigned int codepage, + bool logErrors) { int len = MultiByteToWideChar ( @@ -284,9 +285,12 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) if (len == 0) { - ::syslog(LOG_WARNING, - "Failed to convert string to wide string: " - "error %d", GetLastError()); + if (logErrors) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "%s", GetErrorMessage(GetLastError()).c_str()); + } errno = EINVAL; return NULL; } @@ -295,9 +299,12 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) if (buffer == NULL) { - ::syslog(LOG_WARNING, - "Failed to convert string to wide string: " - "out of memory"); + if (logErrors) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "out of memory"); + } errno = ENOMEM; return NULL; } @@ -314,9 +321,12 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) if (len == 0) { - ::syslog(LOG_WARNING, - "Failed to convert string to wide string: " - "error %i", GetLastError()); + if (logErrors) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "%s", GetErrorMessage(GetLastError()).c_str()); + } errno = EACCES; delete [] buffer; return NULL; @@ -338,7 +348,7 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) // -------------------------------------------------------------------------- WCHAR* ConvertUtf8ToWideString(const char* pString) { - return ConvertToWideString(pString, CP_UTF8); + return ConvertToWideString(pString, CP_UTF8, true); } // -------------------------------------------------------------------------- @@ -427,7 +437,8 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) bool ConvertEncoding(const std::string& rSource, int sourceCodePage, std::string& rDest, int destCodePage) { - WCHAR* pWide = ConvertToWideString(rSource.c_str(), sourceCodePage); + WCHAR* pWide = ConvertToWideString(rSource.c_str(), sourceCodePage, + true); if (pWide == NULL) { ::syslog(LOG_ERR, "Failed to convert string '%s' from " @@ -1474,8 +1485,6 @@ void syslog(int loglevel, const char *frmt, ...) va_end(args); - LPCSTR strings[] = { buffer, NULL }; - if (gSyslogH == 0) { printf("%s\r\n", buffer); @@ -1483,17 +1492,44 @@ void syslog(int loglevel, const char *frmt, ...) return; } - if (!ReportEvent(gSyslogH, // event log handle - errinfo, // event type - 0, // category zero - MSG_ERR, // event identifier - - // we will call them all the same - NULL, // no user security identifier - 1, // one substitution string - 0, // no data - strings, // pointer to string array - NULL)) // pointer to data + WCHAR* pWide = ConvertToWideString(buffer, CP_UTF8, false); + // must delete[] pWide + + DWORD result; + if (pWide == NULL) + { + std::string buffer2 = buffer; + buffer2 += " (failed to convert string encoding)"; + LPCSTR strings[] = { buffer2.c_str(), NULL }; + + result = ReportEventA(gSyslogH, // event log handle + errinfo, // event type + 0, // category zero + MSG_ERR, // event identifier - + // we will call them all the same + NULL, // no user security identifier + 1, // one substitution string + 0, // no data + strings, // pointer to string array + NULL); // pointer to data + } + else + { + LPCWSTR strings[] = { pWide, NULL }; + result = ReportEventW(gSyslogH, // event log handle + errinfo, // event type + 0, // category zero + MSG_ERR, // event identifier - + // we will call them all the same + NULL, // no user security identifier + 1, // one substitution string + 0, // no data + strings, // pointer to string array + NULL); // pointer to data + } + + if (result == 0) { DWORD err = GetLastError(); if (err == ERROR_LOG_FILE_FULL) @@ -1517,9 +1553,6 @@ void syslog(int loglevel, const char *frmt, ...) { sHaveWarnedEventLogFull = false; } - - // printf("%s\r\n", buffer); - // fflush(stdout); } int emu_chdir(const char* pDirName) -- cgit v1.2.3 From 4fe597e2bce808ebd87063407bba662b0efa8464 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 5 Apr 2008 00:53:52 +0000 Subject: Fix memory leak in [2133] (merges [1944]) --- lib/win32/emu.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 05b83812..48db4ec7 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1527,6 +1527,7 @@ void syslog(int loglevel, const char *frmt, ...) 0, // no data strings, // pointer to string array NULL); // pointer to data + delete [] pWide; } if (result == 0) -- cgit v1.2.3 From 430bbb36f6e1040333a22b79938938754dd49aac Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Aug 2008 06:54:40 +0000 Subject: Add getpid() emulation. --- lib/win32/emu.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 8ab74130..a19a86ff 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -205,6 +205,7 @@ struct itimerval //again need to verify these #define S_IFLNK 1 +#define S_IFSOCK 0 #define S_ISLNK(x) ( false ) @@ -292,6 +293,11 @@ inline int ioctl(SOCKET sock, int flag, int * something) return 0; } +extern "C" inline int getpid() +{ + return (int)GetCurrentProcessId(); +} + inline int waitpid(pid_t pid, int *status, int) { return 0; -- cgit v1.2.3 From 33a3d225c7780a5f5d38a5ac5fd068f445e5a434 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 9 Aug 2008 07:07:16 +0000 Subject: Map ERROR_SHARING_VIOLATION to EBUSY in openfile(). --- lib/win32/emu.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 48db4ec7..5a61fc3f 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -667,9 +667,20 @@ HANDLE openfile(const char *pFileName, int flags, int mode) if (hdir == INVALID_HANDLE_VALUE) { + switch(GetLastError()) + { + case ERROR_SHARING_VIOLATION: + errno = EBUSY; + break; + + default: + errno = EINVAL; + } + ::syslog(LOG_WARNING, "Failed to open file '%s': " "%s", pFileName, GetErrorMessage(GetLastError()).c_str()); + return INVALID_HANDLE_VALUE; } -- cgit v1.2.3 From e5717c428009d7702ce5d8bf65217f759f114294 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 14 Sep 2008 00:26:13 +0000 Subject: Prefix event log application name with Box Backup, and remove it from all calls to SetProgramName, for better consistency on Unix. Make bbstoreaccounts and bbackupctl set their program names for logging. Don't override supplied tag with service name when BackupDaemon is run as a service. --- lib/win32/emu.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 5a61fc3f..aeacf344 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1417,9 +1417,8 @@ void openlog(const char * daemonName, int, int) { } - char* name = strdup(daemonName); - BOOL success = AddEventSource(name, 0); - free(name); + std::string name = "Box Backup (" + daemonName + ")"; + BOOL success = AddEventSource(name.c_str(), 0); if (!success) { -- cgit v1.2.3 From 842217a354cdd9c0b27b11f61725d0eca91eeba6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 14 Sep 2008 00:29:32 +0000 Subject: Compile fix for [2285]. --- lib/win32/emu.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index aeacf344..bd7701ae 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1417,8 +1417,13 @@ void openlog(const char * daemonName, int, int) { } - std::string name = "Box Backup (" + daemonName + ")"; - BOOL success = AddEventSource(name.c_str(), 0); + std::string nameStr = "Box Backup ("; + nameStr += daemonName; + nameStr += ")"; + + char* name = strdup(nameStr.c_str()); + BOOL success = AddEventSource(name, 0); + free(name); if (!success) { -- cgit v1.2.3 From dd920e4884ecc89993e68465f6b0503a07cd7103 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 14 Sep 2008 00:40:23 +0000 Subject: FIx [2285] properly for Windows. --- lib/win32/emu.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index bd7701ae..ff5bd12f 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1408,19 +1408,19 @@ static bool sHaveWarnedEventLogFull = false; void openlog(const char * daemonName, int, int) { + std::string nameStr = "Box Backup ("; + nameStr += daemonName; + nameStr += ")"; + // register a default event source, so that we can // log errors with the process of adding or registering our own. gSyslogH = RegisterEventSource( NULL, // uses local computer - daemonName); // source name + nameStr.c_str()); // source name if (gSyslogH == NULL) { } - std::string nameStr = "Box Backup ("; - nameStr += daemonName; - nameStr += ")"; - char* name = strdup(nameStr.c_str()); BOOL success = AddEventSource(name, 0); free(name); @@ -1431,7 +1431,7 @@ void openlog(const char * daemonName, int, int) return; } - HANDLE newSyslogH = RegisterEventSource(NULL, daemonName); + HANDLE newSyslogH = RegisterEventSource(NULL, nameStr.c_str()); if (newSyslogH == NULL) { ::syslog(LOG_ERR, "Failed to register our own event source: " -- cgit v1.2.3 From 03d015abb233e85f784b7ef30c9c3073f3930f8b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 30 Nov 2008 21:53:14 +0000 Subject: Cygwin/MinGW getopt no longer seems to have optreset, so now would be the time to start using that implementation we stole from BSD. --- lib/win32/getopt_long.cpp | 550 ++++++++++++++++++++++++++++++++++++++++++++++ lib/win32/getopt_long.cxx | 550 ---------------------------------------------- 2 files changed, 550 insertions(+), 550 deletions(-) create mode 100755 lib/win32/getopt_long.cpp delete mode 100755 lib/win32/getopt_long.cxx (limited to 'lib/win32') diff --git a/lib/win32/getopt_long.cpp b/lib/win32/getopt_long.cpp new file mode 100755 index 00000000..a24930aa --- /dev/null +++ b/lib/win32/getopt_long.cpp @@ -0,0 +1,550 @@ +/* $OpenBSD: getopt_long.c,v 1.20 2005/10/25 15:49:37 jmc Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ +// Adapted for Box Backup by Chris Wilson + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +// #include "Box.h" + +#include +#include +#include +#include +#include + +#include "getopt.h" + +#if defined _MSC_VER || defined __MINGW32__ +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ +#endif + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#endif + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static void warnx(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + const char * oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; + if (*options == '+' || *options == '-') + options++; + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + optchar == (int)'-' && *place != '\0' || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + /* XXX: disable test for :: if PC? (GNU doesn't) */ + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } else if (!(flags & FLAG_PERMUTE)) { + /* + * If permutation is disabled, we can accept an + * optional arg separated by whitespace so long + * as it does not start with a dash (-). + */ + if (optind + 1 < nargc && *nargv[optind + 1] != '-') + optarg = nargv[++optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* REPLACE_GETOPT */ + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} + diff --git a/lib/win32/getopt_long.cxx b/lib/win32/getopt_long.cxx deleted file mode 100755 index a24930aa..00000000 --- a/lib/win32/getopt_long.cxx +++ /dev/null @@ -1,550 +0,0 @@ -/* $OpenBSD: getopt_long.c,v 1.20 2005/10/25 15:49:37 jmc Exp $ */ -/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ -// Adapted for Box Backup by Chris Wilson - -/* - * Copyright (c) 2002 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ -/*- - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Dieter Baron and Thomas Klausner. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -// #include "Box.h" - -#include -#include -#include -#include -#include - -#include "getopt.h" - -#if defined _MSC_VER || defined __MINGW32__ -#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ -#endif - -#ifdef REPLACE_GETOPT -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ -#endif - -#define PRINT_ERROR ((opterr) && (*options != ':')) - -#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ -#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ -#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ - -/* return values */ -#define BADCH (int)'?' -#define BADARG ((*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 - -#define EMSG "" - -static void warnx(const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); -} - -static int getopt_internal(int, char * const *, const char *, - const struct option *, int *, int); -static int parse_long_options(char * const *, const char *, - const struct option *, int *, int); -static int gcd(int, int); -static void permute_args(int, int, int, char * const *); - -static char *place = EMSG; /* option letter processing */ - -/* XXX: set optreset to 1 rather than these two */ -static int nonopt_start = -1; /* first non option argument (for permute) */ -static int nonopt_end = -1; /* first option after non options (for permute) */ - -/* Error messages */ -static const char recargchar[] = "option requires an argument -- %c"; -static const char recargstring[] = "option requires an argument -- %s"; -static const char ambig[] = "ambiguous option -- %.*s"; -static const char noarg[] = "option doesn't take an argument -- %.*s"; -static const char illoptchar[] = "unknown option -- %c"; -static const char illoptstring[] = "unknown option -- %s"; - -/* - * Compute the greatest common divisor of a and b. - */ -static int -gcd(int a, int b) -{ - int c; - - c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } - - return (b); -} - -/* - * Exchange the block from nonopt_start to nonopt_end with the block - * from nonopt_end to opt_end (keeping the same order of arguments - * in each block). - */ -static void -permute_args(int panonopt_start, int panonopt_end, int opt_end, - char * const *nargv) -{ - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; - - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; - - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - /* LINTED const cast */ - ((char **) nargv)[pos] = nargv[cstart]; - /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; - } - } -} - -/* - * parse_long_options -- - * Parse long options in argc/argv argument vector. - * Returns -1 if short_too is set and the option does not match long_options. - */ -static int -parse_long_options(char * const *nargv, const char *options, - const struct option *long_options, int *idx, int short_too) -{ - char *current_argv, *has_equal; - size_t current_argv_len; - int i, match; - - current_argv = place; - match = -1; - - optind++; - - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; - - if (strlen(long_options[i].name) == current_argv_len) { - /* exact match */ - match = i; - break; - } - /* - * If this is a known short option, don't allow - * a partial match of a single character. - */ - if (short_too && current_argv_len == 1) - continue; - - if (match == -1) /* partial match */ - match = i; - else { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); - optopt = 0; - return (BADCH); - } - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return (BADARG); - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' indicates no error - * should be generated. - */ - if (PRINT_ERROR) - warnx(recargstring, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return (BADARG); - } - } else { /* unknown option */ - if (short_too) { - --optind; - return (-1); - } - if (PRINT_ERROR) - warnx(illoptstring, current_argv); - optopt = 0; - return (BADCH); - } - if (idx) - *idx = match; - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - return (0); - } else - return (long_options[match].val); -} - -/* - * getopt_internal -- - * Parse argc/argv argument vector. Called by user level routines. - */ -static int -getopt_internal(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx, int flags) -{ - const char * oli; /* option letter list index */ - int optchar, short_too; - static int posixly_correct = -1; - - if (options == NULL) - return (-1); - - /* - * Disable GNU extensions if POSIXLY_CORRECT is set or options - * string begins with a '+'. - */ - if (posixly_correct == -1) - posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); - if (posixly_correct || *options == '+') - flags &= ~FLAG_PERMUTE; - else if (*options == '-') - flags |= FLAG_ALLARGS; - if (*options == '+' || *options == '-') - options++; - - /* - * XXX Some GNU programs (like cvs) set optind to 0 instead of - * XXX using optreset. Work around this braindamage. - */ - if (optind == 0) - optind = optreset = 1; - - optarg = NULL; - if (optreset) - nonopt_start = nonopt_end = -1; -start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - if (*(place = nargv[optind]) != '-' || - (place[1] == '\0' && strchr(options, '-') == NULL)) { - place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return (INORDER); - } - if (!(flags & FLAG_PERMUTE)) { - /* - * If no permutation wanted, stop parsing - * at first non-option. - */ - return (-1); - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; - - /* - * If we have "-" do nothing, if "--" we are done. - */ - if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { - optind++; - place = EMSG; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - } - - /* - * Check long options if: - * 1) we were passed some - * 2) the arg is not just "-" - * 3) either the arg starts with -- we are getopt_long_only() - */ - if (long_options != NULL && place != nargv[optind] && - (*place == '-' || (flags & FLAG_LONGONLY))) { - short_too = 0; - if (*place == '-') - place++; /* --foo long option */ - else if (*place != ':' && strchr(options, *place) != NULL) - short_too = 1; /* could be short option too */ - - optchar = parse_long_options(nargv, options, long_options, - idx, short_too); - if (optchar != -1) { - place = EMSG; - return (optchar); - } - } - - if ((optchar = (int)*place++) == (int)':' || - optchar == (int)'-' && *place != '\0' || - (oli = strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); - if (!*place) - ++optind; - if (PRINT_ERROR) - warnx(illoptchar, optchar); - optopt = optchar; - return (BADCH); - } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { - /* -W long-option */ - if (*place) /* no space */ - /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else /* white space */ - place = nargv[optind]; - optchar = parse_long_options(nargv, options, long_options, - idx, 0); - place = EMSG; - return (optchar); - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; - } else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = place; - /* XXX: disable test for :: if PC? (GNU doesn't) */ - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else - optarg = nargv[optind]; - } else if (!(flags & FLAG_PERMUTE)) { - /* - * If permutation is disabled, we can accept an - * optional arg separated by whitespace so long - * as it does not start with a dash (-). - */ - if (optind + 1 < nargc && *nargv[optind + 1] != '-') - optarg = nargv[++optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return (optchar); -} - -#ifdef REPLACE_GETOPT -/* - * getopt -- - * Parse argc/argv argument vector. - * - * [eventually this will replace the BSD getopt] - */ -int -getopt(int nargc, char * const *nargv, const char *options) -{ - - /* - * We don't pass FLAG_PERMUTE to getopt_internal() since - * the BSD getopt(3) (unlike GNU) has never done this. - * - * Furthermore, since many privileged programs call getopt() - * before dropping privileges it makes sense to keep things - * as simple (and bug-free) as possible. - */ - return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); -} -#endif /* REPLACE_GETOPT */ - -/* - * getopt_long -- - * Parse argc/argv argument vector. - */ -int -getopt_long(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) -{ - - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE)); -} - -/* - * getopt_long_only -- - * Parse argc/argv argument vector. - */ -int -getopt_long_only(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) -{ - - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE|FLAG_LONGONLY)); -} - -- cgit v1.2.3 From a2d7aadb6a42dc45cdf3d5547025dd55c0bd9b17 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 30 Nov 2008 21:54:55 +0000 Subject: openfile() stores its Windows error code (from GetLastError() or synthetic) in winerrno, to enable better error handling outside. --- lib/win32/emu.cpp | 16 +++++++++++++--- lib/win32/emu.h | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index ff5bd12f..e31d8a3c 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -31,6 +31,8 @@ static bool gTimerInitialised = false; static bool gFinishTimer; static CRITICAL_SECTION gLock; +DWORD winerrno; + typedef struct { int countDown; @@ -285,11 +287,12 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage, if (len == 0) { + winerrno = GetLastError(); if (logErrors) { ::syslog(LOG_WARNING, "Failed to convert string to wide string: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); } errno = EINVAL; return NULL; @@ -305,6 +308,7 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage, "Failed to convert string to wide string: " "out of memory"); } + winerrno = ERROR_OUTOFMEMORY; errno = ENOMEM; return NULL; } @@ -321,11 +325,12 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage, if (len == 0) { + winerrno = GetLastError(); if (logErrors) { ::syslog(LOG_WARNING, "Failed to convert string to wide string: " - "%s", GetErrorMessage(GetLastError()).c_str()); + "%s", GetErrorMessage(winerrno).c_str()); } errno = EACCES; delete [] buffer; @@ -519,6 +524,7 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) "Failed to open '%s': path too long", pFileName); errno = ENAMETOOLONG; + winerrno = ERROR_INVALID_NAME; tmpStr = ""; return tmpStr; } @@ -594,6 +600,8 @@ std::string GetErrorMessage(DWORD errorCode) // -------------------------------------------------------------------------- HANDLE openfile(const char *pFileName, int flags, int mode) { + winerrno = ERROR_INVALID_FUNCTION; + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); @@ -667,7 +675,8 @@ HANDLE openfile(const char *pFileName, int flags, int mode) if (hdir == INVALID_HANDLE_VALUE) { - switch(GetLastError()) + winerrno = GetLastError(); + switch(winerrno) { case ERROR_SHARING_VIOLATION: errno = EBUSY; @@ -684,6 +693,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode) return INVALID_HANDLE_VALUE; } + winerrno = NO_ERROR; return hdir; } diff --git a/lib/win32/emu.h b/lib/win32/emu.h index a19a86ff..e8d87f19 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -245,6 +245,7 @@ int closedir(DIR *dp); // local constant to open file exclusively without shared access #define O_LOCK 0x10000 +extern DWORD winerrno; /* used to report errors from openfile() */ HANDLE openfile(const char *filename, int flags, int mode); #define LOG_DEBUG LOG_INFO -- cgit v1.2.3 From 6d851fd3042ef3a5e5a3a4d78b9dabbcae472684 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 30 Nov 2008 22:24:28 +0000 Subject: Fix support for O_APPEND on files opened with openfile() on Windows. --- lib/win32/emu.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index e31d8a3c..84246c67 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -693,6 +693,18 @@ HANDLE openfile(const char *pFileName, int flags, int mode) return INVALID_HANDLE_VALUE; } + if (flags & O_APPEND) + { + if (SetFilePointer(hdir, 0, NULL, FILE_END) == + INVALID_SET_FILE_POINTER) + { + winerrno = GetLastError(); + errno = EINVAL; + CloseHandle(hdir); + return INVALID_HANDLE_VALUE; + } + } + winerrno = NO_ERROR; return hdir; } -- cgit v1.2.3 From 53ebf1afe9f796d56af20040bde0893e46ad1b73 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 1 Dec 2008 01:31:51 +0000 Subject: Fix the use of an unreasonably short type as the temporary storage for inode numbers on Windows, resulting in all inode numbers being coerced into 2^16 space and many duplicates on systems with large numbers of files being backed up, possibly resulting in store corruption due to unwanted file rename operations. --- lib/win32/emu.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index e8d87f19..1d3fd150 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -25,6 +25,9 @@ #ifdef __MINGW32__ typedef uint32_t u_int32_t; + typedef uint64_t _ino_t; + typedef _ino_t ino_t; + #define _INO_T_ #else typedef unsigned int mode_t; typedef unsigned int pid_t; -- cgit v1.2.3 From 6f04d8ae0483fad9b93524172db76b51424a228a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 8 Dec 2008 22:11:21 +0000 Subject: Only use replacement BSD getopt on Windows. --- lib/win32/getopt_long.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/getopt_long.cpp b/lib/win32/getopt_long.cpp index a24930aa..5d910e1b 100755 --- a/lib/win32/getopt_long.cpp +++ b/lib/win32/getopt_long.cpp @@ -69,7 +69,6 @@ #if defined _MSC_VER || defined __MINGW32__ #define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ -#endif #ifdef REPLACE_GETOPT int opterr = 1; /* if error message should be printed */ @@ -548,3 +547,4 @@ getopt_long_only(int nargc, char * const *nargv, const char *options, FLAG_PERMUTE|FLAG_LONGONLY)); } +#endif // defined _MSC_VER || defined __MINGW32__ -- cgit v1.2.3 From c13f1bfdc3673ba1d1b79284d834e9248c20e8ef Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 30 Dec 2008 18:30:12 +0000 Subject: Change ConvertTo/FromUtf8 to take a std::string instead of a const char *, for convenience and C++ style. --- lib/win32/emu.cpp | 18 ++++++++++-------- lib/win32/emu.h | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 84246c67..189bf587 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -468,24 +468,26 @@ bool ConvertEncoding(const std::string& rSource, int sourceCodePage, return true; } -bool ConvertToUtf8(const char* pString, std::string& rDest, int sourceCodePage) +bool ConvertToUtf8(const std::string& rSource, std::string& rDest, + int sourceCodePage) { - return ConvertEncoding(pString, sourceCodePage, rDest, CP_UTF8); + return ConvertEncoding(rSource, sourceCodePage, rDest, CP_UTF8); } -bool ConvertFromUtf8(const char* pString, std::string& rDest, int destCodePage) +bool ConvertFromUtf8(const std::string& rSource, std::string& rDest, + int destCodePage) { - return ConvertEncoding(pString, CP_UTF8, rDest, destCodePage); + return ConvertEncoding(rSource, CP_UTF8, rDest, destCodePage); } -bool ConvertConsoleToUtf8(const char* pString, std::string& rDest) +bool ConvertConsoleToUtf8(const std::string& rSource, std::string& rDest) { - return ConvertEncoding(pString, GetConsoleCP(), rDest, CP_UTF8); + return ConvertToUtf8(rSource, rDest, GetConsoleCP()); } -bool ConvertUtf8ToConsole(const char* pString, std::string& rDest) +bool ConvertUtf8ToConsole(const std::string& rSource, std::string& rDest) { - return ConvertEncoding(pString, CP_UTF8, rDest, GetConsoleOutputCP()); + return ConvertFromUtf8(rSource, rDest, GetConsoleOutputCP()); } // -------------------------------------------------------------------------- diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 1d3fd150..67921264 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -384,8 +384,8 @@ bool ConvertToUtf8 (const std::string& rSource, std::string& rDest, int sourceCodePage); bool ConvertFromUtf8 (const std::string& rSource, std::string& rDest, int destCodePage); -bool ConvertUtf8ToConsole(const char* pString, std::string& rDest); -bool ConvertConsoleToUtf8(const char* pString, std::string& rDest); +bool ConvertUtf8ToConsole(const std::string& rSource, std::string& rDest); +bool ConvertConsoleToUtf8(const std::string& rSource, std::string& rDest); // Utility function which returns a default config file name, // based on the path of the current executable. -- cgit v1.2.3 From 4d33206efeeacf0a20d6daabb0f5bcfa6da78a39 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 21 Mar 2009 18:48:19 +0000 Subject: Fix tests (hopefully) on Win32 for struct stat ino_t change from 16 to 64 bits. --- lib/win32/emu.cpp | 156 ++++-------------------------------------------------- lib/win32/emu.h | 66 ++++++++++------------- 2 files changed, 39 insertions(+), 183 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 189bf587..ad8c3041 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -21,149 +21,9 @@ #include // message resource definitions for syslog() - #include "messages.h" -// our implementation for a timer, based on a -// simple thread which sleeps for a period of time - -static bool gTimerInitialised = false; -static bool gFinishTimer; -static CRITICAL_SECTION gLock; - DWORD winerrno; - -typedef struct -{ - int countDown; - int interval; -} -Timer_t; - -std::list gTimerList; -static void (__cdecl *gTimerFunc) (int) = NULL; - -int setitimer(int type, struct itimerval *timeout, void *arg) -{ - assert(gTimerInitialised); - - if (ITIMER_REAL != type) - { - errno = ENOSYS; - return -1; - } - - 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 - { - Timer_t 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++) - { - Timer_t& 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++) - { - Timer_t& rTimer(*it); - - if (rTimer.countDown == -1) - { - gTimerList.erase(it); - - // the iterator is now invalid, so restart search - it = gTimerList.begin(); - - // if the list is now empty, don't try to increment - // the iterator again - if (it == gTimerList.end()) break; - } - } - - 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) -{ - assert(!gTimerInitialised); - - InitializeCriticalSection(&gLock); - - // create our thread - HANDLE ourThread = (HANDLE)_beginthreadex(NULL, 0, RunTimer, 0, - CREATE_SUSPENDED, NULL); - SetThreadPriority(ourThread, THREAD_PRIORITY_LOWEST); - ResumeThread(ourThread); - - gTimerInitialised = true; -} - -void FiniTimer(void) -{ - assert(gTimerInitialised); - gFinishTimer = true; - EnterCriticalSection(&gLock); - DeleteCriticalSection(&gLock); - gTimerInitialised = false; -} - -//Our constants we need to keep track of -//globals struct passwd gTempPasswd; bool EnableBackupRights() @@ -715,11 +575,13 @@ HANDLE openfile(const char *pFileName, int flags, int mode) // // Function // Name: emu_fstat -// Purpose: replacement for fstat supply a windows handle +// Purpose: replacement for fstat. Supply a windows handle. +// Returns a struct emu_stat to have room for 64-bit +// file identifier in st_ino (mingw allows only 16!) // Created: 25th October 2004 // // -------------------------------------------------------------------------- -int emu_fstat(HANDLE hdir, struct stat * st) +int emu_fstat(HANDLE hdir, struct emu_stat * st) { if (hdir == INVALID_HANDLE_VALUE) { @@ -751,7 +613,7 @@ int emu_fstat(HANDLE hdir, struct stat * st) ULARGE_INTEGER conv; conv.HighPart = fi.nFileIndexHigh; conv.LowPart = fi.nFileIndexLow; - st->st_ino = (_ino_t)conv.QuadPart; + st->st_ino = conv.QuadPart; // get the time information st->st_ctime = ConvertFileTimeToTime_t(&fi.ftCreationTime); @@ -898,12 +760,14 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) // // Function // Name: emu_stat -// Purpose: replacement for the lstat and stat functions, -// works with unicode filenames supplied in utf8 format +// Purpose: replacement for the lstat and stat functions. +// Works with unicode filenames supplied in utf8. +// Returns a struct emu_stat to have room for 64-bit +// file identifier in st_ino (mingw allows only 16!) // Created: 25th October 2004 // // -------------------------------------------------------------------------- -int emu_stat(const char * pName, struct stat * st) +int emu_stat(const char * pName, struct emu_stat * st) { HANDLE handle = OpenFileByNameUtf8(pName, FILE_READ_ATTRIBUTES | FILE_READ_EA); diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 67921264..b29c901c 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -1,5 +1,17 @@ // emulates unix syscalls to win32 functions +#ifdef WIN32 + #define EMU_STRUCT_STAT struct emu_stat + #define EMU_STAT emu_stat + #define EMU_FSTAT emu_fstat + #define EMU_LSTAT emu_stat +#else + #define EMU_STRUCT_STAT struct stat + #define EMU_STAT ::stat + #define EMU_FSTAT ::fstat + #define EMU_LSTAT ::lstat +#endif + #if ! defined EMU_INCLUDE && defined WIN32 #define EMU_INCLUDE @@ -25,17 +37,9 @@ #ifdef __MINGW32__ typedef uint32_t u_int32_t; - typedef uint64_t _ino_t; - typedef _ino_t ino_t; - #define _INO_T_ #else typedef unsigned int mode_t; typedef unsigned int pid_t; - - // must define _INO_T_DEFINED before including - // to replace it with our own. - typedef u_int64_t _ino_t; - #define _INO_T_DEFINED #endif // set up to include the necessary parts of Windows headers @@ -81,11 +85,6 @@ #define fileno(struct_file) _fileno(struct_file) #endif -int SetTimerHandler(void (__cdecl *func ) (int)); -int setitimer(int type, struct itimerval *timeout, void *arg); -void InitTimer(void); -void FiniTimer(void); - struct passwd { char *pw_name; char *pw_passwd; @@ -187,13 +186,6 @@ inline int geteuid(void) #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 @@ -313,27 +305,19 @@ struct statfs TCHAR f_mntonname[MAX_PATH]; }; -#if 0 -// 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; +struct emu_stat { + int st_dev; + uint64_t st_ino; DWORD st_mode; short st_nlink; short st_uid; short st_gid; //_dev_t st_rdev; - u_int64_t st_size; + uint64_t st_size; time_t st_atime; time_t st_mtime; time_t st_ctime; }; -#endif // 0 // need this for conversions time_t ConvertFileTimeToTime_t(FILETIME *fileTime); @@ -342,8 +326,8 @@ bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo); int emu_chdir (const char* pDirName); int emu_mkdir (const char* pPathName); int emu_unlink (const char* pFileName); -int emu_fstat (HANDLE file, struct stat* st); -int emu_stat (const char* pName, struct stat* st); +int emu_fstat (HANDLE file, struct emu_stat* st); +int emu_stat (const char* pName, struct emu_stat* st); int emu_utimes (const char* pName, const struct timeval[]); int emu_chmod (const char* pName, mode_t mode); char* emu_getcwd (char* pBuffer, int BufSize); @@ -352,14 +336,22 @@ int emu_rename (const char* pOldName, const char* pNewName); #define chdir(directory) emu_chdir (directory) #define mkdir(path, mode) emu_mkdir (path) #define unlink(file) emu_unlink (file) -#define stat(filename, struct) emu_stat (filename, struct) -#define lstat(filename, struct) emu_stat (filename, struct) -#define fstat(handle, struct) emu_fstat (handle, struct) #define utimes(buffer, times) emu_utimes (buffer, times) #define chmod(file, mode) emu_chmod (file, mode) #define getcwd(buffer, size) emu_getcwd (buffer, size) #define rename(oldname, newname) emu_rename (oldname, newname) +// Not safe to replace stat/fstat/lstat on mingw at least, as struct stat +// has a 16-bit st_ino and we need a 64-bit one. +// +// #define stat(filename, struct) emu_stat (filename, struct) +// #define lstat(filename, struct) emu_stat (filename, struct) +// #define fstat(handle, struct) emu_fstat (handle, struct) +// +// But lstat doesn't exist on Windows, so we have to provide something: + +#define lstat(filename, struct) stat(filename, struct) + int statfs(const char * name, struct statfs * s); int poll(struct pollfd *ufds, unsigned long nfds, int timeout); -- cgit v1.2.3 From 280180a59acf2b59482033a70518e18de34f859a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 2 Apr 2009 00:06:07 +0000 Subject: Fix missing LOG_* defines on Windows. --- lib/win32/emu.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index b29c901c..811e6495 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -257,6 +257,15 @@ void openlog (const char * daemonName, int, int); void closelog(void); void syslog (int loglevel, const char *fmt, ...); +#define LOG_LOCAL0 0 +#define LOG_LOCAL1 0 +#define LOG_LOCAL2 0 +#define LOG_LOCAL3 0 +#define LOG_LOCAL4 0 +#define LOG_LOCAL5 0 +#define LOG_LOCAL6 0 +#define LOG_DAEMON 0 + #ifndef __MINGW32__ #define strtoll _strtoi64 #endif -- cgit v1.2.3 From afcac9017d4a46f4c69bdd0b4151daf2f6d4e68f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 26 Apr 2009 14:40:17 +0000 Subject: Provide a function to close a file handle on Windows, analogous to openfile(). --- lib/win32/emu.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 811e6495..f3389590 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -117,7 +117,7 @@ inline struct passwd * getpwnam(const char * name) #ifndef __MINGW32__ //not sure if these are correct //S_IWRITE - writing permitted - //_S_IREAD - reading permitted + //_S_IREAD - reading permitted //_S_IREAD | _S_IWRITE - #define S_IRUSR S_IWRITE #define S_IWUSR S_IREAD @@ -242,6 +242,15 @@ int closedir(DIR *dp); extern DWORD winerrno; /* used to report errors from openfile() */ HANDLE openfile(const char *filename, int flags, int mode); +inline int closefile(HANDLE handle) +{ + if (CloseHandle(handle) != TRUE) + { + errno = EINVAL; + return -1; + } + return 0; +} #define LOG_DEBUG LOG_INFO #define LOG_INFO 6 -- cgit v1.2.3 From 4f73df1c4f401a56dfcb1ad6bcc01e830b3b3d5d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 2 Aug 2009 18:58:51 +0000 Subject: Add handling of relative paths to emu.cpp's openfile(), needed to handle relative paths in test configuration on Windows. --- lib/win32/emu.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index ad8c3041..3a56661a 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -417,6 +417,32 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) } tmpStr += filename; + + // We are using direct filename access, which does not support .., + // so we need to implement it ourselves. + + for (std::string::size_type i = 1; i < tmpStr.size() - 3; i++) + { + if (tmpStr.substr(i, 3) == "\\..") + { + std::string::size_type lastSlash = + tmpStr.rfind('\\', i - 1); + + if (lastSlash == std::string::npos) + { + // no previous directory, ignore it, + // CreateFile will fail with error 123 + } + else + { + tmpStr.replace(lastSlash, i + 3 - lastSlash, + ""); + } + + i = lastSlash; + } + } + return tmpStr; } -- cgit v1.2.3 From 55689249c942cd865c6da9ce27cb995cba4d1a7c Mon Sep 17 00:00:00 2001 From: Charles Lecklider Date: Fri, 22 Oct 2010 14:17:59 +0000 Subject: This should fix Trac #14. --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 3a56661a..7061aa76 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -654,7 +654,7 @@ int emu_fstat(HANDLE hdir, struct emu_stat * st) { conv.HighPart = fi.nFileSizeHigh; conv.LowPart = fi.nFileSizeLow; - st->st_size = (_off_t)conv.QuadPart; + st->st_size = conv.QuadPart; } // at the mo -- cgit v1.2.3 From d2ab76c315dd3569ef69cb604bfb2c424e75cd6d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 8 Jan 2011 22:04:13 +0000 Subject: Log the adjusted time, not the unadjusted one, as it's the adjusted time that may cause an error if it's invalid. (merges [2743] from 0.11) --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 7061aa76..537494e8 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1814,7 +1814,7 @@ bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo) if (time_breakdown == NULL) { ::syslog(LOG_ERR, "Error: failed to convert time format: " - "%d is not a valid time\n", from); + "%d is not a valid time\n", adjusted); return false; } -- cgit v1.2.3 From 2f2f3882ce78c791faec5f42caf93eb2da2284ea Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 8 Jan 2011 22:08:53 +0000 Subject: Fix syslog of longer messages on Windows. (merges [2741] from 0.11) --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 537494e8..18a37de7 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1365,7 +1365,7 @@ void closelog(void) void syslog(int loglevel, const char *frmt, ...) { WORD errinfo; - char buffer[1024]; + char buffer[4096]; std::string sixfour(frmt); switch (loglevel) -- cgit v1.2.3 From 3991c90bb2d60a5811be90ea88f05e72e5d0d559 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 26 Mar 2011 23:21:03 +0000 Subject: Define WINVER and _WIN32_WINNT to Windows 2000 to avoid importing WSAPoll from winsock2.h, which conflicts with our definition of struct pollfd, on Windows Vista and above. --- lib/win32/emu.h | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index f3389590..1b071f7e 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -50,6 +50,23 @@ #define __MSVCRT_VERSION__ 0x0601 #endif +// WIN32_WINNT versions 0x0600 (Vista) and higher enable WSAPoll() in +// winsock2.h, whose struct pollfd conflicts with ours below, so for +// now we just set it lower than that, to Windows 2000. +#ifdef WINVER + #if WINVER != 0x0500 + #error Must include emu.h before setting WINVER + #endif +#endif +#define WINVER 0x0500 + +#ifdef _WIN32_WINNT + #if _WIN32_WINNT != 0x0500 + #error Must include emu.h before setting _WIN32_WINNT + #endif +#endif +#define _WIN32_WINNT 0x0500 + // Windows headers #include @@ -286,9 +303,18 @@ inline unsigned int sleep(unsigned int secs) } #define INFTIM -1 -#define POLLIN 0x1 -#define POLLERR 0x8 -#define POLLOUT 0x4 + +#ifndef POLLIN +# define POLLIN 0x1 +#endif + +#ifndef POLLERR +# define POLLERR 0x8 +#endif + +#ifndef POLLOUT +# define POLLOUT 0x4 +#endif #define SHUT_RDWR SD_BOTH #define SHUT_RD SD_RECEIVE -- cgit v1.2.3 From a6ea3ec4d7f048ae16637532a1e9d7269b623eba Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 26 Mar 2011 23:49:48 +0000 Subject: Fix off-by-one error in path translation. --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 18a37de7..4c6b2326 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -410,7 +410,7 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) // Must be relative. We need to get the // current directory to make it absolute. tmpStr += wd; - if (tmpStr[tmpStr.length()] != '\\') + if (tmpStr[tmpStr.length()-1] != '\\') { tmpStr += '\\'; } -- cgit v1.2.3 From 82e827c498a4e85c0fca92816baea0a97f68390a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 27 Mar 2011 01:02:42 +0000 Subject: Fix off-by-one causing incomplete normalisation of relative paths. --- lib/win32/emu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 4c6b2326..9549a681 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -439,7 +439,7 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) ""); } - i = lastSlash; + i = lastSlash - 1; } } -- cgit v1.2.3 From 2261a3f11a0f3951e774e339d0b532436445abc6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 27 Mar 2011 15:50:54 +0000 Subject: Add inline definition of ftruncate to fix MSVC compile. --- lib/win32/emu.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 1b071f7e..d5ac7e1e 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -435,6 +435,16 @@ std::string GetErrorMessage(DWORD errorCode); // relatively recent C runtime lib int console_read(char* pBuffer, size_t BufferSize); +// Defined thus by MinGW, but missing from MSVC +// [http://curl.haxx.se/mail/lib-2004-11/0260.html] +#ifndef HAVE_FTRUNCATE + int ftruncate(int, off_t); + inline int ftruncate(int __fd, off_t __length) + { + return _chsize(__fd, __length); + } +#endif + #ifdef _MSC_VER /* disable certain compiler warnings to be able to actually see the show-stopper ones */ #pragma warning(disable:4101) // unreferenced local variable -- cgit v1.2.3 From 28b61af7bdf2131a6a502b077615130bf1d66e57 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 27 Mar 2011 20:29:32 +0000 Subject: Fix another off-by-one error. --- lib/win32/emu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 9549a681..5b2376eb 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -988,7 +988,7 @@ DIR *opendir(const char *name) std::string dirName(name); //append a '\' win32 findfirst is sensitive to this - if ( dirName[dirName.size()] != '\\' || dirName[dirName.size()] != '/' ) + if (dirName[dirName.size()-1] != '\\' || dirName[dirName.size()-1] != '/') { dirName += '\\'; } @@ -1020,7 +1020,7 @@ DIR *opendir(const char *name) delete pDir; return NULL; } - + pDir->result.d_name = 0; return pDir; } -- cgit v1.2.3 From f6ca48ce8b9fb8488997c2b44d4e20c6a159a189 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 28 Mar 2011 23:40:58 +0000 Subject: Make ConvertFromWideString available to other modules. --- lib/win32/emu.cpp | 3 --- lib/win32/emu.h | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 5b2376eb..4b7a1b15 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -82,9 +82,6 @@ bool EnableBackupRights() return true; } -// forward declaration -char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage); - // -------------------------------------------------------------------------- // // Function diff --git a/lib/win32/emu.h b/lib/win32/emu.h index d5ac7e1e..e398d5f6 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -422,6 +422,7 @@ bool ConvertFromUtf8 (const std::string& rSource, std::string& rDest, int destCodePage); bool ConvertUtf8ToConsole(const std::string& rSource, std::string& rDest); bool ConvertConsoleToUtf8(const std::string& rSource, std::string& rDest); +char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage); // Utility function which returns a default config file name, // based on the path of the current executable. -- cgit v1.2.3 From d22fc3f49b5c1d1e1ccf0d250d7123b1a281dc18 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 Apr 2011 20:53:52 +0000 Subject: Add VSS: prefix to VSS log messages. Start a snapshot set and add backup locations as volumes. Modularise IVssAsync waiting code. --- lib/win32/emu.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/win32/emu.h | 3 +++ 2 files changed, 66 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 4b7a1b15..0afb9fa3 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -284,6 +284,69 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) return buffer; } +bool ConvertFromWideString(const std::wstring& rInput, + std::string* pOutput, unsigned int codepage) +{ + int len = WideCharToMultiByte + ( + codepage, // destination code page + 0, // character-type options + rInput.c_str(), // string to map + rInput.size(), // number of bytes in string - auto detect + NULL, // output buffer + 0, // size of buffer - work out + // how much space we need + NULL, // replace unknown chars with system default + NULL // don't tell us when that happened + ); + + if (len == 0) + { + ::syslog(LOG_WARNING, + "Failed to convert wide string to narrow: " + "error %d", GetLastError()); + errno = EINVAL; + return false; + } + + char* buffer = new char[len]; + + if (buffer == NULL) + { + ::syslog(LOG_WARNING, + "Failed to convert wide string to narrow: " + "out of memory"); + errno = ENOMEM; + return false; + } + + len = WideCharToMultiByte + ( + codepage, // source code page + 0, // character-type options + rInput.c_str(), // string to map + rInput.size(), // number of bytes in string - auto detect + buffer, // output buffer + len, // size of buffer + NULL, // replace unknown chars with system default + NULL // don't tell us when that happened + ); + + if (len == 0) + { + ::syslog(LOG_WARNING, + "Failed to convert wide string to narrow: " + "error %i", GetLastError()); + errno = EACCES; + delete [] buffer; + return false; + } + + *pOutput = std::string(buffer, len); + delete [] buffer; + return true; +} + // -------------------------------------------------------------------------- // // Function diff --git a/lib/win32/emu.h b/lib/win32/emu.h index e398d5f6..b7aa5d47 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -423,6 +423,9 @@ bool ConvertFromUtf8 (const std::string& rSource, std::string& rDest, bool ConvertUtf8ToConsole(const std::string& rSource, std::string& rDest); bool ConvertConsoleToUtf8(const std::string& rSource, std::string& rDest); char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage); +bool ConvertFromWideString(const std::wstring& rInput, + std::string* pOutput, unsigned int codepage); +std::string ConvertPathToAbsoluteUnicode(const char *pFileName); // Utility function which returns a default config file name, // based on the path of the current executable. -- cgit v1.2.3 From af6d0e7d543cc43be610e100f224871f4c504fd1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 14 Apr 2011 06:17:56 +0000 Subject: Support paths starting with \\?\, to fix support for backing up VSS snapshots. --- lib/win32/emu.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 0afb9fa3..64858a27 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -451,7 +451,15 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) return tmpStr; } - if (filename.length() > 2 && filename[0] == '\\' && + if (filename.length() > 4 && filename[0] == '\\' && + filename[1] == '\\' && filename[2] == '?' && + filename[3] == '\\') + { + // File is already in absolute utf-8 format, e.g. + // \\?\GLOBALROOT\... + tmpStr = ""; + } + else if (filename.length() > 2 && filename[0] == '\\' && filename[1] == '\\') { tmpStr += "UNC\\"; @@ -461,13 +469,13 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) } else if (filename.length() >= 1 && filename[0] == '\\') { - // root directory of current drive. + // starts with \, i.e. root directory of current drive. tmpStr = wd; tmpStr.resize(2); // drive letter and colon } else if (filename.length() >= 2 && filename[1] != ':') { - // Must be relative. We need to get the + // Must be a relative path. We need to get the // current directory to make it absolute. tmpStr += wd; if (tmpStr[tmpStr.length()-1] != '\\') -- cgit v1.2.3 From 46d65d06b31b88af89d45a837d0af4a92aebc78f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 20 Apr 2011 13:17:33 +0000 Subject: Remove getpid() emulation now that it's included in the SDK, which causes a conflict. --- lib/win32/emu.h | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index b7aa5d47..1ebd45c2 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -333,11 +333,6 @@ inline int ioctl(SOCKET sock, int flag, int * something) return 0; } -extern "C" inline int getpid() -{ - return (int)GetCurrentProcessId(); -} - inline int waitpid(pid_t pid, int *status, int) { return 0; @@ -377,12 +372,12 @@ int emu_chmod (const char* pName, mode_t mode); char* emu_getcwd (char* pBuffer, int BufSize); int emu_rename (const char* pOldName, const char* pNewName); -#define chdir(directory) emu_chdir (directory) -#define mkdir(path, mode) emu_mkdir (path) -#define unlink(file) emu_unlink (file) -#define utimes(buffer, times) emu_utimes (buffer, times) -#define chmod(file, mode) emu_chmod (file, mode) -#define getcwd(buffer, size) emu_getcwd (buffer, size) +#define chdir(directory) emu_chdir (directory) +#define mkdir(path, mode) emu_mkdir (path) +#define unlink(file) emu_unlink (file) +#define utimes(buffer, times) emu_utimes (buffer, times) +#define chmod(file, mode) emu_chmod (file, mode) +#define getcwd(buffer, size) emu_getcwd (buffer, size) #define rename(oldname, newname) emu_rename (oldname, newname) // Not safe to replace stat/fstat/lstat on mingw at least, as struct stat @@ -441,6 +436,8 @@ int console_read(char* pBuffer, size_t BufferSize); // Defined thus by MinGW, but missing from MSVC // [http://curl.haxx.se/mail/lib-2004-11/0260.html] +// note: chsize() doesn't work over 2GB: +// [https://stat.ethz.ch/pipermail/r-devel/2005-May/033339.html] #ifndef HAVE_FTRUNCATE int ftruncate(int, off_t); inline int ftruncate(int __fd, off_t __length) -- cgit v1.2.3 From f04cd092a2711160519c957a5ba8c28babd3004c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 24 May 2011 13:33:50 +0000 Subject: Blind fix for displaying error message as well as code when emu unicode conversion fails. --- lib/win32/emu.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 64858a27..2c1fb0df 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -243,7 +243,7 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) { ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " - "error %d", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); errno = EINVAL; return NULL; } @@ -275,7 +275,7 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) { ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " - "error %i", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); errno = EACCES; delete [] buffer; return NULL; @@ -304,7 +304,7 @@ bool ConvertFromWideString(const std::wstring& rInput, { ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " - "error %d", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); errno = EINVAL; return false; } @@ -336,7 +336,7 @@ bool ConvertFromWideString(const std::wstring& rInput, { ::syslog(LOG_WARNING, "Failed to convert wide string to narrow: " - "error %i", GetLastError()); + "%s", GetErrorMessage(GetLastError()).c_str()); errno = EACCES; delete [] buffer; return false; -- cgit v1.2.3 From 87abf9d2de4c75539b9ba7cb400f4baae35936ba Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 28 Aug 2011 19:07:17 +0000 Subject: Use "more standard" Windows API functions FindFirstFileW and FindNextFileW for directory enumeration instead of _wfindfirst and _wfindnext. Ignore reparse points when enumerating directories to avoid infinite loops. Convert VSS paths back to real paths when notifying users about backup progress. --- lib/win32/emu.cpp | 48 ++++++++++++++++++++++++++++++------------------ lib/win32/emu.h | 38 ++++++++++++++++++++++---------------- 2 files changed, 52 insertions(+), 34 deletions(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 2c1fb0df..ef237671 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1,8 +1,5 @@ // Box Backup Win32 native port by Nick Knight -// Need at least 0x0500 to use GetFileSizeEx on Cygwin/MinGW -#define WINVER 0x0500 - #include "emu.h" #ifdef WIN32 @@ -1080,9 +1077,10 @@ DIR *opendir(const char *name) return NULL; } - pDir->fd = _wfindfirst((const wchar_t*)pDir->name, &(pDir->info)); + pDir->fd = FindFirstFileW(pDir->name, &pDir->info); + DWORD tmp = GetLastError(); - if (pDir->fd == -1) + if (pDir->fd == INVALID_HANDLE_VALUE) { delete [] pDir->name; delete pDir; @@ -1111,26 +1109,37 @@ struct dirent *readdir(DIR *dp) { struct dirent *den = NULL; - if (dp && dp->fd != -1) + if (dp && dp->fd != INVALID_HANDLE_VALUE) { - if (!dp->result.d_name || - _wfindnext(dp->fd, &dp->info) != -1) + // first time around, when dp->result.d_name == NULL, use + // the values returned by FindFirstFile. After that, call + // FindNextFileW to return new ones. + if (!dp->result.d_name || + FindNextFileW(dp->fd, &dp->info) != 0) { den = &dp->result; - std::wstring input(dp->info.name); + std::wstring input(dp->info.cFileName); memset(tempbuff, 0, sizeof(tempbuff)); - WideCharToMultiByte(CP_UTF8, 0, dp->info.name, + WideCharToMultiByte(CP_UTF8, 0, dp->info.cFileName, -1, &tempbuff[0], sizeof (tempbuff), NULL, NULL); //den->d_name = (char *)dp->info.name; den->d_name = &tempbuff[0]; - if (dp->info.attrib & FILE_ATTRIBUTE_DIRECTORY) + den->d_type = dp->info.dwFileAttributes; + } + else // FindNextFileW failed + { + // Why did it fail? No more files? + winerrno = GetLastError(); + den = NULL; + + if (winerrno == ERROR_NO_MORE_FILES) { - den->d_type = S_IFDIR; + errno = 0; // no more files } else { - den->d_type = S_IFREG; + errno = ENOSYS; } } } @@ -1138,6 +1147,7 @@ struct dirent *readdir(DIR *dp) { errno = EBADF; } + return den; } catch (...) @@ -1159,24 +1169,26 @@ int closedir(DIR *dp) { try { - int finres = -1; + BOOL finres = false; + if (dp) { - if(dp->fd != -1) + if(dp->fd != INVALID_HANDLE_VALUE) { - finres = _findclose(dp->fd); + finres = FindClose(dp->fd); } delete [] dp->name; delete dp; } - if (finres == -1) // errors go to EBADF + if (finres == FALSE) // errors go to EBADF { + winerrno = GetLastError(); errno = EBADF; } - return finres; + return (finres == TRUE) ? 0 : -1; } catch (...) { diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 1ebd45c2..151fa2cb 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -50,22 +50,30 @@ #define __MSVCRT_VERSION__ 0x0601 #endif +// We need WINVER at least 0x0500 to use GetFileSizeEx on Cygwin/MinGW, +// and 0x0501 for FindFirstFile(W) for opendir/readdir. +// // WIN32_WINNT versions 0x0600 (Vista) and higher enable WSAPoll() in // winsock2.h, whose struct pollfd conflicts with ours below, so for -// now we just set it lower than that, to Windows 2000. +// now we just set it lower than that, to Windows XP (0x0501). + #ifdef WINVER - #if WINVER != 0x0500 - #error Must include emu.h before setting WINVER - #endif +# if WINVER != 0x0501 +// provoke a redefinition warning to track down the offender +# define WINVER 0x0501 +# error Must include emu.h before setting WINVER +# endif #endif -#define WINVER 0x0500 +#define WINVER 0x0501 #ifdef _WIN32_WINNT - #if _WIN32_WINNT != 0x0500 - #error Must include emu.h before setting _WIN32_WINNT - #endif +# if _WIN32_WINNT != 0x0501 +// provoke a redefinition warning to track down the offender +# define _WIN32_WINNT 0x0501 +# error Must include emu.h before setting _WIN32_WINNT +# endif #endif -#define _WIN32_WINNT 0x0500 +#define _WIN32_WINNT 0x0501 // Windows headers @@ -237,17 +245,15 @@ inline int strcasecmp(const char *s1, const char *s2) struct dirent { char *d_name; - unsigned long d_type; + DWORD d_type; // file attributes }; 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 + HANDLE fd; // the HANDLE returned by FindFirstFile + WIN32_FIND_DATAW info; + struct dirent result; // d_name (first time null) + wchar_t* name; // null-terminated byte string }; DIR *opendir(const char *name); -- cgit v1.2.3 From 79ea9acc7ab54b22ec4f453b75b372fc96152562 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 8 Oct 2011 12:06:34 +0000 Subject: Silence warnings from new MinGW headers that expect __MINGW_FEATURES__ to be defined. Check for fcntl.h and include it if we have it, not just on MSVC, now that MinGW also defines O_BINARY in newer versions. --- lib/win32/emu.h | 5 +++++ lib/win32/getopt_long.cpp | 1 + 2 files changed, 6 insertions(+) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 151fa2cb..81370a1b 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -15,6 +15,11 @@ #if ! defined EMU_INCLUDE && defined WIN32 #define EMU_INCLUDE +// Shut up stupid new warnings. Thanks MinGW! Ever heard of "compatibility"? +#ifdef __MINGW32__ +# define __MINGW_FEATURES__ 0 +#endif + // basic types, may be required by other headers since we // don't include sys/types.h diff --git a/lib/win32/getopt_long.cpp b/lib/win32/getopt_long.cpp index 5d910e1b..31695aa0 100755 --- a/lib/win32/getopt_long.cpp +++ b/lib/win32/getopt_long.cpp @@ -58,6 +58,7 @@ */ // #include "Box.h" +#include "emu.h" #include #include -- cgit v1.2.3 From 22bf0f91ab5a99881556af2085e6027c9766fc8c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 8 Oct 2011 12:41:28 +0000 Subject: Recent Cygwin versions of MinGW now define O_BINARY as well, also in fcntl.h, so include it if we can find it, and only define O_BINARY if it turns out to be missing. --- lib/win32/emu.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 81370a1b..9582b138 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -15,6 +15,9 @@ #if ! defined EMU_INCLUDE && defined WIN32 #define EMU_INCLUDE +// Need feature detection macros below +#include "../common/BoxConfig.h" + // Shut up stupid new warnings. Thanks MinGW! Ever heard of "compatibility"? #ifdef __MINGW32__ # define __MINGW_FEATURES__ 0 @@ -450,7 +453,7 @@ int console_read(char* pBuffer, size_t BufferSize); // note: chsize() doesn't work over 2GB: // [https://stat.ethz.ch/pipermail/r-devel/2005-May/033339.html] #ifndef HAVE_FTRUNCATE - int ftruncate(int, off_t); + extern "C" int ftruncate(int, off_t); inline int ftruncate(int __fd, off_t __length) { return _chsize(__fd, __length); -- cgit v1.2.3 From 29a41bf9a00f560b4234a391b4ce3fe9028357fd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 9 Oct 2011 11:24:45 +0000 Subject: Split Win32 defines out of emu.h to enable Boxi to include them before wx/wx.h (to set UNICODE properly) without also #including winnt.h before UNICODE is set properly. --- lib/win32/emu.h | 35 ++--------------------------------- lib/win32/emu_winver.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 33 deletions(-) create mode 100644 lib/win32/emu_winver.h (limited to 'lib/win32') diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 9582b138..bf408050 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -1,5 +1,7 @@ // emulates unix syscalls to win32 functions +#include "emu_winver.h" + #ifdef WIN32 #define EMU_STRUCT_STAT struct emu_stat #define EMU_STAT emu_stat @@ -50,39 +52,6 @@ typedef unsigned int pid_t; #endif -// set up to include the necessary parts of Windows headers - -#define WIN32_LEAN_AND_MEAN - -#ifndef __MSVCRT_VERSION__ -#define __MSVCRT_VERSION__ 0x0601 -#endif - -// We need WINVER at least 0x0500 to use GetFileSizeEx on Cygwin/MinGW, -// and 0x0501 for FindFirstFile(W) for opendir/readdir. -// -// WIN32_WINNT versions 0x0600 (Vista) and higher enable WSAPoll() in -// winsock2.h, whose struct pollfd conflicts with ours below, so for -// now we just set it lower than that, to Windows XP (0x0501). - -#ifdef WINVER -# if WINVER != 0x0501 -// provoke a redefinition warning to track down the offender -# define WINVER 0x0501 -# error Must include emu.h before setting WINVER -# endif -#endif -#define WINVER 0x0501 - -#ifdef _WIN32_WINNT -# if _WIN32_WINNT != 0x0501 -// provoke a redefinition warning to track down the offender -# define _WIN32_WINNT 0x0501 -# error Must include emu.h before setting _WIN32_WINNT -# endif -#endif -#define _WIN32_WINNT 0x0501 - // Windows headers #include diff --git a/lib/win32/emu_winver.h b/lib/win32/emu_winver.h new file mode 100644 index 00000000..92060150 --- /dev/null +++ b/lib/win32/emu_winver.h @@ -0,0 +1,37 @@ +#ifndef _EMU_WINVER_H +#define _EMU_WINVER_H + +// set up to include the necessary parts of Windows headers + +#define WIN32_LEAN_AND_MEAN + +#ifndef __MSVCRT_VERSION__ +#define __MSVCRT_VERSION__ 0x0601 +#endif + +// We need WINVER at least 0x0500 to use GetFileSizeEx on Cygwin/MinGW, +// and 0x0501 for FindFirstFile(W) for opendir/readdir. +// +// WIN32_WINNT versions 0x0600 (Vista) and higher enable WSAPoll() in +// winsock2.h, whose struct pollfd conflicts with ours below, so for +// now we just set it lower than that, to Windows XP (0x0501). + +#ifdef WINVER +# if WINVER != 0x0501 +// provoke a redefinition warning to track down the offender +# define WINVER 0x0501 +# error Must include emu.h before setting WINVER +# endif +#endif +#define WINVER 0x0501 + +#ifdef _WIN32_WINNT +# if _WIN32_WINNT != 0x0501 +// provoke a redefinition warning to track down the offender +# define _WIN32_WINNT 0x0501 +# error Must include emu.h before setting _WIN32_WINNT +# endif +#endif +#define _WIN32_WINNT 0x0501 + +#endif // _EMU_WINVER_H -- cgit v1.2.3