Feature #13726 » 01-time-subsec.patch
dir.c | ||
---|---|---|
}
|
||
#ifdef _WIN32
|
||
#define STAT(p, s) rb_w32_ustati64((p), (s))
|
||
#define STAT(p, s) rb_w32_ustati64ns((p), (s))
|
||
#undef lstat
|
||
#define lstat(p, s) rb_w32_ulstati64((p), (s))
|
||
#define lstat(p, s) rb_w32_ulstati64ns((p), (s))
|
||
#else
|
||
#define STAT(p, s) stat((p), (s))
|
||
#endif
|
file.c | ||
---|---|---|
/* define system APIs */
|
||
#ifdef _WIN32
|
||
#include "win32/file.h"
|
||
#define STAT(p, s) rb_w32_ustati64((p), (s))
|
||
#define STAT(p, s) rb_w32_ustati64ns((p), (s))
|
||
#undef lstat
|
||
#define lstat(p, s) rb_w32_ulstati64((p), (s))
|
||
#define lstat(p, s) rb_w32_ulstati64ns((p), (s))
|
||
#undef access
|
||
#define access(p, m) rb_w32_uaccess((p), (m))
|
||
#undef truncate
|
include/ruby/win32.h | ||
---|---|---|
#define getppid() rb_w32_getppid()
|
||
#define sleep(x) rb_w32_Sleep((x)*1000)
|
||
#define Sleep(msec) (void)rb_w32_Sleep(msec)
|
||
#define fstati64(fd,st) rb_w32_fstati64(fd,st)
|
||
#undef execv
|
||
#define execv(path,argv) rb_w32_aspawn(P_OVERLAY,path,argv)
|
||
... | ... | |
#define unlink(p) rb_w32_unlink(p)
|
||
#endif /* RUBY_EXPORT */
|
||
/* same with stati64 except nanosecond timestamps */
|
||
struct stati64ns {
|
||
_dev_t st_dev;
|
||
_ino_t st_ino;
|
||
unsigned short st_mode;
|
||
short st_nlink;
|
||
short st_uid;
|
||
short st_gid;
|
||
_dev_t st_rdev;
|
||
__int64 st_size;
|
||
__time64_t st_atime;
|
||
long st_atimensec;
|
||
__time64_t st_mtime;
|
||
long st_mtimensec;
|
||
__time64_t st_ctime;
|
||
long st_ctimensec;
|
||
};
|
||
#if SIZEOF_OFF_T == 8
|
||
#define off_t __int64
|
||
#define stat stati64
|
||
#define fstat(fd,st) fstati64(fd,st)
|
||
#if !defined(_MSC_VER) || RUBY_MSVCRT_VERSION < 80
|
||
#define stati64 _stati64
|
||
#ifndef _stati64
|
||
#define _stati64(path, st) rb_w32_stati64(path, st)
|
||
#endif
|
||
#else
|
||
#define stati64 _stat64
|
||
#define _stat64(path, st) rb_w32_stati64(path, st)
|
||
#endif
|
||
#define stat stati64ns
|
||
#define HAVE_STRUCT_STAT_ST_ATIMENSEC
|
||
#define HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||
#define HAVE_STRUCT_STAT_ST_CTIMENSEC
|
||
#define fstat(fd,st) rb_w32_fstati64ns(fd,st)
|
||
#define stati64ns(path, st) rb_w32_stati64ns(path, st)
|
||
#else
|
||
#define stat(path,st) rb_w32_stat(path,st)
|
||
#define fstat(fd,st) rb_w32_fstat(fd,st)
|
||
extern int rb_w32_stat(const char *, struct stat *);
|
||
extern int rb_w32_fstat(int, struct stat *);
|
||
#endif
|
||
#define lstat(path,st) rb_w32_lstati64(path,st)
|
||
#define lstat(path,st) rb_w32_lstati64ns(path,st)
|
||
#define access(path,mode) rb_w32_access(path,mode)
|
||
#define strcasecmp _stricmp
|
||
... | ... | |
extern int rb_w32_unlink(const char *);
|
||
extern int rb_w32_uunlink(const char *);
|
||
extern int rb_w32_uchmod(const char *, int);
|
||
extern int rb_w32_stati64(const char *, struct stati64 *);
|
||
extern int rb_w32_ustati64(const char *, struct stati64 *);
|
||
extern int rb_w32_lstati64(const char *, struct stati64 *);
|
||
extern int rb_w32_ulstati64(const char *, struct stati64 *);
|
||
extern int rb_w32_stati64ns(const char *, struct stati64ns *);
|
||
extern int rb_w32_ustati64ns(const char *, struct stati64ns *);
|
||
extern int rb_w32_lstati64ns(const char *, struct stati64ns *);
|
||
extern int rb_w32_ulstati64ns(const char *, struct stati64ns *);
|
||
extern int rb_w32_access(const char *, int);
|
||
extern int rb_w32_uaccess(const char *, int);
|
||
extern char rb_w32_fd_is_text(int);
|
||
extern int rb_w32_fstati64(int, struct stati64 *);
|
||
extern int rb_w32_fstati64ns(int, struct stati64ns *);
|
||
extern int rb_w32_dup2(int, int);
|
||
#include <float.h>
|
||
... | ... | |
extern int setuid (rb_uid_t);
|
||
extern int setgid (rb_gid_t);
|
||
extern int fstati64(int, struct stati64 *);
|
||
extern char *rb_w32_strerror(int);
|
||
#ifdef RUBY_EXPORT
|
win32/win32.c | ||
---|---|---|
#endif
|
||
static int w32_wopen(const WCHAR *file, int oflag, int perm);
|
||
static int w32_stati64(const char *path, struct stati64 *st, UINT cp);
|
||
static int w32_lstati64(const char *path, struct stati64 *st, UINT cp);
|
||
static int w32_stati64ns(const char *path, struct stati64ns *st, UINT cp);
|
||
static int w32_lstati64ns(const char *path, struct stati64ns *st, UINT cp);
|
||
static char *w32_getenv(const char *name, UINT cp);
|
||
#undef getenv
|
||
#define DLN_FIND_EXTRA_ARG_DECL ,UINT cp
|
||
#define DLN_FIND_EXTRA_ARG ,cp
|
||
#define rb_w32_stati64(path, st) w32_stati64(path, st, cp)
|
||
#define rb_w32_stati64ns(path, st) w32_stati64ns(path, st, cp)
|
||
#define getenv(name) w32_getenv(name, cp)
|
||
#undef CharNext
|
||
#define CharNext(p) CharNextExA(cp, (p), 0)
|
||
... | ... | |
#include "dln.h"
|
||
#include "dln_find.c"
|
||
#undef MAXPATHLEN
|
||
#undef rb_w32_stati64
|
||
#undef rb_w32_stati64ns
|
||
#undef dln_find_exe_r
|
||
#undef dln_find_file_r
|
||
#define dln_find_exe_r(fname, path, buf, size) rb_w32_udln_find_exe_r(fname, path, buf, size, cp)
|
||
... | ... | |
static int has_redirection(const char *, UINT);
|
||
int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout);
|
||
static int rb_w32_open_osfhandle(intptr_t osfhandle, int flags);
|
||
static int wstati64(const WCHAR *path, struct stati64 *st);
|
||
static int wlstati64(const WCHAR *path, struct stati64 *st);
|
||
static int wstati64ns(const WCHAR *path, struct stati64ns *st);
|
||
static int wlstati64ns(const WCHAR *path, struct stati64ns *st);
|
||
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
|
||
int ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc);
|
||
static FARPROC get_proc_address(const char *module, const char *func, HANDLE *mh);
|
||
... | ... | |
static DIR *
|
||
w32_wopendir(const WCHAR *wpath)
|
||
{
|
||
struct stati64 sbuf;
|
||
struct stati64ns sbuf;
|
||
WIN32_FIND_DATAW fd;
|
||
HANDLE fh;
|
||
DIR *p;
|
||
... | ... | |
//
|
||
// check to see if we've got a directory
|
||
//
|
||
if (wstati64(wpath, &sbuf) < 0) {
|
||
if (wstati64ns(wpath, &sbuf) < 0) {
|
||
return NULL;
|
||
}
|
||
if (!(sbuf.st_mode & S_IFDIR) &&
|
||
... | ... | |
} while (0)
|
||
static time_t filetime_to_unixtime(const FILETIME *ft);
|
||
static long filetime_to_nsec(const FILETIME *ft);
|
||
static WCHAR *name_for_stat(WCHAR *buf, const WCHAR *path);
|
||
static DWORD stati64_handle(HANDLE h, struct stati64 *st);
|
||
static DWORD stati64ns_handle(HANDLE h, struct stati64ns *st);
|
||
/* License: Ruby's */
|
||
static void
|
||
stati64_set_inode(BY_HANDLE_FILE_INFORMATION *pinfo, struct stati64 *st)
|
||
stati64ns_set_inode(BY_HANDLE_FILE_INFORMATION *pinfo, struct stati64ns *st)
|
||
{
|
||
/* struct stati64 layout
|
||
*
|
||
... | ... | |
p4[5] = pinfo->nFileIndexLow;
|
||
}
|
||
/* License: Ruby's */
|
||
static DWORD
|
||
stati64_set_inode_handle(HANDLE h, struct stati64 *st)
|
||
{
|
||
BY_HANDLE_FILE_INFORMATION info;
|
||
DWORD attr = (DWORD)-1;
|
||
if (GetFileInformationByHandle(h, &info)) {
|
||
stati64_set_inode(&info, st);
|
||
}
|
||
return attr;
|
||
}
|
||
#undef fstat
|
||
/* License: Ruby's */
|
||
int
|
||
... | ... | |
/* License: Ruby's */
|
||
int
|
||
rb_w32_fstati64(int fd, struct stati64 *st)
|
||
rb_w32_fstati64ns(int fd, struct stati64ns *st)
|
||
{
|
||
struct stat tmp;
|
||
int ret;
|
||
if (GetEnvironmentVariableW(L"TZ", NULL, 0) == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
|
||
ret = _fstati64(fd, st);
|
||
stati64_set_inode_handle((HANDLE)_get_osfhandle(fd), st);
|
||
return ret;
|
||
}
|
||
ret = fstat(fd, &tmp);
|
||
int ret = fstat(fd, &tmp);
|
||
if (ret) return ret;
|
||
COPY_STAT(tmp, *st, +);
|
||
stati64_handle((HANDLE)_get_osfhandle(fd), st);
|
||
stati64ns_handle((HANDLE)_get_osfhandle(fd), st);
|
||
return ret;
|
||
}
|
||
/* License: Ruby's */
|
||
static DWORD
|
||
stati64_handle(HANDLE h, struct stati64 *st)
|
||
stati64ns_handle(HANDLE h, struct stati64ns *st)
|
||
{
|
||
BY_HANDLE_FILE_INFORMATION info;
|
||
DWORD attr = (DWORD)-1;
|
||
... | ... | |
if (GetFileInformationByHandle(h, &info)) {
|
||
st->st_size = ((__int64)info.nFileSizeHigh << 32) | info.nFileSizeLow;
|
||
st->st_atime = filetime_to_unixtime(&info.ftLastAccessTime);
|
||
st->st_atimensec = filetime_to_nsec(&info.ftLastAccessTime);
|
||
st->st_mtime = filetime_to_unixtime(&info.ftLastWriteTime);
|
||
st->st_mtimensec = filetime_to_nsec(&info.ftLastWriteTime);
|
||
st->st_ctime = filetime_to_unixtime(&info.ftCreationTime);
|
||
st->st_ctimensec = filetime_to_nsec(&info.ftCreationTime);
|
||
st->st_nlink = info.nNumberOfLinks;
|
||
attr = info.dwFileAttributes;
|
||
stati64_set_inode(&info, st);
|
||
stati64ns_set_inode(&info, st);
|
||
}
|
||
return attr;
|
||
}
|
||
... | ... | |
}
|
||
/* License: Ruby's */
|
||
static long
|
||
filetime_to_nsec(const FILETIME *ft)
|
||
{
|
||
ULARGE_INTEGER tmp;
|
||
tmp.LowPart = ft->dwLowDateTime;
|
||
tmp.HighPart = ft->dwHighDateTime;
|
||
return (long)(tmp.QuadPart % 10000000) * 100;
|
||
}
|
||
/* License: Ruby's */
|
||
static unsigned
|
||
fileattr_to_unixmode(DWORD attr, const WCHAR *path)
|
||
{
|
||
... | ... | |
/* License: Ruby's */
|
||
static int
|
||
stat_by_find(const WCHAR *path, struct stati64 *st)
|
||
stat_by_find(const WCHAR *path, struct stati64ns *st)
|
||
{
|
||
HANDLE h;
|
||
WIN32_FIND_DATAW wfd;
|
||
... | ... | |
FindClose(h);
|
||
st->st_mode = fileattr_to_unixmode(wfd.dwFileAttributes, path);
|
||
st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime);
|
||
st->st_atimensec = filetime_to_nsec(&wfd.ftLastAccessTime);
|
||
st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
|
||
st->st_mtimensec = filetime_to_nsec(&wfd.ftLastWriteTime);
|
||
st->st_ctime = filetime_to_unixtime(&wfd.ftCreationTime);
|
||
st->st_ctimensec = filetime_to_nsec(&wfd.ftCreationTime);
|
||
st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
|
||
st->st_nlink = 1;
|
||
return 0;
|
||
... | ... | |
/* License: Ruby's */
|
||
static int
|
||
winnt_stat(const WCHAR *path, struct stati64 *st)
|
||
winnt_stat(const WCHAR *path, struct stati64ns *st)
|
||
{
|
||
HANDLE f;
|
||
WCHAR finalname[PATH_MAX];
|
||
... | ... | |
memset(st, 0, sizeof(*st));
|
||
f = open_special(path, 0, 0);
|
||
if (f != INVALID_HANDLE_VALUE) {
|
||
const DWORD attr = stati64_handle(f, st);
|
||
const DWORD attr = stati64ns_handle(f, st);
|
||
const DWORD len = get_final_path(f, finalname, numberof(finalname), 0);
|
||
CloseHandle(f);
|
||
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
|
||
... | ... | |
/* License: Ruby's */
|
||
static int
|
||
winnt_lstat(const WCHAR *path, struct stati64 *st)
|
||
winnt_lstat(const WCHAR *path, struct stati64ns *st)
|
||
{
|
||
WIN32_FILE_ATTRIBUTE_DATA wfa;
|
||
const WCHAR *p = path;
|
||
... | ... | |
}
|
||
st->st_mode = fileattr_to_unixmode(wfa.dwFileAttributes, path);
|
||
st->st_atime = filetime_to_unixtime(&wfa.ftLastAccessTime);
|
||
st->st_atimensec = filetime_to_nsec(&wfa.ftLastAccessTime);
|
||
st->st_mtime = filetime_to_unixtime(&wfa.ftLastWriteTime);
|
||
st->st_mtimensec = filetime_to_nsec(&wfa.ftLastWriteTime);
|
||
st->st_ctime = filetime_to_unixtime(&wfa.ftCreationTime);
|
||
st->st_ctimensec = filetime_to_nsec(&wfa.ftCreationTime);
|
||
}
|
||
else {
|
||
if (stat_by_find(path, st)) return -1;
|
||
... | ... | |
int
|
||
rb_w32_stat(const char *path, struct stat *st)
|
||
{
|
||
struct stati64 tmp;
|
||
struct stati64ns tmp;
|
||
if (rb_w32_stati64(path, &tmp)) return -1;
|
||
if (rb_w32_stati64ns(path, &tmp)) return -1;
|
||
COPY_STAT(tmp, *st, (_off_t));
|
||
return 0;
|
||
}
|
||
/* License: Ruby's */
|
||
static int
|
||
wstati64(const WCHAR *path, struct stati64 *st)
|
||
wstati64ns(const WCHAR *path, struct stati64ns *st)
|
||
{
|
||
WCHAR *buf1;
|
||
int ret, size;
|
||
... | ... | |
/* License: Ruby's */
|
||
static int
|
||
wlstati64(const WCHAR *path, struct stati64 *st)
|
||
wlstati64ns(const WCHAR *path, struct stati64ns *st)
|
||
{
|
||
WCHAR *buf1;
|
||
int ret, size;
|
||
... | ... | |
/* License: Ruby's */
|
||
int
|
||
rb_w32_ustati64(const char *path, struct stati64 *st)
|
||
rb_w32_ustati64ns(const char *path, struct stati64ns *st)
|
||
{
|
||
return w32_stati64(path, st, CP_UTF8);
|
||
return w32_stati64ns(path, st, CP_UTF8);
|
||
}
|
||
/* License: Ruby's */
|
||
int
|
||
rb_w32_stati64(const char *path, struct stati64 *st)
|
||
rb_w32_stati64ns(const char *path, struct stati64ns *st)
|
||
{
|
||
return w32_stati64(path, st, filecp());
|
||
return w32_stati64ns(path, st, filecp());
|
||
}
|
||
/* License: Ruby's */
|
||
static int
|
||
w32_stati64(const char *path, struct stati64 *st, UINT cp)
|
||
w32_stati64ns(const char *path, struct stati64ns *st, UINT cp)
|
||
{
|
||
WCHAR *wpath;
|
||
int ret;
|
||
if (!(wpath = mbstr_to_wstr(cp, path, -1, NULL)))
|
||
return -1;
|
||
ret = wstati64(wpath, st);
|
||
ret = wstati64ns(wpath, st);
|
||
free(wpath);
|
||
return ret;
|
||
}
|
||
/* License: Ruby's */
|
||
int
|
||
rb_w32_ulstati64(const char *path, struct stati64 *st)
|
||
rb_w32_ulstati64ns(const char *path, struct stati64ns *st)
|
||
{
|
||
return w32_lstati64(path, st, CP_UTF8);
|
||
return w32_lstati64ns(path, st, CP_UTF8);
|
||
}
|
||
/* License: Ruby's */
|
||
int
|
||
rb_w32_lstati64(const char *path, struct stati64 *st)
|
||
rb_w32_lstati64ns(const char *path, struct stati64ns *st)
|
||
{
|
||
return w32_lstati64(path, st, filecp());
|
||
return w32_lstati64ns(path, st, filecp());
|
||
}
|
||
/* License: Ruby's */
|
||
static int
|
||
w32_lstati64(const char *path, struct stati64 *st, UINT cp)
|
||
w32_lstati64ns(const char *path, struct stati64ns *st, UINT cp)
|
||
{
|
||
WCHAR *wpath;
|
||
int ret;
|
||
if (!(wpath = mbstr_to_wstr(cp, path, -1, NULL)))
|
||
return -1;
|
||
ret = wlstati64(wpath, st);
|
||
ret = wlstati64ns(wpath, st);
|
||
free(wpath);
|
||
return ret;
|
||
}
|
||
... | ... | |
int
|
||
rb_w32_access(const char *path, int mode)
|
||
{
|
||
struct stati64 stat;
|
||
if (rb_w32_stati64(path, &stat) != 0)
|
||
struct stati64ns stat;
|
||
if (rb_w32_stati64ns(path, &stat) != 0)
|
||
return -1;
|
||
mode <<= 6;
|
||
if ((stat.st_mode & mode) != mode) {
|
||
... | ... | |
int
|
||
rb_w32_uaccess(const char *path, int mode)
|
||
{
|
||
struct stati64 stat;
|
||
if (rb_w32_ustati64(path, &stat) != 0)
|
||
struct stati64ns stat;
|
||
if (rb_w32_ustati64ns(path, &stat) != 0)
|
||
return -1;
|
||
mode <<= 6;
|
||
if ((stat.st_mode & mode) != mode) {
|
||
... | ... | |
{
|
||
HANDLE hFile;
|
||
FILETIME atime, mtime;
|
||
struct stati64 stat;
|
||
struct stati64ns stat;
|
||
int ret = 0;
|
||
if (wstati64(path, &stat)) {
|
||
if (wstati64ns(path, &stat)) {
|
||
return -1;
|
||
}
|
||