diff options
Diffstat (limited to 'lib/win32')
-rwxr-xr-x | lib/win32/MSG00001.bin | bin | 0 -> 32 bytes | |||
-rw-r--r-- | lib/win32/WinNamedPipeStream.cpp | 350 | ||||
-rw-r--r-- | lib/win32/config.h.win32 | 396 | ||||
-rw-r--r-- | lib/win32/emu.cpp | 1035 | ||||
-rw-r--r-- | lib/win32/emu.h | 348 | ||||
-rwxr-xr-x | lib/win32/getopt.h | 136 | ||||
-rwxr-xr-x | lib/win32/getopt_long.cxx | 550 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/win32/messages.h (renamed from lib/win32/WinNamedPipeStream.h) | 119 | ||||
-rw-r--r-- | lib/win32/messages.mc | 22 | ||||
-rwxr-xr-x | lib/win32/messages.rc | 2 |
10 files changed, 1751 insertions, 1207 deletions
diff --git a/lib/win32/MSG00001.bin b/lib/win32/MSG00001.bin Binary files differnew file mode 100755 index 00000000..b4377b85 --- /dev/null +++ b/lib/win32/MSG00001.bin diff --git a/lib/win32/WinNamedPipeStream.cpp b/lib/win32/WinNamedPipeStream.cpp deleted file mode 100644 index 2a27a206..00000000 --- a/lib/win32/WinNamedPipeStream.cpp +++ /dev/null @@ -1,350 +0,0 @@ -// distribution boxbackup-0.10 (svn version: 494) -// -// Copyright (c) 2003 - 2006 -// Ben Summers and contributors. All rights reserved. -// -// 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 use of this software and associated advertising materials must -// display the following acknowledgment: -// This product includes software developed by Ben Summers. -// 4. The names of the Authors may not be used to endorse or promote -// products derived from this software without specific prior written -// permission. -// -// [Where legally impermissible the Authors do not disclaim liability for -// direct physical injury or death caused solely by defects in the software -// unless it is modified by a third party.] -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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. -// -// -// -// -------------------------------------------------------------------------- -// -// 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 <unistd.h> -#endif - -#include <sys/types.h> -#include <errno.h> -#include <windows.h> - -#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/config.h.win32 b/lib/win32/config.h.win32 deleted file mode 100644 index 42298545..00000000 --- a/lib/win32/config.h.win32 +++ /dev/null @@ -1,396 +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 <asm/byteorder.h> 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 <db.h> 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 <dirent.h> header file, and it defines `DIR'. - */ -/* #undef HAVE_DIRENT_H */ - -/* Define to 1 if you have the <editline/readline.h> header file. */ -/* #undef HAVE_EDITLINE_READLINE_H */ - -/* define if the compiler supports exceptions */ -#define HAVE_EXCEPTIONS - -/* Define to 1 if you have the <execinfo.h> 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 <history.h> header file. */ -/* #undef HAVE_HISTORY_H */ - -/* Define to 1 if you have the <inttypes.h> 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 <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <mntent.h> 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 <ndir.h> header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* Define to 1 if you have the <netinet/in.h> 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 <openssl/ssl.h> header file. */ -#define HAVE_OPENSSL_SSL_H 1 - -/* Define to 1 if you have the <process.h> header file. */ -#define HAVE_PROCESS_H 1 - -/* Define to 1 if you have the <pwd.h> 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 <readline.h> 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 <readline/history.h> header file. */ -/* #undef HAVE_READLINE_HISTORY_H */ - -/* Define to 1 if you have the <readline/readline.h> header file. */ -/* #undef HAVE_READLINE_READLINE_H */ - -/* Define to 1 if you have the <regex.h> 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 <signal.h> 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 <stdint.h> header file. */ -// #define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> 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 <syslog.h> header file. */ -/* #undef HAVE_SYSLOG_H */ - -/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the <sys/endian.h> header file. */ -/* #undef HAVE_SYS_ENDIAN_H */ - -/* Define to 1 if you have the <sys/mnttab.h> header file. */ -/* #undef HAVE_SYS_MNTTAB_H */ - -/* Define to 1 if you have the <sys/mount.h> header file. */ -/* #undef HAVE_SYS_MOUNT_H */ - -/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the <sys/param.h> header file. */ -// #define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the <sys/socket.h> header file. */ -/* #undef HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/syscall.h> header file. */ -/* #undef HAVE_SYS_SYSCALL_H */ - -/* Define to 1 if you have the <sys/time.h> header file. */ -// #define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the <sys/wait.h> header file. */ -/* #undef HAVE_SYS_WAIT_H */ - -/* Define to 1 if you have the <sys/xattr.h> header file. */ -/* #undef HAVE_SYS_XATTR_H */ - -/* Define to 1 if you have the <time.h> 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 <unistd.h> 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 <sys/time.h> and <time.h>. */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your <sys/time.h> 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 <sys/types.h> doesn't define. */ -#define gid_t int - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef mode_t */ - -/* Define to `long' if <sys/types.h> does not define. */ -/* #undef off_t */ - -/* Define to `int' if <sys/types.h> does not define. */ -/* #undef pid_t */ - -/* Define to `unsigned' if <sys/types.h> does not define. */ -/* #undef size_t */ - -/* Define to `int' if <sys/types.h> doesn't define. */ -#define uid_t int diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index c3c0b6f2..e41430c6 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1,4 +1,4 @@ -// distribution boxbackup-0.10 (svn version: 494) +// distribution boxbackup-0.11rc1 (svn version: 2023_2024) // // Copyright (c) 2003 - 2006 // Ben Summers and contributors. All rights reserved. @@ -41,29 +41,31 @@ // 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 <windows.h> +#include <assert.h> #include <fcntl.h> -// #include <atlenc.h> +#include <process.h> +#include <windows.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif -#ifdef HAVE_PROCESS_H - #include <process.h> -#endif #include <string> #include <list> +#include <sstream> + +// 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; @@ -79,24 +81,31 @@ static void (__cdecl *gTimerFunc) (int) = NULL; int setitimer(int type, struct itimerval *timeout, void *arg) { - if (ITIMER_VIRTUAL == type) + assert(gTimerInitialised); + + if (ITIMER_REAL != 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 - { - Timer_t ourTimer; - ourTimer.countDown = timeout->it_value.tv_sec; - ourTimer.interval = timeout->it_interval.tv_sec; - gTimerList.push_back(ourTimer); - } - LeaveCriticalSection(&gLock); + 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; @@ -167,20 +176,26 @@ int SetTimerHandler(void (__cdecl *func ) (int)) void InitTimer(void) { - InitializeCriticalSection(&gLock); + 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 @@ -241,6 +256,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 @@ -398,27 +451,34 @@ 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 = ConvertToWideString(pString, CP_UTF8); + 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; } - char* pConsole = ConvertFromWideString(pWide, GetConsoleOutputCP()); + char* pConsole = ConvertFromWideString(pWide, destCodePage); delete [] pWide; if (!pConsole) { + // Error should have been logged by ConvertFromWideString return false; } @@ -428,39 +488,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()); +} // -------------------------------------------------------------------------- // @@ -472,28 +518,54 @@ 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] != ':') + + 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[0] == '\\' && + filename[1] == '\\') + { + tmpStr += "UNC\\"; + filename.replace(0, 2, ""); + // \\?\UNC\<server>\<share> + // see http://msdn2.microsoft.com/en-us/library/aa365247.aspx + } + else 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()] != '\\') { @@ -501,26 +573,59 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) } } - tmpStr += pFileName; + tmpStr += filename; 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"); + } + + // remove embedded newline + pMsgBuf[chars - 1] = 0; + pMsgBuf[chars - 2] = 0; + + std::ostringstream line; + line << pMsgBuf << " (" << errorCode << ")"; + LocalFree(pMsgBuf); + + return line.str(); +} + // -------------------------------------------------------------------------- // // 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()); @@ -529,68 +634,73 @@ 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 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) { - shareMode = FILE_SHARE_WRITE; + accessRights = FILE_WRITE_DATA; } - if (flags & O_RDWR) + else if (flags & O_RDWR) { - shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + accessRights |= FILE_WRITE_ATTRIBUTES + | FILE_WRITE_DATA | FILE_WRITE_EA; } + 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) + + if ((flags & O_CREAT) && (flags & O_EXCL)) + { + createDisposition = CREATE_NEW; + } + + if (flags & O_LOCK) { shareMode = 0; } + DWORD winFlags = FILE_FLAG_BACKUP_SEMANTICS; + if (flags & O_TEMPORARY) + { + winFlags |= FILE_FLAG_DELETE_ON_CLOSE; + } + HANDLE hdir = CreateFileW(pBuffer, accessRights, shareMode, NULL, createDisposition, - FILE_FLAG_BACKUP_SEMANTICS, + winFlags, NULL); delete [] pBuffer; if (hdir == INVALID_HANDLE_VALUE) { - ::syslog(LOG_WARNING, "Failed to open file %s: " - "error %i", pFileName, GetLastError()); - return NULL; + ::syslog(LOG_WARNING, "Failed to open file '%s': " + "%s", pFileName, + GetErrorMessage(GetLastError()).c_str()); + return INVALID_HANDLE_VALUE; } 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 @@ -601,8 +711,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()"); @@ -614,14 +722,23 @@ 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; + } + + if (INVALID_FILE_ATTRIBUTES == fi.dwFileAttributes) + { + ::syslog(LOG_WARNING, "Failed to get file attributes: " + "%s", GetErrorMessage(GetLastError()).c_str()); 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; @@ -631,41 +748,71 @@ 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: " + "%s", GetErrorMessage(GetLastError()).c_str()); + 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; + // at the mo + st->st_uid = 0; + st->st_gid = 0; + st->st_nlink = 1; - //the mode of the file - st->st_mode = 0; - //DWORD res = GetFileAttributes((LPCSTR)tmpStr.c_str()); + // 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 (INVALID_FILE_ATTRIBUTES != fi.dwFileAttributes) + 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; + } + + // 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 + // 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; @@ -681,9 +828,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 +849,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, @@ -715,7 +863,7 @@ HANDLE OpenFileByNameUtf8(const char* pFileName) // 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, @@ -729,14 +877,16 @@ HANDLE OpenFileByNameUtf8(const char* pFileName) { DWORD err = GetLastError(); - if (err == ERROR_FILE_NOT_FOUND) + if (err == ERROR_FILE_NOT_FOUND || + err == ERROR_PATH_NOT_FOUND) { errno = ENOENT; } 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; } @@ -757,12 +907,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 +941,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) { @@ -807,7 +954,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; @@ -817,7 +965,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 @@ -827,6 +975,115 @@ int statfs(const char * pName, struct statfs * s) // -------------------------------------------------------------------------- // // 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': %s", pName, + GetErrorMessage(GetLastError()).c_str()); + 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': %s", + pName, GetErrorMessage(GetLastError()).c_str()); + 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': %s", + pName, GetErrorMessage(GetLastError()).c_str()); + errno = EACCES; + free(pBuffer); + return -1; + } + + delete [] pBuffer; + return 0; +} + + +// -------------------------------------------------------------------------- +// +// Function // Name: opendir // Purpose: replacement for unix function, uses win32 findfirst routines // Created: 25th October 2004 @@ -903,7 +1160,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, @@ -911,6 +1168,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 @@ -980,10 +1245,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; @@ -996,41 +1261,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]); - return noffds; + if (FD_ISSET(ufd->fd, &readfd)) + { + ufd->revents |= POLLIN; + } + + if (FD_ISSET(ufd->fd, &writefd)) + { + ufd->revents |= POLLOUT; + } + } + } + + return nready; } catch (...) { @@ -1040,9 +1325,151 @@ 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 + + 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; + } + + // 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: %s", + GetErrorMessage(GetLastError()).c_str()); + return FALSE; + } + + // Set the name of the message file. + + 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()); + 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: %s", + GetErrorMessage(GetLastError()).c_str()); + RegCloseKey(hk); + return FALSE; + } + + // Set the category message file and number of categories. + + 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()); + 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: %s", + GetErrorMessage(GetLastError()).c_str()); + 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) + { + } + + 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, daemonName); + if (newSyslogH == NULL) + { + ::syslog(LOG_ERR, "Failed to register our own event source: " + "%s", GetErrorMessage(GetLastError()).c_str()); + return; + } + + DeregisterEventSource(gSyslogH); + gSyslogH = newSyslogH; +} + +void closelog(void) +{ + DeregisterEventSource(gSyslogH); +} + void syslog(int loglevel, const char *frmt, ...) { WORD errinfo; @@ -1082,17 +1509,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 @@ -1108,13 +1550,15 @@ 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; } } 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); } } else @@ -1122,17 +1566,36 @@ void syslog(int loglevel, const char *frmt, ...) sHaveWarnedEventLogFull = false; } - printf("%s\r\n", buffer); + // printf("%s\r\n", buffer); + // fflush(stdout); } int emu_chdir(const char* pDirName) { + /* + std::string AbsPathWithUnicode = + ConvertPathToAbsoluteUnicode(pDirName); + + if (AbsPathWithUnicode.size() == 0) + { + // error already logged by ConvertPathToAbsoluteUnicode() + return -1; + } + + 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; } @@ -1145,7 +1608,7 @@ char* emu_getcwd(char* pBuffer, int BufSize) return NULL; } - if (len > BufSize) + if ((int)len > BufSize) { errno = ENAMETOOLONG; return NULL; @@ -1162,6 +1625,7 @@ char* emu_getcwd(char* pBuffer, int BufSize) if (result <= 0 || result >= len) { errno = EACCES; + delete [] pWide; return NULL; } @@ -1182,7 +1646,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; @@ -1202,18 +1675,112 @@ 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': %s", pFileName, + GetErrorMessage(err).c_str()); + errno = ENOSYS; + } + return -1; + } + + 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; } @@ -1227,12 +1794,12 @@ 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; } - int WideSize = BufferSize / 5; - WCHAR* pWideBuffer = new WCHAR [WideSize]; + size_t WideSize = BufferSize / 5; + WCHAR* pWideBuffer = new WCHAR [WideSize + 1]; if (!pWideBuffer) { @@ -1245,23 +1812,117 @@ 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 )) { - ::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; } pWideBuffer[numCharsRead] = 0; char* pUtf8 = ConvertFromWideString(pWideBuffer, GetConsoleCP()); + delete [] pWideBuffer; + strncpy(pBuffer, pUtf8, BufferSize); delete [] pUtf8; 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: %s", + GetErrorMessage(GetLastError()).c_str()); + return false; + } + + return true; +} + #endif // WIN32 + diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 7e7700f4..e67eeae9 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -1,4 +1,4 @@ -// distribution boxbackup-0.10 (svn version: 494) +// distribution boxbackup-0.11rc1 (svn version: 2023_2024) // // Copyright (c) 2003 - 2006 // Ben Summers and contributors. All rights reserved. @@ -41,7 +41,47 @@ #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 <stdint.h> +#else // MSVC + 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; +#endif + +// emulated types, present on MinGW but not MSVC or vice versa + +#ifdef __MINGW32__ + typedef uint32_t u_int32_t; +#else + typedef unsigned int mode_t; + typedef unsigned int pid_t; + + // must define _INO_T_DEFINED before including <sys/types.h> + // 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 <winsock2.h> #include <fcntl.h> @@ -57,11 +97,13 @@ #include <string> +// emulated functions + #define gmtime_r( _clock, _result ) \ ( *(_result) = *gmtime( (_clock) ), \ (_result) ) -#define ITIMER_VIRTUAL 0 +#define ITIMER_REAL 0 #ifdef _MSC_VER // Microsoft decided to deprecate the standard POSIX functions. Great! @@ -79,17 +121,11 @@ 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; - uid_t pw_uid; - gid_t pw_gid; + int pw_uid; + int pw_gid; time_t pw_change; char *pw_class; char *pw_gecos; @@ -127,14 +163,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 @@ -151,46 +179,9 @@ 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); - -#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 +// 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; @@ -215,6 +206,10 @@ inline int getuid(void) { return 0; } +inline int geteuid(void) +{ + return 0; +} #ifndef PATH_MAX #define PATH_MAX MAX_PATH @@ -222,59 +217,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 @@ -290,25 +233,9 @@ 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 -// 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 @@ -322,26 +249,20 @@ 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) -{ - return emu_mkdir(pPathName); -} - -#ifndef __MINGW32__ inline int strcasecmp(const char *s1, const char *s2) { return _stricmp(s1,s2); } #endif +#ifdef _DIRENT_H_ +#error You must not include the MinGW dirent.h! +#endif + struct dirent { char *d_name; + unsigned long d_type; }; struct DIR @@ -358,32 +279,24 @@ 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_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 -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 @@ -448,73 +361,82 @@ struct stat { time_t st_mtime; time_t st_ctime; }; +#endif // 0 + +// need this for conversions +time_t ConvertFileTimeToTime_t(FILETIME *fileTime); +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_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) +#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) -#ifndef __MINGW32__ -typedef u_int64_t _ino_t; -#endif -#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 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; -} +int poll(struct pollfd *ufds, unsigned long nfds, int timeout); -#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 +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. -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); -// -// MessageId: MSG_ERR_EXIST -// MessageText: -// Box Backup. -// -#define MSG_ERR_EXIST ((DWORD)0xC0000004L) +// 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); -// replacement for _cgetws which requires a relatively recent C runtime lib +// console_read() is a replacement for _cgetws which requires a +// 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 diff --git a/lib/win32/getopt.h b/lib/win32/getopt.h new file mode 100755 index 00000000..0d133477 --- /dev/null +++ b/lib/win32/getopt.h @@ -0,0 +1,136 @@ +// distribution boxbackup-0.11rc1 (svn version: 2023_2024) +// +// Copyright (c) 2003 - 2006 +// Ben Summers and contributors. All rights reserved. +// +// 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 use of this software and associated advertising materials must +// display the following acknowledgment: +// This product includes software developed by Ben Summers. +// 4. The names of the Authors may not be used to endorse or promote +// products derived from this software without specific prior written +// permission. +// +// [Where legally impermissible the Authors do not disclaim liability for +// direct physical injury or death caused solely by defects in the software +// unless it is modified by a third party.] +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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. +// +// +// +/* $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_ */
diff --git a/lib/win32/getopt_long.cxx b/lib/win32/getopt_long.cxx new file mode 100755 index 00000000..a24930aa --- /dev/null +++ b/lib/win32/getopt_long.cxx @@ -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 <chris+boxbackup@qwirx.com>
+
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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/WinNamedPipeStream.h b/lib/win32/messages.h index 4779de08..3a0b032b 100644..100755 --- a/lib/win32/WinNamedPipeStream.h +++ b/lib/win32/messages.h @@ -1,4 +1,4 @@ -// distribution boxbackup-0.10 (svn version: 494) +// distribution boxbackup-0.11rc1 (svn version: 2023_2024) // // Copyright (c) 2003 - 2006 // Ben Summers and contributors. All rights reserved. @@ -36,63 +36,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 + // 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
|