summaryrefslogtreecommitdiff
path: root/lib/win32/emu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/win32/emu.cpp')
-rw-r--r--lib/win32/emu.cpp363
1 files changed, 145 insertions, 218 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)