X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fwin32%2Fcompat%2Fcompat.cpp;h=d5931f439254f717d11449ff39accd88c2b01ecf;hb=6c210279bc094ec7bfedf140e515ed98eb2734a3;hp=0dc526753a710c53f5c7ca7065c20bebcb167303;hpb=004447f83a9647066c1ffd915d1b1ced5c4f7fb5;p=bacula%2Fbacula diff --git a/bacula/src/win32/compat/compat.cpp b/bacula/src/win32/compat/compat.cpp index 0dc526753a..d5931f4392 100644 --- a/bacula/src/win32/compat/compat.cpp +++ b/bacula/src/win32/compat/compat.cpp @@ -5,7 +5,7 @@ // Copyright transferred from Raider Solutions, Inc to // Kern Sibbald and John Walker by express permission. // -// Copyright (C) 2004-2005 Kern Sibbald +// Copyright (C) 2004-2006 Kern Sibbald // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -22,27 +22,60 @@ // $Id$ #include "bacula.h" +#include "compat.h" +#include "jcr.h" + #define b_errno_win32 (1<<29) -#include "vss.h" -#include "../../lib/winapi.h" +/* UTF-8 to UCS2 path conversion is expensive, + so we cache the conversion. During backup the + conversion is called 3 times (lstat, attribs, open), + by using the cache this is reduced to 1 time */ + +static POOLMEM *g_pWin32ConvUTF8Cache = get_pool_memory (PM_FNAME); +static POOLMEM *g_pWin32ConvUCS2Cache = get_pool_memory (PM_FNAME); +static DWORD g_dwWin32ConvUTF8strlen = 0; +static pthread_mutex_t Win32Convmutex = PTHREAD_MUTEX_INITIALIZER; + +static t_pVSSPathConvert g_pVSSPathConvert; +static t_pVSSPathConvertW g_pVSSPathConvertW; + +void SetVSSPathConvert(t_pVSSPathConvert pPathConvert, t_pVSSPathConvertW pPathConvertW) +{ + g_pVSSPathConvert = pPathConvert; + g_pVSSPathConvertW = pPathConvertW; +} + +void Win32ConvCleanupCache() +{ + if (g_pWin32ConvUTF8Cache) { + free_pool_memory(g_pWin32ConvUTF8Cache); + g_pWin32ConvUTF8Cache = NULL; + } + + if (g_pWin32ConvUCS2Cache) { + free_pool_memory(g_pWin32ConvUCS2Cache); + g_pWin32ConvUCS2Cache = NULL; + } + + g_dwWin32ConvUTF8strlen = 0; +} /* to allow the usage of the original version in this file here */ #undef fputs -#define USE_WIN32_COMPAT_IO 1 +//#define USE_WIN32_COMPAT_IO 1 #define USE_WIN32_32KPATHCONVERSION 1 -extern void d_msg(const char *file, int line, int level, const char *fmt,...); extern DWORD g_platform_id; -extern int enable_vss; +extern DWORD g_MinorVersion; // from MicroSoft SDK (KES) is the diff between Jan 1 1601 and Jan 1 1970 #ifdef HAVE_MINGW -#define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000ULL //Not sure it works +#define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000ULL #else #define WIN32_FILETIME_ADJUST 0x19DB1DED53E8000I64 #endif @@ -53,6 +86,22 @@ void conv_unix_to_win32_path(const char *name, char *win32_name, DWORD dwSize) { const char *fname = name; char *tname = win32_name; + + Dmsg0(100, "Enter convert_unix_to_win32_path\n"); + + if ((name[0] == '/' || name[0] == '\\') && + (name[1] == '/' || name[1] == '\\') && + (name[2] == '.') && + (name[3] == '/' || name[3] == '\\')) { + + *win32_name++ = '\\'; + *win32_name++ = '\\'; + *win32_name++ = '.'; + *win32_name++ = '\\'; + + name += 4; + } + while (*name) { /* Check for Unix separator and convert to Win32 */ if (name[0] == '/' && name[1] == '/') { /* double slash? */ @@ -77,54 +126,71 @@ void conv_unix_to_win32_path(const char *name, char *win32_name, DWORD dwSize) *win32_name = 0; } -#ifdef WIN32_VSS /* here we convert to VSS specific file name which can get longer because VSS will make something like \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe from c:\bacula\uninstall.exe */ - if (g_pVSSClient && enable_vss && g_pVSSClient->IsInitialized()) { + Dmsg1(100, "path=%s\n", tname); + if (g_pVSSPathConvert != NULL) { POOLMEM *pszBuf = get_pool_memory (PM_FNAME); pszBuf = check_pool_memory_size(pszBuf, dwSize); bstrncpy(pszBuf, tname, strlen(tname)+1); - g_pVSSClient->GetShadowPath(pszBuf, tname, dwSize); + g_pVSSPathConvert(pszBuf, tname, dwSize); free_pool_memory(pszBuf); } -#endif + Dmsg1(100, "Leave cvt_u_to_win32_path path=%s\n", tname); +} + +/* Conversion of a Unix filename to a Win32 filename */ +void unix_name_to_win32(POOLMEM **win32_name, char *name) +{ + /* One extra byte should suffice, but we double it */ + /* add MAX_PATH bytes for VSS shadow copy name */ + DWORD dwSize = 2*strlen(name)+MAX_PATH; + *win32_name = check_pool_memory_size(*win32_name, dwSize); + conv_unix_to_win32_path(name, *win32_name, dwSize); } POOLMEM* -make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/) +make_wchar_win32_path(POOLMEM *pszUCSPath, BOOL *pBIsRawPath /*= NULL*/) { /* created 02/27/2006 Thorsten Engel - - This function expects an UCS-encoded standard WCHAR in pszUCSPath and - will complete the input path to an absolue path of the form \\?\c:\path\file - - With this trick, it is possible to have 32K characters long paths. - - Optionally one can use pBIsRawPath to determine id pszUCSPath contains a path - to a raw windows partition */ + * + * This function expects an UCS-encoded standard wchar_t in pszUCSPath and + * will complete the input path to an absolue path of the form \\?\c:\path\file + * + * With this trick, it is possible to have 32K characters long paths. + * + * Optionally one can use pBIsRawPath to determine id pszUCSPath contains a path + * to a raw windows partition. + */ - if (pBIsRawPath) - *pBIsRawPath = FALSE; + Dmsg0(100, "Enter wchar_win32_path\n"); + if (pBIsRawPath) { + *pBIsRawPath = FALSE; /* Initialize, set later */ + } - if (!p_GetCurrentDirectoryW) + if (!p_GetCurrentDirectoryW) { + Dmsg0(100, "Leave wchar_win32_path no change \n"); return pszUCSPath; + } - WCHAR* name = (WCHAR*) pszUCSPath; + wchar_t *name = (wchar_t *)pszUCSPath; /* if it has already the desired form, exit without changes */ - if (wcslen(name) > 3 && wcsncmp (name, L"\\\\?\\", 4) == 0) + if (wcslen(name) > 3 && wcsncmp(name, L"\\\\?\\", 4) == 0) { + Dmsg0(100, "Leave wchar_win32_path no change \n"); return pszUCSPath; + } - POOLMEM* pwszBuf = get_pool_memory (PM_FNAME); - POOLMEM* pwszCurDirBuf = get_pool_memory (PM_FNAME); + POOLMEM *pwszBuf = get_pool_memory(PM_FNAME); + POOLMEM *pwszCurDirBuf = get_pool_memory(PM_FNAME); DWORD dwCurDirPathSize = 0; /* get buffer with enough size (name+max 6. wchars+1 null terminator */ DWORD dwBufCharsNeeded = (wcslen(name)+7); - pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(WCHAR)); + pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(wchar_t)); /* add \\?\ to support 32K long filepaths it is important to make absolute paths, so we add drive and @@ -146,17 +212,18 @@ make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/) bAddCurrentPath = FALSE; /* is path relative to itself?, if yes, skip ./ */ - if (wcslen(name) > 2 && ((wcsncmp (name, L"./", 2) == 0) || (wcsncmp (name, L".\\", 2) == 0))) { - name+=2; + if (wcslen(name) > 2 && ((wcsncmp(name, L"./", 2) == 0) || (wcsncmp(name, L".\\", 2) == 0))) { + name += 2; } /* is path of form '//./'? */ - if (wcslen(name) > 3 && ((wcsncmp (name, L"//./", 4) == 0) || (wcsncmp (name, L"\\\\.\\", 4) == 0))) { + if (wcslen(name) > 3 && ((wcsncmp(name, L"//./", 4) == 0) || (wcsncmp(name, L"\\\\.\\", 4) == 0))) { bAddDrive = FALSE; bAddCurrentPath = FALSE; bAddPrefix = FALSE; - if (pBIsRawPath) + if (pBIsRawPath) { *pBIsRawPath = TRUE; + } } int nParseOffset = 0; @@ -164,7 +231,7 @@ make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/) /* add 4 bytes header */ if (bAddPrefix) { nParseOffset = 4; - wcscpy ((WCHAR*) pwszBuf,L"\\\\?\\"); + wcscpy((wchar_t *)pwszBuf, L"\\\\?\\"); } /* get current path if needed */ @@ -172,11 +239,9 @@ make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/) dwCurDirPathSize = p_GetCurrentDirectoryW(0, NULL); if (dwCurDirPathSize > 0) { /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */ - pwszCurDirBuf = check_pool_memory_size(pwszCurDirBuf, (dwCurDirPathSize+1)*sizeof(WCHAR)); - p_GetCurrentDirectoryW(dwCurDirPathSize,(WCHAR*)pwszCurDirBuf); - } - else - { + pwszCurDirBuf = check_pool_memory_size(pwszCurDirBuf, (dwCurDirPathSize+1)*sizeof(wchar_t)); + p_GetCurrentDirectoryW(dwCurDirPathSize,(wchar_t *)pwszCurDirBuf); + } else { /* we have no info for doing so */ bAddDrive = FALSE; bAddCurrentPath = FALSE; @@ -186,18 +251,19 @@ make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/) /* add drive if needed */ if (bAddDrive && !bAddCurrentPath) { - WCHAR szDrive[3]; + wchar_t szDrive[3]; - if (dwCurDirPathSize > 3 && wcsncmp ((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0) + if (dwCurDirPathSize > 3 && wcsncmp((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0) { /* copy drive character */ - wcsncpy ((WCHAR*) szDrive, (LPCWSTR)pwszCurDirBuf+4,2); - else + wcsncpy((wchar_t *)szDrive, (LPCWSTR)pwszCurDirBuf+4, 2); + } else { /* copy drive character */ - wcsncpy ((WCHAR*) szDrive, (LPCWSTR)pwszCurDirBuf,2); + wcsncpy((wchar_t *)szDrive, (LPCWSTR)pwszCurDirBuf, 2); + } szDrive[2] = 0; - wcscat ((WCHAR*) pwszBuf, szDrive); + wcscat((wchar_t *)pwszBuf, szDrive); nParseOffset +=2; } @@ -205,27 +271,28 @@ make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/) if (bAddCurrentPath) { /* the 1 add. character is for the eventually added backslash */ dwBufCharsNeeded += dwCurDirPathSize+1; - pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(WCHAR)); + pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(wchar_t)); /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */ - if (dwCurDirPathSize > 3 && wcsncmp ((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0) + if (dwCurDirPathSize > 3 && wcsncmp((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0) { /* copy complete string */ - wcscpy ((WCHAR*) pwszBuf, (LPCWSTR)pwszCurDirBuf); - else + wcscpy((wchar_t *)pwszBuf, (LPCWSTR)pwszCurDirBuf); + } else { /* append path */ - wcscat ((WCHAR*) pwszBuf, (LPCWSTR)pwszCurDirBuf); + wcscat((wchar_t *)pwszBuf, (LPCWSTR)pwszCurDirBuf); + } - nParseOffset = wcslen ((LPCWSTR) pwszBuf); + nParseOffset = wcslen((LPCWSTR) pwszBuf); /* check if path ends with backslash, if not, add one */ - if (*((WCHAR*) pwszBuf+nParseOffset-1) != L'\\') { - wcscat ((WCHAR*) pwszBuf, L"\\"); + if (*((wchar_t *)pwszBuf+nParseOffset-1) != L'\\') { + wcscat((wchar_t *)pwszBuf, L"\\"); nParseOffset++; } } - WCHAR* win32_name = (WCHAR*) pwszBuf+nParseOffset; + wchar_t *win32_name = (wchar_t *)pwszBuf+nParseOffset; while (*name) { /* Check for Unix separator and convert to Win32 */ @@ -233,11 +300,14 @@ make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/) *win32_name++ = '\\'; /* convert char */ /* If Win32 separated that is "quoted", remove quote */ /* HELPME (Thorsten Engel): I don't understand the following part - and it removes a backslash from e.g. "\\.\c:" which I need for - RAW device access. So I took it out */ -/* } else if (*name == '\\' && name[1] == '\\') { + * and it removes a backslash from e.g. "\\.\c:" which I need for + * RAW device access. So I took it out. + */ +#ifdef needed + } else if (*name == '\\' && name[1] == '\\') { *win32_name++ = '\\'; - name++; */ /* skip first \ */ + name++; /* skip first \ */ +#endif } else { *win32_name++ = *name; /* copy character */ } @@ -247,36 +317,35 @@ make_wchar_win32_path(POOLMEM* pszUCSPath, BOOL* pBIsRawPath /*= NULL*/) /* null terminate string */ *win32_name = 0; -#ifdef WIN32_VSS /* here we convert to VSS specific file name which - can get longer because VSS will make something like - \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe - from c:\bacula\uninstall.exe + * can get longer because VSS will make something like + * \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe + * from c:\bacula\uninstall.exe */ - if (g_pVSSClient && enable_vss && g_pVSSClient->IsInitialized()) { + if (g_pVSSPathConvertW != NULL) { /* is output buffer large enough? */ - pwszBuf = check_pool_memory_size(pwszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(WCHAR)); + pwszBuf = check_pool_memory_size(pwszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(wchar_t)); /* create temp. buffer */ - POOLMEM* pszBuf = get_pool_memory (PM_FNAME); - pszBuf = check_pool_memory_size(pszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(WCHAR)); + POOLMEM* pszBuf = get_pool_memory(PM_FNAME); + pszBuf = check_pool_memory_size(pszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(wchar_t)); if (bAddPrefix) nParseOffset = 4; else nParseOffset = 0; - wcsncpy ((WCHAR*) pszBuf, (WCHAR*) pwszBuf+nParseOffset, wcslen((WCHAR*)pwszBuf)+1-nParseOffset); - g_pVSSClient->GetShadowPathW((WCHAR*)pszBuf,(WCHAR*)pwszBuf,dwBufCharsNeeded+MAX_PATH); + wcsncpy((wchar_t *)pszBuf, (wchar_t *)pwszBuf+nParseOffset, wcslen((wchar_t *)pwszBuf)+1-nParseOffset); + g_pVSSPathConvertW((wchar_t *)pszBuf, (wchar_t *)pwszBuf, dwBufCharsNeeded+MAX_PATH); free_pool_memory(pszBuf); } -#endif - free_pool_memory (pszUCSPath); - free_pool_memory (pwszCurDirBuf); + free_pool_memory(pszUCSPath); + free_pool_memory(pwszCurDirBuf); + Dmsg1(100, "Leave wchar_win32_path=%s\n", pwszBuf); return pwszBuf; } int -wchar_2_UTF8(char *pszUTF, const WCHAR *pszUCS, int cchChar) +wchar_2_UTF8(char *pszUTF, const wchar_t *pszUCS, int cchChar) { /* the return value is the number of bytes written to the buffer. The number includes the byte for the null terminator. */ @@ -287,7 +356,7 @@ wchar_2_UTF8(char *pszUTF, const WCHAR *pszUCS, int cchChar) return nRet; } else - return NULL; + return 0; } int @@ -299,19 +368,19 @@ UTF8_2_wchar(POOLMEM **ppszUCS, const char *pszUTF) if (p_MultiByteToWideChar) { /* strlen of UTF8 +1 is enough */ DWORD cchSize = (strlen(pszUTF)+1); - *ppszUCS = check_pool_memory_size(*ppszUCS, cchSize*sizeof (WCHAR)); + *ppszUCS = check_pool_memory_size(*ppszUCS, cchSize*sizeof (wchar_t)); int nRet = p_MultiByteToWideChar(CP_UTF8, 0, pszUTF, -1, (LPWSTR) *ppszUCS,cchSize); ASSERT (nRet > 0); return nRet; } else - return NULL; + return 0; } void -wchar_win32_path(const char *name, WCHAR *win32_name) +wchar_win32_path(const char *name, wchar_t *win32_name) { const char *fname = name; while (*name) { @@ -338,6 +407,20 @@ wchar_win32_path(const char *name, WCHAR *win32_name) int make_win32_path_UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF, BOOL* pBIsRawPath /*= NULL*/) { + P(Win32Convmutex); + /* if we find the utf8 string in cache, we use the cached ucs2 version. + we compare the stringlength first (quick check) and then compare the content. + */ + if (g_dwWin32ConvUTF8strlen == strlen(pszUTF)) { + if (bstrcmp(pszUTF, g_pWin32ConvUTF8Cache)) { + int32_t nBufSize = sizeof_pool_memory(g_pWin32ConvUCS2Cache); + *pszUCS = check_pool_memory_size(*pszUCS, nBufSize); + wcscpy((LPWSTR) *pszUCS, (LPWSTR) g_pWin32ConvUCS2Cache); + V(Win32Convmutex); + return nBufSize / sizeof (WCHAR); + } + } + /* helper to convert from utf-8 to UCS-2 and to complete a path for 32K path syntax */ int nRet = UTF8_2_wchar(pszUCS, pszUTF); @@ -349,38 +432,44 @@ make_win32_path_UTF8_2_wchar(POOLMEM **pszUCS, const char *pszUTF, BOOL* pBIsRaw *pBIsRawPath = FALSE; #endif + /* populate cache */ + g_pWin32ConvUCS2Cache = check_pool_memory_size(g_pWin32ConvUCS2Cache, sizeof_pool_memory(*pszUCS)); + wcscpy((LPWSTR) g_pWin32ConvUCS2Cache, (LPWSTR) *pszUCS); + + g_dwWin32ConvUTF8strlen = strlen(pszUTF); + g_pWin32ConvUTF8Cache = check_pool_memory_size(g_pWin32ConvUTF8Cache, g_dwWin32ConvUTF8strlen+1); + bstrncpy(g_pWin32ConvUTF8Cache, pszUTF, g_dwWin32ConvUTF8strlen+1); + V(Win32Convmutex); + return nRet; } -#ifndef HAVE_VC8 +#if !defined(_MSC_VER) || (_MSC_VER < 1400) // VC8+ int umask(int) { return 0; } #endif -int chmod(const char *, mode_t) +int fcntl(int fd, int cmd) { return 0; } -int chown(const char *k, uid_t, gid_t) +int chmod(const char *, mode_t) { return 0; } -int lchown(const char *k, uid_t, gid_t) +int chown(const char *k, uid_t, gid_t) { return 0; } -#ifdef needed -bool fstype(const char *fname, char *fs, int fslen) +int lchown(const char *k, uid_t, gid_t) { - return true; /* accept anything */ + return 0; } -#endif - long int random(void) @@ -399,16 +488,16 @@ srandom(unsigned int seed) void cvt_utime_to_ftime(const time_t &time, FILETIME &wintime) { - uint64_t mstime = time; - mstime *= WIN32_FILETIME_SCALE; - mstime += WIN32_FILETIME_ADJUST; + uint64_t mstime = time; + mstime *= WIN32_FILETIME_SCALE; + mstime += WIN32_FILETIME_ADJUST; - #ifdef HAVE_MINGW - wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffUL); - #else - wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffI64); - #endif - wintime.dwHighDateTime = (DWORD) ((mstime>>32)& 0xffffffffUL); +#if defined(_MSC_VER) + wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffI64); +#else + wintime.dwLowDateTime = (DWORD)(mstime & 0xffffffffUL); +#endif + wintime.dwHighDateTime = (DWORD) ((mstime>>32)& 0xffffffffUL); } time_t @@ -439,10 +528,19 @@ errorString(void) 0, NULL); - return (const char *) lpMsgBuf; + /* Strip any \r or \n */ + char *rval = (char *) lpMsgBuf; + char *cp = strchr(rval, '\r'); + if (cp != NULL) { + *cp = 0; + } else { + cp = strchr(rval, '\n'); + if (cp != NULL) + *cp = 0; + } + return rval; } -#ifndef HAVE_MINGW static int statDir(const char *file, struct stat *sb) @@ -459,7 +557,7 @@ statDir(const char *file, struct stat *sb) FILETIME* pftCreationTime; if (file[1] == ':' && file[2] == 0) { - d_msg(__FILE__, __LINE__, 99, "faking ROOT attrs(%s).\n", file); + Dmsg1(99, "faking ROOT attrs(%s).\n", file); sb->st_mode = S_IFDIR; sb->st_mode |= S_IREAD|S_IEXEC|S_IWRITE; time(&sb->st_ctime); @@ -498,7 +596,7 @@ statDir(const char *file, struct stat *sb) if (h == INVALID_HANDLE_VALUE) { const char *err = errorString(); - d_msg(__FILE__, __LINE__, 99, "FindFirstFile(%s):%s\n", file, err); + Dmsg2(99, "FindFirstFile(%s):%s\n", file, err); LocalFree((void *)err); errno = b_errno_win32; return -1; @@ -527,16 +625,59 @@ statDir(const char *file, struct stat *sb) return 0; } +int +fstat(int fd, struct stat *sb) +{ + BY_HANDLE_FILE_INFORMATION info; + char tmpbuf[1024]; + + if (!GetFileInformationByHandle((HANDLE)fd, &info)) { + const char *err = errorString(); + Dmsg2(99, "GetfileInformationByHandle(%s): %s\n", tmpbuf, err); + LocalFree((void *)err); + errno = b_errno_win32; + return -1; + } + + sb->st_dev = info.dwVolumeSerialNumber; + sb->st_ino = info.nFileIndexHigh; + sb->st_ino <<= 32; + sb->st_ino |= info.nFileIndexLow; + sb->st_nlink = (short)info.nNumberOfLinks; + if (sb->st_nlink > 1) { + Dmsg1(99, "st_nlink=%d\n", sb->st_nlink); + } + + sb->st_mode = 0777; /* start with everything */ + if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); + if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) + sb->st_mode &= ~S_IRWXO; /* remove everything for other */ + if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */ + sb->st_mode |= S_IFREG; + + sb->st_size = info.nFileSizeHigh; + sb->st_size <<= 32; + sb->st_size |= info.nFileSizeLow; + sb->st_blksize = 4096; + sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096; + sb->st_atime = cvt_ftime_to_utime(info.ftLastAccessTime); + sb->st_mtime = cvt_ftime_to_utime(info.ftLastWriteTime); + sb->st_ctime = cvt_ftime_to_utime(info.ftCreationTime); + + return 0; +} + static int stat2(const char *file, struct stat *sb) { - BY_HANDLE_FILE_INFORMATION info; HANDLE h; int rval = 0; char tmpbuf[1024]; conv_unix_to_win32_path(file, tmpbuf, 1024); - DWORD attr = -1; + DWORD attr = (DWORD)-1; if (p_GetFileAttributesW) { POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); @@ -548,10 +689,9 @@ stat2(const char *file, struct stat *sb) attr = p_GetFileAttributesA(tmpbuf); } - if (attr == -1) { + if (attr == (DWORD)-1) { const char *err = errorString(); - d_msg(__FILE__, __LINE__, 99, - "GetFileAttributes(%s): %s\n", tmpbuf, err); + Dmsg2(99, "GetFileAttributes(%s): %s\n", tmpbuf, err); LocalFree((void *)err); errno = b_errno_win32; return -1; @@ -565,53 +705,15 @@ stat2(const char *file, struct stat *sb) if (h == INVALID_HANDLE_VALUE) { const char *err = errorString(); - d_msg(__FILE__, __LINE__, 99, - "Cannot open file for stat (%s):%s\n", tmpbuf, err); + Dmsg2(99, "Cannot open file for stat (%s):%s\n", tmpbuf, err); LocalFree((void *)err); - rval = -1; errno = b_errno_win32; - goto error; - } - - if (!GetFileInformationByHandle(h, &info)) { - const char *err = errorString(); - d_msg(__FILE__, __LINE__, 99, - "GetfileInformationByHandle(%s): %s\n", tmpbuf, err); - LocalFree((void *)err); - rval = -1; - errno = b_errno_win32; - goto error; - } - - sb->st_dev = info.dwVolumeSerialNumber; - sb->st_ino = info.nFileIndexHigh; - sb->st_ino <<= 32; - sb->st_ino |= info.nFileIndexLow; - sb->st_nlink = (short)info.nNumberOfLinks; - if (sb->st_nlink > 1) { - d_msg(__FILE__, __LINE__, 99, "st_nlink=%d\n", sb->st_nlink); + return -1; } - sb->st_mode = 0777; /* start with everything */ - if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) - sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); - if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) - sb->st_mode &= ~S_IRWXO; /* remove everything for other */ - if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) - sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */ - sb->st_mode |= S_IFREG; - - sb->st_size = info.nFileSizeHigh; - sb->st_size <<= 32; - sb->st_size |= info.nFileSizeLow; - sb->st_blksize = 4096; - sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096; - sb->st_atime = cvt_ftime_to_utime(info.ftLastAccessTime); - sb->st_mtime = cvt_ftime_to_utime(info.ftLastWriteTime); - sb->st_ctime = cvt_ftime_to_utime(info.ftCreationTime); - -error: + rval = fstat((int)h, sb); CloseHandle(h); + return rval; } @@ -678,7 +780,27 @@ stat(const char *file, struct stat *sb) return 0; } -#endif //HAVE_MINGW +int fcntl(int fd, int cmd, long arg) +{ + int rval = 0; + + switch (cmd) { + case F_GETFL: + rval = O_NONBLOCK; + break; + + case F_SETFL: + rval = 0; + break; + + default: + errno = EINVAL; + rval = -1; + break; + } + + return rval; +} int lstat(const char *file, struct stat *sb) @@ -760,23 +882,24 @@ strcasecmp(const char *s1, const char *s2) int strncasecmp(const char *s1, const char *s2, int len) { - register int ch1, ch2; + register int ch1 = 0, ch2 = 0; - if (s1==s2) - return 0; /* strings are equal if same object. */ - else if (!s1) - return -1; - else if (!s2) - return 1; - while (len--) { - ch1 = *s1; - ch2 = *s2; - s1++; - s2++; - if (ch1 == 0 || tolower(ch1) != tolower(ch2)) break; - } + if (s1==s2) + return 0; /* strings are equal if same object. */ + else if (!s1) + return -1; + else if (!s2) + return 1; - return (ch1 - ch2); + while (len--) { + ch1 = *s1; + ch2 = *s2; + s1++; + s2++; + if (ch1 == 0 || tolower(ch1) != tolower(ch2)) break; + } + + return (ch1 - ch2); } int @@ -806,13 +929,17 @@ gettimeofday(struct timeval *tv, struct timezone *) } -int -syslog(int type, const char *fmt, const char *msg) +/* For apcupsd this is in src/lib/wincompat.c */ +extern "C" void syslog(int type, const char *fmt, ...) { /*#ifndef HAVE_CONSOLE MessageBox(NULL, msg, "Bacula", MB_OK); #endif*/ - return 0; +} + +void +closelog() +{ } struct passwd * @@ -851,6 +978,7 @@ opendir(const char *path) return NULL; } + Dmsg1(100, "Opendir path=%s\n", path); rval = (_dir *)malloc(sizeof(_dir)); memset (rval, 0, sizeof (_dir)); if (rval == NULL) return NULL; @@ -861,6 +989,7 @@ opendir(const char *path) #ifdef WIN32_VSS /* will append \\?\ at front itself */ conv_unix_to_win32_path(path, tspec, max_len-4); + Dmsg1(100, "win32 path=%s\n", tspec); #else /* allow path to be 32767 bytes */ tspec[0] = '\\'; @@ -869,9 +998,11 @@ opendir(const char *path) tspec[3] = '\\'; tspec[4] = 0; conv_unix_to_win32_path(path, tspec+4, max_len-4); + Dmsg1(100, "win32 path=%s\n", tspec); #endif } else { conv_unix_to_win32_path(path, tspec, max_len); + Dmsg1(100, "win32 path=%s\n", tspec); } // add backslash only if there is none yet (think of c:\) @@ -882,10 +1013,10 @@ opendir(const char *path) rval->spec = tspec; - // convert to WCHAR + // convert to wchar_t if (p_FindFirstFileW) { POOLMEM* pwcBuf = get_pool_memory(PM_FNAME);; - make_win32_path_UTF8_2_wchar(&pwcBuf,rval->spec); + make_win32_path_UTF8_2_wchar(&pwcBuf, rval->spec); rval->dirh = p_FindFirstFileW((LPCWSTR)pwcBuf, &rval->data_w); @@ -901,21 +1032,20 @@ opendir(const char *path) } else goto err; - d_msg(__FILE__, __LINE__, - 99, "opendir(%s)\n\tspec=%s,\n\tFindFirstFile returns %d\n", + Dmsg3(99, "opendir(%s)\n\tspec=%s,\n\tFindFirstFile returns %d\n", path, rval->spec, rval->dirh); rval->offset = 0; if (rval->dirh == INVALID_HANDLE_VALUE) goto err; - if (rval->valid_w) - d_msg(__FILE__, __LINE__, - 99, "\tFirstFile=%s\n", rval->data_w.cFileName); + if (rval->valid_w) { + Dmsg1(99, "\tFirstFile=%s\n", rval->data_w.cFileName); + } - if (rval->valid_a) - d_msg(__FILE__, __LINE__, - 99, "\tFirstFile=%s\n", rval->data_a.cFileName); + if (rval->valid_a) { + Dmsg1(99, "\tFirstFile=%s\n", rval->data_a.cFileName); + } return (DIR *)rval; @@ -982,11 +1112,10 @@ readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) } *result = entry; /* return entry address */ - d_msg(__FILE__, __LINE__, - 99, "readdir_r(%p, { d_name=\"%s\", d_reclen=%d, d_off=%d\n", + Dmsg4(99, "readdir_r(%p, { d_name=\"%s\", d_reclen=%d, d_off=%d\n", dirp, entry->d_name, entry->d_reclen, entry->d_off); } else { -// d_msg(__FILE__, __LINE__, 99, "readdir_r !valid\n"); +// Dmsg0(99, "readdir_r !valid\n"); errno = b_errno_win32; return -1; } @@ -1146,11 +1275,11 @@ win32_getcwd(char *buf, int maxlen) if (p_GetCurrentDirectoryW) { POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); - pwszBuf = check_pool_memory_size (pwszBuf, maxlen*sizeof(WCHAR)); + pwszBuf = check_pool_memory_size (pwszBuf, maxlen*sizeof(wchar_t)); n = p_GetCurrentDirectoryW(maxlen, (LPWSTR) pwszBuf); if (n!=0) - n = wchar_2_UTF8 (buf, (WCHAR*)pwszBuf, maxlen)-1; + n = wchar_2_UTF8 (buf, (wchar_t *)pwszBuf, maxlen)-1; free_pool_memory(pwszBuf); } else if (p_GetCurrentDirectoryA) @@ -1216,7 +1345,7 @@ win32_cgets (char* buffer, int len) HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE); if (hIn && (hIn != INVALID_HANDLE_VALUE) && p_WideCharToMultiByte && p_MultiByteToWideChar) { DWORD dwRead; - WCHAR wszBuf[1024]; + wchar_t wszBuf[1024]; char szBuf[1024]; /* nt and unicode conversion */ @@ -1251,9 +1380,9 @@ win32_cgets (char* buffer, int len) dwRead --; } - /* convert from ansii to WCHAR */ + /* convert from ansii to wchar_t */ p_MultiByteToWideChar(GetConsoleCP(), 0, szBuf, -1, wszBuf,1024); - /* convert from WCHAR to UTF-8 */ + /* convert from wchar_t to UTF-8 */ if (wchar_2_UTF8(buffer, wszBuf, len)) return buffer; } @@ -1315,6 +1444,7 @@ win32_unlink(const char *filename) char WIN_VERSION_LONG[64]; char WIN_VERSION[32]; +char WIN_RAWVERSION[32]; class winver { public: @@ -1323,8 +1453,6 @@ public: static winver INIT; // cause constructor to be called before main() -#include "bacula.h" -#include "jcr.h" winver::winver(void) { @@ -1338,8 +1466,11 @@ winver::winver(void) version = "Unknown"; platform = "Unknown"; } - else - switch (_mkversion(osvinfo.dwPlatformId, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion)) + const int ver = _mkversion(osvinfo.dwPlatformId, + osvinfo.dwMajorVersion, + osvinfo.dwMinorVersion); + snprintf(WIN_RAWVERSION, sizeof(WIN_RAWVERSION), "Windows %#08x", ver); + switch (ver) { case MS_WINDOWS_95: (version = "Windows 95"); break; case MS_WINDOWS_98: (version = "Windows 98"); break; @@ -1348,11 +1479,11 @@ winver::winver(void) case MS_WINDOWS_2K: (version = "Windows 2000");platform = "NT"; break; case MS_WINDOWS_XP: (version = "Windows XP");platform = "NT"; break; case MS_WINDOWS_S2003: (version = "Windows Server 2003");platform = "NT"; break; - default: version = "Windows ??"; break; + default: version = WIN_RAWVERSION; break; } bstrncpy(WIN_VERSION_LONG, version, sizeof(WIN_VERSION_LONG)); - snprintf(WIN_VERSION, sizeof(WIN_VERSION), "%s %d.%d.%d", + snprintf(WIN_VERSION, sizeof(WIN_VERSION), "%s %lu.%lu.%lu", platform, osvinfo.dwMajorVersion, osvinfo.dwMinorVersion, osvinfo.dwBuildNumber); #if 0 @@ -1420,12 +1551,18 @@ getArgv0(const char *cmdline) HANDLE CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err) { + static const char *comspec = NULL; PROCESS_INFORMATION piProcInfo; STARTUPINFOA siStartInfo; BOOL bFuncRetn = FALSE; - // Set up members of the PROCESS_INFORMATION structure. + if (comspec == NULL) { + comspec = getenv("COMSPEC"); + } + if (comspec == NULL) // should never happen + return INVALID_HANDLE_VALUE; + // Set up members of the PROCESS_INFORMATION structure. ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); // Set up members of the STARTUPINFO structure. @@ -1453,18 +1590,14 @@ CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err) // Create the child process. char exeFile[256]; + int cmdLen = strlen(cmdline) + strlen(comspec) + 16; - const char *comspec = getenv("COMSPEC"); + char *cmdLine = (char *)alloca(cmdLen); - if (comspec == NULL) // should never happen - return INVALID_HANDLE_VALUE; - - char *cmdLine = (char *)alloca(strlen(cmdline) + strlen(comspec) + 16); - - strcpy(exeFile, comspec); - strcpy(cmdLine, comspec); - strcat(cmdLine, " /c "); - strcat(cmdLine, cmdline); + bstrncpy(exeFile, comspec, sizeof(exeFile)); + bstrncpy(cmdLine, comspec, cmdLen); + bstrncat(cmdLine, " /c ", cmdLen); + bstrncat(cmdLine, cmdline, cmdLen); // try to execute program bFuncRetn = CreateProcessA(exeFile, @@ -1481,8 +1614,7 @@ CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err) if (bFuncRetn == 0) { ErrorExit("CreateProcess failed\n"); const char *err = errorString(); - d_msg(__FILE__, __LINE__, 99, - "CreateProcess(%s, %s, ...)=%s\n", exeFile, cmdLine, err); + Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n", exeFile, cmdLine, err); LocalFree((void *)err); return INVALID_HANDLE_VALUE; } @@ -1497,7 +1629,7 @@ CreateChildProcess(const char *cmdline, HANDLE in, HANDLE out, HANDLE err) void ErrorExit (LPCSTR lpszMessage) { - d_msg(__FILE__, __LINE__, 0, "%s", lpszMessage); + Dmsg1(0, "%s", lpszMessage); } @@ -1519,7 +1651,6 @@ CloseIfValid(HANDLE handle) CloseHandle(handle); } -#ifndef HAVE_MINGW BPIPE * open_bpipe(char *prog, int wait, const char *mode) { @@ -1645,7 +1776,6 @@ cleanup: return NULL; } -#endif //HAVE_MINGW int kill(int pid, int signal) @@ -1659,7 +1789,6 @@ kill(int pid, int signal) return rval; } -#ifndef HAVE_MINGW int close_bpipe(BPIPE *bpipe) @@ -1675,8 +1804,7 @@ close_bpipe(BPIPE *bpipe) if (!GetExitCodeProcess((HANDLE)bpipe->worker_pid, &exitCode)) { const char *err = errorString(); rval = b_errno_win32; - d_msg(__FILE__, __LINE__, 0, - "GetExitCode error %s\n", err); + Dmsg1(0, "GetExitCode error %s\n", err); LocalFree((void *)err); break; } @@ -1726,9 +1854,9 @@ int utime(const char *fname, struct utimbuf *times) { FILETIME acc, mod; - char tmpbuf[1024]; + char tmpbuf[5000]; - conv_unix_to_win32_path(fname, tmpbuf, 1024); + conv_unix_to_win32_path(fname, tmpbuf, 5000); cvt_utime_to_ftime(times->actime, acc); cvt_utime_to_ftime(times->modtime, mod); @@ -1739,29 +1867,28 @@ utime(const char *fname, struct utimbuf *times) POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf); - h = p_CreateFileW((LPCWSTR) pwszBuf, + h = p_CreateFileW((LPCWSTR)pwszBuf, FILE_WRITE_ATTRIBUTES, - FILE_SHARE_WRITE, + FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, - 0, + FILE_FLAG_BACKUP_SEMANTICS, // required for directories NULL); free_pool_memory(pwszBuf); } else if (p_CreateFileA) { h = p_CreateFileA(tmpbuf, FILE_WRITE_ATTRIBUTES, - FILE_SHARE_WRITE, + FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, - 0, + FILE_FLAG_BACKUP_SEMANTICS, // required for directories NULL); } if (h == INVALID_HANDLE_VALUE) { const char *err = errorString(); - d_msg(__FILE__, __LINE__, 99, - "Cannot open file \"%s\" for utime(): ERR=%s", tmpbuf, err); + Dmsg2(99, "Cannot open file \"%s\" for utime(): ERR=%s", tmpbuf, err); LocalFree((void *)err); errno = b_errno_win32; return -1; @@ -1775,67 +1902,9 @@ utime(const char *fname, struct utimbuf *times) return rval; } -#if USE_WIN32_COMPAT_IO - -int -open(const char *file, int flags, int mode) -{ - if (p_wopen) { - POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); - make_win32_path_UTF8_2_wchar(&pwszBuf, file); - - int nRet = p_wopen((LPCWSTR) pwszBuf, flags|_O_BINARY, mode); - free_pool_memory(pwszBuf); - - return nRet; - } - - return _open(file, flags|_O_BINARY, mode); -} - -/* - * Note, this works only for a file. If you want - * to close a socket, use closesocket(). - * Bacula has been modified in src/lib/bnet.c - * to use closesocket(). - */ -#ifndef HAVE_VC8 -int -close(int fd) -{ - return _close(fd); -} - -#ifndef HAVE_WXCONSOLE -ssize_t -read(int fd, void *buf, ssize_t len) -{ - return _read(fd, buf, (size_t)len); -} - -ssize_t -write(int fd, const void *buf, ssize_t len) -{ - return _write(fd, buf, (size_t)len); -} -#endif - - -off_t -lseek(int fd, off_t offset, int whence) -{ - return (off_t)_lseeki64(fd, offset, whence); -} - -int -dup2(int fd1, int fd2) -{ - return _dup2(fd1, fd2); -} -#endif -#else +#if 0 int -open(const char *file, int flags, int mode) +file_open(const char *file, int flags, int mode) { DWORD access = 0; DWORD shareMode = 0; @@ -1848,13 +1917,18 @@ open(const char *file, int flags, int mode) else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE; else access = GENERIC_READ; - if (flags & O_CREAT) create = CREATE_NEW; - else create = OPEN_EXISTING; - - if (flags & O_TRUNC) create = TRUNCATE_EXISTING; + if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + create = CREATE_NEW; + else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) + create = CREATE_ALWAYS; + else if (flags & O_CREAT) + create = OPEN_ALWAYS; + else if (flags & O_TRUNC) + create = TRUNCATE_EXISTING; + else + create = OPEN_EXISTING; - if (!(flags & O_EXCL)) - shareMode = FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE; + shareMode = 0; if (flags & O_APPEND) { printf("open...APPEND not implemented yet."); @@ -1863,12 +1937,11 @@ open(const char *file, int flags, int mode) if (p_CreateFileW) { POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); - make_win32_path_UTF8_2_wchar(pwszBuf, file); + make_win32_path_UTF8_2_wchar(&pwszBuf, file); foo = p_CreateFileW((LPCWSTR) pwszBuf, access, shareMode, NULL, create, msflags, NULL); free_pool_memory(pwszBuf); - } - else if (p_CreateFileA) + } else if (p_CreateFileA) foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL); if (INVALID_HANDLE_VALUE == foo) { @@ -1881,7 +1954,7 @@ open(const char *file, int flags, int mode) int -close(int fd) +file_close(int fd) { if (!CloseHandle((HANDLE)fd)) { errno = b_errno_win32; @@ -1892,7 +1965,7 @@ close(int fd) } ssize_t -write(int fd, const void *data, ssize_t len) +file_write(int fd, const void *data, ssize_t len) { BOOL status; DWORD bwrite; @@ -1904,7 +1977,7 @@ write(int fd, const void *data, ssize_t len) ssize_t -read(int fd, void *data, ssize_t len) +file_read(int fd, void *data, ssize_t len) { BOOL status; DWORD bread; @@ -1916,7 +1989,7 @@ read(int fd, void *data, ssize_t len) } off_t -lseek(int fd, off_t offset, int whence) +file_seek(int fd, off_t offset, int whence) { DWORD method = 0; DWORD val; @@ -1944,18 +2017,14 @@ lseek(int fd, off_t offset, int whence) } int -dup2(int, int) +file_dup2(int, int) { errno = ENOSYS; return -1; } - - #endif -#endif //HAVE_MINGW - #ifdef HAVE_MINGW /* syslog function, added by Nicolas Boichat */ -void closelog() {} +void openlog(const char *ident, int option, int facility) {} #endif //HAVE_MINGW