Project

General

Profile

Feature #13726 ยป 01-time-subsec.patch

MSP-Greg (Greg L), 07/07/2017 02:25 AM

View differences:

dir.c
1300 1300
}
1301 1301

  
1302 1302
#ifdef _WIN32
1303
#define STAT(p, s)	rb_w32_ustati64((p), (s))
1303
#define STAT(p, s)	rb_w32_ustati64ns((p), (s))
1304 1304
#undef lstat
1305
#define lstat(p, s)	rb_w32_ulstati64((p), (s))
1305
#define lstat(p, s)	rb_w32_ulstati64ns((p), (s))
1306 1306
#else
1307 1307
#define STAT(p, s)	stat((p), (s))
1308 1308
#endif
file.c
100 100
/* define system APIs */
101 101
#ifdef _WIN32
102 102
#include "win32/file.h"
103
#define STAT(p, s)	rb_w32_ustati64((p), (s))
103
#define STAT(p, s)	rb_w32_ustati64ns((p), (s))
104 104
#undef lstat
105
#define lstat(p, s)	rb_w32_ulstati64((p), (s))
105
#define lstat(p, s)	rb_w32_ulstati64ns((p), (s))
106 106
#undef access
107 107
#define access(p, m)	rb_w32_uaccess((p), (m))
108 108
#undef truncate
include/ruby/win32.h
151 151
#define getppid()		rb_w32_getppid()
152 152
#define sleep(x)		rb_w32_Sleep((x)*1000)
153 153
#define Sleep(msec)		(void)rb_w32_Sleep(msec)
154
#define fstati64(fd,st) 	rb_w32_fstati64(fd,st)
155 154

  
156 155
#undef execv
157 156
#define execv(path,argv)	rb_w32_aspawn(P_OVERLAY,path,argv)
......
166 165
#define unlink(p)		rb_w32_unlink(p)
167 166
#endif /* RUBY_EXPORT */
168 167

  
168
/* same with stati64 except nanosecond timestamps */
169
struct stati64ns {
170
  _dev_t st_dev;
171
  _ino_t st_ino;
172
  unsigned short st_mode;
173
  short st_nlink;
174
  short st_uid;
175
  short st_gid;
176
  _dev_t st_rdev;
177
  __int64 st_size;
178
  __time64_t st_atime;
179
  long st_atimensec;
180
  __time64_t st_mtime;
181
  long st_mtimensec;
182
  __time64_t st_ctime;
183
  long st_ctimensec;
184
};
185

  
169 186
#if SIZEOF_OFF_T == 8
170 187
#define off_t __int64
171
#define stat stati64
172
#define fstat(fd,st)		fstati64(fd,st)
173
#if !defined(_MSC_VER) || RUBY_MSVCRT_VERSION < 80
174
#define stati64 _stati64
175
#ifndef _stati64
176
#define _stati64(path, st) rb_w32_stati64(path, st)
177
#endif
178
#else
179
#define stati64 _stat64
180
#define _stat64(path, st) rb_w32_stati64(path, st)
181
#endif
188
#define stat stati64ns
189
#define HAVE_STRUCT_STAT_ST_ATIMENSEC
190
#define HAVE_STRUCT_STAT_ST_MTIMENSEC
191
#define HAVE_STRUCT_STAT_ST_CTIMENSEC
192
#define fstat(fd,st)		rb_w32_fstati64ns(fd,st)
193
#define stati64ns(path, st)	rb_w32_stati64ns(path, st)
182 194
#else
183 195
#define stat(path,st)		rb_w32_stat(path,st)
184 196
#define fstat(fd,st)		rb_w32_fstat(fd,st)
185 197
extern int rb_w32_stat(const char *, struct stat *);
186 198
extern int rb_w32_fstat(int, struct stat *);
187 199
#endif
188
#define lstat(path,st)		rb_w32_lstati64(path,st)
200
#define lstat(path,st)		rb_w32_lstati64ns(path,st)
189 201
#define access(path,mode)	rb_w32_access(path,mode)
190 202

  
191 203
#define strcasecmp		_stricmp
......
316 328
extern int rb_w32_unlink(const char *);
317 329
extern int rb_w32_uunlink(const char *);
318 330
extern int rb_w32_uchmod(const char *, int);
319
extern int rb_w32_stati64(const char *, struct stati64 *);
320
extern int rb_w32_ustati64(const char *, struct stati64 *);
321
extern int rb_w32_lstati64(const char *, struct stati64 *);
322
extern int rb_w32_ulstati64(const char *, struct stati64 *);
331
extern int rb_w32_stati64ns(const char *, struct stati64ns *);
332
extern int rb_w32_ustati64ns(const char *, struct stati64ns *);
333
extern int rb_w32_lstati64ns(const char *, struct stati64ns *);
334
extern int rb_w32_ulstati64ns(const char *, struct stati64ns *);
323 335
extern int rb_w32_access(const char *, int);
324 336
extern int rb_w32_uaccess(const char *, int);
325 337
extern char rb_w32_fd_is_text(int);
326
extern int rb_w32_fstati64(int, struct stati64 *);
338
extern int rb_w32_fstati64ns(int, struct stati64ns *);
327 339
extern int rb_w32_dup2(int, int);
328 340

  
329 341
#include <float.h>
......
440 452
extern int       setuid (rb_uid_t);
441 453
extern int       setgid (rb_gid_t);
442 454

  
443
extern int fstati64(int, struct stati64 *);
444

  
445 455
extern char *rb_w32_strerror(int);
446 456

  
447 457
#ifdef RUBY_EXPORT
win32/win32.c
60 60
#endif
61 61

  
62 62
static int w32_wopen(const WCHAR *file, int oflag, int perm);
63
static int w32_stati64(const char *path, struct stati64 *st, UINT cp);
64
static int w32_lstati64(const char *path, struct stati64 *st, UINT cp);
63
static int w32_stati64ns(const char *path, struct stati64ns *st, UINT cp);
64
static int w32_lstati64ns(const char *path, struct stati64ns *st, UINT cp);
65 65
static char *w32_getenv(const char *name, UINT cp);
66 66

  
67 67
#undef getenv
68 68
#define DLN_FIND_EXTRA_ARG_DECL ,UINT cp
69 69
#define DLN_FIND_EXTRA_ARG ,cp
70
#define rb_w32_stati64(path, st) w32_stati64(path, st, cp)
70
#define rb_w32_stati64ns(path, st) w32_stati64ns(path, st, cp)
71 71
#define getenv(name) w32_getenv(name, cp)
72 72
#undef CharNext
73 73
#define CharNext(p) CharNextExA(cp, (p), 0)
......
76 76
#include "dln.h"
77 77
#include "dln_find.c"
78 78
#undef MAXPATHLEN
79
#undef rb_w32_stati64
79
#undef rb_w32_stati64ns
80 80
#undef dln_find_exe_r
81 81
#undef dln_find_file_r
82 82
#define dln_find_exe_r(fname, path, buf, size) rb_w32_udln_find_exe_r(fname, path, buf, size, cp)
......
121 121
static int has_redirection(const char *, UINT);
122 122
int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout);
123 123
static int rb_w32_open_osfhandle(intptr_t osfhandle, int flags);
124
static int wstati64(const WCHAR *path, struct stati64 *st);
125
static int wlstati64(const WCHAR *path, struct stati64 *st);
124
static int wstati64ns(const WCHAR *path, struct stati64ns *st);
125
static int wlstati64ns(const WCHAR *path, struct stati64ns *st);
126 126
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
127 127
int ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc);
128 128
static FARPROC get_proc_address(const char *module, const char *func, HANDLE *mh);
......
1973 1973
static DIR *
1974 1974
w32_wopendir(const WCHAR *wpath)
1975 1975
{
1976
    struct stati64 sbuf;
1976
    struct stati64ns sbuf;
1977 1977
    WIN32_FIND_DATAW fd;
1978 1978
    HANDLE fh;
1979 1979
    DIR *p;
......
1987 1987
    //
1988 1988
    // check to see if we've got a directory
1989 1989
    //
1990
    if (wstati64(wpath, &sbuf) < 0) {
1990
    if (wstati64ns(wpath, &sbuf) < 0) {
1991 1991
	return NULL;
1992 1992
    }
1993 1993
    if (!(sbuf.st_mode & S_IFDIR) &&
......
5344 5344
    } while (0)
5345 5345

  
5346 5346
static time_t filetime_to_unixtime(const FILETIME *ft);
5347
static long filetime_to_nsec(const FILETIME *ft);
5347 5348
static WCHAR *name_for_stat(WCHAR *buf, const WCHAR *path);
5348
static DWORD stati64_handle(HANDLE h, struct stati64 *st);
5349
static DWORD stati64ns_handle(HANDLE h, struct stati64ns *st);
5349 5350

  
5350 5351
/* License: Ruby's */
5351 5352
static void
5352
stati64_set_inode(BY_HANDLE_FILE_INFORMATION *pinfo, struct stati64 *st)
5353
stati64ns_set_inode(BY_HANDLE_FILE_INFORMATION *pinfo, struct stati64ns *st)
5353 5354
{
5354 5355
    /* struct stati64 layout
5355 5356
     *
......
5376 5377
    p4[5] = pinfo->nFileIndexLow;
5377 5378
}
5378 5379

  
5379
/* License: Ruby's */
5380
static DWORD
5381
stati64_set_inode_handle(HANDLE h, struct stati64 *st)
5382
{
5383
    BY_HANDLE_FILE_INFORMATION info;
5384
    DWORD attr = (DWORD)-1;
5385

  
5386
    if (GetFileInformationByHandle(h, &info)) {
5387
	stati64_set_inode(&info, st);
5388
    }
5389
    return attr;
5390
}
5391

  
5392 5380
#undef fstat
5393 5381
/* License: Ruby's */
5394 5382
int
......
5409 5397

  
5410 5398
/* License: Ruby's */
5411 5399
int
5412
rb_w32_fstati64(int fd, struct stati64 *st)
5400
rb_w32_fstati64ns(int fd, struct stati64ns *st)
5413 5401
{
5414 5402
    struct stat tmp;
5415
    int ret;
5416

  
5417
    if (GetEnvironmentVariableW(L"TZ", NULL, 0) == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
5418
	ret = _fstati64(fd, st);
5419
	stati64_set_inode_handle((HANDLE)_get_osfhandle(fd), st);
5420
	return ret;
5421
    }
5422
    ret = fstat(fd, &tmp);
5403
    int ret = fstat(fd, &tmp);
5423 5404

  
5424 5405
    if (ret) return ret;
5425 5406
    COPY_STAT(tmp, *st, +);
5426
    stati64_handle((HANDLE)_get_osfhandle(fd), st);
5407
    stati64ns_handle((HANDLE)_get_osfhandle(fd), st);
5427 5408
    return ret;
5428 5409
}
5429 5410

  
5430 5411
/* License: Ruby's */
5431 5412
static DWORD
5432
stati64_handle(HANDLE h, struct stati64 *st)
5413
stati64ns_handle(HANDLE h, struct stati64ns *st)
5433 5414
{
5434 5415
    BY_HANDLE_FILE_INFORMATION info;
5435 5416
    DWORD attr = (DWORD)-1;
......
5437 5418
    if (GetFileInformationByHandle(h, &info)) {
5438 5419
	st->st_size = ((__int64)info.nFileSizeHigh << 32) | info.nFileSizeLow;
5439 5420
	st->st_atime = filetime_to_unixtime(&info.ftLastAccessTime);
5421
	st->st_atimensec = filetime_to_nsec(&info.ftLastAccessTime);
5440 5422
	st->st_mtime = filetime_to_unixtime(&info.ftLastWriteTime);
5423
	st->st_mtimensec = filetime_to_nsec(&info.ftLastWriteTime);
5441 5424
	st->st_ctime = filetime_to_unixtime(&info.ftCreationTime);
5425
	st->st_ctimensec = filetime_to_nsec(&info.ftCreationTime);
5442 5426
	st->st_nlink = info.nNumberOfLinks;
5443 5427
	attr = info.dwFileAttributes;
5444
	stati64_set_inode(&info, st);
5428
	stati64ns_set_inode(&info, st);
5445 5429
    }
5446 5430
    return attr;
5447 5431
}
......
5459 5443
}
5460 5444

  
5461 5445
/* License: Ruby's */
5446
static long
5447
filetime_to_nsec(const FILETIME *ft)
5448
{
5449
    ULARGE_INTEGER tmp;
5450
    tmp.LowPart = ft->dwLowDateTime;
5451
    tmp.HighPart = ft->dwHighDateTime;
5452
    return (long)(tmp.QuadPart % 10000000) * 100;
5453
}
5454

  
5455
/* License: Ruby's */
5462 5456
static unsigned
5463 5457
fileattr_to_unixmode(DWORD attr, const WCHAR *path)
5464 5458
{
......
5546 5540

  
5547 5541
/* License: Ruby's */
5548 5542
static int
5549
stat_by_find(const WCHAR *path, struct stati64 *st)
5543
stat_by_find(const WCHAR *path, struct stati64ns *st)
5550 5544
{
5551 5545
    HANDLE h;
5552 5546
    WIN32_FIND_DATAW wfd;
......
5568 5562
    FindClose(h);
5569 5563
    st->st_mode  = fileattr_to_unixmode(wfd.dwFileAttributes, path);
5570 5564
    st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime);
5565
    st->st_atimensec = filetime_to_nsec(&wfd.ftLastAccessTime);
5571 5566
    st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
5567
    st->st_mtimensec = filetime_to_nsec(&wfd.ftLastWriteTime);
5572 5568
    st->st_ctime = filetime_to_unixtime(&wfd.ftCreationTime);
5569
    st->st_ctimensec = filetime_to_nsec(&wfd.ftCreationTime);
5573 5570
    st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
5574 5571
    st->st_nlink = 1;
5575 5572
    return 0;
......
5587 5584

  
5588 5585
/* License: Ruby's */
5589 5586
static int
5590
winnt_stat(const WCHAR *path, struct stati64 *st)
5587
winnt_stat(const WCHAR *path, struct stati64ns *st)
5591 5588
{
5592 5589
    HANDLE f;
5593 5590
    WCHAR finalname[PATH_MAX];
......
5595 5592
    memset(st, 0, sizeof(*st));
5596 5593
    f = open_special(path, 0, 0);
5597 5594
    if (f != INVALID_HANDLE_VALUE) {
5598
	const DWORD attr = stati64_handle(f, st);
5595
	const DWORD attr = stati64ns_handle(f, st);
5599 5596
	const DWORD len = get_final_path(f, finalname, numberof(finalname), 0);
5600 5597
	CloseHandle(f);
5601 5598
	if (attr & FILE_ATTRIBUTE_DIRECTORY) {
......
5620 5617

  
5621 5618
/* License: Ruby's */
5622 5619
static int
5623
winnt_lstat(const WCHAR *path, struct stati64 *st)
5620
winnt_lstat(const WCHAR *path, struct stati64ns *st)
5624 5621
{
5625 5622
    WIN32_FILE_ATTRIBUTE_DATA wfa;
5626 5623
    const WCHAR *p = path;
......
5651 5648
	}
5652 5649
	st->st_mode  = fileattr_to_unixmode(wfa.dwFileAttributes, path);
5653 5650
	st->st_atime = filetime_to_unixtime(&wfa.ftLastAccessTime);
5651
	st->st_atimensec = filetime_to_nsec(&wfa.ftLastAccessTime);
5654 5652
	st->st_mtime = filetime_to_unixtime(&wfa.ftLastWriteTime);
5653
	st->st_mtimensec = filetime_to_nsec(&wfa.ftLastWriteTime);
5655 5654
	st->st_ctime = filetime_to_unixtime(&wfa.ftCreationTime);
5655
	st->st_ctimensec = filetime_to_nsec(&wfa.ftCreationTime);
5656 5656
    }
5657 5657
    else {
5658 5658
	if (stat_by_find(path, st)) return -1;
......
5667 5667
int
5668 5668
rb_w32_stat(const char *path, struct stat *st)
5669 5669
{
5670
    struct stati64 tmp;
5670
    struct stati64ns tmp;
5671 5671

  
5672
    if (rb_w32_stati64(path, &tmp)) return -1;
5672
    if (rb_w32_stati64ns(path, &tmp)) return -1;
5673 5673
    COPY_STAT(tmp, *st, (_off_t));
5674 5674
    return 0;
5675 5675
}
5676 5676

  
5677 5677
/* License: Ruby's */
5678 5678
static int
5679
wstati64(const WCHAR *path, struct stati64 *st)
5679
wstati64ns(const WCHAR *path, struct stati64ns *st)
5680 5680
{
5681 5681
    WCHAR *buf1;
5682 5682
    int ret, size;
......
5699 5699

  
5700 5700
/* License: Ruby's */
5701 5701
static int
5702
wlstati64(const WCHAR *path, struct stati64 *st)
5702
wlstati64ns(const WCHAR *path, struct stati64ns *st)
5703 5703
{
5704 5704
    WCHAR *buf1;
5705 5705
    int ret, size;
......
5756 5756

  
5757 5757
/* License: Ruby's */
5758 5758
int
5759
rb_w32_ustati64(const char *path, struct stati64 *st)
5759
rb_w32_ustati64ns(const char *path, struct stati64ns *st)
5760 5760
{
5761
    return w32_stati64(path, st, CP_UTF8);
5761
    return w32_stati64ns(path, st, CP_UTF8);
5762 5762
}
5763 5763

  
5764 5764
/* License: Ruby's */
5765 5765
int
5766
rb_w32_stati64(const char *path, struct stati64 *st)
5766
rb_w32_stati64ns(const char *path, struct stati64ns *st)
5767 5767
{
5768
    return w32_stati64(path, st, filecp());
5768
    return w32_stati64ns(path, st, filecp());
5769 5769
}
5770 5770

  
5771 5771
/* License: Ruby's */
5772 5772
static int
5773
w32_stati64(const char *path, struct stati64 *st, UINT cp)
5773
w32_stati64ns(const char *path, struct stati64ns *st, UINT cp)
5774 5774
{
5775 5775
    WCHAR *wpath;
5776 5776
    int ret;
5777 5777

  
5778 5778
    if (!(wpath = mbstr_to_wstr(cp, path, -1, NULL)))
5779 5779
	return -1;
5780
    ret = wstati64(wpath, st);
5780
    ret = wstati64ns(wpath, st);
5781 5781
    free(wpath);
5782 5782
    return ret;
5783 5783
}
5784 5784

  
5785 5785
/* License: Ruby's */
5786 5786
int
5787
rb_w32_ulstati64(const char *path, struct stati64 *st)
5787
rb_w32_ulstati64ns(const char *path, struct stati64ns *st)
5788 5788
{
5789
    return w32_lstati64(path, st, CP_UTF8);
5789
    return w32_lstati64ns(path, st, CP_UTF8);
5790 5790
}
5791 5791

  
5792 5792
/* License: Ruby's */
5793 5793
int
5794
rb_w32_lstati64(const char *path, struct stati64 *st)
5794
rb_w32_lstati64ns(const char *path, struct stati64ns *st)
5795 5795
{
5796
    return w32_lstati64(path, st, filecp());
5796
    return w32_lstati64ns(path, st, filecp());
5797 5797
}
5798 5798

  
5799 5799
/* License: Ruby's */
5800 5800
static int
5801
w32_lstati64(const char *path, struct stati64 *st, UINT cp)
5801
w32_lstati64ns(const char *path, struct stati64ns *st, UINT cp)
5802 5802
{
5803 5803
    WCHAR *wpath;
5804 5804
    int ret;
5805 5805

  
5806 5806
    if (!(wpath = mbstr_to_wstr(cp, path, -1, NULL)))
5807 5807
	return -1;
5808
    ret = wlstati64(wpath, st);
5808
    ret = wlstati64ns(wpath, st);
5809 5809
    free(wpath);
5810 5810
    return ret;
5811 5811
}
......
5814 5814
int
5815 5815
rb_w32_access(const char *path, int mode)
5816 5816
{
5817
    struct stati64 stat;
5818
    if (rb_w32_stati64(path, &stat) != 0)
5817
    struct stati64ns stat;
5818
    if (rb_w32_stati64ns(path, &stat) != 0)
5819 5819
	return -1;
5820 5820
    mode <<= 6;
5821 5821
    if ((stat.st_mode & mode) != mode) {
......
5829 5829
int
5830 5830
rb_w32_uaccess(const char *path, int mode)
5831 5831
{
5832
    struct stati64 stat;
5833
    if (rb_w32_ustati64(path, &stat) != 0)
5832
    struct stati64ns stat;
5833
    if (rb_w32_ustati64ns(path, &stat) != 0)
5834 5834
	return -1;
5835 5835
    mode <<= 6;
5836 5836
    if ((stat.st_mode & mode) != mode) {
......
7266 7266
{
7267 7267
    HANDLE hFile;
7268 7268
    FILETIME atime, mtime;
7269
    struct stati64 stat;
7269
    struct stati64ns stat;
7270 7270
    int ret = 0;
7271 7271

  
7272
    if (wstati64(path, &stat)) {
7272
    if (wstati64ns(path, &stat)) {
7273 7273
	return -1;
7274 7274
    }
7275 7275