mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-08 01:20:53 +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;
|
||||
size_t repo_path_len = strlen(repo_path);
|
||||
char work_path[PATH__MAX_UNC_LEN];
|
||||
git_win32_path target;
|
||||
size_t path_len;
|
||||
int fMode;
|
||||
|
||||
if (!git_win32__findfirstfile_filter(pathw, path)) {
|
||||
error = -1;
|
||||
@ -374,46 +372,19 @@ int git_win32_path_dirload_with_stat(
|
||||
cmp_len = min(start_len, path_len);
|
||||
if (!(cmp_len && strncomp(work_path, start_stat, cmp_len) < 0)) {
|
||||
cmp_len = min(end_len, path_len);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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)) {
|
||||
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_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
|
||||
|
@ -140,44 +140,10 @@ static int lstat_w(
|
||||
WIN32_FILE_ATTRIBUTE_DATA fdata;
|
||||
|
||||
if (GetFileAttributesExW(path, 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;
|
||||
|
||||
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;
|
||||
return git_win32__file_attribute_to_stat(buf, &fdata, path);
|
||||
}
|
||||
|
||||
errno = ENOENT;
|
||||
|
@ -9,8 +9,21 @@
|
||||
#define INCLUDE_w32_util_h__
|
||||
|
||||
#include "utf-conv.h"
|
||||
#include "posix.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)
|
||||
{
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
Loading…
Reference in New Issue
Block a user