diff options
Diffstat (limited to 'CPP/Windows')
| -rw-r--r-- | CPP/Windows/FileDir.cpp | 102 | ||||
| -rw-r--r-- | CPP/Windows/FileDir.h | 1 | ||||
| -rw-r--r-- | CPP/Windows/FileIO.cpp | 248 | ||||
| -rw-r--r-- | CPP/Windows/FileIO.h | 45 |
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 | ||
| 37 | static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts) | 37 | extern |
| 38 | bool FiTime_To_timespec(const CFiTime *ft, timespec &ts); | ||
| 39 | bool 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 | ||
| 171 | bool SetFileAttrib(CFSTR path, DWORD attrib) | 173 | bool 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 | ||
| 1243 | struct C_umask | 1249 | C_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 | ||
| 1260 | static C_umask g_umask; | 1274 | C_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 | ||
| 1290 | int 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 | |||
| 1276 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib) | 1296 | bool 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 | ||
| 48 | int my_chown(CFSTR path, uid_t owner, gid_t group); | 48 | int my_chown(CFSTR path, uid_t owner, gid_t group); |
| 49 | int 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 | ||
| 20 | typedef LONG NTSTATUS; | ||
| 21 | typedef 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() | |||
| 33 | extern bool g_IsNT; | 56 | extern 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 | ||
| 63 | typedef LONG Z7_WIN_NTSTATUS; | ||
| 64 | typedef 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 | |||
| 75 | typedef 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 | ||
| 82 | typedef ULONG (WINAPI *Func_RtlNtStatusToDosError)(Z7_WIN_NTSTATUS Status); | ||
| 83 | |||
| 84 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | ||
| 85 | static Func_NtSetInformationFile g_NtSetInformationFile; | ||
| 86 | static Func_RtlNtStatusToDosError g_RtlNtStatusToDosError; | ||
| 87 | static 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 | |||
| 36 | using namespace NWindows; | 101 | using namespace NWindows; |
| 37 | using namespace NFile; | 102 | using namespace NFile; |
| 38 | using namespace NName; | 103 | using 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) | |||
| 539 | bool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes) | 604 | bool 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 | ||
| 607 | DWORD 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 | |||
| 635 | bool 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 | |||
| 542 | bool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw() | 671 | bool 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 | ||
| 760 | extern | ||
| 761 | bool FiTime_To_timespec(const CFiTime *ft, timespec &ts); | ||
| 762 | |||
| 631 | namespace NWindows { | 763 | namespace NWindows { |
| 632 | namespace NFile { | 764 | namespace NFile { |
| 633 | 765 | ||
| 634 | namespace NDir { | 766 | namespace NDir { |
| 767 | |||
| 768 | extern C_umask g_umask; | ||
| 769 | |||
| 635 | bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime); | 770 | bool 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 | ||
| 741 | bool CInFile::Open(const char *name) | 904 | bool 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 | ||
| 746 | bool CInFile::OpenShared(const char *name, bool) | 909 | bool 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 | |||
| 906 | bool COutFile::Close() | 1072 | bool 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 | ||
| 1161 | bool 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 | |||
| 945 | bool COutFile::SetMTime(const CFiTime *mTime) throw() | 1179 | bool 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 | ||
| 22 | typedef 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 | ||
| 32 | typedef 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 | } | ||
| 41 | Z7_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 | ||
| 367 | namespace NDir { | ||
| 368 | struct C_umask | ||
| 369 | { | ||
| 370 | mode_t mask; | ||
| 371 | C_umask(); | ||
| 372 | }; | ||
| 373 | extern C_umask g_umask; | ||
| 374 | } | ||
| 375 | |||
| 341 | namespace NIO { | 376 | namespace NIO { |
| 342 | 377 | ||
| 343 | bool GetReparseData(CFSTR path, CByteBuffer &reparseData); | 378 | bool GetReparseData(CFSTR path, CByteBuffer &reparseData); |
| @@ -347,6 +382,7 @@ bool GetReparseData(CFSTR path, CByteBuffer &reparseData); | |||
| 347 | bool SetSymLink(CFSTR from, CFSTR to); | 382 | bool SetSymLink(CFSTR from, CFSTR to); |
| 348 | bool SetSymLink_UString(CFSTR from, const UString &to); | 383 | bool SetSymLink_UString(CFSTR from, const UString &to); |
| 349 | 384 | ||
| 385 | const mode_t k_OutFile_mode_default = 0666; | ||
| 350 | 386 | ||
| 351 | class CFileBase | 387 | class 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 */); |
| 363 | public: | 399 | public: |
| 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 | ||
