aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-06-20 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2023-12-17 13:35:20 +0500
commita3e1d227377188734b82f023f96f8e25dc40f3e6 (patch)
tree23cad8d47eb23d26ea727b4f7f4a65124f724065 /CPP/Windows
parentf19f813537c7aea1c20749c914e756b54a9c3cf5 (diff)
download7zip-22.00.tar.gz
7zip-22.00.tar.bz2
7zip-22.00.zip
22.0022.00
Diffstat (limited to 'CPP/Windows')
-rw-r--r--CPP/Windows/FileDir.cpp73
-rw-r--r--CPP/Windows/FileDir.h10
-rw-r--r--CPP/Windows/FileFind.cpp133
-rw-r--r--CPP/Windows/FileFind.h95
-rw-r--r--CPP/Windows/FileIO.cpp88
-rw-r--r--CPP/Windows/FileIO.h44
-rw-r--r--CPP/Windows/PropVariant.cpp132
-rw-r--r--CPP/Windows/PropVariant.h52
-rw-r--r--CPP/Windows/PropVariantConv.cpp58
-rw-r--r--CPP/Windows/PropVariantConv.h5
-rw-r--r--CPP/Windows/SecurityUtils.cpp2
-rw-r--r--CPP/Windows/TimeUtils.cpp220
-rw-r--r--CPP/Windows/TimeUtils.h130
13 files changed, 848 insertions, 194 deletions
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
index 8a33fc8..cce2638 100644
--- a/CPP/Windows/FileDir.cpp
+++ b/CPP/Windows/FileDir.cpp
@@ -17,7 +17,6 @@
17 17
18#include "../Common/StringConvert.h" 18#include "../Common/StringConvert.h"
19#include "../Common/C_FileIO.h" 19#include "../Common/C_FileIO.h"
20#include "TimeUtils.h"
21#endif 20#endif
22 21
23#include "FileDir.h" 22#include "FileDir.h"
@@ -32,6 +31,30 @@ using namespace NWindows;
32using namespace NFile; 31using namespace NFile;
33using namespace NName; 32using namespace NName;
34 33
34#ifndef _WIN32
35
36static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts)
37{
38 if (ft)
39 {
40 ts = *ft;
41 return true;
42 }
43 // else
44 {
45 ts.tv_sec = 0;
46 ts.tv_nsec =
47 #ifdef UTIME_OMIT
48 UTIME_OMIT; // -2 keep old timesptamp
49 #else
50 // UTIME_NOW; -1 // set to the current time
51 0;
52 #endif
53 return false;
54 }
55}
56#endif
57
35namespace NWindows { 58namespace NWindows {
36namespace NFile { 59namespace NFile {
37namespace NDir { 60namespace NDir {
@@ -86,7 +109,7 @@ bool GetSystemDir(FString &path)
86#endif // UNDER_CE 109#endif // UNDER_CE
87 110
88 111
89bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) 112bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
90{ 113{
91 #ifndef _UNICODE 114 #ifndef _UNICODE
92 if (!g_IsNT) 115 if (!g_IsNT)
@@ -920,39 +943,11 @@ bool GetCurrentDir(FString &path)
920 // #define UTIME_OMIT -2 943 // #define UTIME_OMIT -2
921#endif 944#endif
922 945
923static bool FILETME_To_timespec(const FILETIME *ft, timespec &ts)
924{
925 if (ft)
926 {
927 const Int64 sec = NTime::FileTimeToUnixTime64(*ft);
928 // time_t is long
929 const time_t sec2 = (time_t)sec;
930 if (sec2 == sec)
931 {
932 ts.tv_sec = sec2;
933 const UInt64 winTime = (((UInt64)ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
934 ts.tv_nsec = (long)((winTime % 10000000) * 100);
935 return true;
936 }
937 }
938 // else
939 {
940 ts.tv_sec = 0;
941 ts.tv_nsec =
942 #ifdef UTIME_OMIT
943 UTIME_OMIT; // keep old timesptamp
944 #else
945 // UTIME_NOW; // set to the current time
946 0;
947 #endif
948 return false;
949 }
950}
951 946
952 947
953 948
954 949
955bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) 950bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
956{ 951{
957 // need testing 952 // need testing
958 /* 953 /*
@@ -998,12 +993,18 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const
998 UNUSED_VAR(cTime) 993 UNUSED_VAR(cTime)
999 994
1000 bool needChange; 995 bool needChange;
1001 needChange = FILETME_To_timespec(aTime, times[0]); 996 needChange = FiTime_To_timespec(aTime, times[0]);
1002 needChange |= FILETME_To_timespec(mTime, times[1]); 997 needChange |= FiTime_To_timespec(mTime, times[1]);
998
999 /*
1000 if (mTime)
1001 {
1002 printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec);
1003 }
1004 */
1003 1005
1004 if (!needChange) 1006 if (!needChange)
1005 return true; 1007 return true;
1006
1007 const int flags = 0; // follow link 1008 const int flags = 0; // follow link
1008 // = AT_SYMLINK_NOFOLLOW; // don't follow link 1009 // = AT_SYMLINK_NOFOLLOW; // don't follow link
1009 return utimensat(AT_FDCWD, path, times, flags) == 0; 1010 return utimensat(AT_FDCWD, path, times, flags) == 0;
@@ -1039,6 +1040,10 @@ static C_umask g_umask;
1039#define TRACE_chmod(s, mode) \ 1040#define TRACE_chmod(s, mode) \
1040 PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode))); 1041 PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode)));
1041 1042
1043int my_chown(CFSTR path, uid_t owner, gid_t group)
1044{
1045 return chown(path, owner, group);
1046}
1042 1047
1043bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) 1048bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
1044{ 1049{
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
index 6d6ddea..08281aa 100644
--- a/CPP/Windows/FileDir.h
+++ b/CPP/Windows/FileDir.h
@@ -14,7 +14,12 @@ namespace NDir {
14bool GetWindowsDir(FString &path); 14bool GetWindowsDir(FString &path);
15bool GetSystemDir(FString &path); 15bool GetSystemDir(FString &path);
16 16
17bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); 17/*
18WIN32 API : SetFileTime() doesn't allow to set zero timestamps in file
19but linux : allows unix time = 0 in filesystem
20*/
21
22bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);
18 23
19 24
20#ifdef _WIN32 25#ifdef _WIN32
@@ -27,6 +32,9 @@ bool SetFileAttrib(CFSTR path, DWORD attrib);
27 SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute 32 SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute
28 bits that are related to current system only. 33 bits that are related to current system only.
29*/ 34*/
35#else
36
37int my_chown(CFSTR path, uid_t owner, gid_t group);
30 38
31#endif 39#endif
32 40
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp
index 591f8df..c655759 100644
--- a/CPP/Windows/FileFind.cpp
+++ b/CPP/Windows/FileFind.cpp
@@ -7,6 +7,8 @@
7#ifndef _WIN32 7#ifndef _WIN32
8#include <fcntl.h> /* Definition of AT_* constants */ 8#include <fcntl.h> /* Definition of AT_* constants */
9#include "TimeUtils.h" 9#include "TimeUtils.h"
10// for major
11// #include <sys/sysmacros.h>
10#endif 12#endif
11 13
12#include "FileFind.h" 14#include "FileFind.h"
@@ -62,24 +64,35 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
62 64
63namespace NFind { 65namespace NFind {
64 66
67/*
68#ifdef _WIN32
65#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0; 69#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;
70#else
71#define MY_CLEAR_FILETIME(ft) ft.tv_sec = 0; ft.tv_nsec = 0;
72#endif
73*/
66 74
67void CFileInfoBase::ClearBase() throw() 75void CFileInfoBase::ClearBase() throw()
68{ 76{
69 Size = 0; 77 Size = 0;
70 MY_CLEAR_FILETIME(CTime); 78 FiTime_Clear(CTime);
71 MY_CLEAR_FILETIME(ATime); 79 FiTime_Clear(ATime);
72 MY_CLEAR_FILETIME(MTime); 80 FiTime_Clear(MTime);
81
82 #ifdef _WIN32
73 Attrib = 0; 83 Attrib = 0;
74 // ReparseTag = 0; 84 // ReparseTag = 0;
75 IsAltStream = false; 85 IsAltStream = false;
76 IsDevice = false; 86 IsDevice = false;
77 87 #else
78 #ifndef _WIN32 88 dev = 0;
79 ino = 0; 89 ino = 0;
80 nlink = 0;
81 mode = 0; 90 mode = 0;
82 #endif 91 nlink = 0;
92 uid = 0;
93 gid = 0;
94 rdev = 0;
95 #endif
83} 96}
84 97
85bool CFileInfo::IsDots() const throw() 98bool CFileInfo::IsDots() const throw()
@@ -439,6 +452,20 @@ also we support paths that are not supported by FindFirstFile:
439bool CFileInfo::Find(CFSTR path, bool followLink) 452bool CFileInfo::Find(CFSTR path, bool followLink)
440{ 453{
441 #ifdef SUPPORT_DEVICE_FILE 454 #ifdef SUPPORT_DEVICE_FILE
455
456 if (IS_PATH_SEPAR(path[0]) &&
457 IS_PATH_SEPAR(path[1]) &&
458 path[2] == '.' &&
459 path[3] == 0)
460 {
461 // 22.00 : it's virtual directory for devices
462 // IsDevice = true;
463 ClearBase();
464 Name = path + 2;
465 Attrib = FILE_ATTRIBUTE_DIRECTORY;
466 return true;
467 }
468
442 if (IsDevicePath(path)) 469 if (IsDevicePath(path))
443 { 470 {
444 ClearBase(); 471 ClearBase();
@@ -469,7 +496,7 @@ bool CFileInfo::Find(CFSTR path, bool followLink)
469 496
470 #if defined(_WIN32) && !defined(UNDER_CE) 497 #if defined(_WIN32) && !defined(UNDER_CE)
471 498
472 int colonPos = FindAltStreamColon(path); 499 const int colonPos = FindAltStreamColon(path);
473 if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0) 500 if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0)
474 { 501 {
475 UString streamName = fs2us(path + (unsigned)colonPos); 502 UString streamName = fs2us(path + (unsigned)colonPos);
@@ -635,7 +662,7 @@ bool CFileInfo::Find(CFSTR path, bool followLink)
635 return Fill_From_ByHandleFileInfo(path); 662 return Fill_From_ByHandleFileInfo(path);
636} 663}
637 664
638bool CFileInfo::Fill_From_ByHandleFileInfo(CFSTR path) 665bool CFileInfoBase::Fill_From_ByHandleFileInfo(CFSTR path)
639{ 666{
640 BY_HANDLE_FILE_INFORMATION info; 667 BY_HANDLE_FILE_INFORMATION info;
641 if (!NIO::CFileBase::GetFileInformation(path, &info)) 668 if (!NIO::CFileBase::GetFileInformation(path, &info))
@@ -950,13 +977,6 @@ static const char *Get_Name_from_Path(CFSTR path) throw()
950} 977}
951 978
952 979
953void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft)
954{
955 UInt64 v = NTime::UnixTime64ToFileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);
956 ft.dwLowDateTime = (DWORD)v;
957 ft.dwHighDateTime = (DWORD)(v >> 32);
958}
959
960UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode) 980UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode)
961{ 981{
962 UInt32 attrib = S_ISDIR(mode) ? 982 UInt32 attrib = S_ISDIR(mode) ?
@@ -984,7 +1004,7 @@ UInt32 Get_WinAttrib_From_stat(const struct stat &st)
984 1004
985void CFileInfo::SetFrom_stat(const struct stat &st) 1005void CFileInfo::SetFrom_stat(const struct stat &st)
986{ 1006{
987 IsDevice = false; 1007 // IsDevice = false;
988 1008
989 if (S_ISDIR(st.st_mode)) 1009 if (S_ISDIR(st.st_mode))
990 { 1010 {
@@ -995,7 +1015,7 @@ void CFileInfo::SetFrom_stat(const struct stat &st)
995 Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename 1015 Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename
996 } 1016 }
997 1017
998 Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode); 1018 // Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode);
999 1019
1000 // NTime::UnixTimeToFileTime(st.st_ctime, CTime); 1020 // NTime::UnixTimeToFileTime(st.st_ctime, CTime);
1001 // NTime::UnixTimeToFileTime(st.st_mtime, MTime); 1021 // NTime::UnixTimeToFileTime(st.st_mtime, MTime);
@@ -1010,27 +1030,89 @@ void CFileInfo::SetFrom_stat(const struct stat &st)
1010 */ 1030 */
1011 // timespec_To_FILETIME(st.st_birthtimespec, CTime); 1031 // timespec_To_FILETIME(st.st_birthtimespec, CTime);
1012 // #else 1032 // #else
1013 timespec_To_FILETIME(st.st_ctimespec, CTime); 1033 // timespec_To_FILETIME(st.st_ctimespec, CTime);
1014 // #endif 1034 // #endif
1015 timespec_To_FILETIME(st.st_mtimespec, MTime); 1035 // timespec_To_FILETIME(st.st_mtimespec, MTime);
1016 timespec_To_FILETIME(st.st_atimespec, ATime); 1036 // timespec_To_FILETIME(st.st_atimespec, ATime);
1037 CTime = st.st_ctimespec;
1038 MTime = st.st_mtimespec;
1039 ATime = st.st_atimespec;
1040
1017 #else 1041 #else
1018 timespec_To_FILETIME(st.st_ctim, CTime); 1042 // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100);
1019 timespec_To_FILETIME(st.st_mtim, MTime); 1043 // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100);
1020 timespec_To_FILETIME(st.st_atim, ATime); 1044 // timespec_To_FILETIME(st.st_atim, ATime, &ATime_ns100);
1045 CTime = st.st_ctim;
1046 MTime = st.st_mtim;
1047 ATime = st.st_atim;
1048
1021 #endif 1049 #endif
1022 1050
1023 dev = st.st_dev; 1051 dev = st.st_dev;
1024 ino = st.st_ino; 1052 ino = st.st_ino;
1025 nlink = st.st_nlink;
1026 mode = st.st_mode; 1053 mode = st.st_mode;
1054 nlink = st.st_nlink;
1055 uid = st.st_uid;
1056 gid = st.st_gid;
1057 rdev = st.st_rdev;
1058
1059 /*
1060 printf("\n sizeof timespec = %d", (int)sizeof(timespec));
1061 printf("\n sizeof st_rdev = %d", (int)sizeof(rdev));
1062 printf("\n sizeof st_ino = %d", (int)sizeof(ino));
1063 printf("\n sizeof mode_t = %d", (int)sizeof(mode_t));
1064 printf("\n sizeof nlink_t = %d", (int)sizeof(nlink_t));
1065 printf("\n sizeof uid_t = %d", (int)sizeof(uid_t));
1066 printf("\n");
1067 */
1068 /*
1069 printf("\n st_rdev = %llx", (long long)rdev);
1070 printf("\n st_dev = %llx", (long long)dev);
1071 printf("\n dev : major = %5x minor = %5x", (unsigned)major(dev), (unsigned)minor(dev));
1072 printf("\n st_ino = %lld", (long long)(ino));
1073 printf("\n rdev : major = %5x minor = %5x", (unsigned)major(rdev), (unsigned)minor(rdev));
1074 printf("\n size = %lld \n", (long long)(Size));
1075 printf("\n");
1076 */
1077}
1078
1079/*
1080int Uid_To_Uname(uid_t uid, AString &name)
1081{
1082 name.Empty();
1083 struct passwd *passwd;
1084
1085 if (uid != 0 && uid == cached_no_such_uid)
1086 {
1087 *uname = xstrdup ("");
1088 return;
1089 }
1090
1091 if (!cached_uname || uid != cached_uid)
1092 {
1093 passwd = getpwuid (uid);
1094 if (passwd)
1095 {
1096 cached_uid = uid;
1097 assign_string (&cached_uname, passwd->pw_name);
1098 }
1099 else
1100 {
1101 cached_no_such_uid = uid;
1102 *uname = xstrdup ("");
1103 return;
1104 }
1105 }
1106 *uname = xstrdup (cached_uname);
1027} 1107}
1108*/
1028 1109
1029bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink) 1110bool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink)
1030{ 1111{
1031 struct stat st; 1112 struct stat st;
1032 if (MY__lstat(path, &st, followLink) != 0) 1113 if (MY__lstat(path, &st, followLink) != 0)
1033 return false; 1114 return false;
1115 // printf("\nFind_DontFill_Name : name=%s\n", path);
1034 SetFrom_stat(st); 1116 SetFrom_stat(st);
1035 return true; 1117 return true;
1036} 1118}
@@ -1232,6 +1314,7 @@ bool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool f
1232 1314
1233 if (res != 0) 1315 if (res != 0)
1234 return false; 1316 return false;
1317 // printf("\nname=%s\n", de.Name.Ptr());
1235 fileInfo.SetFrom_stat(st); 1318 fileInfo.SetFrom_stat(st);
1236 fileInfo.Name = de.Name; 1319 fileInfo.Name = de.Name;
1237 return true; 1320 return true;
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h
index 8f28ee3..fcfe02c 100644
--- a/CPP/Windows/FileFind.h
+++ b/CPP/Windows/FileFind.h
@@ -9,10 +9,14 @@
9#include <dirent.h> 9#include <dirent.h>
10#endif 10#endif
11 11
12#include "../Common/MyLinux.h"
12#include "../Common/MyString.h" 13#include "../Common/MyString.h"
13#include "../Common/MyWindows.h" 14#include "../Common/MyWindows.h"
15
14#include "Defs.h" 16#include "Defs.h"
15 17
18#include "FileIO.h"
19
16namespace NWindows { 20namespace NWindows {
17namespace NFile { 21namespace NFile {
18namespace NFind { 22namespace NFind {
@@ -32,6 +36,7 @@ bool DoesFileOrDirExist(CFSTR name);
32 36
33DWORD GetFileAttrib(CFSTR path); 37DWORD GetFileAttrib(CFSTR path);
34 38
39#ifdef _WIN32
35 40
36namespace NAttributes 41namespace NAttributes
37{ 42{
@@ -42,21 +47,38 @@ namespace NAttributes
42 inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; } 47 inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; }
43 inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; } 48 inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; }
44 inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; } 49 inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; }
50
51 inline UInt32 Get_PosixMode_From_WinAttrib(DWORD attrib)
52 {
53 UInt32 v = IsDir(attrib) ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG;
54 /* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY).
55 So extracting at Linux will be allowed to write files inside (0777) directories. */
56 v |= ((IsReadOnly(attrib) && !IsDir(attrib)) ? 0555 : 0777);
57 return v;
58 }
45} 59}
46 60
61#else
62
63UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode);
64
65#endif
66
47class CFileInfoBase 67class CFileInfoBase
48{ 68{
69 #ifdef _WIN32
49 bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); } 70 bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); }
71 #endif
50public: 72public:
51 UInt64 Size; 73 UInt64 Size;
52 FILETIME CTime; 74 CFiTime CTime;
53 FILETIME ATime; 75 CFiTime ATime;
54 FILETIME MTime; 76 CFiTime MTime;
77 #ifdef _WIN32
55 DWORD Attrib; 78 DWORD Attrib;
56 bool IsAltStream; 79 bool IsAltStream;
57 bool IsDevice; 80 bool IsDevice;
58 81
59 #ifdef _WIN32
60 /* 82 /*
61 #ifdef UNDER_CE 83 #ifdef UNDER_CE
62 DWORD ObjectID; 84 DWORD ObjectID;
@@ -64,24 +86,25 @@ public:
64 UINT32 ReparseTag; 86 UINT32 ReparseTag;
65 #endif 87 #endif
66 */ 88 */
67 #else 89 #else
68 dev_t dev; 90 dev_t dev; /* ID of device containing file */
69 ino_t ino; 91 ino_t ino;
70 nlink_t nlink;
71 mode_t mode; 92 mode_t mode;
93 nlink_t nlink;
94 uid_t uid; /* user ID of owner */
95 gid_t gid; /* group ID of owner */
96 dev_t rdev; /* device ID (defined, if S_ISCHR(mode) || S_ISBLK(mode)) */
72 // bool Use_lstat; 97 // bool Use_lstat;
73 #endif 98 #endif
74 99
75 CFileInfoBase() { ClearBase(); } 100 CFileInfoBase() { ClearBase(); }
76 void ClearBase() throw(); 101 void ClearBase() throw();
77 102
78 void SetAsDir() 103 #ifdef _WIN32
79 { 104
80 Attrib = FILE_ATTRIBUTE_DIRECTORY; 105 bool Fill_From_ByHandleFileInfo(CFSTR path);
81 #ifndef _WIN32 106 void SetAsDir() { Attrib = FILE_ATTRIBUTE_DIRECTORY; } // |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16));
82 Attrib |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16)); 107 void SetAsFile() { Attrib = 0; }
83 #endif
84 }
85 108
86 bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); } 109 bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }
87 bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); } 110 bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }
@@ -96,13 +119,33 @@ public:
96 bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); } 119 bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); }
97 bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); } 120 bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); }
98 121
99 #ifndef _WIN32 122 UInt32 GetWinAttrib() const { return Attrib; }
100 bool IsPosixLink() const 123 UInt32 GetPosixAttrib() const
101 { 124 {
102 const UInt32 mod = Attrib >> 16; 125 return NAttributes::Get_PosixMode_From_WinAttrib(Attrib);
103 return S_ISLNK(mod);
104 } 126 }
105 #endif 127 bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; }
128
129 #else
130
131 UInt32 GetPosixAttrib() const { return mode; }
132 UInt32 GetWinAttrib() const { return Get_WinAttribPosix_From_PosixMode(mode); }
133
134 bool IsDir() const { return S_ISDIR(mode); }
135 void SetAsDir() { mode = S_IFDIR; }
136 void SetAsFile() { mode = S_IFREG; }
137
138 bool IsReadOnly() const
139 {
140 // does linux support writing to ReadOnly files?
141 if ((mode & 0222) == 0) // S_IWUSR in p7zip
142 return true;
143 return false;
144 }
145
146 bool IsPosixLink() const { return S_ISLNK(mode); }
147
148 #endif
106 149
107 bool IsOsSymLink() const 150 bool IsOsSymLink() const
108 { 151 {
@@ -126,7 +169,7 @@ struct CFileInfo: public CFileInfoBase
126 bool Find_FollowLink(CFSTR path) { return Find(path, true); } 169 bool Find_FollowLink(CFSTR path) { return Find(path, true); }
127 170
128 #ifdef _WIN32 171 #ifdef _WIN32
129 bool Fill_From_ByHandleFileInfo(CFSTR path); 172 // bool Fill_From_ByHandleFileInfo(CFSTR path);
130 // bool FollowReparse(CFSTR path, bool isDir); 173 // bool FollowReparse(CFSTR path, bool isDir);
131 #else 174 #else
132 bool Find_DontFill_Name(CFSTR path, bool followLink = false); 175 bool Find_DontFill_Name(CFSTR path, bool followLink = false);
@@ -287,16 +330,8 @@ inline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode)
287} 330}
288*/ 331*/
289 332
290UInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode);
291
292// UInt32 Get_WinAttrib_From_stat(const struct stat &st); 333// UInt32 Get_WinAttrib_From_stat(const struct stat &st);
293#if defined(_AIX)
294 #define MY_ST_TIMESPEC st_timespec
295#else
296 #define MY_ST_TIMESPEC timespec
297#endif
298 334
299void timespec_To_FILETIME(const MY_ST_TIMESPEC &ts, FILETIME &ft);
300 335
301#endif // WIN32 336#endif // WIN32
302 337
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
index 2974b1b..e51b0eb 100644
--- a/CPP/Windows/FileIO.cpp
+++ b/CPP/Windows/FileIO.cpp
@@ -8,6 +8,14 @@
8 8
9// #include <stdio.h> 9// #include <stdio.h>
10 10
11/*
12#ifndef _WIN32
13// for ioctl BLKGETSIZE64
14#include <sys/ioctl.h>
15#include <linux/fs.h>
16#endif
17*/
18
11#include "FileIO.h" 19#include "FileIO.h"
12#include "FileName.h" 20#include "FileName.h"
13 21
@@ -615,7 +623,7 @@ namespace NWindows {
615namespace NFile { 623namespace NFile {
616 624
617namespace NDir { 625namespace NDir {
618bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime); 626bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);
619} 627}
620 628
621namespace NIO { 629namespace NIO {
@@ -629,6 +637,19 @@ bool CFileBase::OpenBinary(const char *name, int flags)
629 Close(); 637 Close();
630 _handle = ::open(name, flags, 0666); 638 _handle = ::open(name, flags, 0666);
631 return _handle != -1; 639 return _handle != -1;
640
641 /*
642 if (_handle == -1)
643 return false;
644 if (IsString1PrefixedByString2(name, "/dev/"))
645 {
646 // /dev/sda
647 // IsDeviceFile = true; // for debug
648 // SizeDefined = false;
649 // SizeDefined = (GetDeviceSize_InBytes(Size) == 0);
650 }
651 return true;
652 */
632} 653}
633 654
634bool CFileBase::Close() 655bool CFileBase::Close()
@@ -638,6 +659,10 @@ bool CFileBase::Close()
638 if (close(_handle) != 0) 659 if (close(_handle) != 0)
639 return false; 660 return false;
640 _handle = -1; 661 _handle = -1;
662 /*
663 IsDeviceFile = false;
664 SizeDefined = false;
665 */
641 return true; 666 return true;
642} 667}
643 668
@@ -651,15 +676,35 @@ bool CFileBase::GetLength(UInt64 &length) const
651 const off_t lengthTemp = seek(0, SEEK_END); 676 const off_t lengthTemp = seek(0, SEEK_END);
652 seek(curPos, SEEK_SET); 677 seek(curPos, SEEK_SET);
653 length = (UInt64)lengthTemp; 678 length = (UInt64)lengthTemp;
679
680 /*
681 // 22.00:
682 if (lengthTemp == 1)
683 if (IsDeviceFile && SizeDefined)
684 {
685 length = Size;
686 return true;
687 }
688 */
689
654 return (lengthTemp != -1); 690 return (lengthTemp != -1);
655} 691}
656 692
657off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const 693off_t CFileBase::seek(off_t distanceToMove, int moveMethod) const
658{ 694{
695 /*
696 if (IsDeviceFile && SizeDefined && moveMethod == SEEK_END)
697 {
698 printf("\n seek : IsDeviceFile moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove);
699 distanceToMove += Size;
700 moveMethod = SEEK_SET;
701 }
702 */
703
659 // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove); 704 // printf("\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld", moveMethod, (long long)distanceToMove);
660 // off_t res = ::lseek(_handle, distanceToMove, moveMethod); 705 // off_t res = ::lseek(_handle, distanceToMove, moveMethod);
706 // printf("\n lseek : moveMethod = %d distanceToMove = %ld\n", moveMethod, distanceToMove);
661 return ::lseek(_handle, distanceToMove, moveMethod); 707 return ::lseek(_handle, distanceToMove, moveMethod);
662 // printf(" res = %lld", (long long)res);
663 // return res; 708 // return res;
664} 709}
665 710
@@ -694,6 +739,28 @@ bool CInFile::OpenShared(const char *name, bool)
694 return Open(name); 739 return Open(name);
695} 740}
696 741
742
743/*
744int CFileBase::my_ioctl_BLKGETSIZE64(unsigned long long *numBlocks)
745{
746 // we can read "/sys/block/sda/size" "/sys/block/sda/sda1/size" - partition
747 // #include <linux/fs.h>
748 return ioctl(_handle, BLKGETSIZE64, numBlocks);
749 // in block size
750}
751
752int CFileBase::GetDeviceSize_InBytes(UInt64 &size)
753{
754 size = 0;
755 unsigned long long numBlocks;
756 int res = my_ioctl_BLKGETSIZE64(&numBlocks);
757 if (res == 0)
758 size = numBlocks; // another blockSize s possible?
759 printf("\nGetDeviceSize_InBytes res = %d, size = %lld\n", res, (long long)size);
760 return res;
761}
762*/
763
697/* 764/*
698On Linux (32-bit and 64-bit): 765On Linux (32-bit and 64-bit):
699read(), write() (and similar system calls) will transfer at most 766read(), write() (and similar system calls) will transfer at most
@@ -802,7 +869,7 @@ bool COutFile::Close()
802 return res; 869 return res;
803} 870}
804 871
805bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() 872bool COutFile::SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw()
806{ 873{
807 // On some OS (cygwin, MacOSX ...), you must close the file before updating times 874 // On some OS (cygwin, MacOSX ...), you must close the file before updating times
808 // return true; 875 // return true;
@@ -811,9 +878,22 @@ bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILET
811 if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false; 878 if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false;
812 if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; 879 if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
813 return true; 880 return true;
881
882 /*
883 struct timespec times[2];
884 UNUSED_VAR(cTime)
885 if (!aTime && !mTime)
886 return true;
887 bool needChange;
888 needChange = FiTime_To_timespec(aTime, times[0]);
889 needChange |= FiTime_To_timespec(mTime, times[1]);
890 if (!needChange)
891 return true;
892 return futimens(_handle, times) == 0;
893 */
814} 894}
815 895
816bool COutFile::SetMTime(const FILETIME *mTime) throw() 896bool COutFile::SetMTime(const CFiTime *mTime) throw()
817{ 897{
818 if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; 898 if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
819 return true; 899 return true;
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
index 22998eb..8050965 100644
--- a/CPP/Windows/FileIO.h
+++ b/CPP/Windows/FileIO.h
@@ -30,6 +30,8 @@
30#include "../Common/MyString.h" 30#include "../Common/MyString.h"
31#include "../Common/MyBuffer.h" 31#include "../Common/MyBuffer.h"
32 32
33#include "../Windows/TimeUtils.h"
34
33#include "Defs.h" 35#include "Defs.h"
34 36
35HRESULT GetLastError_noZero_HRESULT(); 37HRESULT GetLastError_noZero_HRESULT();
@@ -94,6 +96,12 @@ struct CReparseAttr
94 UString GetPath() const; 96 UString GetPath() const;
95}; 97};
96 98
99#ifdef _WIN32
100#define CFiInfo BY_HANDLE_FILE_INFORMATION
101#define ST_MTIME(st) (st).ftLastWriteTime
102#else
103#define CFiInfo stat
104#endif
97 105
98#ifdef _WIN32 106#ifdef _WIN32
99 107
@@ -142,6 +150,8 @@ public:
142 CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {}; 150 CFileBase(): _handle(INVALID_HANDLE_VALUE), PreserveATime(false) {};
143 ~CFileBase() { Close(); } 151 ~CFileBase() { Close(); }
144 152
153 HANDLE GetHandle() const { return _handle; }
154
145 bool Close() throw(); 155 bool Close() throw();
146 156
147 bool GetPosition(UInt64 &position) const throw(); 157 bool GetPosition(UInt64 &position) const throw();
@@ -213,6 +223,15 @@ public:
213 223
214 #ifndef UNDER_CE 224 #ifndef UNDER_CE
215 225
226 bool Open_for_ReadAttributes(CFSTR fileName)
227 {
228 return Create(fileName, FILE_READ_ATTRIBUTES,
229 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
230 OPEN_EXISTING,
231 FILE_FLAG_BACKUP_SEMANTICS);
232 // we must use (FILE_FLAG_BACKUP_SEMANTICS) to open handle of directory.
233 }
234
216 bool OpenReparse(CFSTR fileName) 235 bool OpenReparse(CFSTR fileName)
217 { 236 {
218 // 17.02 fix: to support Windows XP compatibility junctions: 237 // 17.02 fix: to support Windows XP compatibility junctions:
@@ -240,8 +259,8 @@ public:
240 bool Create(CFSTR fileName, bool createAlways); 259 bool Create(CFSTR fileName, bool createAlways);
241 bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes); 260 bool CreateAlways(CFSTR fileName, DWORD flagsAndAttributes);
242 261
243 bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); 262 bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw();
244 bool SetMTime(const FILETIME *mTime) throw(); 263 bool SetMTime(const CFiTime *mTime) throw();
245 bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); 264 bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw();
246 bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw(); 265 bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw();
247 bool WriteFull(const void *data, size_t size) throw(); 266 bool WriteFull(const void *data, size_t size) throw();
@@ -270,6 +289,12 @@ class CFileBase
270protected: 289protected:
271 int _handle; 290 int _handle;
272 291
292 /*
293 bool IsDeviceFile;
294 bool SizeDefined;
295 UInt64 Size; // it can be larger than real available size
296 */
297
273 bool OpenBinary(const char *name, int flags); 298 bool OpenBinary(const char *name, int flags);
274public: 299public:
275 bool PreserveATime; 300 bool PreserveATime;
@@ -283,6 +308,11 @@ public:
283 off_t seekToCur() const throw(); 308 off_t seekToCur() const throw();
284 // bool SeekToBegin() throw(); 309 // bool SeekToBegin() throw();
285 int my_fstat(struct stat *st) const { return fstat(_handle, st); } 310 int my_fstat(struct stat *st) const { return fstat(_handle, st); }
311 /*
312 int my_ioctl_BLKGETSIZE64(unsigned long long *val);
313 int GetDeviceSize_InBytes(UInt64 &size);
314 void CalcDeviceSize(CFSTR s);
315 */
286}; 316};
287 317
288class CInFile: public CFileBase 318class CInFile: public CFileBase
@@ -301,9 +331,9 @@ class COutFile: public CFileBase
301 bool ATime_defined; 331 bool ATime_defined;
302 bool MTime_defined; 332 bool MTime_defined;
303 333
304 FILETIME CTime; 334 CFiTime CTime;
305 FILETIME ATime; 335 CFiTime ATime;
306 FILETIME MTime; 336 CFiTime MTime;
307 337
308 AString Path; 338 AString Path;
309 ssize_t write_part(const void *data, size_t size) throw(); 339 ssize_t write_part(const void *data, size_t size) throw();
@@ -333,8 +363,8 @@ public:
333 { 363 {
334 return SetLength(length); 364 return SetLength(length);
335 } 365 }
336 bool SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw(); 366 bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw();
337 bool SetMTime(const FILETIME *mTime) throw(); 367 bool SetMTime(const CFiTime *mTime) throw();
338}; 368};
339 369
340} 370}
diff --git a/CPP/Windows/PropVariant.cpp b/CPP/Windows/PropVariant.cpp
index 6e43c7b..2b17950 100644
--- a/CPP/Windows/PropVariant.cpp
+++ b/CPP/Windows/PropVariant.cpp
@@ -193,7 +193,7 @@ BSTR CPropVariant::AllocBstr(unsigned numChars)
193} 193}
194 194
195#define SET_PROP_id_dest(id, dest) \ 195#define SET_PROP_id_dest(id, dest) \
196 if (vt != id) { InternalClear(); vt = id; } dest = value; 196 if (vt != id) { InternalClear(); vt = id; } dest = value; wReserved1 = 0;
197 197
198void CPropVariant::Set_Int32(Int32 value) throw() 198void CPropVariant::Set_Int32(Int32 value) throw()
199{ 199{
@@ -217,67 +217,83 @@ SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)
217// SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart) 217// SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)
218SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) 218SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)
219 219
220#define CASE_SIMPLE_VT_VALUES \
221 case VT_EMPTY: \
222 case VT_BOOL: \
223 case VT_FILETIME: \
224 case VT_UI8: \
225 case VT_UI4: \
226 case VT_UI2: \
227 case VT_UI1: \
228 case VT_I8: \
229 case VT_I4: \
230 case VT_I2: \
231 case VT_I1: \
232 case VT_UINT: \
233 case VT_INT: \
234 case VT_NULL: \
235 case VT_ERROR: \
236 case VT_R4: \
237 case VT_R8: \
238 case VT_CY: \
239 case VT_DATE: \
240
241
242/*
243 ::VariantClear() and ::VariantCopy() don't work, if (vt == VT_FILETIME)
244 So we handle VT_FILETIME and another simple types directly
245 we call system functions for VT_BSTR and for unknown typed
246*/
247
248CPropVariant::~CPropVariant()
249{
250 switch ((unsigned)vt)
251 {
252 CASE_SIMPLE_VT_VALUES
253 // vt = VT_EMPTY; // it's optional
254 return;
255 }
256 ::VariantClear((tagVARIANT *)this);
257}
258
220HRESULT PropVariant_Clear(PROPVARIANT *prop) throw() 259HRESULT PropVariant_Clear(PROPVARIANT *prop) throw()
221{ 260{
222 switch (prop->vt) 261 switch ((unsigned)prop->vt)
223 { 262 {
224 case VT_EMPTY: 263 CASE_SIMPLE_VT_VALUES
225 case VT_UI1:
226 case VT_I1:
227 case VT_I2:
228 case VT_UI2:
229 case VT_BOOL:
230 case VT_I4:
231 case VT_UI4:
232 case VT_R4:
233 case VT_INT:
234 case VT_UINT:
235 case VT_ERROR:
236 case VT_FILETIME:
237 case VT_UI8:
238 case VT_R8:
239 case VT_CY:
240 case VT_DATE:
241 prop->vt = VT_EMPTY; 264 prop->vt = VT_EMPTY;
242 prop->wReserved1 = 0; 265 break;
243 prop->wReserved2 = 0; 266 default:
244 prop->wReserved3 = 0; 267 {
245 prop->uhVal.QuadPart = 0; 268 const HRESULT res = ::VariantClear((VARIANTARG *)prop);
246 return S_OK; 269 if (res != S_OK || prop->vt != VT_EMPTY)
270 return res;
271 break;
272 }
247 } 273 }
248 return ::VariantClear((VARIANTARG *)prop); 274 prop->wReserved1 = 0;
249 // return ::PropVariantClear(prop); 275 prop->wReserved2 = 0;
250 // PropVariantClear can clear VT_BLOB. 276 prop->wReserved3 = 0;
277 prop->uhVal.QuadPart = 0;
278 return S_OK;
251} 279}
252 280
253HRESULT CPropVariant::Clear() throw() 281HRESULT CPropVariant::Clear() throw()
254{ 282{
255 if (vt == VT_EMPTY) 283 if (vt == VT_EMPTY)
284 {
285 wReserved1 = 0;
256 return S_OK; 286 return S_OK;
287 }
257 return PropVariant_Clear(this); 288 return PropVariant_Clear(this);
258} 289}
259 290
260HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw() 291HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()
261{ 292{
262 ::VariantClear((tagVARIANT *)this); 293 Clear();
263 switch (pSrc->vt) 294 switch ((unsigned)pSrc->vt)
264 { 295 {
265 case VT_UI1: 296 CASE_SIMPLE_VT_VALUES
266 case VT_I1:
267 case VT_I2:
268 case VT_UI2:
269 case VT_BOOL:
270 case VT_I4:
271 case VT_UI4:
272 case VT_R4:
273 case VT_INT:
274 case VT_UINT:
275 case VT_ERROR:
276 case VT_FILETIME:
277 case VT_UI8:
278 case VT_R8:
279 case VT_CY:
280 case VT_DATE:
281 memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); 297 memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));
282 return S_OK; 298 return S_OK;
283 } 299 }
@@ -287,12 +303,13 @@ HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()
287 303
288HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw() 304HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()
289{ 305{
290 HRESULT hr = Clear(); 306 const HRESULT hr = Clear();
291 if (FAILED(hr)) 307 if (FAILED(hr))
292 return hr; 308 return hr;
293 // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT)); 309 // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT));
294 *(PROPVARIANT *)this = *pSrc; 310 *(PROPVARIANT *)this = *pSrc;
295 pSrc->vt = VT_EMPTY; 311 pSrc->vt = VT_EMPTY;
312 pSrc->wReserved1 = 0;
296 return S_OK; 313 return S_OK;
297} 314}
298 315
@@ -300,21 +317,25 @@ HRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()
300{ 317{
301 if (pDest->vt != VT_EMPTY) 318 if (pDest->vt != VT_EMPTY)
302 { 319 {
303 HRESULT hr = PropVariant_Clear(pDest); 320 const HRESULT hr = PropVariant_Clear(pDest);
304 if (FAILED(hr)) 321 if (FAILED(hr))
305 return hr; 322 return hr;
306 } 323 }
307 // memcpy(pDest, this, sizeof(PROPVARIANT)); 324 // memcpy(pDest, this, sizeof(PROPVARIANT));
308 *pDest = *(PROPVARIANT *)this; 325 *pDest = *(PROPVARIANT *)this;
309 vt = VT_EMPTY; 326 vt = VT_EMPTY;
327 wReserved1 = 0;
310 return S_OK; 328 return S_OK;
311} 329}
312 330
313HRESULT CPropVariant::InternalClear() throw() 331HRESULT CPropVariant::InternalClear() throw()
314{ 332{
315 if (vt == VT_EMPTY) 333 if (vt == VT_EMPTY)
334 {
335 wReserved1 = 0;
316 return S_OK; 336 return S_OK;
317 HRESULT hr = Clear(); 337 }
338 const HRESULT hr = Clear();
318 if (FAILED(hr)) 339 if (FAILED(hr))
319 { 340 {
320 vt = VT_ERROR; 341 vt = VT_ERROR;
@@ -325,7 +346,7 @@ HRESULT CPropVariant::InternalClear() throw()
325 346
326void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) 347void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
327{ 348{
328 HRESULT hr = Copy(pSrc); 349 const HRESULT hr = Copy(pSrc);
329 if (FAILED(hr)) 350 if (FAILED(hr))
330 { 351 {
331 if (hr == E_OUTOFMEMORY) 352 if (hr == E_OUTOFMEMORY)
@@ -335,11 +356,12 @@ void CPropVariant::InternalCopy(const PROPVARIANT *pSrc)
335 } 356 }
336} 357}
337 358
359
338int CPropVariant::Compare(const CPropVariant &a) throw() 360int CPropVariant::Compare(const CPropVariant &a) throw()
339{ 361{
340 if (vt != a.vt) 362 if (vt != a.vt)
341 return MyCompare(vt, a.vt); 363 return MyCompare(vt, a.vt);
342 switch (vt) 364 switch ((unsigned)vt)
343 { 365 {
344 case VT_EMPTY: return 0; 366 case VT_EMPTY: return 0;
345 // case VT_I1: return MyCompare(cVal, a.cVal); 367 // case VT_I1: return MyCompare(cVal, a.cVal);
@@ -352,7 +374,15 @@ int CPropVariant::Compare(const CPropVariant &a) throw()
352 case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); 374 case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);
353 case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); 375 case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);
354 case VT_BOOL: return -MyCompare(boolVal, a.boolVal); 376 case VT_BOOL: return -MyCompare(boolVal, a.boolVal);
355 case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); 377 case VT_FILETIME:
378 {
379 const int res = CompareFileTime(&filetime, &a.filetime);
380 if (res != 0)
381 return res;
382 const unsigned v1 = Get_Ns100();
383 const unsigned v2 = a.Get_Ns100();
384 return MyCompare(v1, v2);
385 }
356 case VT_BSTR: return 0; // Not implemented 386 case VT_BSTR: return 0; // Not implemented
357 default: return 0; 387 default: return 0;
358 } 388 }
diff --git a/CPP/Windows/PropVariant.h b/CPP/Windows/PropVariant.h
index 108bf6b..171402f 100644
--- a/CPP/Windows/PropVariant.h
+++ b/CPP/Windows/PropVariant.h
@@ -29,11 +29,14 @@ inline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw()
29 p->uhVal.QuadPart = v; 29 p->uhVal.QuadPart = v;
30} 30}
31 31
32inline void PropVarEm_Set_FileTime64(PROPVARIANT *p, UInt64 v) throw() 32inline void PropVarEm_Set_FileTime64_Prec(PROPVARIANT *p, UInt64 v, unsigned prec) throw()
33{ 33{
34 p->vt = VT_FILETIME; 34 p->vt = VT_FILETIME;
35 p->filetime.dwLowDateTime = (DWORD)v; 35 p->filetime.dwLowDateTime = (DWORD)v;
36 p->filetime.dwHighDateTime = (DWORD)(v >> 32); 36 p->filetime.dwHighDateTime = (DWORD)(v >> 32);
37 p->wReserved1 = (WORD)prec;
38 p->wReserved2 = 0;
39 p->wReserved3 = 0;
37} 40}
38 41
39inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw() 42inline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw()
@@ -63,7 +66,51 @@ public:
63 // uhVal.QuadPart = 0; 66 // uhVal.QuadPart = 0;
64 bstrVal = 0; 67 bstrVal = 0;
65 } 68 }
66 ~CPropVariant() throw() { Clear(); } 69
70
71 void Set_FtPrec(unsigned prec)
72 {
73 wReserved1 = (WORD)prec;
74 wReserved2 = 0;
75 wReserved3 = 0;
76 }
77
78 void SetAsTimeFrom_FT_Prec(const FILETIME &ft, unsigned prec)
79 {
80 operator=(ft);
81 Set_FtPrec(prec);
82 }
83
84 void SetAsTimeFrom_Ft64_Prec(UInt64 v, unsigned prec)
85 {
86 FILETIME ft;
87 ft.dwLowDateTime = (DWORD)(UInt32)v;
88 ft.dwHighDateTime = (DWORD)(UInt32)(v >> 32);
89 operator=(ft);
90 Set_FtPrec(prec);
91 }
92
93 void SetAsTimeFrom_FT_Prec_Ns100(const FILETIME &ft, unsigned prec, unsigned ns100)
94 {
95 operator=(ft);
96 wReserved1 = (WORD)prec;
97 wReserved2 = (WORD)ns100;
98 wReserved3 = 0;
99 }
100
101 unsigned Get_Ns100() const
102 {
103 const unsigned prec = wReserved1;
104 const unsigned ns100 = wReserved2;
105 if (prec == 0
106 && prec <= k_PropVar_TimePrec_1ns
107 && ns100 < 100
108 && wReserved3 == 0)
109 return ns100;
110 return 0;
111 }
112
113 ~CPropVariant();
67 CPropVariant(const PROPVARIANT &varSrc); 114 CPropVariant(const PROPVARIANT &varSrc);
68 CPropVariant(const CPropVariant &varSrc); 115 CPropVariant(const CPropVariant &varSrc);
69 CPropVariant(BSTR bstrSrc); 116 CPropVariant(BSTR bstrSrc);
@@ -118,7 +165,6 @@ public:
118 165
119 HRESULT InternalClear() throw(); 166 HRESULT InternalClear() throw();
120 void InternalCopy(const PROPVARIANT *pSrc); 167 void InternalCopy(const PROPVARIANT *pSrc);
121
122 int Compare(const CPropVariant &a) throw(); 168 int Compare(const CPropVariant &a) throw();
123}; 169};
124 170
diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp
index b58d37e..3c9bbd1 100644
--- a/CPP/Windows/PropVariantConv.cpp
+++ b/CPP/Windows/PropVariantConv.cpp
@@ -9,7 +9,7 @@
9 9
10#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } 10#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; }
11 11
12bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw() 12bool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level) throw()
13{ 13{
14 *s = 0; 14 *s = 0;
15 FILETIME ft; 15 FILETIME ft;
@@ -18,7 +18,10 @@ bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
18 18
19 SYSTEMTIME st; 19 SYSTEMTIME st;
20 if (!BOOLToBool(FileTimeToSystemTime(&ft, &st))) 20 if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))
21 {
22 // win10 : that function doesn't work, if bit 63 of 64-bit FILETIME is set.
21 return false; 23 return false;
24 }
22 25
23 { 26 {
24 unsigned val = st.wYear; 27 unsigned val = st.wYear;
@@ -71,6 +74,12 @@ bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
71 numDigits = (unsigned)level; 74 numDigits = (unsigned)level;
72 s += numDigits; 75 s += numDigits;
73 } 76 }
77 if (level >= kTimestampPrintLevel_NTFS + 1)
78 {
79 *s++ = (char)('0' + (ns100 / 10));
80 if (level >= kTimestampPrintLevel_NTFS + 2)
81 *s++ = (char)('0' + (ns100 % 10));
82 }
74 } 83 }
75 } 84 }
76 } 85 }
@@ -80,6 +89,25 @@ bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
80} 89}
81 90
82 91
92bool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()
93{
94 return ConvertUtcFileTimeToString2(utc, 0, s, level);
95}
96
97bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw()
98{
99 char s[32];
100 bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level);
101 for (unsigned i = 0;; i++)
102 {
103 Byte c = (Byte)s[i];
104 dest[i] = c;
105 if (c == 0)
106 break;
107 }
108 return res;
109}
110
83bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw() 111bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw()
84{ 112{
85 char s[32]; 113 char s[32];
@@ -106,7 +134,19 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw(
106 case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; 134 case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
107 case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; 135 case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
108 case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; 136 case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
109 case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; 137 case VT_FILETIME:
138 {
139 // const unsigned prec = prop.wReserved1;
140 int level = 0;
141 /*
142 if (prec == 0)
143 level = 7;
144 else if (prec > 16 && prec <= 16 + 9)
145 level = prec - 16;
146 */
147 ConvertUtcFileTimeToString(prop.filetime, dest, level);
148 return;
149 }
110 // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; 150 // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
111 case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; 151 case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
112 case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; 152 case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
@@ -127,7 +167,19 @@ void ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) thr
127 case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return; 167 case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;
128 case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return; 168 case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;
129 case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return; 169 case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;
130 case VT_FILETIME: ConvertUtcFileTimeToString(prop.filetime, dest); return; 170 case VT_FILETIME:
171 {
172 // const unsigned prec = prop.wReserved1;
173 int level = 0;
174 /*
175 if (prec == 0)
176 level = 7;
177 else if (prec > 16 && prec <= 16 + 9)
178 level = prec - 16;
179 */
180 ConvertUtcFileTimeToString(prop.filetime, dest, level);
181 return;
182 }
131 // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return; 183 // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;
132 case VT_I2: ConvertInt64ToString(prop.iVal, dest); return; 184 case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;
133 case VT_I4: ConvertInt64ToString(prop.lVal, dest); return; 185 case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;
diff --git a/CPP/Windows/PropVariantConv.h b/CPP/Windows/PropVariantConv.h
index 390e0b8..6067784 100644
--- a/CPP/Windows/PropVariantConv.h
+++ b/CPP/Windows/PropVariantConv.h
@@ -10,11 +10,14 @@
10#define kTimestampPrintLevel_DAY -3 10#define kTimestampPrintLevel_DAY -3
11// #define kTimestampPrintLevel_HOUR -2 11// #define kTimestampPrintLevel_HOUR -2
12#define kTimestampPrintLevel_MIN -1 12#define kTimestampPrintLevel_MIN -1
13#define kTimestampPrintLevel_SEC 0 13#define kTimestampPrintLevel_SEC 0
14#define kTimestampPrintLevel_NTFS 7 14#define kTimestampPrintLevel_NTFS 7
15#define kTimestampPrintLevel_NS 9
15 16
16bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw(); 17bool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw();
17bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw(); 18bool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw();
19bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, char *s, int level = kTimestampPrintLevel_SEC) throw();
20bool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw();
18 21
19// provide at least 32 bytes for buffer including zero-end 22// provide at least 32 bytes for buffer including zero-end
20// don't send VT_BSTR to these functions 23// don't send VT_BSTR to these functions
diff --git a/CPP/Windows/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp
index 640c90d..8a7f45c 100644
--- a/CPP/Windows/SecurityUtils.cpp
+++ b/CPP/Windows/SecurityUtils.cpp
@@ -2,8 +2,6 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../Common/MyString.h"
6
7#include "SecurityUtils.h" 5#include "SecurityUtils.h"
8 6
9namespace NWindows { 7namespace NWindows {
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp
index 1f1335f..77d2c51 100644
--- a/CPP/Windows/TimeUtils.cpp
+++ b/CPP/Windows/TimeUtils.cpp
@@ -22,7 +22,7 @@ static const UInt64 kUnixTimeOffset =
22 (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); 22 (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));
23static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; 23static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond;
24 24
25bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() 25bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw()
26{ 26{
27 #if defined(_WIN32) && !defined(UNDER_CE) 27 #if defined(_WIN32) && !defined(UNDER_CE)
28 return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); 28 return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft));
@@ -43,7 +43,7 @@ bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw()
43static const UInt32 kHighDosTime = 0xFF9FBF7D; 43static const UInt32 kHighDosTime = 0xFF9FBF7D;
44static const UInt32 kLowDosTime = 0x210000; 44static const UInt32 kLowDosTime = 0x210000;
45 45
46bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() 46bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw()
47{ 47{
48 #if defined(_WIN32) && !defined(UNDER_CE) 48 #if defined(_WIN32) && !defined(UNDER_CE)
49 49
@@ -121,49 +121,86 @@ bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw()
121 return true; 121 return true;
122} 122}
123 123
124UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw() 124
125bool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw()
126{
127 FILETIME loc = { 0, 0 };
128 const UInt64 u1 = FILETIME_To_UInt64(utc);
129 const UInt64 kDelta = ((UInt64)1 << 41); // it's larger than quantums in 1 sec.
130 if (u1 >= kDelta)
131 {
132 if (!FileTimeToLocalFileTime(&utc, &loc))
133 loc = utc;
134 else
135 {
136 const UInt64 u2 = FILETIME_To_UInt64(loc);
137 const UInt64 delta = u1 < u2 ? (u2 - u1) : (u1 - u2);
138 if (delta > kDelta) // if FileTimeToLocalFileTime() overflow, we use UTC time
139 loc = utc;
140 }
141 }
142 return FileTime_To_DosTime(loc, dosTime);
143}
144
145UInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw()
125{ 146{
126 return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; 147 return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond;
127} 148}
128 149
129void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() 150void UnixTime_To_FileTime(UInt32 unixTime, FILETIME &ft) throw()
130{ 151{
131 UInt64 v = UnixTimeToFileTime64(unixTime); 152 const UInt64 v = UnixTime_To_FileTime64(unixTime);
132 ft.dwLowDateTime = (DWORD)v; 153 ft.dwLowDateTime = (DWORD)v;
133 ft.dwHighDateTime = (DWORD)(v >> 32); 154 ft.dwHighDateTime = (DWORD)(v >> 32);
134} 155}
135 156
136UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw() 157UInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw()
137{ 158{
138 return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; 159 return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond;
139} 160}
140 161
141bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() 162
163bool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw()
142{ 164{
143 if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) 165 if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset))
144 { 166 {
145 ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; 167 fileTime = (UInt64)(Int64)-1;
146 return false; 168 return false;
147 } 169 }
148 Int64 v = (Int64)kUnixTimeOffset + unixTime; 170 if (unixTime < -(Int64)kUnixTimeOffset)
149 if (v < 0)
150 { 171 {
151 ft.dwLowDateTime = ft.dwHighDateTime = 0; 172 fileTime = 0;
152 return false; 173 return false;
153 } 174 }
154 UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; 175 fileTime = UnixTime64_To_FileTime64(unixTime);
155 ft.dwLowDateTime = (DWORD)v2;
156 ft.dwHighDateTime = (DWORD)(v2 >> 32);
157 return true; 176 return true;
158} 177}
159 178
160Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() 179
180bool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &ft) throw()
161{ 181{
162 UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; 182 UInt64 v;
183 const bool res = UnixTime64_To_FileTime64(unixTime, v);
184 ft.dwLowDateTime = (DWORD)v;
185 ft.dwHighDateTime = (DWORD)(v >> 32);
186 return res;
187}
188
189
190Int64 FileTime_To_UnixTime64(const FILETIME &ft) throw()
191{
192 const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
193 return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
194}
195
196Int64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw()
197{
198 const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
199 quantums = (UInt32)(winTime % kNumTimeQuantumsInSecond);
163 return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; 200 return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
164} 201}
165 202
166bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() 203bool FileTime_To_UnixTime(const FILETIME &ft, UInt32 &unixTime) throw()
167{ 204{
168 UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; 205 UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
169 winTime /= kNumTimeQuantumsInSecond; 206 winTime /= kNumTimeQuantumsInSecond;
@@ -173,9 +210,9 @@ bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw()
173 return false; 210 return false;
174 } 211 }
175 winTime -= kUnixTimeOffset; 212 winTime -= kUnixTimeOffset;
176 if (winTime > 0xFFFFFFFF) 213 if (winTime > (UInt32)0xFFFFFFFF)
177 { 214 {
178 unixTime = 0xFFFFFFFF; 215 unixTime = (UInt32)0xFFFFFFFF;
179 return false; 216 return false;
180 } 217 }
181 unixTime = (UInt32)winTime; 218 unixTime = (UInt32)winTime;
@@ -202,12 +239,13 @@ bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
202 return true; 239 return true;
203} 240}
204 241
205void GetCurUtcFileTime(FILETIME &ft) throw() 242
243void GetCurUtc_FiTime(CFiTime &ft) throw()
206{ 244{
245 #ifdef _WIN32
246
207 // Both variants provide same low resolution on WinXP: about 15 ms. 247 // Both variants provide same low resolution on WinXP: about 15 ms.
208 // But GetSystemTimeAsFileTime is much faster. 248 // But GetSystemTimeAsFileTime is much faster.
209 #ifdef _WIN32
210
211 #ifdef UNDER_CE 249 #ifdef UNDER_CE
212 SYSTEMTIME st; 250 SYSTEMTIME st;
213 GetSystemTime(&st); 251 GetSystemTime(&st);
@@ -216,8 +254,22 @@ void GetCurUtcFileTime(FILETIME &ft) throw()
216 GetSystemTimeAsFileTime(&ft); 254 GetSystemTimeAsFileTime(&ft);
217 #endif 255 #endif
218 256
219 #else 257 #else
220 258
259 FiTime_Clear(ft);
260 struct timeval now;
261 if (gettimeofday(&now, 0 ) == 0)
262 {
263 ft.tv_sec = now.tv_sec;
264 ft.tv_nsec = now.tv_usec * 1000;
265 }
266
267 #endif
268}
269
270#ifndef _WIN32
271void GetCurUtcFileTime(FILETIME &ft) throw()
272{
221 UInt64 v = 0; 273 UInt64 v = 0;
222 struct timeval now; 274 struct timeval now;
223 if (gettimeofday(&now, 0 ) == 0) 275 if (gettimeofday(&now, 0 ) == 0)
@@ -227,8 +279,126 @@ void GetCurUtcFileTime(FILETIME &ft) throw()
227 } 279 }
228 ft.dwLowDateTime = (DWORD)v; 280 ft.dwLowDateTime = (DWORD)v;
229 ft.dwHighDateTime = (DWORD)(v >> 32); 281 ft.dwHighDateTime = (DWORD)(v >> 32);
230
231 #endif
232} 282}
283#endif
284
233 285
234}} 286}}
287
288
289#ifdef _WIN32
290
291/*
292void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec)
293{
294 if (prec == k_PropVar_TimePrec_0
295 || prec == k_PropVar_TimePrec_HighPrec
296 || prec >= k_PropVar_TimePrec_100ns)
297 return;
298 UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
299
300 int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;
301 UInt32 d;
302 if (prec == k_PropVar_TimePrec_DOS)
303 {
304 // we round up as windows DosDateTimeToFileTime()
305 v += NWindows::NTime::kNumTimeQuantumsInSecond * 2 - 1;
306 d = NWindows::NTime::kNumTimeQuantumsInSecond * 2;
307 }
308 else
309 {
310 if (prec == k_PropVar_TimePrec_Unix)
311 numDigits = 0;
312 else if (numDigits < 0)
313 return;
314 d = 1;
315 for (unsigned k = numDigits; k < 7; k++)
316 d *= 10;
317 }
318 v /= d;
319 v *= d;
320 ft.dwLowDateTime = (DWORD)v;
321 ft.dwHighDateTime = (DWORD)(v >> 32);
322}
323*/
324
325#else
326
327/*
328void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec)
329{
330 if (prec >= k_PropVar_TimePrec_1ns
331 || prec == k_PropVar_TimePrec_HighPrec)
332 return;
333
334 int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;
335 UInt32 d;
336 if (prec == k_PropVar_TimePrec_Unix ||
337 prec == (int)k_PropVar_TimePrec_Base)
338 {
339 ft.tv_nsec = 0;
340 return;
341 }
342 if (prec == k_PropVar_TimePrec_DOS)
343 {
344 // we round up as windows DosDateTimeToFileTime()
345 const unsigned sec1 = (ft.tv_sec & 1);
346 if (ft.tv_nsec == 0 && sec1 == 0)
347 return;
348 ft.tv_nsec = 0;
349 ft.tv_sec += 2 - sec1;
350 return;
351 }
352 {
353 if (prec == k_PropVar_TimePrec_0
354 || numDigits < 0)
355 numDigits = 7;
356 d = 1;
357 for (unsigned k = numDigits; k < 9; k++)
358 d *= 10;
359 ft.tv_nsec /= d;
360 ft.tv_nsec *= d;
361 }
362}
363*/
364
365int Compare_FiTime(const CFiTime *a1, const CFiTime *a2)
366{
367 if (a1->tv_sec < a2->tv_sec) return -1;
368 if (a1->tv_sec > a2->tv_sec) return 1;
369 if (a1->tv_nsec < a2->tv_nsec) return -1;
370 if (a1->tv_nsec > a2->tv_nsec) return 1;
371 return 0;
372}
373
374bool FILETIME_To_timespec(const FILETIME &ft, timespec &ts)
375{
376 UInt32 quantums;
377 const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums);
378 // time_t is long
379 const time_t sec2 = (time_t)sec;
380 if (sec2 == sec)
381 {
382 ts.tv_sec = sec2;
383 ts.tv_nsec = (long)(quantums * 100);
384 return true;
385 }
386 return false;
387}
388
389void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100)
390{
391 const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);
392 ns100 = (unsigned)((UInt64)ts.tv_nsec % 100);
393 ft.dwLowDateTime = (DWORD)v;
394 ft.dwHighDateTime = (DWORD)(v >> 32);
395}
396
397void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft)
398{
399 const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);
400 ft.dwLowDateTime = (DWORD)v;
401 ft.dwHighDateTime = (DWORD)(v >> 32);
402}
403
404#endif
diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h
index d1d8c15..60ee739 100644
--- a/CPP/Windows/TimeUtils.h
+++ b/CPP/Windows/TimeUtils.h
@@ -5,28 +5,142 @@
5 5
6#include "../Common/MyTypes.h" 6#include "../Common/MyTypes.h"
7#include "../Common/MyWindows.h" 7#include "../Common/MyWindows.h"
8#include "PropVariant.h"
9
10inline UInt64 FILETIME_To_UInt64(const FILETIME &ft)
11{
12 return (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
13}
14
15inline void FILETIME_Clear(FILETIME &ft)
16{
17 ft.dwLowDateTime = 0;
18 ft.dwHighDateTime = 0;
19}
20
21inline bool FILETIME_IsZero(const FILETIME &ft)
22{
23 return (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0);
24}
25
26
27#ifdef _WIN32
28 #define CFiTime FILETIME
29 #define Compare_FiTime ::CompareFileTime
30 inline void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft)
31 {
32 ft = ts;
33 }
34 /*
35 inline void FILETIME_To_FiTime(const FILETIME &ft, CFiTime &ts)
36 {
37 ts = ft;
38 }
39 */
40 inline void FiTime_Clear(CFiTime &ft)
41 {
42 ft.dwLowDateTime = 0;
43 ft.dwHighDateTime = 0;
44 }
45#else
46
47 #include <sys/stat.h>
48
49 #if defined(_AIX)
50 #define CFiTime st_timespec
51 #else
52 #define CFiTime timespec
53 #endif
54 int Compare_FiTime(const CFiTime *a1, const CFiTime *a2);
55 bool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts);
56 void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft);
57 void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100);
58 inline void FiTime_Clear(CFiTime &ft)
59 {
60 ft.tv_sec = 0;
61 ft.tv_nsec = 0;
62 }
63
64 #ifdef __APPLE__
65 #define ST_MTIME(st) st.st_mtimespec
66 #define ST_ATIME(st) st.st_atimespec
67 #define ST_CTIME(st) st.st_ctimespec
68 #else
69 #define ST_MTIME(st) st.st_mtim
70 #define ST_ATIME(st) st.st_atim
71 #define ST_CTIME(st) st.st_ctim
72 #endif
73
74#endif
75
76// void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec);
8 77
9namespace NWindows { 78namespace NWindows {
10namespace NTime { 79namespace NTime {
11 80
12bool DosTimeToFileTime(UInt32 dosTime, FILETIME &fileTime) throw(); 81bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &fileTime) throw();
13bool FileTimeToDosTime(const FILETIME &fileTime, UInt32 &dosTime) throw(); 82bool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw();
83bool FileTime_To_DosTime(const FILETIME &fileTime, UInt32 &dosTime) throw();
14 84
15// UInt32 Unix Time : for dates 1970-2106 85// UInt32 Unix Time : for dates 1970-2106
16UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw(); 86UInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw();
17void UnixTimeToFileTime(UInt32 unixTime, FILETIME &fileTime) throw(); 87void UnixTime_To_FileTime(UInt32 unixTime, FILETIME &fileTime) throw();
18 88
19// Int64 Unix Time : negative values for dates before 1970 89// Int64 Unix Time : negative values for dates before 1970
20UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw(); 90UInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw(); // no check
21bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &fileTime) throw(); 91bool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw();
92bool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &fileTime) throw();
22 93
23bool FileTimeToUnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw(); 94Int64 FileTime64_To_UnixTime64(UInt64 ft64) throw();
24Int64 FileTimeToUnixTime64(const FILETIME &ft) throw(); 95bool FileTime_To_UnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw();
96Int64 FileTime_To_UnixTime64(const FILETIME &ft) throw();
97Int64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw();
25 98
26bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, 99bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,
27 unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw(); 100 unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw();
101
102void GetCurUtc_FiTime(CFiTime &ft) throw();
103#ifdef _WIN32
104#define GetCurUtcFileTime GetCurUtc_FiTime
105#else
28void GetCurUtcFileTime(FILETIME &ft) throw(); 106void GetCurUtcFileTime(FILETIME &ft) throw();
107#endif
29 108
30}} 109}}
31 110
111inline void PropVariant_SetFrom_UnixTime(NWindows::NCOM::CPropVariant &prop, UInt32 unixTime)
112{
113 FILETIME ft;
114 NWindows::NTime::UnixTime_To_FileTime(unixTime, ft);
115 prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Unix);
116}
117
118inline void PropVariant_SetFrom_NtfsTime(NWindows::NCOM::CPropVariant &prop, const FILETIME &ft)
119{
120 prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_100ns);
121}
122
123inline void PropVariant_SetFrom_FiTime(NWindows::NCOM::CPropVariant &prop, const CFiTime &fts)
124{
125 #ifdef _WIN32
126 PropVariant_SetFrom_NtfsTime(prop, fts);
127 #else
128 unsigned ns100;
129 FILETIME ft;
130 FiTime_To_FILETIME_ns100(fts, ft, ns100);
131 prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100);
132 #endif
133}
134
135inline bool PropVariant_SetFrom_DosTime(NWindows::NCOM::CPropVariant &prop, UInt32 dosTime)
136{
137 FILETIME localFileTime, utc;
138 if (!NWindows::NTime::DosTime_To_FileTime(dosTime, localFileTime))
139 return false;
140 if (!LocalFileTimeToFileTime(&localFileTime, &utc))
141 return false;
142 prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_DOS);
143 return true;
144}
145
32#endif 146#endif