mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-11 16:34:33 +00:00
win32: abstract file attributes -> struct stat fn
This commit is contained in:
parent
1920ee4ef6
commit
f3c444b879
@ -330,9 +330,7 @@ int git_win32_path_dirload_with_stat(
|
|||||||
const char *repo_path = path + prefix_len;
|
const char *repo_path = path + prefix_len;
|
||||||
size_t repo_path_len = strlen(repo_path);
|
size_t repo_path_len = strlen(repo_path);
|
||||||
char work_path[PATH__MAX_UNC_LEN];
|
char work_path[PATH__MAX_UNC_LEN];
|
||||||
git_win32_path target;
|
|
||||||
size_t path_len;
|
size_t path_len;
|
||||||
int fMode;
|
|
||||||
|
|
||||||
if (!git_win32__findfirstfile_filter(pathw, path)) {
|
if (!git_win32__findfirstfile_filter(pathw, path)) {
|
||||||
error = -1;
|
error = -1;
|
||||||
@ -374,46 +372,19 @@ int git_win32_path_dirload_with_stat(
|
|||||||
cmp_len = min(start_len, path_len);
|
cmp_len = min(start_len, path_len);
|
||||||
if (!(cmp_len && strncomp(work_path, start_stat, cmp_len) < 0)) {
|
if (!(cmp_len && strncomp(work_path, start_stat, cmp_len) < 0)) {
|
||||||
cmp_len = min(end_len, path_len);
|
cmp_len = min(end_len, path_len);
|
||||||
|
|
||||||
if (!(cmp_len && strncomp(work_path, end_stat, cmp_len) > 0)) {
|
if (!(cmp_len && strncomp(work_path, end_stat, cmp_len) > 0)) {
|
||||||
fMode = S_IREAD;
|
|
||||||
|
|
||||||
if (dir->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
||||||
fMode |= S_IFDIR;
|
|
||||||
else
|
|
||||||
fMode |= S_IFREG;
|
|
||||||
|
|
||||||
if (!(dir->f.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
|
|
||||||
fMode |= S_IWRITE;
|
|
||||||
|
|
||||||
ps = git__calloc(1, sizeof(git_path_with_stat) + path_len + 2);
|
ps = git__calloc(1, sizeof(git_path_with_stat) + path_len + 2);
|
||||||
|
|
||||||
|
if ((error = git_win32__file_attribute_to_stat(&ps->st,
|
||||||
|
(WIN32_FILE_ATTRIBUTE_DATA *)&dir->f,
|
||||||
|
NULL)) < 0) {
|
||||||
|
git__free(ps);
|
||||||
|
goto clean_up_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(ps->path, work_path, path_len + 1);
|
memcpy(ps->path, work_path, path_len + 1);
|
||||||
ps->path_len = path_len;
|
ps->path_len = path_len;
|
||||||
ps->st.st_atime = filetime_to_time_t(&dir->f.ftLastAccessTime);
|
|
||||||
ps->st.st_ctime = filetime_to_time_t(&dir->f.ftCreationTime);
|
|
||||||
ps->st.st_mtime = filetime_to_time_t(&dir->f.ftLastWriteTime);
|
|
||||||
ps->st.st_size = dir->f.nFileSizeHigh;
|
|
||||||
ps->st.st_size <<= 32;
|
|
||||||
ps->st.st_size |= dir->f.nFileSizeLow;
|
|
||||||
ps->st.st_dev = ps->st.st_rdev = (_getdrive() - 1);
|
|
||||||
ps->st.st_mode = (mode_t)fMode;
|
|
||||||
ps->st.st_ino = 0;
|
|
||||||
ps->st.st_gid = 0;
|
|
||||||
ps->st.st_uid = 0;
|
|
||||||
ps->st.st_nlink = 1;
|
|
||||||
|
|
||||||
if (dir->f.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
|
||||||
if (git_win32_path_readlink_w(target, dir->f.cFileName) >= 0) {
|
|
||||||
ps->st.st_mode = (ps->st.st_mode & ~S_IFMT) | S_IFLNK;
|
|
||||||
|
|
||||||
/* st_size gets the UTF-8 length of the target name, in bytes,
|
|
||||||
* not counting the NULL terminator */
|
|
||||||
if ((ps->st.st_size = git__utf16_to_8(NULL, 0, target)) < 0) {
|
|
||||||
error = -1;
|
|
||||||
giterr_set(GITERR_OS, "Could not manage reparse link '%s'", dir->f.cFileName);
|
|
||||||
goto clean_up_and_exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (S_ISDIR(ps->st.st_mode)) {
|
if (S_ISDIR(ps->st.st_mode)) {
|
||||||
ps->path[ps->path_len++] = '/';
|
ps->path[ps->path_len++] = '/';
|
||||||
|
@ -52,12 +52,4 @@ extern int p_lstat_posixly(const char *filename, struct stat *buf);
|
|||||||
extern struct tm * p_localtime_r(const time_t *timer, struct tm *result);
|
extern struct tm * p_localtime_r(const time_t *timer, struct tm *result);
|
||||||
extern struct tm * p_gmtime_r(const time_t *timer, struct tm *result);
|
extern struct tm * p_gmtime_r(const time_t *timer, struct tm *result);
|
||||||
|
|
||||||
GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
|
|
||||||
{
|
|
||||||
long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
|
|
||||||
winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
|
|
||||||
winTime /= 10000000; /* Nano to seconds resolution */
|
|
||||||
return (time_t)winTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -140,44 +140,10 @@ static int lstat_w(
|
|||||||
WIN32_FILE_ATTRIBUTE_DATA fdata;
|
WIN32_FILE_ATTRIBUTE_DATA fdata;
|
||||||
|
|
||||||
if (GetFileAttributesExW(path, GetFileExInfoStandard, &fdata)) {
|
if (GetFileAttributesExW(path, GetFileExInfoStandard, &fdata)) {
|
||||||
int fMode = S_IREAD;
|
|
||||||
|
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
return git_win32__file_attribute_to_stat(buf, &fdata, path);
|
||||||
fMode |= S_IFDIR;
|
|
||||||
else
|
|
||||||
fMode |= S_IFREG;
|
|
||||||
|
|
||||||
if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
|
|
||||||
fMode |= S_IWRITE;
|
|
||||||
|
|
||||||
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));
|
|
||||||
|
|
||||||
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
|
||||||
git_win32_path target;
|
|
||||||
|
|
||||||
if (git_win32_path_readlink_w(target, path) >= 0) {
|
|
||||||
buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFLNK;
|
|
||||||
|
|
||||||
/* st_size gets the UTF-8 length of the target name, in bytes,
|
|
||||||
* not counting the NULL terminator */
|
|
||||||
if ((buf->st_size = git__utf16_to_8(NULL, 0, target)) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
@ -9,8 +9,21 @@
|
|||||||
#define INCLUDE_w32_util_h__
|
#define INCLUDE_w32_util_h__
|
||||||
|
|
||||||
#include "utf-conv.h"
|
#include "utf-conv.h"
|
||||||
|
#include "posix.h"
|
||||||
#include "path_w32.h"
|
#include "path_w32.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "path.h"
|
||||||
|
#include "path_w32.h"
|
||||||
|
#include "utf-conv.h"
|
||||||
|
#include "posix.h"
|
||||||
|
#include "reparse.h"
|
||||||
|
#include "dir.h"
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
GIT_INLINE(bool) git_win32__isalpha(wchar_t c)
|
GIT_INLINE(bool) git_win32__isalpha(wchar_t c)
|
||||||
{
|
{
|
||||||
return ((c >= L'A' && c <= L'Z') || (c >= L'a' && c <= L'z'));
|
return ((c >= L'A' && c <= L'Z') || (c >= L'a' && c <= L'z'));
|
||||||
@ -52,4 +65,63 @@ size_t git_win32__path_trim_end(wchar_t *str, size_t len);
|
|||||||
*/
|
*/
|
||||||
size_t git_win32__canonicalize_path(wchar_t *str, size_t len);
|
size_t git_win32__canonicalize_path(wchar_t *str, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a FILETIME structure to a time_t.
|
||||||
|
*
|
||||||
|
* @param FILETIME A pointer to a FILETIME
|
||||||
|
* @return A time_t containing the same time
|
||||||
|
*/
|
||||||
|
GIT_INLINE(time_t) git_win32__filetime_to_time_t(const FILETIME *ft)
|
||||||
|
{
|
||||||
|
long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
|
||||||
|
winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
|
||||||
|
winTime /= 10000000; /* Nano to seconds resolution */
|
||||||
|
return (time_t)winTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
GIT_INLINE(int) git_win32__file_attribute_to_stat(
|
||||||
|
struct stat *st,
|
||||||
|
const WIN32_FILE_ATTRIBUTE_DATA *attrdata,
|
||||||
|
const wchar_t *path)
|
||||||
|
{
|
||||||
|
mode_t mode = S_IREAD;
|
||||||
|
|
||||||
|
if (attrdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
mode |= S_IFDIR;
|
||||||
|
else
|
||||||
|
mode |= S_IFREG;
|
||||||
|
|
||||||
|
if ((attrdata->dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
|
||||||
|
mode |= S_IWRITE;
|
||||||
|
|
||||||
|
st->st_ino = 0;
|
||||||
|
st->st_gid = 0;
|
||||||
|
st->st_uid = 0;
|
||||||
|
st->st_nlink = 1;
|
||||||
|
st->st_mode = mode;
|
||||||
|
st->st_size = ((git_off_t)attrdata->nFileSizeHigh << 32) + attrdata->nFileSizeLow;
|
||||||
|
st->st_dev = _getdrive() - 1;
|
||||||
|
st->st_rdev = st->st_dev;
|
||||||
|
st->st_atime = git_win32__filetime_to_time_t(&(attrdata->ftLastAccessTime));
|
||||||
|
st->st_mtime = git_win32__filetime_to_time_t(&(attrdata->ftLastWriteTime));
|
||||||
|
st->st_ctime = git_win32__filetime_to_time_t(&(attrdata->ftCreationTime));
|
||||||
|
|
||||||
|
if (attrdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && path) {
|
||||||
|
git_win32_path target;
|
||||||
|
|
||||||
|
if (git_win32_path_readlink_w(target, path) >= 0) {
|
||||||
|
st->st_mode = (st->st_mode & ~S_IFMT) | S_IFLNK;
|
||||||
|
|
||||||
|
/* st_size gets the UTF-8 length of the target name, in bytes,
|
||||||
|
* not counting the NULL terminator */
|
||||||
|
if ((st->st_size = git__utf16_to_8(NULL, 0, target)) < 0) {
|
||||||
|
giterr_set(GITERR_OS, "Could not convert reparse point name for '%s'", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user