forked from simonsj/fdupes-jody
-
Notifications
You must be signed in to change notification settings - Fork 0
/
win_stat.c
71 lines (62 loc) · 2.21 KB
/
win_stat.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
* Windows-native code for getting stat()-like information
*
* Copyright (C) 2017 by Jody Bruchon <[email protected]>
* Released under The MIT License
*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <limits.h>
#include "win_stat.h"
#include <stdint.h>
/* Convert NT epoch to UNIX epoch */
static time_t nttime_to_unixtime(const uint64_t * const restrict timestamp)
{
uint64_t newstamp;
memcpy(&newstamp, timestamp, sizeof(uint64_t));
newstamp /= 10000000LL;
if (newstamp <= 11644473600LL) return 0;
newstamp -= 11644473600LL;
return newstamp;
}
/* Get stat()-like extra information for a file on Windows */
int win_stat(const char * const filename, struct winstat * const restrict buf)
{
HANDLE hFile;
BY_HANDLE_FILE_INFORMATION bhfi;
uint64_t timetemp;
#ifdef UNICODE
static wchar_t wname[PATH_MAX];
if (!buf) return -127;
if (!MultiByteToWideChar(CP_UTF8, 0, filename, -1, wname, PATH_MAX)) return -126;
hFile = CreateFileW(wname, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
#else
if (!buf) return -127;
hFile = CreateFile(filename, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
#endif
if (hFile == INVALID_HANDLE_VALUE) goto failure;
if (!GetFileInformationByHandle(hFile, &bhfi)) goto failure2;
buf->inode = ((uint64_t)(bhfi.nFileIndexHigh) << 32) + (uint64_t)bhfi.nFileIndexLow;
buf->size = ((uint64_t)(bhfi.nFileSizeHigh) << 32) + (uint64_t)bhfi.nFileSizeLow;
timetemp = ((uint64_t)(bhfi.ftCreationTime.dwHighDateTime) << 32) + bhfi.ftCreationTime.dwLowDateTime;
buf->ctime = nttime_to_unixtime(&timetemp);
timetemp = ((uint64_t)(bhfi.ftLastWriteTime.dwHighDateTime) << 32) + bhfi.ftLastWriteTime.dwLowDateTime;
buf->mtime = nttime_to_unixtime(&timetemp);
timetemp = ((uint64_t)(bhfi.ftLastAccessTime.dwHighDateTime) << 32) + bhfi.ftLastAccessTime.dwLowDateTime;
buf->atime = nttime_to_unixtime(&timetemp);
buf->device = (uint32_t)bhfi.dwVolumeSerialNumber;
buf->nlink = (uint32_t)bhfi.nNumberOfLinks;
buf->mode = (uint32_t)bhfi.dwFileAttributes;
CloseHandle(hFile);
return 0;
failure:
CloseHandle(hFile);
return -1;
failure2:
CloseHandle(hFile);
return -2;
}