Commit f3c444b8 by Edward Thomson

win32: abstract file attributes -> struct stat fn

parent 1920ee4e
......@@ -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 (!(cmp_len && strncomp(work_path, end_stat, cmp_len) > 0)) {
ps = git__calloc(1, sizeof(git_path_with_stat) + path_len + 2);
if (!(dir->f.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
fMode |= S_IWRITE;
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;
}
ps = git__calloc(1, sizeof(git_path_with_stat) + path_len + 2);
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment