diff options
author | Reinhard Tartler <siretart@tauware.de> | 2018-02-20 21:49:13 -0500 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2018-02-20 21:49:13 -0500 |
commit | f28f88e5e72ba1499409047a9d6985eb312c0232 (patch) | |
tree | c9c267f18264b3dfe715a363935bb6ac20904492 /lib/win32 | |
parent | e19a5db232e1ef90e9a02159d2fbd9707ffe4373 (diff) | |
parent | 6d7e9562e8485591a4888f1fc2d3c6c657dc7a01 (diff) |
Merge tag 'BoxBackup-0.12.master.180102.6d7e956' into upstream
Diffstat (limited to 'lib/win32')
-rw-r--r-- | lib/win32/box_getopt.h | 14 | ||||
-rwxr-xr-x | lib/win32/bsd_getopt.h (renamed from lib/win32/getopt.h) | 203 | ||||
-rw-r--r-- | lib/win32/emu.cpp | 287 | ||||
-rw-r--r-- | lib/win32/emu.h | 97 | ||||
-rwxr-xr-x | lib/win32/getopt_long.cpp | 11 | ||||
-rwxr-xr-x | lib/win32/messages.h | 114 |
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) + |