int p_unlink(const char *path) { git_win32_path buf; git_win32_path_from_c(buf, path); _wchmod(buf, 0666); return _wunlink(buf); }
static int winhttp_connect( winhttp_subtransport *t, const char *url) { wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; git_win32_path host; int32_t port; const char *default_port = "80"; /* Prepare port */ if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0) return -1; /* Prepare host */ git_win32_path_from_c(host, t->connection_data.host); /* Establish session */ t->session = WinHttpOpen( ua, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!t->session) { giterr_set(GITERR_OS, QT_TRANSLATE_NOOP("libgit2", "Failed to init WinHTTP")); return -1; } /* Establish connection */ t->connection = WinHttpConnect( t->session, host, (INTERNET_PORT) port, 0); if (!t->connection) { giterr_set(GITERR_OS, QT_TRANSLATE_NOOP("libgit2", "Failed to connect to host")); return -1; } return 0; }
static int do_lstat( const char *file_name, struct stat *buf, int posix_enotdir) { WIN32_FILE_ATTRIBUTE_DATA fdata; git_win32_path fbuf; wchar_t lastch; int flen; flen = git_win32_path_from_c(fbuf, file_name); /* truncate trailing slashes */ for (; flen > 0; --flen) { lastch = fbuf[flen - 1]; if (WIN32_IS_WSEP(lastch)) fbuf[flen - 1] = L'\0'; else if (lastch != L'\0') break; } if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) { int fMode = S_IREAD; if (!buf) return 0; 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; if ((fMode & (S_IFDIR | S_IFLNK)) == (S_IFDIR | S_IFLNK)) // junction 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)); /* Windows symlinks have zero file size, call readlink to determine * the length of the path pointed to, which we expect everywhere else */ if (S_ISLNK(fMode)) { git_win32_path_as_utf8 target; int readlink_result; readlink_result = p_readlink(file_name, target, sizeof(target)); if (readlink_result == -1) return -1; buf->st_size = strlen(target); } return 0; } errno = ENOENT; /* We need POSIX behavior, then ENOTDIR must set when any of the folders in the * file path is a regular file,otherwise ENOENT must be set. */ if (posix_enotdir) { /* scan up path until we find an existing item */ while (1) { /* remove last directory component */ for (--flen; flen > 0 && !WIN32_IS_WSEP(fbuf[flen]); --flen); if (flen <= 0) break; fbuf[flen] = L'\0'; if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) { if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) errno = ENOTDIR; break; } } } return -1; }
/* * Parts of the The p_readlink function are heavily inspired by the php * readlink function in link_win32.c * * Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. * * For details of the PHP license see http://www.php.net/license/3_01.txt */ 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; git_win32_path 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) { HMODULE module = GetModuleHandle("kernel32"); if (module != NULL) pGetFinalPath = (fpath_func)GetProcAddress(module, "GetFinalPathNameByHandleW"); if (pGetFinalPath == NULL) { giterr_set(GITERR_OS, "'GetFinalPathNameByHandleW' is not available in this platform"); return -1; } } git_win32_path_from_c(link_w, 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 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; }