// distribution boxbackup-0.10 (svn version: 494)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. All use of this software and associated advertising materials must
// display the following acknowledgment:
// This product includes software developed by Ben Summers.
// 4. The names of the Authors may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// [Where legally impermissible the Authors do not disclaim liability for
// direct physical injury or death caused solely by defects in the software
// unless it is modified by a third party.]
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//
//
// Box Backup Win32 native port by Nick Knight
// Need at least 0x0500 to use GetFileSizeEx on Cygwin/MinGW
#define WINVER 0x0500
#include "Box.h"
#ifdef WIN32
// #include "emu.h"
#include <windows.h>
#include <fcntl.h>
// #include <atlenc.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#include <string>
#include <list>
// our implementation for a timer, based on a
// simple thread which sleeps for a period of time
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)
{
if (ITIMER_VIRTUAL == type)
{
EnterCriticalSection(&gLock);
// we only need seconds for the mo!
if (timeout->it_value.tv_sec == 0 &&
timeout->it_value.tv_usec == 0)
{
gTimerList.clear();
}
else
{
Timer_t ourTimer;
ourTimer.countDown = timeout->it_value.tv_sec;
ourTimer.interval = timeout->it_interval.tv_sec;
gTimerList.push_back(ourTimer);
}
LeaveCriticalSection(&gLock);
}
// 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)
{
InitializeCriticalSection(&gLock);
// create our thread
HANDLE ourThread = (HANDLE)_beginthreadex(NULL, 0, RunTimer, 0,
CREATE_SUSPENDED, NULL);
SetThreadPriority(ourThread, THREAD_PRIORITY_LOWEST);
ResumeThread(ourThread);
}
void FiniTimer(void)
{
gFinishTimer = true;
EnterCriticalSection(&gLock);
DeleteCriticalSection(&gLock);
}
//Our constants we need to keep track of
//globals
struct passwd gTempPasswd;
bool EnableBackupRights( void )
{
HANDLE hToken;
TOKEN_PRIVILEGES token_priv;
//open current process to adjust privileges
if( !OpenProcessToken( GetCurrentProcess( ),
TOKEN_ADJUST_PRIVILEGES,
&hToken ))
{
printf( "Cannot open process token: error %d\n",
(int)GetLastError() );
return false;
}
//let's build the token privilege struct -
//first, look up the LUID for the backup privilege
if( !LookupPrivilegeValue( NULL, //this system
SE_BACKUP_NAME, //the name of the privilege
&( token_priv.Privileges[0].Luid )) ) //result
{
printf( "Cannot lookup backup privilege: error %d\n",
(int)GetLastError( ) );
return false;
}
token_priv.PrivilegeCount = 1;
token_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// now set the privilege
// 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
false, //we're not disabling everything
&token_priv, //address of structure
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( ) );
return false;
}
else
{
return true;
}
}
// --------------------------------------------------------------------------
//
// Function
// Name: ConvertToWideString
// Purpose: Converts a string from specified codepage to
// a wide string (WCHAR*). Returns a buffer which
// MUST be freed by the caller with delete[].
// In case of fire, logs the error and returns NULL.
// Created: 4th February 2006
//
// --------------------------------------------------------------------------
WCHAR* ConvertToWideString(const char* pString, unsigned int codepage)
{
int len = MultiByteToWideChar
(
codepage, // source code page
0, // character-type options
pString, // string to map
-1, // number of bytes in string - auto detect
NULL, // wide-character buffer
0 // size of buffer - work out
// how much space we need
);
if (len == 0)
{
::syslog(LOG_WARNING,
"Failed to convert string to wide string: "
"error %d", GetLastError());
errno = EINVAL;
return NULL;
}
WCHAR* buffer = new WCHAR[len];
if (buffer == NULL)
{
::syslog(LOG_WARNING,
"Failed to convert string to wide string: "
"out of memory");
errno = ENOMEM;
return NULL;
}
len = MultiByteToWideChar
(
codepage, // source code page
0, // character-type options
pString, // string to map
-1, // number of bytes in string - auto detect
buffer, // wide-character buffer
len // size of buffer
);
if (len == 0)
{
::syslog(LOG_WARNING,
"Failed to convert string to wide string: "
"error %i", GetLastError());
errno = EACCES;
delete [] buffer;
return NULL;
}
return buffer;
}
// --------------------------------------------------------------------------
//
// Function
// Name: ConvertUtf8ToWideString
// Purpose: Converts a string from UTF-8 to a wide string.
// Returns a buffer which MUST be freed by the caller
// with delete[].
// In case of fire, logs the error and returns NULL.
// Created: 4th February 2006
//
// --------------------------------------------------------------------------
WCHAR* ConvertUtf8ToWideString(const char* pString)
{
return ConvertToWideString(pString, CP_UTF8);
}
// --------------------------------------------------------------------------
//
// Function
// Name: ConvertFromWideString
// Purpose: Converts a wide string to a narrow string in the
// specified code page. Returns a buffer which MUST
// be freed by the caller with delete[].
// In case of fire, logs the error and returns NULL.
// Created: 4th February 2006
//
// --------------------------------------------------------------------------
char* ConvertFromWideString(const WCHAR* pString, unsigned int codepage)
{
int len = WideCharToMultiByte
(
codepage, // destination code page
0, // character-type options
pString, // string to map
-1, // number of bytes in string - auto detect
NULL, // output buffer
0, // size of buffer - work out
// how much space we need
NULL, // replace unknown chars with system default
NULL // don't tell us when that happened
);
if (len == 0)
{
::syslog(LOG_WARNING,
"Failed to convert wide string to narrow: "
"error %d", GetLastError());
errno = EINVAL;
return NULL;
}
char* buffer = new char[len];
if (buffer == NULL)
{
::syslog(LOG_WARNING,
"Failed to convert wide string to narrow: "
"out of memory");
errno = ENOMEM;
return NULL;
}
len = WideCharToMultiByte
(
codepage, // source code page
0, // character-type options
pString, // string to map
-1, // number of bytes in string - auto detect
buffer, // output buffer
len, // size of buffer
NULL, // replace unknown chars with system default
NULL // don't tell us when that happened
);
if (len == 0)
{
::syslog(LOG_WARNING,
"Failed to convert wide string to narrow: "
"error %i", GetLastError());
errno = EACCES;
delete [] buffer;
return NULL;
}
return buffer;
}
// --------------------------------------------------------------------------
//
// Function
// Name: ConvertUtf8ToConsole
// Purpose: Converts a string from UTF-8 to the console
// code page. On success, replaces contents of rDest
// and returns true. In case of fire, logs the error
// and returns false.
// Created: 4th February 2006
//
// --------------------------------------------------------------------------
bool ConvertUtf8ToConsole(const char* pString, std::string& rDest)
{
WCHAR* pWide = ConvertToWideString(pString, CP_UTF8);
if (pWide == NULL)
{
return false;
}
char* pConsole = ConvertFromWideString(pWide, GetConsoleOutputCP());
delete [] pWide;
if (!pConsole)
{
return false;
}
rDest = pConsole;
delete [] pConsole;
return true;
}
// --------------------------------------------------------------------------
//
// Function
// Name: ConvertConsoleToUtf8
// Purpose: Converts a string from the console code page
// to UTF-8. On success, replaces contents of rDest
// and returns true. In case of fire, logs the error
// and returns false.
// Created: 4th February 2006
//
// --------------------------------------------------------------------------
bool ConvertConsoleToUtf8(const char* pString, std::string& rDest)
{
WCHAR* pWide = ConvertToWideString(pString, GetConsoleCP());
if (pWide == NULL)
{
return false;
}
char* pConsole = ConvertFromWideString(pWide, CP_UTF8);
delete [] pWide;
if (!pConsole)
{
return false;
}
rDest = pConsole;
delete [] pConsole;
return true;
}
// --------------------------------------------------------------------------
//
// Function
// Name: ConvertPathToAbsoluteUnicode
// Purpose: Converts relative paths to absolute (with unicode marker)
// Created: 4th February 2006
//
// --------------------------------------------------------------------------
std::string ConvertPathToAbsoluteUnicode(const char *pFileName)
{
std::string tmpStr("\\\\?\\");
// Is the path relative or absolute?
// Absolute paths on Windows are always a drive letter
// followed by ':'
if (pFileName[1] != ':')
{
// Must be relative. We need to get the
// current directory to make it absolute.
char wd[PATH_MAX];
if (::getcwd(wd, PATH_MAX) == 0)
{
::syslog(LOG_WARNING,
"Failed to open '%s': path too long",
pFileName);
errno = ENAMETOOLONG;
tmpStr = "";
return tmpStr;
}
tmpStr += wd;
if (tmpStr[tmpStr.length()] != '\\')
{
tmpStr += '\\';
}
}
tmpStr += pFileName;
return tmpStr;
}
// --------------------------------------------------------------------------
//
// Function
// Name: openfile
// Purpose: replacement for any open calls - handles unicode filenames - supplied in utf8
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
HANDLE openfile(const char *pFileName, int flags, int mode)
{
std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName);
if (AbsPathWithUnicode.size() == 0)
{
// error already logged by ConvertPathToAbsoluteUnicode()
return NULL;
}
WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str());
// We are responsible for freeing pBuffer
if (pBuffer == NULL)
{
// error already logged by ConvertUtf8ToWideString()
return NULL;
}
// flags could be O_WRONLY | O_CREAT | O_RDONLY
DWORD createDisposition = OPEN_EXISTING;
DWORD shareMode = FILE_SHARE_READ;
DWORD accessRights = FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA;
if (flags & O_WRONLY)
{
shareMode = FILE_SHARE_WRITE;
}
if (flags & O_RDWR)
{
shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
}
if (flags & O_CREAT)
{
createDisposition = OPEN_ALWAYS;
shareMode |= FILE_SHARE_WRITE;
accessRights |= FILE_WRITE_ATTRIBUTES
| FILE_WRITE_DATA | FILE_WRITE_EA
| FILE_ALL_ACCESS;
}
if (flags & O_TRUNC)
{
createDisposition = CREATE_ALWAYS;
}
if (flags & O_EXCL)
{
shareMode = 0;
}
HANDLE hdir = CreateFileW(pBuffer,
accessRights,
shareMode,
NULL,
createDisposition,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
delete [] pBuffer;
if (hdir == INVALID_HANDLE_VALUE)
{
::syslog(LOG_WARNING, "Failed to open file %s: "
"error %i", pFileName, GetLastError());
return NULL;
}
return hdir;
}
// MinGW provides a getopt implementation
#ifndef __MINGW32__
//works with getopt
char *optarg;
//optind looks like an index into the string - how far we have moved along
int optind = 1;
char nextchar = -1;
#endif
// --------------------------------------------------------------------------
//
// Function
// Name: emu_fstat
// Purpose: replacement for fstat supply a windows handle
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
int emu_fstat(HANDLE hdir, struct stat * st)
{
ULARGE_INTEGER conv;
if (hdir == INVALID_HANDLE_VALUE)
{
::syslog(LOG_ERR, "Error: invalid file handle in emu_fstat()");
errno = EBADF;
return -1;
}
BY_HANDLE_FILE_INFORMATION fi;
if (!GetFileInformationByHandle(hdir, &fi))
{
::syslog(LOG_WARNING, "Failed to read file information: "
"error %d", GetLastError());
errno = EACCES;
return -1;
}
memset(st, 0, sizeof(*st));
// This next example is how we get our INODE (equivalent) information
conv.HighPart = fi.nFileIndexHigh;
conv.LowPart = fi.nFileIndexLow;
st->st_ino = (_ino_t)conv.QuadPart;
// get the time information
st->st_ctime = ConvertFileTimeToTime_t(&fi.ftCreationTime);
st->st_atime = ConvertFileTimeToTime_t(&fi.ftLastAccessTime);
st->st_mtime = ConvertFileTimeToTime_t(&fi.ftLastWriteTime);
// size of the file
LARGE_INTEGER st_size;
if (!GetFileSizeEx(hdir, &st_size))
{
::syslog(LOG_WARNING, "Failed to get file size: error %d",
GetLastError());
errno = EACCES;
return -1;
}
conv.HighPart = st_size.HighPart;
conv.LowPart = st_size.LowPart;
st->st_size = (_off_t)conv.QuadPart;
//the mode of the file
st->st_mode = 0;
//DWORD res = GetFileAttributes((LPCSTR)tmpStr.c_str());
if (INVALID_FILE_ATTRIBUTES != fi.dwFileAttributes)
{
if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
st->st_mode |= S_IFDIR;
}
else
{
st->st_mode |= S_IFREG;
}
}
else
{
::syslog(LOG_WARNING, "Failed to get file attributes: "
"error %d", GetLastError());
errno = EACCES;
return -1;
}
return 0;
}
// --------------------------------------------------------------------------
//
// Function
// Name: OpenFileByNameUtf8
// Purpose: Converts filename to Unicode and returns
// a handle to it. In case of error, sets errno,
// logs the error and returns NULL.
// Created: 10th December 2004
//
// --------------------------------------------------------------------------
HANDLE OpenFileByNameUtf8(const char* pFileName)
{
std::string AbsPathWithUnicode = ConvertPathToAbsoluteUnicode(pFileName);
if (AbsPathWithUnicode.size() == 0)
{
// error already logged by ConvertPathToAbsoluteUnicode()
return NULL;
}
WCHAR* pBuffer = ConvertUtf8ToWideString(AbsPathWithUnicode.c_str());
// We are responsible for freeing pBuffer
if (pBuffer == NULL)
{
// error already logged by ConvertUtf8ToWideString()
return NULL;
}
HANDLE handle = CreateFileW(pBuffer,
FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_READ_EA,
FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (handle == INVALID_HANDLE_VALUE)
{
// if our open fails we should always be able to
// open in this mode - to get the inode information
// at least one process must have the file open -
// in this case someone else does.
handle = CreateFileW(pBuffer,
0,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
}
delete [] pBuffer;
if (handle == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError();
if (err == ERROR_FILE_NOT_FOUND)
{
errno = ENOENT;
}
else
{
::syslog(LOG_WARNING,
"Failed to open '%s': error %d", pFileName, err);
errno = EACCES;
}
return NULL;
}
return handle;
}
// --------------------------------------------------------------------------
//
// Function
// Name: emu_stat
// Purpose: replacement for the lstat and stat functions,
// works with unicode filenames supplied in utf8 format
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
int emu_stat(const char * pName, struct stat * st)
{
// at the mo
st->st_uid = 0;
st->st_gid = 0;
st->st_nlink = 1;
HANDLE handle = OpenFileByNameUtf8(pName);
if (handle == NULL)
{
// errno already set and error logged by OpenFileByNameUtf8()
return -1;
}
int retVal = emu_fstat(handle, st);
if (retVal != 0)
{
// error logged, but without filename
::syslog(LOG_WARNING, "Failed to get file information "
"for '%s'", pName);
}
// close the handle
CloseHandle(handle);
return retVal;
}
// --------------------------------------------------------------------------
//
// Function
// Name: statfs
// Purpose: returns the mount point of where a file is located -
// in this case the volume serial number
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
int statfs(const char * pName, struct statfs * s)
{
HANDLE handle = OpenFileByNameUtf8(pName);
if (handle == NULL)
{
// errno already set and error logged by OpenFileByNameUtf8()
return -1;
}
BY_HANDLE_FILE_INFORMATION fi;
if (!GetFileInformationByHandle(handle, &fi))
{
::syslog(LOG_WARNING, "Failed to get file information "
"for '%s': error %d", pName, GetLastError());
CloseHandle(handle);
errno = EACCES;
return -1;
}
// convert volume serial number to a string
_ui64toa(fi.dwVolumeSerialNumber, s->f_mntonname + 1, 16);
// pseudo unix mount point
s->f_mntonname[0] = DIRECTORY_SEPARATOR_ASCHAR;
CloseHandle(handle); // close the handle
return 0;
}
// --------------------------------------------------------------------------
//
// Function
// Name: opendir
// Purpose: replacement for unix function, uses win32 findfirst routines
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
DIR *opendir(const char *name)
{
if (!name || !name[0])
{
errno = EINVAL;
return NULL;
}
std::string dirName(name);
//append a '\' win32 findfirst is sensitive to this
if ( dirName[dirName.size()] != '\\' || dirName[dirName.size()] != '/' )
{
dirName += '\\';
}
// what is the search string? - everything
dirName += '*';
DIR *pDir = new DIR;
if (pDir == NULL)
{
errno = ENOMEM;
return NULL;
}
pDir->name = ConvertUtf8ToWideString(dirName.c_str());
// We are responsible for freeing dir->name
if (pDir->name == NULL)
{
delete pDir;
return NULL;
}
pDir->fd = _wfindfirst((const wchar_t*)pDir->name, &(pDir->info));
if (pDir->fd == -1)
{
delete [] pDir->name;
delete pDir;
return NULL;
}
pDir->result.d_name = 0;
return pDir;
}
// this kinda makes it not thread friendly!
// but I don't think it needs to be.
char tempbuff[MAX_PATH];
// --------------------------------------------------------------------------
//
// Function
// Name: readdir
// Purpose: as function above
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
struct dirent *readdir(DIR *dp)
{
try
{
struct dirent *den = NULL;
if (dp && dp->fd != -1)
{
if (!dp->result.d_name ||
_wfindnext(dp->fd, &dp->info) != -1)
{
den = &dp->result;
std::wstring input(dp->info.name);
memset(tempbuff, 0, sizeof(tempbuff));
WideCharToMultiByte(CP_UTF8, 0, dp->info.name,
-1, &tempbuff[0], sizeof (tempbuff),
NULL, NULL);
//den->d_name = (char *)dp->info.name;
den->d_name = &tempbuff[0];
}
}
else
{
errno = EBADF;
}
return den;
}
catch (...)
{
printf("Caught readdir");
}
return NULL;
}
// --------------------------------------------------------------------------
//
// Function
// Name: closedir
// Purpose: as function above
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
int closedir(DIR *dp)
{
try
{
int finres = -1;
if (dp)
{
if(dp->fd != -1)
{
finres = _findclose(dp->fd);
}
delete [] dp->name;
delete dp;
}
if (finres == -1) // errors go to EBADF
{
errno = EBADF;
}
return finres;
}
catch (...)
{
printf("Caught closedir");
}
return -1;
}
// --------------------------------------------------------------------------
//
// Function
// Name: poll
// Purpose: a weak implimentation (just enough for box)
// of the unix poll for winsock2
// Created: 25th October 2004
//
// --------------------------------------------------------------------------
int poll (struct pollfd *ufds, unsigned long nfds, int timeout)
{
try
{
fd_set readfd;
fd_set writefd;
readfd.fd_count = 0;
writefd.fd_count = 0;
struct pollfd *ufdsTmp = ufds;
timeval timOut;
timeval *tmpptr;
if (timeout == INFTIM)
tmpptr = NULL;
else
tmpptr = &timOut;
timOut.tv_sec = timeout / 1000;
timOut.tv_usec = timeout * 1000;
if (ufds->events & POLLIN)
{
for (unsigned long i = 0; i < nfds; i++)
{
readfd.fd_array[i] = ufdsTmp->fd;
readfd.fd_count++;
}
}
if (ufds->events & POLLOUT)
{
for (unsigned long i = 0; i < nfds; i++)
{
writefd.fd_array[i]=ufdsTmp->fd;
writefd.fd_count++;
}
}
int noffds = select(0, &readfd, &writefd, 0, tmpptr);
if (noffds == SOCKET_ERROR)
{
// int errval = WSAGetLastError();
ufdsTmp = ufds;
for (unsigned long i = 0; i < nfds; i++)
{
ufdsTmp->revents = POLLERR;
ufdsTmp++;
}
return (-1);
}
return noffds;
}
catch (...)
{
printf("Caught poll");
}
return -1;
}
HANDLE gSyslogH = 0;
static bool sHaveWarnedEventLogFull = false;
void syslog(int loglevel, const char *frmt, ...)
{
WORD errinfo;
char buffer[1024];
std::string sixfour(frmt);
switch (loglevel)
{
case LOG_INFO:
errinfo = EVENTLOG_INFORMATION_TYPE;
break;
case LOG_ERR:
errinfo = EVENTLOG_ERROR_TYPE;
break;
case LOG_WARNING:
errinfo = EVENTLOG_WARNING_TYPE;
break;
default:
errinfo = EVENTLOG_WARNING_TYPE;
break;
}
// taken from MSDN
int sixfourpos;
while ( (sixfourpos = (int)sixfour.find("%ll")) != -1 )
{
// maintain portability - change the 64 bit formater...
std::string temp = sixfour.substr(0,sixfourpos);
temp += "%I64";
temp += sixfour.substr(sixfourpos+3, sixfour.length());
sixfour = temp;
}
// printf("parsed string is:%s\r\n", sixfour.c_str());
va_list args;
va_start(args, frmt);
int len = vsnprintf(buffer, sizeof(buffer)-1, sixfour.c_str(), args);
ASSERT(len < sizeof(buffer))
buffer[sizeof(buffer)-1] = 0;
va_end(args);
LPCSTR strings[] = { buffer, NULL };
if (!ReportEvent(gSyslogH, // event log handle
errinfo, // event type
0, // category zero
MSG_ERR_EXIST, // 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
{
DWORD err = GetLastError();
if (err == ERROR_LOG_FILE_FULL)
{
if (!sHaveWarnedEventLogFull)
{
printf("Unable to send message to Event Log "
"(Event Log is full):\r\n");
sHaveWarnedEventLogFull = TRUE;
}
}
else
{
printf("Unable to send message to Event Log: "
"error %i:\r\n", (int)err);
}
}
else
{
sHaveWarnedEventLogFull = false;
}
printf("%s\r\n", buffer);
}
int emu_chdir(const char* pDirName)
{
WCHAR* pBuffer = ConvertUtf8ToWideString(pDirName);
if (!pBuffer) return -1;
int result = SetCurrentDirectoryW(pBuffer);
delete [] pBuffer;
if (result != 0) return 0;
errno = EACCES;
return -1;
}
char* emu_getcwd(char* pBuffer, int BufSize)
{
DWORD len = GetCurrentDirectoryW(0, NULL);
if (len == 0)
{
errno = EINVAL;
return NULL;
}
if (len > BufSize)
{
errno = ENAMETOOLONG;
return NULL;
}
WCHAR* pWide = new WCHAR [len];
if (!pWide)
{
errno = ENOMEM;
return NULL;
}
DWORD result = GetCurrentDirectoryW(len, pWide);
if (result <= 0 || result >= len)
{
errno = EACCES;
return NULL;
}
char* pUtf8 = ConvertFromWideString(pWide, CP_UTF8);
delete [] pWide;
if (!pUtf8)
{
return NULL;
}
strncpy(pBuffer, pUtf8, BufSize - 1);
pBuffer[BufSize - 1] = 0;
delete [] pUtf8;
return pBuffer;
}
int emu_mkdir(const char* pPathName)
{
WCHAR* pBuffer = ConvertToWideString(pPathName, CP_UTF8);
if (!pBuffer)
{
return -1;
}
BOOL result = CreateDirectoryW(pBuffer, NULL);
delete [] pBuffer;
if (!result)
{
errno = EACCES;
return -1;
}
return 0;
}
int emu_unlink(const char* pFileName)
{
WCHAR* pBuffer = ConvertToWideString(pFileName, CP_UTF8);
if (!pBuffer)
{
return -1;
}
BOOL result = DeleteFileW(pBuffer);
delete [] pBuffer;
if (!result)
{
errno = EACCES;
return -1;
}
return 0;
}
int console_read(char* pBuffer, size_t BufferSize)
{
HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE)
{
::fprintf(stderr, "Failed to get a handle on standard input: "
"error %d\n", GetLastError());
return -1;
}
int WideSize = BufferSize / 5;
WCHAR* pWideBuffer = new WCHAR [WideSize];
if (!pWideBuffer)
{
::perror("Failed to allocate wide character buffer");
return -1;
}
DWORD numCharsRead = 0;
if (!ReadConsoleW(
hConsole,
pWideBuffer,
WideSize - 1,
&numCharsRead,
NULL // reserved
))
{
::fprintf(stderr, "Failed to read from console: error %d\n",
GetLastError());
return -1;
}
pWideBuffer[numCharsRead] = 0;
char* pUtf8 = ConvertFromWideString(pWideBuffer, GetConsoleCP());
strncpy(pBuffer, pUtf8, BufferSize);
delete [] pUtf8;
return strlen(pBuffer);
}
#endif // WIN32
syntax highlighted by Code2HTML, v. 0.9.1