summaryrefslogtreecommitdiff
path: root/lib/win32
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2018-02-20 21:49:13 -0500
committerReinhard Tartler <siretart@tauware.de>2018-02-20 21:49:13 -0500
commitf28f88e5e72ba1499409047a9d6985eb312c0232 (patch)
treec9c267f18264b3dfe715a363935bb6ac20904492 /lib/win32
parente19a5db232e1ef90e9a02159d2fbd9707ffe4373 (diff)
parent6d7e9562e8485591a4888f1fc2d3c6c657dc7a01 (diff)
Merge tag 'BoxBackup-0.12.master.180102.6d7e956' into upstream
Diffstat (limited to 'lib/win32')
-rw-r--r--lib/win32/box_getopt.h14
-rwxr-xr-xlib/win32/bsd_getopt.h (renamed from lib/win32/getopt.h)203
-rw-r--r--lib/win32/emu.cpp287
-rw-r--r--lib/win32/emu.h97
-rwxr-xr-xlib/win32/getopt_long.cpp11
-rwxr-xr-xlib/win32/messages.h114
6 files changed, 423 insertions, 303 deletions
diff --git a/lib/win32/box_getopt.h b/lib/win32/box_getopt.h
new file mode 100644
index 00000000..f18446d4
--- /dev/null
+++ b/lib/win32/box_getopt.h
@@ -0,0 +1,14 @@
+#if defined _MSC_VER || defined __MINGW32__
+#define REPLACE_GETOPT 1 /* use this getopt as the system getopt(3) */
+#else
+#define REPLACE_GETOPT 0 // force a conflict if included multiple times
+#endif
+
+#if REPLACE_GETOPT
+# include "bsd_getopt.h"
+# define BOX_BSD_GETOPT
+#else
+# include <getopt.h>
+# undef BOX_BSD_GETOPT
+#endif
+
diff --git a/lib/win32/getopt.h b/lib/win32/bsd_getopt.h
index 7c290343..3e2441ca 100755
--- a/lib/win32/getopt.h
+++ b/lib/win32/bsd_getopt.h
@@ -1,98 +1,105 @@
-/* $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_ */
+/* $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 REPLACE_GETOPT
+#error You must include box_getopt.h, not bsd_getopt.h
+#endif
+
+#if REPLACE_GETOPT // defined in box_getopt.h; until end of file
+
+#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_ */
+#endif // REPLACE_GETOPT
diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp
index ef237671..1f6392d5 100644
--- a/lib/win32/emu.cpp
+++ b/lib/win32/emu.cpp
@@ -32,8 +32,9 @@ bool EnableBackupRights()
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,
&hToken))
{
+ winerrno = GetLastError();
::syslog(LOG_ERR, "Failed to open process token: %s",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
return false;
}
@@ -45,8 +46,9 @@ bool EnableBackupRights()
SE_BACKUP_NAME, //the name of the privilege
&( token_priv.Privileges[0].Luid ))) //result
{
+ winerrno = GetLastError();
::syslog(LOG_ERR, "Failed to lookup backup privilege: %s",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
CloseHandle(hToken);
return false;
}
@@ -68,8 +70,9 @@ bool EnableBackupRights()
//this function is a little tricky - if we were adjusting
//more than one privilege, it could return success but not
//adjust them all - in the general case, you need to trap this
+ winerrno = GetLastError();
::syslog(LOG_ERR, "Failed to enable backup privilege: %s",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
CloseHandle(hToken);
return false;
@@ -238,9 +241,10 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage)
if (len == 0)
{
+ winerrno = GetLastError();
::syslog(LOG_WARNING,
"Failed to convert wide string to narrow: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
errno = EINVAL;
return NULL;
}
@@ -270,9 +274,10 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage)
if (len == 0)
{
+ winerrno = GetLastError();
::syslog(LOG_WARNING,
"Failed to convert wide string to narrow: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
errno = EACCES;
delete [] buffer;
return NULL;
@@ -299,9 +304,10 @@ bool ConvertFromWideString(const std::wstring& rInput,
if (len == 0)
{
+ winerrno = GetLastError();
::syslog(LOG_WARNING,
"Failed to convert wide string to narrow: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
errno = EINVAL;
return false;
}
@@ -331,9 +337,10 @@ bool ConvertFromWideString(const std::wstring& rInput,
if (len == 0)
{
+ winerrno = GetLastError();
::syslog(LOG_WARNING,
"Failed to convert wide string to narrow: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
errno = EACCES;
delete [] buffer;
return false;
@@ -363,10 +370,11 @@ bool ConvertEncoding(const std::string& rSource, int sourceCodePage,
true);
if (pWide == NULL)
{
+ winerrno = GetLastError();
::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());
+ GetErrorMessage(winerrno).c_str());
return false;
}
@@ -528,7 +536,10 @@ std::string GetErrorMessage(DWORD errorCode)
if (chars == 0 || pMsgBuf == NULL)
{
- return std::string("failed to get error message");
+ std::ostringstream oss;
+ oss << "Failed to get error message for error code " << errorCode << ": error " <<
+ GetLastError();
+ return oss.str();
}
// remove embedded newline
@@ -605,7 +616,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode)
createDisposition = CREATE_NEW;
}
- if (flags & O_LOCK)
+ if (flags & BOX_OPEN_LOCK)
{
shareMode = 0;
}
@@ -641,7 +652,7 @@ HANDLE openfile(const char *pFileName, int flags, int mode)
::syslog(LOG_WARNING, "Failed to open file '%s': "
"%s", pFileName,
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
return INVALID_HANDLE_VALUE;
}
@@ -684,16 +695,18 @@ int emu_fstat(HANDLE hdir, struct emu_stat * st)
BY_HANDLE_FILE_INFORMATION fi;
if (!GetFileInformationByHandle(hdir, &fi))
{
+ winerrno = GetLastError();
::syslog(LOG_WARNING, "Failed to read file information: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
errno = EACCES;
return -1;
}
if (INVALID_FILE_ATTRIBUTES == fi.dwFileAttributes)
{
+ winerrno = GetLastError();
::syslog(LOG_WARNING, "Failed to get file attributes: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
errno = EACCES;
return -1;
}
@@ -826,10 +839,10 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags)
if (handle == INVALID_HANDLE_VALUE)
{
- DWORD err = GetLastError();
+ winerrno = GetLastError();
- if (err == ERROR_FILE_NOT_FOUND ||
- err == ERROR_PATH_NOT_FOUND)
+ if (winerrno == ERROR_FILE_NOT_FOUND ||
+ winerrno == ERROR_PATH_NOT_FOUND)
{
errno = ENOENT;
}
@@ -837,7 +850,7 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags)
{
::syslog(LOG_WARNING, "Failed to open '%s': "
"%s", pFileName,
- GetErrorMessage(err).c_str());
+ GetErrorMessage(winerrno).c_str());
errno = EACCES;
}
@@ -906,9 +919,10 @@ int statfs(const char * pName, struct statfs * s)
BY_HANDLE_FILE_INFORMATION fi;
if (!GetFileInformationByHandle(handle, &fi))
{
+ winerrno = GetLastError();
::syslog(LOG_WARNING, "Failed to get file information "
"for '%s': %s", pName,
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
CloseHandle(handle);
errno = EACCES;
return -1;
@@ -961,8 +975,9 @@ int emu_utimes(const char * pName, const struct timeval times[])
if (!SetFileTime(handle, &creationTime, NULL, &modificationTime))
{
+ winerrno = GetLastError();
::syslog(LOG_ERR, "Failed to set times on '%s': %s", pName,
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
CloseHandle(handle);
return 1;
}
@@ -1004,8 +1019,9 @@ int emu_chmod(const char * pName, mode_t mode)
DWORD attribs = GetFileAttributesW(pBuffer);
if (attribs == INVALID_FILE_ATTRIBUTES)
{
+ winerrno = GetLastError();
::syslog(LOG_ERR, "Failed to get file attributes of '%s': %s",
- pName, GetErrorMessage(GetLastError()).c_str());
+ pName, GetErrorMessage(winerrno).c_str());
errno = EACCES;
free(pBuffer);
return -1;
@@ -1022,8 +1038,9 @@ int emu_chmod(const char * pName, mode_t mode)
if (!SetFileAttributesW(pBuffer, attribs))
{
+ winerrno = GetLastError();
::syslog(LOG_ERR, "Failed to set file attributes of '%s': %s",
- pName, GetErrorMessage(GetLastError()).c_str());
+ pName, GetErrorMessage(winerrno).c_str());
errno = EACCES;
free(pBuffer);
return -1;
@@ -1078,7 +1095,6 @@ DIR *opendir(const char *name)
}
pDir->fd = FindFirstFileW(pDir->name, &pDir->info);
- DWORD tmp = GetLastError();
if (pDir->fd == INVALID_HANDLE_VALUE)
{
@@ -1297,7 +1313,7 @@ int poll (struct pollfd *ufds, unsigned long nfds, int timeout)
BOOL AddEventSource
(
- LPTSTR pszSrcName, // event source name
+ const std::string& name, // event source name
DWORD dwNum // number of categories
)
{
@@ -1309,8 +1325,9 @@ BOOL AddEventSource
if (len == 0)
{
+ winerrno = GetLastError();
::syslog(LOG_ERR, "Failed to get the program file name: %s",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
return FALSE;
}
@@ -1318,31 +1335,39 @@ BOOL AddEventSource
std::string regkey("SYSTEM\\CurrentControlSet\\Services\\EventLog\\"
"Application\\");
- regkey += pszSrcName;
+ regkey += name;
HKEY hk;
DWORD dwDisp;
- if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, regkey.c_str(),
- 0, NULL, REG_OPTION_NON_VOLATILE,
- KEY_WRITE, NULL, &hk, &dwDisp))
+ winerrno = RegCreateKeyEx(HKEY_LOCAL_MACHINE, regkey.c_str(),
+ 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_WRITE, NULL, &hk, &dwDisp);
+ if (winerrno == ERROR_ACCESS_DENIED)
{
- ::syslog(LOG_ERR, "Failed to create the registry key: %s",
- GetErrorMessage(GetLastError()).c_str());
+ ::syslog(LOG_ERR, "Failed to create the registry key: access denied. You must "
+ "be an Administrator to register new event sources in %s", regkey.c_str());
+ return FALSE;
+ }
+ else if (winerrno != ERROR_SUCCESS)
+ {
+ ::syslog(LOG_ERR, "Failed to create the registry key: %s: %s",
+ GetErrorMessage(winerrno).c_str(), regkey.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
+ winerrno = 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
+ if (winerrno != ERROR_SUCCESS)
{
::syslog(LOG_ERR, "Failed to set the event message file: %s",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
RegCloseKey(hk);
return FALSE;
}
@@ -1352,43 +1377,46 @@ BOOL AddEventSource
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
+ winerrno = 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
+ if (winerrno != ERROR_SUCCESS)
{
::syslog(LOG_ERR, "Failed to set the supported types: %s",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).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
+ winerrno = 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
+ if (winerrno != ERROR_SUCCESS)
{
::syslog(LOG_ERR, "Failed to set the category message file: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
RegCloseKey(hk);
return FALSE;
}
- if (RegSetValueEx(hk, // subkey handle
+ winerrno = 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
+ sizeof(DWORD)); // length of value data
+ if (winerrno != ERROR_SUCCESS)
{
::syslog(LOG_ERR, "Failed to set the category count: %s",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
RegCloseKey(hk);
return FALSE;
}
@@ -1397,7 +1425,7 @@ BOOL AddEventSource
return TRUE;
}
-static HANDLE gSyslogH = 0;
+static HANDLE gSyslogH = INVALID_HANDLE_VALUE;
static bool sHaveWarnedEventLogFull = false;
void openlog(const char * daemonName, int, int)
@@ -1406,19 +1434,21 @@ void openlog(const char * daemonName, int, int)
nameStr += daemonName;
nameStr += ")";
- // register a default event source, so that we can
- // log errors with the process of adding or registering our own.
+ // Don't try to open a new handle when one is already open. It will leak handles.
+ assert(gSyslogH == INVALID_HANDLE_VALUE);
+
+ // Register a default event source, so that we can log errors with the process of
+ // adding or registering our own, which follows. If this fails, there's not much we
+ // can do about it, certainly not send anything to the event log!
gSyslogH = RegisterEventSource(
NULL, // uses local computer
nameStr.c_str()); // source name
if (gSyslogH == NULL)
{
+ gSyslogH = INVALID_HANDLE_VALUE;
}
- char* name = strdup(nameStr.c_str());
- BOOL success = AddEventSource(name, 0);
- free(name);
-
+ BOOL success = AddEventSource(nameStr, 0);
if (!success)
{
::syslog(LOG_ERR, "Failed to add our own event source");
@@ -1428,8 +1458,9 @@ void openlog(const char * daemonName, int, int)
HANDLE newSyslogH = RegisterEventSource(NULL, nameStr.c_str());
if (newSyslogH == NULL)
{
+ winerrno = GetLastError();
::syslog(LOG_ERR, "Failed to register our own event source: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
return;
}
@@ -1439,7 +1470,11 @@ void openlog(const char * daemonName, int, int)
void closelog(void)
{
- DeregisterEventSource(gSyslogH);
+ if(gSyslogH != INVALID_HANDLE_VALUE)
+ {
+ DeregisterEventSource(gSyslogH);
+ gSyslogH = INVALID_HANDLE_VALUE;
+ }
}
void syslog(int loglevel, const char *frmt, ...)
@@ -1494,7 +1529,7 @@ void syslog(int loglevel, const char *frmt, ...)
va_end(args);
- if (gSyslogH == 0)
+ if (gSyslogH == INVALID_HANDLE_VALUE)
{
printf("%s\r\n", buffer);
fflush(stdout);
@@ -1541,22 +1576,20 @@ void syslog(int loglevel, const char *frmt, ...)
if (result == 0)
{
- DWORD err = GetLastError();
- if (err == ERROR_LOG_FILE_FULL)
+ winerrno = GetLastError();
+ if (winerrno == ERROR_LOG_FILE_FULL)
{
if (!sHaveWarnedEventLogFull)
{
printf("Unable to send message to Event Log "
- "(Event Log is full):\r\n");
- fflush(stdout);
+ "(Event Log is full): %s\r\n", buffer);
sHaveWarnedEventLogFull = TRUE;
}
}
else
{
- printf("Unable to send message to Event Log: %s:\r\n",
- GetErrorMessage(err).c_str());
- fflush(stdout);
+ printf("Unable to send message to Event Log: %s: %s\r\n",
+ GetErrorMessage(winerrno).c_str(), buffer);
}
}
else
@@ -1589,8 +1622,9 @@ int emu_chdir(const char* pDirName)
if (result != 0) return 0;
errno = EACCES;
+ winerrno = GetLastError();
fprintf(stderr, "Failed to change directory to '%s': %s\n",
- pDirName, GetErrorMessage(GetLastError()).c_str());
+ pDirName, GetErrorMessage(winerrno).c_str());
return -1;
}
@@ -1668,6 +1702,74 @@ int emu_mkdir(const char* pPathName)
return 0;
}
+int emu_link(const char* pOldPath, const char* pNewPath)
+{
+ std::string AbsOldPathWithUnicode =
+ ConvertPathToAbsoluteUnicode(pOldPath);
+
+ if (AbsOldPathWithUnicode.size() == 0)
+ {
+ // error already logged by ConvertPathToAbsoluteUnicode()
+ return -1;
+ }
+
+ std::string AbsNewPathWithUnicode =
+ ConvertPathToAbsoluteUnicode(pNewPath);
+
+ if (AbsNewPathWithUnicode.size() == 0)
+ {
+ // error already logged by ConvertPathToAbsoluteUnicode()
+ return -1;
+ }
+
+ WCHAR* pOldBuffer = ConvertUtf8ToWideString(AbsOldPathWithUnicode.c_str());
+ if (!pOldBuffer)
+ {
+ return -1;
+ }
+
+ WCHAR* pNewBuffer = ConvertUtf8ToWideString(AbsNewPathWithUnicode.c_str());
+ if (!pNewBuffer)
+ {
+ delete [] pOldBuffer;
+ return -1;
+ }
+
+ BOOL result = CreateHardLinkW(pNewBuffer, pOldBuffer, NULL);
+ winerrno = GetLastError();
+ delete [] pOldBuffer;
+ delete [] pNewBuffer;
+
+ if (!result)
+ {
+ if (winerrno == ERROR_FILE_NOT_FOUND ||
+ winerrno == ERROR_PATH_NOT_FOUND)
+ {
+ errno = ENOENT;
+ }
+ else if (winerrno == ERROR_SHARING_VIOLATION)
+ {
+ errno = EBUSY;
+ }
+ else if (winerrno == ERROR_ACCESS_DENIED)
+ {
+ errno = EACCES;
+ }
+ else
+ {
+ ::syslog(LOG_WARNING, "Failed to hardlink file "
+ "'%s' to '%s': %s", pOldPath, pNewPath,
+ GetErrorMessage(winerrno).c_str());
+ errno = ENOSYS;
+ }
+
+ return -1;
+ }
+
+ return 0;
+
+}
+
int emu_unlink(const char* pFileName)
{
std::string AbsPathWithUnicode =
@@ -1686,20 +1788,21 @@ int emu_unlink(const char* pFileName)
}
BOOL result = DeleteFileW(pBuffer);
- DWORD err = GetLastError();
+ winerrno = GetLastError();
delete [] pBuffer;
if (!result)
{
- if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
+ if (winerrno == ERROR_FILE_NOT_FOUND ||
+ winerrno == ERROR_PATH_NOT_FOUND)
{
errno = ENOENT;
}
- else if (err == ERROR_SHARING_VIOLATION)
+ else if (winerrno == ERROR_SHARING_VIOLATION)
{
errno = EBUSY;
}
- else if (err == ERROR_ACCESS_DENIED)
+ else if (winerrno == ERROR_ACCESS_DENIED)
{
errno = EACCES;
}
@@ -1707,9 +1810,10 @@ int emu_unlink(const char* pFileName)
{
::syslog(LOG_WARNING, "Failed to delete file "
"'%s': %s", pFileName,
- GetErrorMessage(err).c_str());
+ GetErrorMessage(winerrno).c_str());
errno = ENOSYS;
}
+
return -1;
}
@@ -1751,21 +1855,22 @@ int emu_rename(const char* pOldFileName, const char* pNewFileName)
}
BOOL result = MoveFileW(pOldBuffer, pNewBuffer);
- DWORD err = GetLastError();
+ winerrno = GetLastError();
delete [] pOldBuffer;
delete [] pNewBuffer;
if (!result)
{
- if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
+ if (winerrno == ERROR_FILE_NOT_FOUND ||
+ winerrno == ERROR_PATH_NOT_FOUND)
{
errno = ENOENT;
}
- else if (err == ERROR_SHARING_VIOLATION)
+ else if (winerrno == ERROR_SHARING_VIOLATION)
{
errno = EBUSY;
}
- else if (err == ERROR_ACCESS_DENIED)
+ else if (winerrno == ERROR_ACCESS_DENIED)
{
errno = EACCES;
}
@@ -1773,7 +1878,7 @@ int emu_rename(const char* pOldFileName, const char* pNewFileName)
{
::syslog(LOG_WARNING, "Failed to rename file "
"'%s' to '%s': %s", pOldFileName, pNewFileName,
- GetErrorMessage(err).c_str());
+ GetErrorMessage(winerrno).c_str());
errno = ENOSYS;
}
return -1;
@@ -1788,8 +1893,9 @@ int console_read(char* pBuffer, size_t BufferSize)
if (hConsole == INVALID_HANDLE_VALUE)
{
+ winerrno = GetLastError();
::fprintf(stderr, "Failed to get a handle on standard input: "
- "%s", GetErrorMessage(GetLastError()).c_str());
+ "%s", GetErrorMessage(winerrno).c_str());
return -1;
}
@@ -1812,8 +1918,9 @@ int console_read(char* pBuffer, size_t BufferSize)
NULL // reserved
))
{
+ winerrno = GetLastError();
::fprintf(stderr, "Failed to read from console: %s\n",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
return -1;
}
@@ -1864,7 +1971,7 @@ int writev(int filedes, const struct iovec *vector, size_t count)
return bytes;
}
-// need this for conversions
+// Need this for conversions. Works in UTC.
time_t ConvertFileTimeToTime_t(FILETIME *fileTime)
{
SYSTEMTIME stUTC;
@@ -1883,18 +1990,17 @@ time_t ConvertFileTimeToTime_t(FILETIME *fileTime)
// timeinfo.tm_yday = ...;
timeinfo.tm_year = stUTC.wYear - 1900;
- time_t retVal = mktime(&timeinfo) - _timezone;
+ time_t retVal = _mkgmtime(&timeinfo);
return retVal;
}
bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo)
{
- time_t adjusted = from + _timezone;
- struct tm *time_breakdown = gmtime(&adjusted);
+ struct tm *time_breakdown = gmtime(&from);
if (time_breakdown == NULL)
{
::syslog(LOG_ERR, "Error: failed to convert time format: "
- "%d is not a valid time\n", adjusted);
+ "%d is not a valid time\n", from);
return false;
}
@@ -1911,8 +2017,9 @@ bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo)
// Convert the last-write time to local time.
if (!SystemTimeToFileTime(&stUTC, pTo))
{
+ winerrno = GetLastError();
syslog(LOG_ERR, "Failed to convert between time formats: %s",
- GetErrorMessage(GetLastError()).c_str());
+ GetErrorMessage(winerrno).c_str());
return false;
}
diff --git a/lib/win32/emu.h b/lib/win32/emu.h
index bf408050..91793004 100644
--- a/lib/win32/emu.h
+++ b/lib/win32/emu.h
@@ -18,7 +18,14 @@
#define EMU_INCLUDE
// Need feature detection macros below
-#include "../common/BoxConfig.h"
+#if defined BOX_CMAKE
+# include "../common/BoxConfig.cmake.h"
+#elif defined _MSC_VER
+# include "../common/BoxConfig-MSVC.h"
+# define NEED_BOX_VERSION_H
+#else
+# include "../common/BoxConfig.h"
+#endif
// Shut up stupid new warnings. Thanks MinGW! Ever heard of "compatibility"?
#ifdef __MINGW32__
@@ -27,31 +34,21 @@
// 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
+#include <stdint.h>
// emulated types, present on MinGW but not MSVC or vice versa
-#ifdef __MINGW32__
- typedef uint32_t u_int32_t;
-#else
+#ifndef __MINGW32__
typedef unsigned int mode_t;
typedef unsigned int pid_t;
+ typedef unsigned int uid_t;
+ typedef unsigned int gid_t;
#endif
+// Disable Windows' non-standard implementation of min() and max():
+// http://stackoverflow.com/a/5004874/648162
+#define NOMINMAX
+
// Windows headers
#include <winsock2.h>
@@ -76,17 +73,6 @@
#define ITIMER_REAL 0
-#ifdef _MSC_VER
-// Microsoft decided to deprecate the standard POSIX functions. Great!
-#define open(file,flags,mode) _open(file,flags,mode)
-#define close(fd) _close(fd)
-#define dup(fd) _dup(fd)
-#define read(fd,buf,count) _read(fd,buf,count)
-#define write(fd,buf,count) _write(fd,buf,count)
-#define lseek(fd,off,whence) _lseek(fd,off,whence)
-#define fileno(struct_file) _fileno(struct_file)
-#endif
-
struct passwd {
char *pw_name;
char *pw_passwd;
@@ -110,26 +96,34 @@ inline struct passwd * getpwnam(const char * name)
return &gTempPasswd;
}
-#define S_IRWXG 1
-#define S_IRWXO 2
-#define S_ISUID 4
-#define S_ISGID 8
-#define S_ISVTX 16
-
-#ifndef __MINGW32__
+#ifndef S_IRGRP
+ // these constants are only defined in MinGW64, not the original MinGW headers,
+ // nor MSVC, so use poor man's feature detection to define them only if needed.
//not sure if these are correct
//S_IWRITE - writing permitted
//_S_IREAD - reading permitted
//_S_IREAD | _S_IWRITE -
- #define S_IRUSR S_IWRITE
- #define S_IWUSR S_IREAD
- #define S_IRWXU (S_IREAD|S_IWRITE|S_IEXEC)
+# define S_IRUSR S_IWRITE
+# define S_IWUSR S_IREAD
+# define S_IRGRP S_IWRITE
+# define S_IWGRP S_IREAD
+# define S_IROTH S_IWRITE | S_IREAD
+# define S_IWOTH S_IREAD | S_IREAD
+# define S_IRWXU (S_IREAD|S_IWRITE|S_IEXEC)
+# define S_IRWXG 1
+# define S_IRWXO 2
+#endif
+#define S_ISUID 4
+#define S_ISGID 8
+#define S_ISVTX 16
+
+#ifndef __MINGW32__
#define S_ISREG(x) (S_IFREG & x)
#define S_ISDIR(x) (S_IFDIR & x)
#endif
-inline int chown(const char * Filename, u_int32_t uid, u_int32_t gid)
+inline int chown(const char * Filename, uint32_t uid, uint32_t gid)
{
//important - this needs implementing
//If a large restore is required then
@@ -183,7 +177,7 @@ inline int geteuid(void)
// MinGW provides a getopt implementation
#ifndef __MINGW32__
-#include "getopt.h"
+#include "box_getopt.h"
#endif // !__MINGW32__
#define timespec timeval
@@ -195,11 +189,6 @@ inline int geteuid(void)
typedef int socklen_t;
#endif
-#define S_IRGRP S_IWRITE
-#define S_IWGRP S_IREAD
-#define S_IROTH S_IWRITE | S_IREAD
-#define S_IWOTH S_IREAD | S_IREAD
-
//again need to verify these
#define S_IFLNK 1
#define S_IFSOCK 0
@@ -209,9 +198,14 @@ inline int geteuid(void)
#define vsnprintf _vsnprintf
#ifndef __MINGW32__
+#define snprintf _snprintf
inline int strcasecmp(const char *s1, const char *s2)
{
- return _stricmp(s1,s2);
+ return _stricmp(s1, s2);
+}
+inline int strncasecmp(const char *s1, const char *s2, size_t count)
+{
+ return _strnicmp(s1, s2, count);
}
#endif
@@ -238,7 +232,7 @@ struct dirent *readdir(DIR *dp);
int closedir(DIR *dp);
// local constant to open file exclusively without shared access
-#define O_LOCK 0x10000
+#define BOX_OPEN_LOCK 0x10000
extern DWORD winerrno; /* used to report errors from openfile() */
HANDLE openfile(const char *filename, int flags, int mode);
@@ -279,7 +273,7 @@ void syslog (int loglevel, const char *fmt, ...);
#define strtoll _strtoi64
#endif
-inline unsigned int sleep(unsigned int secs)
+extern "C" inline unsigned int sleep(unsigned int secs)
{
Sleep(secs*1000);
return(ERROR_SUCCESS);
@@ -347,6 +341,7 @@ bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo);
int emu_chdir (const char* pDirName);
int emu_mkdir (const char* pPathName);
+int emu_link (const char* pOldPath, const char* pNewPath);
int emu_unlink (const char* pFileName);
int emu_fstat (HANDLE file, struct emu_stat* st);
int emu_stat (const char* pName, struct emu_stat* st);
@@ -357,6 +352,7 @@ int emu_rename (const char* pOldName, const char* pNewName);
#define chdir(directory) emu_chdir (directory)
#define mkdir(path, mode) emu_mkdir (path)
+#define link(oldpath, newpath) emu_link (oldpath, newpath)
#define unlink(file) emu_unlink (file)
#define utimes(buffer, times) emu_utimes (buffer, times)
#define chmod(file, mode) emu_chmod (file, mode)
@@ -403,6 +399,7 @@ bool ConvertConsoleToUtf8(const std::string& rSource, std::string& rDest);
char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage);
bool ConvertFromWideString(const std::wstring& rInput,
std::string* pOutput, unsigned int codepage);
+WCHAR* ConvertUtf8ToWideString(const char* pString);
std::string ConvertPathToAbsoluteUnicode(const char *pFileName);
// Utility function which returns a default config file name,
diff --git a/lib/win32/getopt_long.cpp b/lib/win32/getopt_long.cpp
index 31695aa0..af2833a1 100755
--- a/lib/win32/getopt_long.cpp
+++ b/lib/win32/getopt_long.cpp
@@ -66,18 +66,15 @@
#include <stdio.h>
#include <string.h>
-#include "getopt.h"
+#include "box_getopt.h"
-#if defined _MSC_VER || defined __MINGW32__
-#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
+#ifdef REPLACE_GETOPT // until end of file
-#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 != ':'))
@@ -499,7 +496,6 @@ start:
return (optchar);
}
-#ifdef REPLACE_GETOPT
/*
* getopt --
* Parse argc/argv argument vector.
@@ -520,7 +516,6 @@ getopt(int nargc, char * const *nargv, const char *options)
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
}
-#endif /* REPLACE_GETOPT */
/*
* getopt_long --
@@ -548,4 +543,4 @@ getopt_long_only(int nargc, char * const *nargv, const char *options,
FLAG_PERMUTE|FLAG_LONGONLY));
}
-#endif // defined _MSC_VER || defined __MINGW32__
+#endif // REPLACE_GETOPT
diff --git a/lib/win32/messages.h b/lib/win32/messages.h
index 6959591b..22290226 100755
--- a/lib/win32/messages.h
+++ b/lib/win32/messages.h
@@ -1,57 +1,57 @@
- // Message source file, to be compiled to a resource file with
- // Microsoft Message Compiler (MC), to an object file with a Resource
- // Compiler, and linked into the application.
-
- // The main reason for this file is to work around Windows' stupid
- // messages in the Event Log, which say:
-
- // The description for Event ID ( 4 ) in Source ( Box Backup (bbackupd) )
- // cannot be found. The local computer may not have the necessary
- // registry information or message DLL files to display messages from a
- // remote computer. The following information is part of the event:
- // Message definitions follow
-//
-// Values are 32 bit values layed out as follows:
-//
-// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
-// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-// +---+-+-+-----------------------+-------------------------------+
-// |Sev|C|R| Facility | Code |
-// +---+-+-+-----------------------+-------------------------------+
-//
-// where
-//
-// Sev - is the severity code
-//
-// 00 - Success
-// 01 - Informational
-// 10 - Warning
-// 11 - Error
-//
-// C - is the Customer code flag
-//
-// R - is a reserved bit
-//
-// Facility - is the facility code
-//
-// Code - is the facility's status code
-//
-//
-// Define the facility codes
-//
-
-
-//
-// Define the severity codes
-//
-
-
-//
-// MessageId: MSG_ERR
-//
-// MessageText:
-//
-// %1
-//
-#define MSG_ERR ((DWORD)0x40000001L)
-
+ // 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)
+