aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/Windows')
-rw-r--r--CPP/Windows/FileDir.cpp102
-rw-r--r--CPP/Windows/FileDir.h1
-rw-r--r--CPP/Windows/FileIO.cpp248
-rw-r--r--CPP/Windows/FileIO.h45
4 files changed, 349 insertions, 47 deletions
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp
index ad0d8c9..bf77c15 100644
--- a/CPP/Windows/FileDir.cpp
+++ b/CPP/Windows/FileDir.cpp
@@ -34,7 +34,9 @@ using namespace NName;
34 34
35#ifndef _WIN32 35#ifndef _WIN32
36 36
37static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts) 37extern
38bool FiTime_To_timespec(const CFiTime *ft, timespec &ts);
39bool FiTime_To_timespec(const CFiTime *ft, timespec &ts)
38{ 40{
39 if (ft) 41 if (ft)
40 { 42 {
@@ -51,7 +53,7 @@ static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts)
51 ts.tv_sec = 0; 53 ts.tv_sec = 0;
52 ts.tv_nsec = 54 ts.tv_nsec =
53 #ifdef UTIME_OMIT 55 #ifdef UTIME_OMIT
54 UTIME_OMIT; // -2 keep old timesptamp 56 UTIME_OMIT; // -2 keep old timestamp
55 #else 57 #else
56 // UTIME_NOW; -1 // set to the current time 58 // UTIME_NOW; -1 // set to the current time
57 0; 59 0;
@@ -170,6 +172,10 @@ bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, con
170 172
171bool SetFileAttrib(CFSTR path, DWORD attrib) 173bool SetFileAttrib(CFSTR path, DWORD attrib)
172{ 174{
175 /* win10:
176 if (attrib == 0), it sets (FILE_ATTRIBUTE_NORMAL) attribute
177 (FILE_ATTRIBUTE_DIRECTORY and some another attributes are ignored for files).
178 */
173 #ifndef _UNICODE 179 #ifndef _UNICODE
174 if (!g_IsNT) 180 if (!g_IsNT)
175 { 181 {
@@ -1078,7 +1084,7 @@ static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progres
1078 } 1084 }
1079 // There is file IO error or process was interrupted by user. 1085 // There is file IO error or process was interrupted by user.
1080 // We close output file and delete it. 1086 // We close output file and delete it.
1081 // DeleteFileAlways doesn't change errno (if successed), but we restore errno. 1087 // DeleteFileAlways doesn't change errno (if succeed), but we restore errno.
1082 const int errno_save = errno; 1088 const int errno_save = errno;
1083 DeleteFileAlways(newFile); 1089 DeleteFileAlways(newFile);
1084 errno = errno_save; 1090 errno = errno_save;
@@ -1240,26 +1246,34 @@ bool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, con
1240} 1246}
1241 1247
1242 1248
1243struct C_umask 1249C_umask::C_umask()
1244{ 1250{
1245 mode_t mask; 1251/*
1246 1252 For security purposes, we restrict the file (mode) attributes
1247 C_umask() 1253 using the process's file mode creation mask (umask).
1248 { 1254 System's umask is used by open(), mkdir(), and other system calls
1249 /* by security reasons we restrict attributes according 1255 that create files to modify the permissions placed on newly
1250 with process's file mode creation mask (umask) */ 1256 created files or directories.
1251 const mode_t um = umask(0); // octal :0022 is expected 1257 We use (g_umask.mask) for any function that changes the file's access
1252 mask = 0777 & (~um); // octal: 0755 is expected 1258 mode but is not affected by the system's umask.
1253 umask(um); // restore the umask 1259 We use additional mask restiction 0777 for security purposes.
1254 // printf("\n umask = 0%03o mask = 0%03o\n", um, mask); 1260 So we don't create the following mode bits for files and directories:
1255 1261 S_ISUID 04000 set-user-ID bit
1256 // mask = 0777; // debug we can disable the restriction: 1262 S_ISGID 02000 set-group-ID bit
1257 } 1263 S_ISVTX 01000 sticky bit
1258}; 1264 system's open(), mkdir() also can have similar 0777 restiction for some cases.
1265*/
1266 const mode_t um = umask(0); // um = 0022 (octal) is expected
1267 mask = ~um
1268 & 0777; // 0777 is our additional mode restruction : is secure
1269 // & 07777; // for debug : 07777 to support all mode bits : is not secure
1270 // mask = 07777; // for debug : to restore all mode bits
1271 umask(um); // restore original umask that was changed by umask(0) in code above
1272}
1259 1273
1260static C_umask g_umask; 1274C_umask g_umask;
1261 1275
1262// #define PRF(x) x; 1276// #define PRF(x) x
1263#define PRF(x) 1277#define PRF(x)
1264 1278
1265#define TRACE_SetFileAttrib(msg) \ 1279#define TRACE_SetFileAttrib(msg) \
@@ -1273,12 +1287,17 @@ int my_chown(CFSTR path, uid_t owner, gid_t group)
1273 return chown(path, owner, group); 1287 return chown(path, owner, group);
1274} 1288}
1275 1289
1290int my_chown_Link(CFSTR path, uid_t owner, gid_t group)
1291{
1292 return lchown(path, owner, group);
1293 // return fchownat(AT_FDCWD, path, owner, group, AT_SYMLINK_NOFOLLOW);
1294}
1295
1276bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) 1296bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
1277{ 1297{
1278 TRACE_SetFileAttrib("") 1298 TRACE_SetFileAttrib("")
1279 1299 mode_t mode;
1280 struct stat st; 1300 struct stat st;
1281
1282 bool use_lstat = true; 1301 bool use_lstat = true;
1283 if (use_lstat) 1302 if (use_lstat)
1284 { 1303 {
@@ -1297,20 +1316,26 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
1297 return false; 1316 return false;
1298 } 1317 }
1299 } 1318 }
1300 1319 mode = st.st_mode;
1320
1301 if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION) 1321 if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)
1302 { 1322 {
1303 TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION") 1323 TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION")
1304 st.st_mode = attrib >> 16; 1324 mode = attrib >> 16;
1305 if (S_ISDIR(st.st_mode)) 1325 if (S_ISDIR(mode))
1306 { 1326 {
1327 if (!S_ISDIR(st.st_mode))
1328 return true;
1307 // user/7z must be able to create files in this directory 1329 // user/7z must be able to create files in this directory
1308 st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR); 1330 mode |= (S_IRUSR | S_IWUSR | S_IXUSR);
1331 }
1332 else
1333 {
1334 if (!S_ISREG(mode) || !S_ISREG(st.st_mode))
1335 return true;
1309 } 1336 }
1310 else if (!S_ISREG(st.st_mode))
1311 return true;
1312 } 1337 }
1313 else if (S_ISLNK(st.st_mode)) 1338 else if (S_ISLNK(mode))
1314 { 1339 {
1315 /* for most systems: permissions for symlinks are fixed to rwxrwxrwx. 1340 /* for most systems: permissions for symlinks are fixed to rwxrwxrwx.
1316 so we don't need chmod() for symlinks. */ 1341 so we don't need chmod() for symlinks. */
@@ -1322,27 +1347,28 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
1322 { 1347 {
1323 TRACE_SetFileAttrib("Only Windows Attributes") 1348 TRACE_SetFileAttrib("Only Windows Attributes")
1324 // Only Windows Attributes 1349 // Only Windows Attributes
1325 if (S_ISDIR(st.st_mode) 1350 if (S_ISDIR(mode)
1326 || (attrib & FILE_ATTRIBUTE_READONLY) == 0) 1351 || (attrib & FILE_ATTRIBUTE_READONLY) == 0)
1327 return true; 1352 return true;
1328 st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions 1353 mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions
1329 } 1354 }
1330 1355
1331 int res; 1356 int res;
1357 mode &= g_umask.mask;
1332 /* 1358 /*
1333 if (S_ISLNK(st.st_mode)) 1359 if (S_ISLNK(mode))
1334 { 1360 {
1335 printf("\nfchmodat()\n"); 1361 printf("\nfchmodat()\n");
1336 TRACE_chmod(path, (st.st_mode) & g_umask.mask) 1362 TRACE_chmod(path, (mode))
1337 // AT_SYMLINK_NOFOLLOW is not implemted still in Linux. 1363 // AT_SYMLINK_NOFOLLOW is not implemented still in Linux.
1338 res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask, 1364 res = fchmodat(AT_FDCWD, path, (mode),
1339 S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0); 1365 S_ISLNK(mode) ? AT_SYMLINK_NOFOLLOW : 0);
1340 } 1366 }
1341 else 1367 else
1342 */ 1368 */
1343 { 1369 {
1344 TRACE_chmod(path, (st.st_mode) & g_umask.mask) 1370 TRACE_chmod(path, mode)
1345 res = chmod(path, (st.st_mode) & g_umask.mask); 1371 res = chmod(path, mode);
1346 } 1372 }
1347 // TRACE_SetFileAttrib("End") 1373 // TRACE_SetFileAttrib("End")
1348 return (res == 0); 1374 return (res == 0);
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h
index 9ba98fc..e8d9d31 100644
--- a/CPP/Windows/FileDir.h
+++ b/CPP/Windows/FileDir.h
@@ -46,6 +46,7 @@ bool SetFileAttrib(CFSTR path, DWORD attrib);
46#else 46#else
47 47
48int my_chown(CFSTR path, uid_t owner, gid_t group); 48int my_chown(CFSTR path, uid_t owner, gid_t group);
49int my_chown_Link(CFSTR path, uid_t owner, gid_t group);
49 50
50#endif 51#endif
51 52
diff --git a/CPP/Windows/FileIO.cpp b/CPP/Windows/FileIO.cpp
index dc4de14..8be06fc 100644
--- a/CPP/Windows/FileIO.cpp
+++ b/CPP/Windows/FileIO.cpp
@@ -6,6 +6,29 @@
6#include "../../C/Alloc.h" 6#include "../../C/Alloc.h"
7#endif 7#endif
8 8
9#ifdef _WIN32
10#ifdef __MINGW32_VERSION
11// #if !defined(_MSC_VER) && (__GNUC__) && (__GNUC__ < 10)
12// for old mingw
13#include <ddk/ntddk.h>
14#else
15#ifndef Z7_OLD_WIN_SDK
16 #if !defined(_M_IA64)
17 #include <winternl.h>
18 #endif
19#else
20typedef LONG NTSTATUS;
21typedef struct _IO_STATUS_BLOCK {
22 union {
23 NTSTATUS Status;
24 PVOID Pointer;
25 };
26 ULONG_PTR Information;
27} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
28#endif
29#endif
30#endif // _WIN32
31
9// #include <stdio.h> 32// #include <stdio.h>
10 33
11/* 34/*
@@ -33,6 +56,48 @@ HRESULT GetLastError_noZero_HRESULT()
33extern bool g_IsNT; 56extern bool g_IsNT;
34#endif 57#endif
35 58
59#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500) && !defined(_M_IA64)
60#define Z7_WIN_NTSTATUS NTSTATUS
61#define Z7_WIN_IO_STATUS_BLOCK IO_STATUS_BLOCK
62#else
63typedef LONG Z7_WIN_NTSTATUS;
64typedef struct
65{
66 union
67 {
68 Z7_WIN_NTSTATUS Status;
69 PVOID Pointer;
70 } DUMMYUNIONNAME;
71 ULONG_PTR Information;
72} Z7_WIN_IO_STATUS_BLOCK;
73#endif
74
75typedef Z7_WIN_NTSTATUS (WINAPI *Func_NtSetInformationFile)(
76 HANDLE FileHandle,
77 Z7_WIN_IO_STATUS_BLOCK *IoStatusBlock,
78 PVOID FileInformation,
79 ULONG Length,
80 Z7_WIN_FILE_INFORMATION_CLASS FileInformationClass);
81// NTAPI
82typedef ULONG (WINAPI *Func_RtlNtStatusToDosError)(Z7_WIN_NTSTATUS Status);
83
84Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
85static Func_NtSetInformationFile g_NtSetInformationFile;
86static Func_RtlNtStatusToDosError g_RtlNtStatusToDosError;
87static struct C_Init_NtSetInformationFile
88{
89 C_Init_NtSetInformationFile()
90 {
91 const HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
92 g_NtSetInformationFile = Z7_GET_PROC_ADDRESS(
93 Func_NtSetInformationFile, ntdll,
94 "NtSetInformationFile");
95 g_RtlNtStatusToDosError = Z7_GET_PROC_ADDRESS(
96 Func_RtlNtStatusToDosError, ntdll,
97 "RtlNtStatusToDosError");
98 }
99} g_C_Init_NtSetInformationFile;
100
36using namespace NWindows; 101using namespace NWindows;
37using namespace NFile; 102using namespace NFile;
38using namespace NName; 103using namespace NName;
@@ -353,7 +418,7 @@ void CInFile::CalcDeviceSize(CFSTR s)
353 WinXP 64-bit: 418 WinXP 64-bit:
354 419
355 HDD \\.\PhysicalDrive0 (MBR): 420 HDD \\.\PhysicalDrive0 (MBR):
356 GetPartitionInfo == GeometryEx : corrrect size? (includes tail) 421 GetPartitionInfo == GeometryEx : correct size? (includes tail)
357 Geometry : smaller than GeometryEx (no tail, maybe correct too?) 422 Geometry : smaller than GeometryEx (no tail, maybe correct too?)
358 MyGetDiskFreeSpace : FAIL 423 MyGetDiskFreeSpace : FAIL
359 Size correction is slow and block size (kClusterSize) must be small? 424 Size correction is slow and block size (kClusterSize) must be small?
@@ -365,8 +430,8 @@ void CInFile::CalcDeviceSize(CFSTR s)
365 430
366 CD-ROM drive (ISO): 431 CD-ROM drive (ISO):
367 MyGetDiskFreeSpace : correct size. Same size can be calculated after correction 432 MyGetDiskFreeSpace : correct size. Same size can be calculated after correction
368 Geometry == CdRomGeometry : smaller than corrrect size 433 Geometry == CdRomGeometry : smaller than correct size
369 GetPartitionInfo == GeometryEx : larger than corrrect size 434 GetPartitionInfo == GeometryEx : larger than correct size
370 435
371 Floppy \\.\a: (FAT): 436 Floppy \\.\a: (FAT):
372 Geometry : correct size. 437 Geometry : correct size.
@@ -539,6 +604,70 @@ bool COutFile::Open_Disposition(CFSTR fileName, DWORD creationDisposition)
539bool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes) 604bool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes)
540 { return Open(fileName, FILE_SHARE_READ, CREATE_ALWAYS, flagsAndAttributes); } 605 { return Open(fileName, FILE_SHARE_READ, CREATE_ALWAYS, flagsAndAttributes); }
541 606
607DWORD CFileBase::Call_NtSetInformationFile_return_WinError(
608 void *data, ULONG len, Z7_WIN_FILE_INFORMATION_CLASS fileInformationClass) const
609{
610 if (!g_NtSetInformationFile)
611 return ERROR_PROC_NOT_FOUND;
612 Z7_WIN_IO_STATUS_BLOCK ioStatus;
613 Z7_memset_0_VAR(ioStatus); // optional
614 const Z7_WIN_NTSTATUS status = g_NtSetInformationFile(_handle,
615 &ioStatus, data, len, fileInformationClass);
616 if (status == 0) // MY_STATUS_SUCCESS
617 return 0;
618 if (g_RtlNtStatusToDosError)
619 {
620 const ULONG res = g_RtlNtStatusToDosError(status);
621 if (res != ERROR_MR_MID_NOT_FOUND)
622 return res;
623 }
624 return 1;
625}
626
627
628#define SET_TIME_FIELD_IF_DEFINED(dest, src) \
629{ if (src) { \
630 dest.LowPart = (src)->dwLowDateTime; \
631 dest.HighPart = (LONG)(src)->dwHighDateTime; \
632 } \
633}
634
635bool COutFile::Set_Time_and_WinAttrib(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime, DWORD attrib) throw()
636{
637#ifdef _WIN32
638 // similar to GetAttrib_PosixHighDetect(attrib)
639 if (attrib & 0xF0000000)
640 attrib &= 0x3FFF;
641#endif
642
643 Z7_WIN_FILE_BASIC_INFORMATION fbi;
644 Z7_memset_0_VAR(fbi);
645 SET_TIME_FIELD_IF_DEFINED (fbi.CreationTime, cTime)
646 SET_TIME_FIELD_IF_DEFINED (fbi.LastAccessTime, aTime)
647 SET_TIME_FIELD_IF_DEFINED (fbi.LastWriteTime, mTime)
648 // fbi.ChangeTime.QuadPart = 0;
649 /*
650 if (attrib == 0)
651 { win10: NtSetInformationFile() doesn't change file attribute
652 if (attrib & FILE_ATTRIBUTE_DIRECTORY)
653 { win10: NtSetInformationFile() returns (STATUS_INVALID_PARAMETER) }
654 we provide similar attribute processing as
655 SetFileAttributes():
656 - we ignore (FILE_ATTRIBUTE_DIRECTORY)
657 - we write (FILE_ATTRIBUTE_NORMAL) instead of (0)
658 */
659 attrib &= ~(DWORD)FILE_ATTRIBUTE_DIRECTORY;
660 if (attrib == 0)
661 attrib = FILE_ATTRIBUTE_NORMAL;
662 fbi.FileAttributes = attrib;
663 const DWORD wres = Call_NtSetInformationFile_return_WinError(
664 &fbi, sizeof(fbi), Z7_WIN_FileBasicInformation);
665 if (wres == 0)
666 return true;
667 SetLastError(wres);
668 return false;
669}
670
542bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() 671bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw()
543 { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); } 672 { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }
544 673
@@ -628,10 +757,16 @@ bool COutFile::SetLength_KeepPosition(UInt64 length) throw()
628#include <fcntl.h> 757#include <fcntl.h>
629#include <unistd.h> 758#include <unistd.h>
630 759
760extern
761bool FiTime_To_timespec(const CFiTime *ft, timespec &ts);
762
631namespace NWindows { 763namespace NWindows {
632namespace NFile { 764namespace NFile {
633 765
634namespace NDir { 766namespace NDir {
767
768extern C_umask g_umask;
769
635bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); 770bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);
636} 771}
637 772
@@ -644,6 +779,34 @@ bool CFileBase::OpenBinary(const char *name, int flags, mode_t mode)
644 #endif 779 #endif
645 780
646 Close(); 781 Close();
782 /*
783 The mode argument specifies the file mode bits to be
784 applied when a new file is created. If neither O_CREAT nor
785 O_TMPFILE is specified in flags, then mode is ignored (and
786 can thus be specified as 0, or simply omitted).
787
788 The effective mode is modified by the process's umask in
789 the usual way: in the absence of a default ACL, the mode of
790 the created file is (mode & ~umask).
791
792 Note that mode applies only to future accesses of the newly
793 created file; the open() call that creates a read-only file
794 may well return a read/write file descriptor.
795
796 POSIX: if other bits (~0777) are set in mode : the effect is unspecified
797 Linux:
798 S_ISUID 04000 set-user-ID bit
799 S_ISGID 02000 set-group-ID bit
800 S_ISVTX 01000 sticky bit
801
802 S_ISVTX can be set, but it's useless for file in modern linux.
803 by security reasons:
804 open() ignores S_ISUID
805 open() ignores S_ISGID, if S_IXGRP is set.
806 */
807 // mode |= S_ISUID | S_ISGID | S_ISVTX; // for debug
808 // printf("\n open() mode=%o\n", (unsigned)(mode));
809
647 _handle = ::open(name, flags, mode); 810 _handle = ::open(name, flags, mode);
648 return _handle != -1; 811 return _handle != -1;
649 812
@@ -740,7 +903,7 @@ bool CFileBase::SeekToBegin() const throw()
740 903
741bool CInFile::Open(const char *name) 904bool CInFile::Open(const char *name)
742{ 905{
743 return CFileBase::OpenBinary(name, O_RDONLY); 906 return CFileBase::OpenBinary(name, O_RDONLY, k_OutFile_mode_default);
744} 907}
745 908
746bool CInFile::OpenShared(const char *name, bool) 909bool CInFile::OpenShared(const char *name, bool)
@@ -903,11 +1066,64 @@ bool COutFile::SetLength(UInt64 length) throw()
903 return (iret == 0); 1066 return (iret == 0);
904} 1067}
905 1068
1069// #define PRF(x) x
1070#define PRF(x)
1071
906bool COutFile::Close() 1072bool COutFile::Close()
907{ 1073{
908 const bool res = CFileBase::Close(); 1074 bool res = true;
909 if (!res) 1075 if (_handle == -1)
910 return res; 1076 return true;
1077 {
1078 // bool res2 = true;
1079 if (mode_for_Close_defined)
1080 {
1081 PRF(printf("\n COutFile::Close() mode=%o\n", (unsigned)(mode_for_Close));)
1082 // fchmod() function ignores the file creation mask set by umask()
1083 // so we can restore any of (07777) mode bits
1084 // mode_for_Close |= (0xffff << 12); // for debug
1085 if (fchmod(_handle, mode_for_Close) == 0)
1086 {
1087 mode_for_Close_defined = false;
1088 PRF(printf("\n COutFile::Close() fchmod() == 0\n");)
1089 }
1090 // else res2 = false;
1091 }
1092 {
1093 if (MTime_defined || ATime_defined)
1094 {
1095 struct timespec times[2];
1096 FiTime_To_timespec(ATime_defined ? &ATime : NULL, times[0]);
1097 FiTime_To_timespec(MTime_defined ? &MTime : NULL, times[1]);
1098 // futimens : POSIX.1-2008
1099 if (futimens(_handle, times) == 0)
1100 {
1101 PRF(printf("\n futimens() OK \n");)
1102 ATime_defined = false;
1103 MTime_defined = false;
1104 }
1105 else
1106 {
1107 PRF(printf("\n futimens() ERROR: %d=%s\n", errno, strerror(errno));)
1108 }
1109 }
1110 }
1111 res = CFileBase::Close();
1112 if (!res)
1113 return res;
1114 // res = res2;
1115 }
1116 if (mode_for_Close_defined)
1117 {
1118 // chmod() ignores the file creation mask set by umask()
1119 // so we can restore any of (07777) mode bits
1120 // const int res_chmod =
1121 chmod(Path, mode_for_Close);
1122 mode_for_Close_defined = false;
1123 // if (res_chmod != 0 && res == true) res = false;
1124 // PRF(printf("\n COutFile::Close() chmod res=%d\n", (int)res_chmod);)
1125 }
1126
911 if (CTime_defined || ATime_defined || MTime_defined) 1127 if (CTime_defined || ATime_defined || MTime_defined)
912 { 1128 {
913 /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path, 1129 /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path,
@@ -942,6 +1158,24 @@ bool COutFile::SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime
942 */ 1158 */
943} 1159}
944 1160
1161bool COutFile::Set_Time_and_WinAttrib(
1162 const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD attrib) throw()
1163{
1164 PRF(printf("\n Set_Time_and_WinAttrib() mode=%o\n", (unsigned)(attrib >> 16));)
1165 SetTime(cTime, aTime, mTime);
1166 // we will use fchmod() or chmod() later in Close() fucntion.
1167 // fchmod() or chmod() are not limited by system umask.
1168 // but for security reasons we use the system mask (g_umask.mask) derived from umask().
1169 mode_t mode = k_OutFile_mode_default; // 0666
1170 if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)
1171 mode = (attrib >> 16);
1172 else if (attrib & FILE_ATTRIBUTE_READONLY)
1173 mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions
1174 mode_for_Close = mode & NDir::g_umask.mask;
1175 mode_for_Close_defined = true;
1176 return true;
1177}
1178
945bool COutFile::SetMTime(const CFiTime *mTime) throw() 1179bool COutFile::SetMTime(const CFiTime *mTime) throw()
946{ 1180{
947 if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false; 1181 if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;
diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h
index a202df5..9c32137 100644
--- a/CPP/Windows/FileIO.h
+++ b/CPP/Windows/FileIO.h
@@ -19,6 +19,27 @@
19#include <winioctl.h> 19#include <winioctl.h>
20#endif 20#endif
21 21
22typedef enum
23{
24 Z7_WIN_FileDirectoryInformation = 1,
25 Z7_WIN_FileFullDirectoryInformation,
26 Z7_WIN_FileBothDirectoryInformation,
27 Z7_WIN_FileBasicInformation,
28 Z7_WIN_FileRenameInformation = 10
29} Z7_WIN_FILE_INFORMATION_CLASS;
30
31// FILE_BASIC_INFORMATION / FILE_BASIC_INFO
32typedef struct
33{
34 LARGE_INTEGER CreationTime;
35 LARGE_INTEGER LastAccessTime;
36 LARGE_INTEGER LastWriteTime;
37 LARGE_INTEGER ChangeTime;
38 ULONG FileAttributes;
39 ULONG Reserved; // it's expected dummy variable for alignment : optional
40}
41Z7_WIN_FILE_BASIC_INFORMATION;
42
22#else 43#else
23 44
24#include <sys/types.h> 45#include <sys/types.h>
@@ -205,6 +226,9 @@ public:
205 return false; 226 return false;
206 return file.GetFileInformation(info); 227 return file.GetFileInformation(info);
207 } 228 }
229
230 DWORD Call_NtSetInformationFile_return_WinError(void *data, ULONG len,
231 Z7_WIN_FILE_INFORMATION_CLASS fileInformationClass) const;
208}; 232};
209 233
210#ifndef UNDER_CE 234#ifndef UNDER_CE
@@ -323,6 +347,8 @@ public:
323 347
324 bool Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes); 348 bool Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes);
325 349
350 bool Set_Time_and_WinAttrib(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD attrib) throw();
351
326 bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); 352 bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw();
327 bool SetMTime(const CFiTime *mTime) throw(); 353 bool SetMTime(const CFiTime *mTime) throw();
328 bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw(); 354 bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw();
@@ -338,6 +364,15 @@ public:
338 364
339#else // _WIN32 365#else // _WIN32
340 366
367namespace NDir {
368struct C_umask
369{
370 mode_t mask;
371 C_umask();
372};
373extern C_umask g_umask;
374}
375
341namespace NIO { 376namespace NIO {
342 377
343bool GetReparseData(CFSTR path, CByteBuffer &reparseData); 378bool GetReparseData(CFSTR path, CByteBuffer &reparseData);
@@ -347,6 +382,7 @@ bool GetReparseData(CFSTR path, CByteBuffer &reparseData);
347bool SetSymLink(CFSTR from, CFSTR to); 382bool SetSymLink(CFSTR from, CFSTR to);
348bool SetSymLink_UString(CFSTR from, const UString &to); 383bool SetSymLink_UString(CFSTR from, const UString &to);
349 384
385const mode_t k_OutFile_mode_default = 0666;
350 386
351class CFileBase 387class CFileBase
352{ 388{
@@ -359,7 +395,7 @@ protected:
359 UInt64 Size; // it can be larger than real available size 395 UInt64 Size; // it can be larger than real available size
360 */ 396 */
361 397
362 bool OpenBinary(const char *name, int flags, mode_t mode = 0666); 398 bool OpenBinary(const char *name, int flags, mode_t mode /* = k_OutFile_mode_default */);
363public: 399public:
364 bool PreserveATime; 400 bool PreserveATime;
365#if 0 401#if 0
@@ -411,9 +447,11 @@ class COutFile: public CFileBase
411 bool CTime_defined; 447 bool CTime_defined;
412 bool ATime_defined; 448 bool ATime_defined;
413 bool MTime_defined; 449 bool MTime_defined;
450 bool mode_for_Close_defined;
414 CFiTime CTime; 451 CFiTime CTime;
415 CFiTime ATime; 452 CFiTime ATime;
416 CFiTime MTime; 453 CFiTime MTime;
454 mode_t mode_for_Close;
417 455
418 AString Path; 456 AString Path;
419 ssize_t write_part(const void *data, size_t size) throw(); 457 ssize_t write_part(const void *data, size_t size) throw();
@@ -425,9 +463,11 @@ public:
425 CTime_defined(false), 463 CTime_defined(false),
426 ATime_defined(false), 464 ATime_defined(false),
427 MTime_defined(false), 465 MTime_defined(false),
428 mode_for_Create(0666) 466 mode_for_Close_defined(false),
467 mode_for_Create(k_OutFile_mode_default) // 0666
429 {} 468 {}
430 469
470 ~COutFile() { Close(); }
431 bool Close(); 471 bool Close();
432 472
433 bool Open_EXISTING(CFSTR fileName); 473 bool Open_EXISTING(CFSTR fileName);
@@ -454,6 +494,7 @@ public:
454 return SetLength(length); 494 return SetLength(length);
455 } 495 }
456 bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw(); 496 bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw();
497 bool Set_Time_and_WinAttrib(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD attrib) throw();
457 bool SetMTime(const CFiTime *mTime) throw(); 498 bool SetMTime(const CFiTime *mTime) throw();
458}; 499};
459 500