diff options
author | Reinhard Tartler <siretart@tauware.de> | 2009-04-02 13:58:11 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2009-04-02 13:58:11 +0200 |
commit | a84d45498bd861c9225080232948a99c2e317bb8 (patch) | |
tree | 8f1f5fb7bf7ffbf6f24cf4a4fd6888a235dbcc08 /lib/win32 | |
parent | 25db897553a0db0f912602b375029e724f51556e (diff) |
Import upstream version 0.11~rc3~r2491
Diffstat (limited to 'lib/win32')
-rw-r--r-- | lib/win32/emu.cpp | 363 | ||||
-rw-r--r-- | lib/win32/emu.h | 83 | ||||
-rwxr-xr-x | lib/win32/getopt_long.cpp (renamed from lib/win32/getopt_long.cxx) | 2 |
3 files changed, 193 insertions, 255 deletions
diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 071dc788..ad8c3041 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -21,173 +21,36 @@ #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; - -typedef struct -{ - int countDown; - int interval; -} -Timer_t; - -std::list<Timer_t> gTimerList; -static void (__cdecl *gTimerFunc) (int) = NULL; - -int setitimer(int type, struct itimerval *timeout, void *arg) -{ - assert(gTimerInitialised); - - if (ITIMER_REAL != type) - { - errno = ENOSYS; - return -1; - } - - EnterCriticalSection(&gLock); - - // we only need seconds for the mo! - if (timeout->it_value.tv_sec == 0 && - timeout->it_value.tv_usec == 0) - { - gTimerList.clear(); - } - else - { - Timer_t ourTimer; - ourTimer.countDown = timeout->it_value.tv_sec; - ourTimer.interval = timeout->it_interval.tv_sec; - gTimerList.push_back(ourTimer); - } - - LeaveCriticalSection(&gLock); - - // indicate success - return 0; -} - -static unsigned int WINAPI RunTimer(LPVOID lpParameter) -{ - gFinishTimer = false; - - while (!gFinishTimer) - { - std::list<Timer_t>::iterator it; - EnterCriticalSection(&gLock); - - for (it = gTimerList.begin(); it != gTimerList.end(); it++) - { - Timer_t& rTimer(*it); - - rTimer.countDown --; - if (rTimer.countDown == 0) - { - if (gTimerFunc != NULL) - { - gTimerFunc(0); - } - if (rTimer.interval) - { - rTimer.countDown = rTimer.interval; - } - else - { - // mark for deletion - rTimer.countDown = -1; - } - } - } - - for (it = gTimerList.begin(); it != gTimerList.end(); it++) - { - Timer_t& rTimer(*it); - - if (rTimer.countDown == -1) - { - gTimerList.erase(it); - - // the iterator is now invalid, so restart search - it = gTimerList.begin(); - - // if the list is now empty, don't try to increment - // the iterator again - if (it == gTimerList.end()) break; - } - } - - LeaveCriticalSection(&gLock); - // we only need to have a 1 second resolution - Sleep(1000); - } - - return 0; -} - -int SetTimerHandler(void (__cdecl *func ) (int)) -{ - gTimerFunc = func; - return 0; -} - -void InitTimer(void) -{ - assert(!gTimerInitialised); - - InitializeCriticalSection(&gLock); - - // create our thread - HANDLE ourThread = (HANDLE)_beginthreadex(NULL, 0, RunTimer, 0, - CREATE_SUSPENDED, NULL); - SetThreadPriority(ourThread, THREAD_PRIORITY_LOWEST); - ResumeThread(ourThread); - - gTimerInitialised = true; -} - -void FiniTimer(void) -{ - assert(gTimerInitialised); - gFinishTimer = true; - EnterCriticalSection(&gLock); - DeleteCriticalSection(&gLock); - gTimerInitialised = false; -} - -//Our constants we need to keep track of -//globals +DWORD winerrno; struct passwd gTempPasswd; -bool EnableBackupRights( void ) +bool EnableBackupRights() { HANDLE hToken; TOKEN_PRIVILEGES token_priv; //open current process to adjust privileges - if( !OpenProcessToken( GetCurrentProcess( ), - TOKEN_ADJUST_PRIVILEGES, - &hToken )) + if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, + &hToken)) { - printf( "Cannot open process token: error %d\n", - (int)GetLastError() ); + ::syslog(LOG_ERR, "Failed to open process token: %s", + GetErrorMessage(GetLastError()).c_str()); return false; } //let's build the token privilege struct - //first, look up the LUID for the backup privilege - if( !LookupPrivilegeValue( NULL, //this system + if (!LookupPrivilegeValue( + NULL, //this system SE_BACKUP_NAME, //the name of the privilege - &( token_priv.Privileges[0].Luid )) ) //result + &( token_priv.Privileges[0].Luid ))) //result { - printf( "Cannot lookup backup privilege: error %d\n", - (int)GetLastError( ) ); + ::syslog(LOG_ERR, "Failed to lookup backup privilege: %s", + GetErrorMessage(GetLastError()).c_str()); + CloseHandle(hToken); return false; } @@ -198,24 +61,25 @@ bool EnableBackupRights( void ) // because we're going exit right after dumping the streams, there isn't // any need to save current state - if( !AdjustTokenPrivileges( hToken, //our process token + if (!AdjustTokenPrivileges( + hToken, //our process token false, //we're not disabling everything &token_priv, //address of structure - sizeof( token_priv ), //size of structure - NULL, NULL )) //don't save current state + sizeof(token_priv), //size of structure + NULL, NULL)) //don't save current state { //this function is a little tricky - if we were adjusting //more than one privilege, it could return success but not //adjust them all - in the general case, you need to trap this - printf( "Could not enable backup privileges: error %d\n", - (int)GetLastError( ) ); + ::syslog(LOG_ERR, "Failed to enable backup privilege: %s", + GetErrorMessage(GetLastError()).c_str()); + CloseHandle(hToken); return false; } - else - { - return true; - } + + CloseHandle(hToken); + return true; } // forward declaration @@ -267,7 +131,8 @@ std::string GetDefaultConfigFilePath(const std::string& rName) // Created: 4th February 2006 // // -------------------------------------------------------------------------- -WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) +WCHAR* ConvertToWideString(const char* pString, unsigned int codepage, + bool logErrors) { int len = MultiByteToWideChar ( @@ -282,9 +147,13 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) if (len == 0) { - ::syslog(LOG_WARNING, - "Failed to convert string to wide string: " - "error %d", GetLastError()); + winerrno = GetLastError(); + if (logErrors) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "%s", GetErrorMessage(winerrno).c_str()); + } errno = EINVAL; return NULL; } @@ -293,9 +162,13 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) if (buffer == NULL) { - ::syslog(LOG_WARNING, - "Failed to convert string to wide string: " - "out of memory"); + if (logErrors) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "out of memory"); + } + winerrno = ERROR_OUTOFMEMORY; errno = ENOMEM; return NULL; } @@ -312,9 +185,13 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) if (len == 0) { - ::syslog(LOG_WARNING, - "Failed to convert string to wide string: " - "error %i", GetLastError()); + winerrno = GetLastError(); + if (logErrors) + { + ::syslog(LOG_WARNING, + "Failed to convert string to wide string: " + "%s", GetErrorMessage(winerrno).c_str()); + } errno = EACCES; delete [] buffer; return NULL; @@ -336,7 +213,7 @@ WCHAR* ConvertToWideString(const char* pString, unsigned int codepage) // -------------------------------------------------------------------------- WCHAR* ConvertUtf8ToWideString(const char* pString) { - return ConvertToWideString(pString, CP_UTF8); + return ConvertToWideString(pString, CP_UTF8, true); } // -------------------------------------------------------------------------- @@ -425,7 +302,8 @@ char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage) bool ConvertEncoding(const std::string& rSource, int sourceCodePage, std::string& rDest, int destCodePage) { - WCHAR* pWide = ConvertToWideString(rSource.c_str(), sourceCodePage); + WCHAR* pWide = ConvertToWideString(rSource.c_str(), sourceCodePage, + true); if (pWide == NULL) { ::syslog(LOG_ERR, "Failed to convert string '%s' from " @@ -450,24 +328,26 @@ bool ConvertEncoding(const std::string& rSource, int sourceCodePage, return true; } -bool ConvertToUtf8(const char* pString, std::string& rDest, int sourceCodePage) +bool ConvertToUtf8(const std::string& rSource, std::string& rDest, + int sourceCodePage) { - return ConvertEncoding(pString, sourceCodePage, rDest, CP_UTF8); + return ConvertEncoding(rSource, sourceCodePage, rDest, CP_UTF8); } -bool ConvertFromUtf8(const char* pString, std::string& rDest, int destCodePage) +bool ConvertFromUtf8(const std::string& rSource, std::string& rDest, + int destCodePage) { - return ConvertEncoding(pString, CP_UTF8, rDest, destCodePage); + return ConvertEncoding(rSource, CP_UTF8, rDest, destCodePage); } -bool ConvertConsoleToUtf8(const char* pString, std::string& rDest) +bool ConvertConsoleToUtf8(const std::string& rSource, std::string& rDest) { - return ConvertEncoding(pString, GetConsoleCP(), rDest, CP_UTF8); + return ConvertToUtf8(rSource, rDest, GetConsoleCP()); } -bool ConvertUtf8ToConsole(const char* pString, std::string& rDest) +bool ConvertUtf8ToConsole(const std::string& rSource, std::string& rDest) { - return ConvertEncoding(pString, CP_UTF8, rDest, GetConsoleOutputCP()); + return ConvertFromUtf8(rSource, rDest, GetConsoleOutputCP()); } // -------------------------------------------------------------------------- @@ -506,6 +386,7 @@ std::string ConvertPathToAbsoluteUnicode(const char *pFileName) "Failed to open '%s': path too long", pFileName); errno = ENAMETOOLONG; + winerrno = ERROR_INVALID_NAME; tmpStr = ""; return tmpStr; } @@ -581,6 +462,8 @@ std::string GetErrorMessage(DWORD errorCode) // -------------------------------------------------------------------------- HANDLE openfile(const char *pFileName, int flags, int mode) { + winerrno = ERROR_INVALID_FUNCTION; + std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName); @@ -654,12 +537,37 @@ HANDLE openfile(const char *pFileName, int flags, int mode) if (hdir == INVALID_HANDLE_VALUE) { + winerrno = GetLastError(); + switch(winerrno) + { + case ERROR_SHARING_VIOLATION: + errno = EBUSY; + break; + + default: + errno = EINVAL; + } + ::syslog(LOG_WARNING, "Failed to open file '%s': " "%s", pFileName, GetErrorMessage(GetLastError()).c_str()); + return INVALID_HANDLE_VALUE; } + if (flags & O_APPEND) + { + if (SetFilePointer(hdir, 0, NULL, FILE_END) == + INVALID_SET_FILE_POINTER) + { + winerrno = GetLastError(); + errno = EINVAL; + CloseHandle(hdir); + return INVALID_HANDLE_VALUE; + } + } + + winerrno = NO_ERROR; return hdir; } @@ -667,11 +575,13 @@ HANDLE openfile(const char *pFileName, int flags, int mode) // // Function // Name: emu_fstat -// Purpose: replacement for fstat supply a windows handle +// Purpose: replacement for fstat. Supply a windows handle. +// Returns a struct emu_stat to have room for 64-bit +// file identifier in st_ino (mingw allows only 16!) // Created: 25th October 2004 // // -------------------------------------------------------------------------- -int emu_fstat(HANDLE hdir, struct stat * st) +int emu_fstat(HANDLE hdir, struct emu_stat * st) { if (hdir == INVALID_HANDLE_VALUE) { @@ -702,8 +612,8 @@ int emu_fstat(HANDLE hdir, struct stat * st) // This is how we get our INODE (equivalent) information ULARGE_INTEGER conv; conv.HighPart = fi.nFileIndexHigh; - conv.LowPart = fi.nFileIndexLow; - st->st_ino = (_ino_t)conv.QuadPart; + conv.LowPart = fi.nFileIndexLow; + st->st_ino = conv.QuadPart; // get the time information st->st_ctime = ConvertFileTimeToTime_t(&fi.ftCreationTime); @@ -716,20 +626,8 @@ int emu_fstat(HANDLE hdir, struct stat * st) } else { - // size of the file - LARGE_INTEGER st_size; - memset(&st_size, 0, sizeof(st_size)); - - if (!GetFileSizeEx(hdir, &st_size)) - { - ::syslog(LOG_WARNING, "Failed to get file size: " - "%s", GetErrorMessage(GetLastError()).c_str()); - errno = EACCES; - return -1; - } - - conv.HighPart = st_size.HighPart; - conv.LowPart = st_size.LowPart; + conv.HighPart = fi.nFileSizeHigh; + conv.LowPart = fi.nFileSizeLow; st->st_size = (_off_t)conv.QuadPart; } @@ -862,12 +760,14 @@ HANDLE OpenFileByNameUtf8(const char* pFileName, DWORD flags) // // Function // Name: emu_stat -// Purpose: replacement for the lstat and stat functions, -// works with unicode filenames supplied in utf8 format +// Purpose: replacement for the lstat and stat functions. +// Works with unicode filenames supplied in utf8. +// Returns a struct emu_stat to have room for 64-bit +// file identifier in st_ino (mingw allows only 16!) // Created: 25th October 2004 // // -------------------------------------------------------------------------- -int emu_stat(const char * pName, struct stat * st) +int emu_stat(const char * pName, struct emu_stat * st) { HANDLE handle = OpenFileByNameUtf8(pName, FILE_READ_ATTRIBUTES | FILE_READ_EA); @@ -1078,7 +978,7 @@ DIR *opendir(const char *name) } pDir->name = ConvertUtf8ToWideString(dirName.c_str()); - // We are responsible for freeing dir->name + // We are responsible for freeing dir->name with delete[] if (pDir->name == NULL) { @@ -1396,16 +1296,20 @@ static bool sHaveWarnedEventLogFull = false; void openlog(const char * daemonName, int, int) { + std::string nameStr = "Box Backup ("; + nameStr += daemonName; + nameStr += ")"; + // register a default event source, so that we can // log errors with the process of adding or registering our own. gSyslogH = RegisterEventSource( NULL, // uses local computer - daemonName); // source name + nameStr.c_str()); // source name if (gSyslogH == NULL) { } - char* name = strdup(daemonName); + char* name = strdup(nameStr.c_str()); BOOL success = AddEventSource(name, 0); free(name); @@ -1415,7 +1319,7 @@ void openlog(const char * daemonName, int, int) return; } - HANDLE newSyslogH = RegisterEventSource(NULL, daemonName); + HANDLE newSyslogH = RegisterEventSource(NULL, nameStr.c_str()); if (newSyslogH == NULL) { ::syslog(LOG_ERR, "Failed to register our own event source: " @@ -1484,8 +1388,6 @@ void syslog(int loglevel, const char *frmt, ...) va_end(args); - LPCSTR strings[] = { buffer, NULL }; - if (gSyslogH == 0) { printf("%s\r\n", buffer); @@ -1493,17 +1395,45 @@ void syslog(int loglevel, const char *frmt, ...) return; } - if (!ReportEvent(gSyslogH, // event log handle - errinfo, // event type - 0, // category zero - MSG_ERR, // event identifier - - // we will call them all the same - NULL, // no user security identifier - 1, // one substitution string - 0, // no data - strings, // pointer to string array - NULL)) // pointer to data + WCHAR* pWide = ConvertToWideString(buffer, CP_UTF8, false); + // must delete[] pWide + DWORD result; + + if (pWide == NULL) + { + std::string buffer2 = buffer; + buffer2 += " (failed to convert string encoding)"; + LPCSTR strings[] = { buffer2.c_str(), NULL }; + + result = ReportEventA(gSyslogH, // event log handle + errinfo, // event type + 0, // category zero + MSG_ERR, // event identifier - + // we will call them all the same + NULL, // no user security identifier + 1, // one substitution string + 0, // no data + strings, // pointer to string array + NULL); // pointer to data + } + else + { + LPCWSTR strings[] = { pWide, NULL }; + result = ReportEventW(gSyslogH, // event log handle + errinfo, // event type + 0, // category zero + MSG_ERR, // event identifier - + // we will call them all the same + NULL, // no user security identifier + 1, // one substitution string + 0, // no data + strings, // pointer to string array + NULL); // pointer to data + delete [] pWide; + } + + if (result == 0) { DWORD err = GetLastError(); if (err == ERROR_LOG_FILE_FULL) @@ -1527,9 +1457,6 @@ void syslog(int loglevel, const char *frmt, ...) { sHaveWarnedEventLogFull = false; } - - // printf("%s\r\n", buffer); - // fflush(stdout); } int emu_chdir(const char* pDirName) diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 8ab74130..811e6495 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -1,5 +1,17 @@ // emulates unix syscalls to win32 functions +#ifdef WIN32 + #define EMU_STRUCT_STAT struct emu_stat + #define EMU_STAT emu_stat + #define EMU_FSTAT emu_fstat + #define EMU_LSTAT emu_stat +#else + #define EMU_STRUCT_STAT struct stat + #define EMU_STAT ::stat + #define EMU_FSTAT ::fstat + #define EMU_LSTAT ::lstat +#endif + #if ! defined EMU_INCLUDE && defined WIN32 #define EMU_INCLUDE @@ -28,11 +40,6 @@ #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 @@ -78,11 +85,6 @@ #define fileno(struct_file) _fileno(struct_file) #endif -int SetTimerHandler(void (__cdecl *func ) (int)); -int setitimer(int type, struct itimerval *timeout, void *arg); -void InitTimer(void); -void FiniTimer(void); - struct passwd { char *pw_name; char *pw_passwd; @@ -184,13 +186,6 @@ inline int geteuid(void) #define timespec timeval -//not available in win32 -struct itimerval -{ - timeval it_interval; - timeval it_value; -}; - //win32 deals in usec not nsec - so need to ensure this follows through #define tv_nsec tv_usec @@ -205,6 +200,7 @@ struct itimerval //again need to verify these #define S_IFLNK 1 +#define S_IFSOCK 0 #define S_ISLNK(x) ( false ) @@ -244,6 +240,7 @@ int closedir(DIR *dp); // local constant to open file exclusively without shared access #define O_LOCK 0x10000 +extern DWORD winerrno; /* used to report errors from openfile() */ HANDLE openfile(const char *filename, int flags, int mode); #define LOG_DEBUG LOG_INFO @@ -260,6 +257,15 @@ void openlog (const char * daemonName, int, int); void closelog(void); void syslog (int loglevel, const char *fmt, ...); +#define LOG_LOCAL0 0 +#define LOG_LOCAL1 0 +#define LOG_LOCAL2 0 +#define LOG_LOCAL3 0 +#define LOG_LOCAL4 0 +#define LOG_LOCAL5 0 +#define LOG_LOCAL6 0 +#define LOG_DAEMON 0 + #ifndef __MINGW32__ #define strtoll _strtoi64 #endif @@ -292,6 +298,11 @@ inline int ioctl(SOCKET sock, int flag, int * something) return 0; } +extern "C" inline int getpid() +{ + return (int)GetCurrentProcessId(); +} + inline int waitpid(pid_t pid, int *status, int) { return 0; @@ -303,27 +314,19 @@ struct statfs TCHAR f_mntonname[MAX_PATH]; }; -#if 0 -// I think this should get us going -// Although there is a warning about -// mount points in win32 can now exists - which means inode number can be -// duplicated, so potential of a problem - perhaps this needs to be -// implemented with a little more thought... TODO - -struct stat { - //_dev_t st_dev; - u_int64_t st_ino; +struct emu_stat { + int st_dev; + uint64_t st_ino; DWORD st_mode; short st_nlink; short st_uid; short st_gid; //_dev_t st_rdev; - u_int64_t st_size; + uint64_t st_size; time_t st_atime; time_t st_mtime; time_t st_ctime; }; -#endif // 0 // need this for conversions time_t ConvertFileTimeToTime_t(FILETIME *fileTime); @@ -332,8 +335,8 @@ bool ConvertTime_tToFileTime(const time_t from, FILETIME *pTo); int emu_chdir (const char* pDirName); int emu_mkdir (const char* pPathName); int emu_unlink (const char* pFileName); -int emu_fstat (HANDLE file, struct stat* st); -int emu_stat (const char* pName, struct stat* st); +int emu_fstat (HANDLE file, struct emu_stat* st); +int emu_stat (const char* pName, struct emu_stat* st); int emu_utimes (const char* pName, const struct timeval[]); int emu_chmod (const char* pName, mode_t mode); char* emu_getcwd (char* pBuffer, int BufSize); @@ -342,14 +345,22 @@ int emu_rename (const char* pOldName, const char* pNewName); #define chdir(directory) emu_chdir (directory) #define mkdir(path, mode) emu_mkdir (path) #define unlink(file) emu_unlink (file) -#define stat(filename, struct) emu_stat (filename, struct) -#define lstat(filename, struct) emu_stat (filename, struct) -#define fstat(handle, struct) emu_fstat (handle, struct) #define utimes(buffer, times) emu_utimes (buffer, times) #define chmod(file, mode) emu_chmod (file, mode) #define getcwd(buffer, size) emu_getcwd (buffer, size) #define rename(oldname, newname) emu_rename (oldname, newname) +// Not safe to replace stat/fstat/lstat on mingw at least, as struct stat +// has a 16-bit st_ino and we need a 64-bit one. +// +// #define stat(filename, struct) emu_stat (filename, struct) +// #define lstat(filename, struct) emu_stat (filename, struct) +// #define fstat(handle, struct) emu_fstat (handle, struct) +// +// But lstat doesn't exist on Windows, so we have to provide something: + +#define lstat(filename, struct) stat(filename, struct) + int statfs(const char * name, struct statfs * s); int poll(struct pollfd *ufds, unsigned long nfds, int timeout); @@ -374,8 +385,8 @@ bool ConvertToUtf8 (const std::string& rSource, std::string& rDest, int sourceCodePage); bool ConvertFromUtf8 (const std::string& rSource, std::string& rDest, int destCodePage); -bool ConvertUtf8ToConsole(const char* pString, std::string& rDest); -bool ConvertConsoleToUtf8(const char* pString, std::string& rDest); +bool ConvertUtf8ToConsole(const std::string& rSource, std::string& rDest); +bool ConvertConsoleToUtf8(const std::string& rSource, std::string& rDest); // Utility function which returns a default config file name, // based on the path of the current executable. diff --git a/lib/win32/getopt_long.cxx b/lib/win32/getopt_long.cpp index a24930aa..5d910e1b 100755 --- a/lib/win32/getopt_long.cxx +++ b/lib/win32/getopt_long.cpp @@ -69,7 +69,6 @@ #if defined _MSC_VER || defined __MINGW32__
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
-#endif
#ifdef REPLACE_GETOPT
int opterr = 1; /* if error message should be printed */
@@ -548,3 +547,4 @@ getopt_long_only(int nargc, char * const *nargv, const char *options, FLAG_PERMUTE|FLAG_LONGONLY));
}
+#endif // defined _MSC_VER || defined __MINGW32__
|