extern int p_rename(const char *from, const char *to) { wchar_t *wfrom = gitwin_to_utf16(from); wchar_t *wto = gitwin_to_utf16(to); int ret; ret = MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR; git__free(wfrom); git__free(wto); return ret; }
char *p_realpath(const char *orig_path, char *buffer) { int ret; wchar_t* orig_path_w = gitwin_to_utf16(orig_path); wchar_t* buffer_w = (wchar_t*)git__malloc(GIT_PATH_MAX * sizeof(wchar_t)); ret = GetFullPathNameW(orig_path_w, GIT_PATH_MAX, buffer_w, NULL); git__free(orig_path_w); if (!ret || ret > GIT_PATH_MAX) { buffer = NULL; goto done; } if (buffer == NULL) { int buffer_sz = WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, NULL, 0, NULL, NULL); if (!buffer_sz || !(buffer = (char *)git__malloc(buffer_sz)) || !WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, buffer, buffer_sz, NULL, NULL)) { git__free(buffer); buffer = NULL; } } else { if (!WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, buffer, GIT_PATH_MAX, NULL, NULL)) buffer = NULL; } done: git__free(buffer_w); if (buffer) git_path_mkposix(buffer); return buffer; }
int p_rmdir(const char* path) { wchar_t* buf = gitwin_to_utf16(path); int ret = _wrmdir(buf); git__free(buf); return ret; }
int p_chmod(const char* path, mode_t mode) { wchar_t* buf = gitwin_to_utf16(path); int ret = _wchmod(buf, mode); git__free(buf); return ret; }
int p_creat(const char *path, mode_t mode) { int fd; wchar_t* buf = gitwin_to_utf16(path); fd = _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode); git__free(buf); return fd; }
int p_open(const char *path, int flags) { int fd; wchar_t* buf = gitwin_to_utf16(path); fd = _wopen(buf, flags | _O_BINARY); git__free(buf); return fd; }
int p_unlink(const char *path) { int ret = 0; wchar_t* buf; buf = gitwin_to_utf16(path); _wchmod(buf, 0666); ret = _wunlink(buf); git__free(buf); return ret; }
static int do_lstat(const char *file_name, struct stat *buf) { WIN32_FILE_ATTRIBUTE_DATA fdata; wchar_t* fbuf = gitwin_to_utf16(file_name); if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) { int fMode = S_IREAD; if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) fMode |= S_IFDIR; else fMode |= S_IFREG; if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) fMode |= S_IWRITE; if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) fMode |= S_IFLNK; buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_nlink = 1; buf->st_mode = (mode_t)fMode; buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */ buf->st_dev = buf->st_rdev = (_getdrive() - 1); buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); git__free(fbuf); return GIT_SUCCESS; } git__free(fbuf); switch (GetLastError()) { case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: case ERROR_LOCK_VIOLATION: case ERROR_SHARING_BUFFER_EXCEEDED: return GIT_EOSERR; case ERROR_BUFFER_OVERFLOW: case ERROR_NOT_ENOUGH_MEMORY: return GIT_ENOMEM; default: return GIT_EINVALIDPATH; } }
int p_hide_directory__w32(const char *path) { int error; wchar_t* buf = gitwin_to_utf16(path); error = SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0 ? GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */ git__free(buf); if (error < GIT_SUCCESS) error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path); return error; }
static int do_lstat(const char *file_name, struct stat *buf) { WIN32_FILE_ATTRIBUTE_DATA fdata; DWORD last_error; wchar_t* fbuf = gitwin_to_utf16(file_name); if (!fbuf) return -1; if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) { int fMode = S_IREAD; if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) fMode |= S_IFDIR; else fMode |= S_IFREG; if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) fMode |= S_IWRITE; if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) fMode |= S_IFLNK; buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_nlink = 1; buf->st_mode = (mode_t)fMode; buf->st_size = ((git_off_t)fdata.nFileSizeHigh << 32) + fdata.nFileSizeLow; buf->st_dev = buf->st_rdev = (_getdrive() - 1); buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); git__free(fbuf); return 0; } last_error = GetLastError(); if (last_error == ERROR_FILE_NOT_FOUND) errno = ENOENT; else if (last_error == ERROR_PATH_NOT_FOUND) errno = ENOTDIR; git__free(fbuf); return -1; }
int git_futils_creat_locked(const char *path, const mode_t mode) { int fd; #ifdef GIT_WIN32 wchar_t* buf; buf = gitwin_to_utf16(path); fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_EXCL, mode); git__free(buf); #else fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_EXCL, mode); #endif if (fd < 0) { giterr_set(GITERR_OS, "Failed to create locked file '%s'", path); return -1; } return fd; }
int p_readlink(const char *link, char *target, size_t target_len) { typedef DWORD (WINAPI *fpath_func)(HANDLE, LPWSTR, DWORD, DWORD); static fpath_func pGetFinalPath = NULL; HANDLE hFile; DWORD dwRet; wchar_t* link_w; wchar_t* target_w; int error = 0; assert(link && target && target_len > 0); /* * Try to load the pointer to pGetFinalPath dynamically, because * it is not available in platforms older than Vista */ if (pGetFinalPath == NULL) { HINSTANCE library = LoadLibrary("kernel32"); if (library != NULL) pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleW"); if (pGetFinalPath == NULL) { giterr_set(GITERR_OS, "'GetFinalPathNameByHandleW' is not available in this platform"); return -1; } } link_w = gitwin_to_utf16(link); GITERR_CHECK_ALLOC(link_w); hFile = CreateFileW(link_w, // file to open GENERIC_READ, // open for reading FILE_SHARE_READ, // share for reading NULL, // default security OPEN_EXISTING, // existing file only FILE_FLAG_BACKUP_SEMANTICS, // normal file NULL); // no attr. template git__free(link_w); if (hFile == INVALID_HANDLE_VALUE) { giterr_set(GITERR_OS, "Cannot open '%s' for reading", link); return -1; } target_w = (wchar_t*)git__malloc(target_len * sizeof(wchar_t)); GITERR_CHECK_ALLOC(target_w); dwRet = pGetFinalPath(hFile, target_w, (DWORD)target_len, 0x0); if (dwRet == 0 || dwRet >= target_len || !WideCharToMultiByte(CP_UTF8, 0, target_w, -1, target, (int)(target_len * sizeof(char)), NULL, NULL)) error = -1; git__free(target_w); CloseHandle(hFile); if (error) return error; /* Skip first 4 characters if they are "\\?\" */ if (dwRet > 4 && target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') { unsigned int offset = 4; dwRet -= 4; /* \??\UNC\ */ if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') { offset += 2; dwRet -= 2; target[offset] = '\\'; } memmove(target, target + offset, dwRet); } target[dwRet] = '\0'; return dwRet; }
int p_readlink(const char *link, char *target, size_t target_len) { typedef DWORD (WINAPI *fpath_func)(HANDLE, LPWSTR, DWORD, DWORD); static fpath_func pGetFinalPath = NULL; HANDLE hFile; DWORD dwRet; wchar_t* link_w; wchar_t* target_w; /* * Try to load the pointer to pGetFinalPath dynamically, because * it is not available in platforms older than Vista */ if (pGetFinalPath == NULL) { HINSTANCE library = LoadLibrary("kernel32"); if (library != NULL) pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleW"); if (pGetFinalPath == NULL) return git__throw(GIT_EOSERR, "'GetFinalPathNameByHandleW' is not available in this platform"); } link_w = gitwin_to_utf16(link); hFile = CreateFileW(link_w, // file to open GENERIC_READ, // open for reading FILE_SHARE_READ, // share for reading NULL, // default security OPEN_EXISTING, // existing file only FILE_FLAG_BACKUP_SEMANTICS, // normal file NULL); // no attr. template git__free(link_w); if (hFile == INVALID_HANDLE_VALUE) return GIT_EOSERR; if (target_len <= 0) { return GIT_EINVALIDARGS; } target_w = (wchar_t*)git__malloc(target_len * sizeof(wchar_t)); dwRet = pGetFinalPath(hFile, target_w, target_len, 0x0); if (dwRet >= target_len) { git__free(target_w); CloseHandle(hFile); return GIT_ENOMEM; } if (!WideCharToMultiByte(CP_UTF8, 0, target_w, -1, target, target_len * sizeof(char), NULL, NULL)) { git__free(target_w); return GIT_EOSERR; } git__free(target_w); CloseHandle(hFile); if (dwRet > 4) { /* Skip first 4 characters if they are "\\?\" */ if (target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') { char tmp[GIT_PATH_MAX]; unsigned int offset = 4; dwRet -= 4; /* \??\UNC\ */ if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') { offset += 2; dwRet -= 2; target[offset] = '\\'; } memcpy(tmp, target + offset, dwRet); memcpy(target, tmp, dwRet); } } target[dwRet] = '\0'; return dwRet; }