diff --git a/contrib/win32/win32compat/fileio.c b/contrib/win32/win32compat/fileio.c index 04ddebaa5..542c60725 100644 --- a/contrib/win32/win32compat/fileio.c +++ b/contrib/win32/win32compat/fileio.c @@ -37,6 +37,7 @@ #include #include #include "inc\utf.h" +#include "misc_internal.h" /* internal read buffer size */ #define READ_BUFFER_SIZE 100*1024 @@ -76,7 +77,7 @@ int fileio_pipe(struct w32_io* pio[2]) { HANDLE read_handle = INVALID_HANDLE_VALUE, write_handle = INVALID_HANDLE_VALUE; struct w32_io *pio_read = NULL, *pio_write = NULL; - char pipe_name[MAX_PATH]; + char pipe_name[PATH_MAX]; SECURITY_ATTRIBUTES sec_attributes; if (pio == NULL) { @@ -86,7 +87,7 @@ fileio_pipe(struct w32_io* pio[2]) { } /* create name for named pipe */ - if (-1 == sprintf_s(pipe_name, MAX_PATH, "\\\\.\\Pipe\\W32PosixPipe.%08x.%08x", + if (-1 == sprintf_s(pipe_name, PATH_MAX, "\\\\.\\Pipe\\W32PosixPipe.%08x.%08x", GetCurrentProcessId(), pipe_counter++)) { errno = EOTHER; debug("pipe - ERROR sprintf_s %d", errno); @@ -564,15 +565,15 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf) { int fileio_stat(const char *path, struct _stat64 *buf) { - wchar_t wpath[MAX_PATH]; - wchar_t* wtmp = NULL; + wchar_t wpath[PATH_MAX]; + wchar_t* wtmp = NULL; - if ((wtmp = utf8_to_utf16(path)) == NULL) - fatal("failed to covert input arguments"); - wcscpy(&wpath[0], wtmp); - free(wtmp); + if ((wtmp = utf8_to_utf16(path)) == NULL) + fatal("failed to covert input arguments"); + wcscpy(&wpath[0], wtmp); + free(wtmp); - return _wstat64(wpath, buf); + return _wstat64(wpath, buf); } long diff --git a/contrib/win32/win32compat/inc/dirent.h b/contrib/win32/win32compat/inc/dirent.h index a74081518..8ac3a598b 100644 --- a/contrib/win32/win32compat/inc/dirent.h +++ b/contrib/win32/win32compat/inc/dirent.h @@ -10,10 +10,11 @@ #include #include #include +#include "..\misc_internal.h" struct dirent { int d_ino; /* Inode number */ - char d_name[256]; /* Null-terminated filename */ + char d_name[PATH_MAX]; /* Null-terminated filename */ }; typedef struct DIR_ DIR; diff --git a/contrib/win32/win32compat/lsa/Ssh-lsa.c b/contrib/win32/win32compat/lsa/Ssh-lsa.c index 26a69c6f7..103fdc259 100644 --- a/contrib/win32/win32compat/lsa/Ssh-lsa.c +++ b/contrib/win32/win32compat/lsa/Ssh-lsa.c @@ -38,6 +38,7 @@ #include #include #include +#include "..\misc_internal.h" #define Unsigned unsigned #define Char char @@ -264,7 +265,7 @@ LsaApLogonUser(PLSA_CLIENT_REQUEST request, SECURITY_LOGON_TYPE logonType, UNICODE_STRING *flatName = NULL; UCHAR *userAuth = NULL; ULONG userAuthSize; - wchar_t homeDir[MAX_PATH]; + wchar_t homeDir[PATH_MAX]; TOKEN_SOURCE tokenSource; HANDLE token = NULL; @@ -292,9 +293,9 @@ LsaApLogonUser(PLSA_CLIENT_REQUEST request, SECURITY_LOGON_TYPE logonType, *authority, &token, logonId, *accountName, subStat)); - NTFAIL(LsaApi.AllocateClientBuffer(request, MAX_PATH * sizeof(wchar_t), profile)); - *profileSize = MAX_PATH; - NTFAIL(LsaApi.CopyToClientBuffer(request, MAX_PATH * sizeof(wchar_t), + NTFAIL(LsaApi.AllocateClientBuffer(request, PATH_MAX * sizeof(wchar_t), profile)); + *profileSize = PATH_MAX; + NTFAIL(LsaApi.CopyToClientBuffer(request, PATH_MAX * sizeof(wchar_t), *profile, homeDir)); PLSA_TOKEN_INFORMATION_V1 outTokenInfo; diff --git a/contrib/win32/win32compat/misc.c b/contrib/win32/win32compat/misc.c index 00e3a5c7d..80ca223c0 100644 --- a/contrib/win32/win32compat/misc.c +++ b/contrib/win32/win32compat/misc.c @@ -38,6 +38,7 @@ #include #include "misc_internal.h" #include "inc\dlfcn.h" +#include "inc\dirent.h" int usleep(unsigned int useconds) { @@ -134,7 +135,7 @@ FARPROC dlsym(HMODULE handle, const char *symbol) { */ FILE* w32_fopen_utf8(const char *path, const char *mode) { - wchar_t wpath[MAX_PATH], wmode[5]; + wchar_t wpath[PATH_MAX], wmode[5]; FILE* f; char utf8_bom[] = { 0xEF,0xBB,0xBF }; char first3_bytes[3]; @@ -144,7 +145,7 @@ w32_fopen_utf8(const char *path, const char *mode) { return NULL; } - if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, MAX_PATH) == 0 || + if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX) == 0 || MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, 5) == 0) { errno = EFAULT; debug("WideCharToMultiByte failed for %c - ERROR:%d", path, GetLastError()); @@ -478,8 +479,7 @@ settimes(wchar_t * path, FILETIME *cretime, FILETIME *acttime, FILETIME *modtime return -1; } - if (SetFileTime(handle, cretime, acttime, modtime) == 0) - { + if (SetFileTime(handle, cretime, acttime, modtime) == 0) { errno = GetLastError(); debug("w32_settimes - SetFileTime ERROR:%d", errno); CloseHandle(handle); @@ -533,6 +533,28 @@ w32_rename(const char *old_name, const char *new_name) { return -1; } + /* + * To be consistent with linux rename(), + * 1) if the new_name is file, then delete it so that _wrename will succeed. + * 2) if the new_name is directory and it is empty then delete it so that _wrename will succeed. + */ + struct _stat64 st; + if (fileio_stat(sanitized_path(new_name), &st) != -1) { + if(((st.st_mode & _S_IFMT) == _S_IFREG)) { + w32_unlink(new_name); + } else { + DIR *dirp = opendir(new_name); + if (NULL != dirp) { + struct dirent *dp = readdir(dirp); + closedir(dirp); + + if (dp == NULL) { + w32_rmdir(new_name); + } + } + } + } + int returnStatus = _wrename(resolvedOldPathName_utf16, resolvedNewPathName_utf16); free(resolvedOldPathName_utf16); free(resolvedNewPathName_utf16); @@ -585,10 +607,10 @@ w32_chdir(const char *dirname_utf8) { char * w32_getcwd(char *buffer, int maxlen) { - wchar_t wdirname[MAX_PATH]; + wchar_t wdirname[PATH_MAX]; char* putf8 = NULL; - _wgetcwd(&wdirname[0], MAX_PATH); + _wgetcwd(&wdirname[0], PATH_MAX); if ((putf8 = utf16_to_utf8(&wdirname[0])) == NULL) fatal("failed to convert input arguments"); @@ -655,19 +677,25 @@ convertToForwardslash(char *str) { } /* -* This method will resolves references to /./, /../ and extra '/' characters in the null-terminated string named by -* path to produce a canonicalized absolute pathname. -*/ + * This method will resolves references to /./, /../ and extra '/' characters in the null-terminated string named by + * path to produce a canonicalized absolute pathname. + */ char * -realpath(const char *path, char resolved[MAX_PATH]) { - char tempPath[MAX_PATH]; +realpath(const char *path, char resolved[PATH_MAX]) { + char tempPath[PATH_MAX]; - if ( (strlen(path) >= 2) && (path[0] == '/') && (path[2] == ':') ) + if ((path[0] == '/') && path[1] && (path[2] == ':')) { strncpy(resolved, path + 1, strlen(path)); // skip the first '/' - else + } else { strncpy(resolved, path, strlen(path) + 1); + } - if (_fullpath(tempPath, resolved, MAX_PATH) == NULL) + if ((resolved[0]) && (resolved[1] == ':') && (resolved[2] == '\0')) { // make "x:" as "x:\\" + resolved[2] = '\\'; + resolved[3] = '\0'; + } + + if (_fullpath(tempPath, resolved, PATH_MAX) == NULL) return NULL; convertToForwardslash(tempPath); @@ -677,6 +705,27 @@ realpath(const char *path, char resolved[MAX_PATH]) { return resolved; } +char* +sanitized_path(const char *path) { + static char newPath[PATH_MAX] = { '\0', }; + + if (path[0] == '/' && path[1]) { + if (path[2] == ':') { + if (path[3] == '\0') { // make "/x:" as "x:\\" + strncpy(newPath, path + 1, strlen(path) - 1); + newPath[2] = '\\'; + newPath[3] = '\0'; + + return newPath; + } else { + return (char *)(path + 1); // skip the first "/" + } + } + } + + return (char *)path; +} + // Maximum reparse buffer info size. The max user defined reparse // data is 16KB, plus there's a header. #define MAX_REPARSE_SIZE 17000 @@ -813,7 +862,7 @@ int statvfs(const char *path, struct statvfs *buf) { buf->f_favail = -1; buf->f_fsid = 0; buf->f_flag = 0; - buf->f_namemax = MAX_PATH - 1; + buf->f_namemax = PATH_MAX - 1; free(path_utf16); return 0; diff --git a/contrib/win32/win32compat/misc_internal.h b/contrib/win32/win32compat/misc_internal.h index 0cd236921..f4b6d7902 100644 --- a/contrib/win32/win32compat/misc_internal.h +++ b/contrib/win32/win32compat/misc_internal.h @@ -1,3 +1,4 @@ +#define PATH_MAX MAX_PATH /* removes first '/' for Windows paths that are unix styled. Ex: /c:/ab.cd */ -#define sanitized_path(p) (((p)[0] == '/' && (p)[1] != '\0' && (p)[2] == ':')? (p)+1 : (p)) \ No newline at end of file +char * sanitized_path(const char *); \ No newline at end of file diff --git a/contrib/win32/win32compat/pwd.c b/contrib/win32/win32compat/pwd.c index 9d0a4a797..9a80afa08 100644 --- a/contrib/win32/win32compat/pwd.c +++ b/contrib/win32/win32compat/pwd.c @@ -39,6 +39,7 @@ #include "inc\pwd.h" #include "inc\grp.h" #include "inc\utf.h" +#include "misc_internal.h" static struct passwd pw; static char* pw_shellpath = NULL; @@ -87,9 +88,9 @@ get_passwd(const char *user_utf8, LPWSTR user_sid) { char *uname_utf8 = NULL, *pw_home_utf8 = NULL; LPBYTE user_info = NULL; LPWSTR user_sid_local = NULL; - wchar_t reg_path[MAX_PATH], profile_home[MAX_PATH]; + wchar_t reg_path[PATH_MAX], profile_home[PATH_MAX]; HKEY reg_key = 0; - int tmp_len = MAX_PATH; + int tmp_len = PATH_MAX; PDOMAIN_CONTROLLER_INFOW pdc = NULL; errno = 0; @@ -141,10 +142,10 @@ get_passwd(const char *user_utf8, LPWSTR user_sid) { user_sid = user_sid_local; } - if (swprintf(reg_path, MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", user_sid) == MAX_PATH || + if (swprintf(reg_path, PATH_MAX, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%ls", user_sid) == PATH_MAX || RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY, ®_key) != 0 || RegQueryValueExW(reg_key, L"ProfileImagePath", 0, NULL, (LPBYTE)profile_home, &tmp_len) != 0) - GetWindowsDirectoryW(profile_home, MAX_PATH); + GetWindowsDirectoryW(profile_home, PATH_MAX); if ((uname_utf8 = _strdup(user_utf8)) == NULL || (pw_home_utf8 = utf16_to_utf8(profile_home)) == NULL) { diff --git a/contrib/win32/win32compat/shell-host.c b/contrib/win32/win32compat/shell-host.c index 545bcbe32..06bde1ece 100644 --- a/contrib/win32/win32compat/shell-host.c +++ b/contrib/win32/win32compat/shell-host.c @@ -35,6 +35,7 @@ #include #include #include +#include "misc_internal.h" #define MAX_CONSOLE_COLUMNS 9999 #define MAX_CONSOLE_ROWS 9999 @@ -1068,15 +1069,15 @@ int start_with_pty(int ac, wchar_t **av) { /*TODO - pick this up from system32*/ cmd[0] = L'\0'; if (ac) - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L"cmd.exe")); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, PATH_MAX, L"cmd.exe")); ac--; av++; if (ac) - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" /c")); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, PATH_MAX, L" /c")); while (ac) { - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" ")); - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, *av)); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, PATH_MAX, L" ")); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, PATH_MAX, *av)); ac--; av++; } @@ -1182,14 +1183,14 @@ int start_withno_pty(int ac, wchar_t **av) { /*TODO - pick this up from system32*/ cmd[0] = L'\0'; - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L"cmd.exe")); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, PATH_MAX, L"cmd.exe")); ac -= 2; av += 2; if (ac) - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" /c")); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, PATH_MAX, L" /c")); while (ac) { - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, L" ")); - GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_PATH, *av)); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, PATH_MAX, L" ")); + GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, PATH_MAX, *av)); ac--; av++; } diff --git a/contrib/win32/win32compat/ssh-agent/agent.c b/contrib/win32/win32compat/ssh-agent/agent.c index 62e625d98..b97227a76 100644 --- a/contrib/win32/win32compat/ssh-agent/agent.c +++ b/contrib/win32/win32compat/ssh-agent/agent.c @@ -31,6 +31,7 @@ #include "agent.h" #include #include +#include "..\misc_internal.h" #define BUFSIZE 5 * 1024 static HANDLE ioc_port = NULL; @@ -179,15 +180,15 @@ agent_listen_loop() { } else { /* spawn a child to take care of this*/ - wchar_t path[MAX_PATH], module_path[MAX_PATH]; + wchar_t path[PATH_MAX], module_path[PATH_MAX]; PROCESS_INFORMATION pi; STARTUPINFOW si; si.cb = sizeof(STARTUPINFOW); memset(&si, 0, sizeof(STARTUPINFOW)); - GetModuleFileNameW(NULL, module_path, MAX_PATH); + GetModuleFileNameW(NULL, module_path, PATH_MAX); SetHandleInformation(con, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - if ((swprintf_s(path, MAX_PATH, L"%s %d", module_path, (int)(intptr_t)con) == -1 ) || + if ((swprintf_s(path, PATH_MAX, L"%s %d", module_path, (int)(intptr_t)con) == -1 ) || (CreateProcessW(NULL, path, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi) == FALSE)) { diff --git a/contrib/win32/win32compat/ssh-agent/agentconfig.c b/contrib/win32/win32compat/ssh-agent/agentconfig.c index ec261be72..9761a02c3 100644 --- a/contrib/win32/win32compat/ssh-agent/agentconfig.c +++ b/contrib/win32/win32compat/ssh-agent/agentconfig.c @@ -87,15 +87,15 @@ int GetCurrentModulePath(wchar_t *path, int pathSize) } int load_config() { - wchar_t basePath[MAX_PATH] = { 0 }; - wchar_t path[MAX_PATH] = { 0 }; + wchar_t basePath[PATH_MAX] = { 0 }; + wchar_t path[PATH_MAX] = { 0 }; /* TODO - account for UNICODE paths*/ - if (GetCurrentModulePath(basePath, MAX_PATH) == -1) + if (GetCurrentModulePath(basePath, PATH_MAX) == -1) return -1; - wcsncpy(path, basePath, MAX_PATH); - wcsncat(path, L"/sshd_config", MAX_PATH); + wcsncpy(path, basePath, PATH_MAX); + wcsncat(path, L"/sshd_config", PATH_MAX); if ((config_file_name = utf16_to_utf8(path)) == NULL) return -1; diff --git a/contrib/win32/win32compat/w32log.c b/contrib/win32/win32compat/w32log.c index 73b402e1e..d23e2ef62 100644 --- a/contrib/win32/win32compat/w32log.c +++ b/contrib/win32/win32compat/w32log.c @@ -33,6 +33,7 @@ #include #include #include "inc\syslog.h" +#include "misc_internal.h" #define MSGBUFSIZ 1024 static int logfd = -1; @@ -41,11 +42,12 @@ void openlog(char *ident, unsigned int option, int facility) { if (logfd != -1 || ident == NULL) return; + + wchar_t path[PATH_MAX], log_file[PATH_MAX + 12]; + if (GetModuleFileNameW(NULL, path, PATH_MAX) == 0) - wchar_t path[MAX_PATH], log_file[MAX_PATH + 12]; - if (GetModuleFileNameW(NULL, path, MAX_PATH) == 0) return; - path[MAX_PATH - 1] = '\0'; + path[PATH_MAX - 1] = '\0'; /* split path root and module */ { diff --git a/contrib/win32/win32compat/win32_dirent.c b/contrib/win32/win32compat/win32_dirent.c index 2418e13d4..dcfe77a29 100644 --- a/contrib/win32/win32compat/win32_dirent.c +++ b/contrib/win32/win32compat/win32_dirent.c @@ -27,7 +27,7 @@ DIR * opendir(const char *name) struct _wfinddata_t c_file; intptr_t hFile; DIR *pdir; - wchar_t searchstr[MAX_PATH]; + wchar_t searchstr[PATH_MAX]; wchar_t* wname = NULL; int needed; @@ -37,7 +37,7 @@ DIR * opendir(const char *name) } // add *.* for Windows _findfirst() search pattern - swprintf_s(searchstr, MAX_PATH, L"%s\\*.*", wname); + swprintf_s(searchstr, PATH_MAX, L"%s\\*.*", wname); free(wname); if ((hFile = _wfindfirst(searchstr, &c_file)) == -1L) @@ -77,7 +77,7 @@ int closedir(DIR *dirp) by a later readdir call on the same DIR stream. */ struct dirent *readdir(void *avp) { - struct dirent *pdirentry; + static struct dirent pdirentry; struct _wfinddata_t c_file; DIR *dirp = (DIR *)avp; char *tmp = NULL; @@ -92,19 +92,18 @@ struct dirent *readdir(void *avp) if (wcscmp(c_file.name, L".") == 0 || wcscmp(c_file.name, L"..") == 0 ) continue; - - if ((pdirentry = malloc(sizeof(struct dirent))) == NULL || - (tmp = utf16_to_utf8(c_file.name)) == NULL) { + + if ((tmp = utf16_to_utf8(c_file.name)) == NULL) { errno = ENOMEM; return NULL; } - strncpy(pdirentry->d_name, tmp, strlen(tmp) + 1); + strncpy(pdirentry.d_name, tmp, strlen(tmp) + 1); free(tmp); - pdirentry->d_ino = 1; // a fictious one like UNIX to say it is nonzero - return pdirentry ; - } + pdirentry.d_ino = 1; // a fictious one like UNIX to say it is nonzero + return &pdirentry ; + } } // return last part of a path. The last path being a filename. @@ -123,4 +122,3 @@ char *basename(char *path) return path; // path does not have a slash } -// end of dirent functions in Windows