diff options
Diffstat (limited to '')
-rw-r--r-- | CPP/7zip/Common/FileStreams.cpp | 292 |
1 files changed, 265 insertions, 27 deletions
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index 9e0e79c..6862a9b 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp | |||
@@ -2,18 +2,30 @@ | |||
2 | 2 | ||
3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
4 | 4 | ||
5 | // #include <stdio.h> | ||
6 | |||
5 | #ifndef _WIN32 | 7 | #ifndef _WIN32 |
6 | #include <fcntl.h> | 8 | #include <fcntl.h> |
7 | #include <unistd.h> | 9 | #include <unistd.h> |
8 | #include <errno.h> | 10 | #include <errno.h> |
9 | #include "../../Windows/FileFind.h" | 11 | #include <grp.h> |
12 | #include <pwd.h> | ||
13 | |||
14 | // for major minor | ||
15 | // BSD: <sys/types.h> | ||
16 | #include <sys/sysmacros.h> | ||
17 | |||
10 | #endif | 18 | #endif |
11 | 19 | ||
20 | #include "../../Windows/FileFind.h" | ||
21 | |||
12 | #ifdef SUPPORT_DEVICE_FILE | 22 | #ifdef SUPPORT_DEVICE_FILE |
13 | #include "../../../C/Alloc.h" | 23 | #include "../../../C/Alloc.h" |
14 | #include "../../Common/Defs.h" | 24 | #include "../../Common/Defs.h" |
15 | #endif | 25 | #endif |
16 | 26 | ||
27 | #include "../PropID.h" | ||
28 | |||
17 | #include "FileStreams.h" | 29 | #include "FileStreams.h" |
18 | 30 | ||
19 | static inline HRESULT GetLastError_HRESULT() | 31 | static inline HRESULT GetLastError_HRESULT() |
@@ -37,12 +49,19 @@ static const UInt32 kClusterSize = 1 << 18; | |||
37 | #endif | 49 | #endif |
38 | 50 | ||
39 | CInFileStream::CInFileStream(): | 51 | CInFileStream::CInFileStream(): |
40 | #ifdef SUPPORT_DEVICE_FILE | 52 | #ifdef SUPPORT_DEVICE_FILE |
41 | VirtPos(0), | 53 | VirtPos(0), |
42 | PhyPos(0), | 54 | PhyPos(0), |
43 | Buf(0), | 55 | Buf(0), |
44 | BufSize(0), | 56 | BufSize(0), |
45 | #endif | 57 | #endif |
58 | #ifndef _WIN32 | ||
59 | _uid(0), | ||
60 | _gid(0), | ||
61 | StoreOwnerId(false), | ||
62 | StoreOwnerName(false), | ||
63 | #endif | ||
64 | _info_WasLoaded(false), | ||
46 | SupportHardLinks(false), | 65 | SupportHardLinks(false), |
47 | Callback(NULL), | 66 | Callback(NULL), |
48 | CallbackRef(0) | 67 | CallbackRef(0) |
@@ -56,7 +75,7 @@ CInFileStream::~CInFileStream() | |||
56 | #endif | 75 | #endif |
57 | 76 | ||
58 | if (Callback) | 77 | if (Callback) |
59 | Callback->InFileStream_On_Destroy(CallbackRef); | 78 | Callback->InFileStream_On_Destroy(this, CallbackRef); |
60 | } | 79 | } |
61 | 80 | ||
62 | STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) | 81 | STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) |
@@ -306,8 +325,14 @@ STDMETHODIMP CInFileStream::GetSize(UInt64 *size) | |||
306 | 325 | ||
307 | STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) | 326 | STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) |
308 | { | 327 | { |
328 | if (!_info_WasLoaded) | ||
329 | RINOK(ReloadProps()); | ||
330 | const BY_HANDLE_FILE_INFORMATION &info = _info; | ||
331 | /* | ||
309 | BY_HANDLE_FILE_INFORMATION info; | 332 | BY_HANDLE_FILE_INFORMATION info; |
310 | if (File.GetFileInformation(&info)) | 333 | if (!File.GetFileInformation(&info)) |
334 | return GetLastError_HRESULT(); | ||
335 | */ | ||
311 | { | 336 | { |
312 | if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; | 337 | if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; |
313 | if (cTime) *cTime = info.ftCreationTime; | 338 | if (cTime) *cTime = info.ftCreationTime; |
@@ -316,13 +341,18 @@ STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT | |||
316 | if (attrib) *attrib = info.dwFileAttributes; | 341 | if (attrib) *attrib = info.dwFileAttributes; |
317 | return S_OK; | 342 | return S_OK; |
318 | } | 343 | } |
319 | return GetLastError_HRESULT(); | ||
320 | } | 344 | } |
321 | 345 | ||
322 | STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | 346 | STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) |
323 | { | 347 | { |
348 | if (!_info_WasLoaded) | ||
349 | RINOK(ReloadProps()); | ||
350 | const BY_HANDLE_FILE_INFORMATION &info = _info; | ||
351 | /* | ||
324 | BY_HANDLE_FILE_INFORMATION info; | 352 | BY_HANDLE_FILE_INFORMATION info; |
325 | if (File.GetFileInformation(&info)) | 353 | if (!File.GetFileInformation(&info)) |
354 | return GetLastError_HRESULT(); | ||
355 | */ | ||
326 | { | 356 | { |
327 | props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; | 357 | props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow; |
328 | props->VolID = info.dwVolumeSerialNumber; | 358 | props->VolID = info.dwVolumeSerialNumber; |
@@ -335,27 +365,114 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | |||
335 | props->MTime = info.ftLastWriteTime; | 365 | props->MTime = info.ftLastWriteTime; |
336 | return S_OK; | 366 | return S_OK; |
337 | } | 367 | } |
338 | return GetLastError_HRESULT(); | ||
339 | } | 368 | } |
340 | 369 | ||
370 | STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value) | ||
371 | { | ||
372 | if (!_info_WasLoaded) | ||
373 | RINOK(ReloadProps()); | ||
374 | |||
375 | if (!_info_WasLoaded) | ||
376 | return S_OK; | ||
377 | |||
378 | NWindows::NCOM::CPropVariant prop; | ||
379 | |||
380 | #ifdef SUPPORT_DEVICE_FILE | ||
381 | if (File.IsDeviceFile) | ||
382 | { | ||
383 | switch (propID) | ||
384 | { | ||
385 | case kpidSize: | ||
386 | if (File.SizeDefined) | ||
387 | prop = File.Size; | ||
388 | break; | ||
389 | // case kpidAttrib: prop = (UInt32)0; break; | ||
390 | case kpidPosixAttrib: | ||
391 | { | ||
392 | prop = (UInt32)NWindows::NFile::NFind::NAttributes:: | ||
393 | Get_PosixMode_From_WinAttrib(0); | ||
394 | /* GNU TAR by default can't extract file with MY_LIN_S_IFBLK attribute | ||
395 | so we don't use MY_LIN_S_IFBLK here */ | ||
396 | // prop = (UInt32)(MY_LIN_S_IFBLK | 0600); // for debug | ||
397 | break; | ||
398 | } | ||
399 | /* | ||
400 | case kpidDeviceMajor: | ||
401 | prop = (UInt32)8; // id for SCSI type device (sda) | ||
402 | break; | ||
403 | case kpidDeviceMinor: | ||
404 | prop = (UInt32)0; | ||
405 | break; | ||
406 | */ | ||
407 | } | ||
408 | } | ||
409 | else | ||
410 | #endif | ||
411 | { | ||
412 | switch (propID) | ||
413 | { | ||
414 | case kpidSize: | ||
415 | { | ||
416 | const UInt64 size = (((UInt64)_info.nFileSizeHigh) << 32) + _info.nFileSizeLow; | ||
417 | prop = size; | ||
418 | break; | ||
419 | } | ||
420 | case kpidAttrib: prop = (UInt32)_info.dwFileAttributes; break; | ||
421 | case kpidCTime: PropVariant_SetFrom_FiTime(prop, _info.ftCreationTime); break; | ||
422 | case kpidATime: PropVariant_SetFrom_FiTime(prop, _info.ftLastAccessTime); break; | ||
423 | case kpidMTime: PropVariant_SetFrom_FiTime(prop, _info.ftLastWriteTime); break; | ||
424 | case kpidPosixAttrib: | ||
425 | prop = (UInt32)NWindows::NFile::NFind::NAttributes:: | ||
426 | Get_PosixMode_From_WinAttrib(_info.dwFileAttributes); | ||
427 | // | (UInt32)(1 << 21); // for debug | ||
428 | break; | ||
429 | } | ||
430 | } | ||
431 | prop.Detach(value); | ||
432 | return S_OK; | ||
433 | } | ||
434 | |||
435 | |||
436 | STDMETHODIMP CInFileStream::ReloadProps() | ||
437 | { | ||
438 | #ifdef SUPPORT_DEVICE_FILE | ||
439 | if (File.IsDeviceFile) | ||
440 | { | ||
441 | memset(&_info, 0, sizeof(_info)); | ||
442 | if (File.SizeDefined) | ||
443 | { | ||
444 | _info.nFileSizeHigh = (DWORD)(File.Size >> 32); | ||
445 | _info.nFileSizeLow = (DWORD)(File.Size); | ||
446 | } | ||
447 | _info.nNumberOfLinks = 1; | ||
448 | _info_WasLoaded = true; | ||
449 | return S_OK; | ||
450 | } | ||
451 | #endif | ||
452 | _info_WasLoaded = File.GetFileInformation(&_info); | ||
453 | if (!_info_WasLoaded) | ||
454 | return GetLastError_HRESULT(); | ||
455 | return S_OK; | ||
456 | } | ||
457 | |||
458 | |||
341 | #elif !defined(_WIN32) | 459 | #elif !defined(_WIN32) |
342 | 460 | ||
343 | STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) | 461 | STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) |
344 | { | 462 | { |
463 | if (!_info_WasLoaded) | ||
464 | RINOK(ReloadProps()); | ||
465 | const struct stat &st = _info; | ||
466 | /* | ||
345 | struct stat st; | 467 | struct stat st; |
346 | if (File.my_fstat(&st) != 0) | 468 | if (File.my_fstat(&st) != 0) |
347 | return GetLastError_HRESULT(); | 469 | return GetLastError_HRESULT(); |
348 | 470 | */ | |
471 | |||
349 | if (size) *size = (UInt64)st.st_size; | 472 | if (size) *size = (UInt64)st.st_size; |
350 | #ifdef __APPLE__ | 473 | if (cTime) FiTime_To_FILETIME (ST_CTIME(st), *cTime); |
351 | if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, *cTime); | 474 | if (aTime) FiTime_To_FILETIME (ST_ATIME(st), *aTime); |
352 | if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, *aTime); | 475 | if (mTime) FiTime_To_FILETIME (ST_MTIME(st), *mTime); |
353 | if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, *mTime); | ||
354 | #else | ||
355 | if (cTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, *cTime); | ||
356 | if (aTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, *aTime); | ||
357 | if (mTime) NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, *mTime); | ||
358 | #endif | ||
359 | if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); | 476 | if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); |
360 | 477 | ||
361 | return S_OK; | 478 | return S_OK; |
@@ -365,9 +482,14 @@ STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aT | |||
365 | 482 | ||
366 | STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | 483 | STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) |
367 | { | 484 | { |
485 | if (!_info_WasLoaded) | ||
486 | RINOK(ReloadProps()); | ||
487 | const struct stat &st = _info; | ||
488 | /* | ||
368 | struct stat st; | 489 | struct stat st; |
369 | if (File.my_fstat(&st) != 0) | 490 | if (File.my_fstat(&st) != 0) |
370 | return GetLastError_HRESULT(); | 491 | return GetLastError_HRESULT(); |
492 | */ | ||
371 | 493 | ||
372 | props->Size = (UInt64)st.st_size; | 494 | props->Size = (UInt64)st.st_size; |
373 | /* | 495 | /* |
@@ -381,15 +503,9 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | |||
381 | props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) | 503 | props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long) |
382 | props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); | 504 | props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); |
383 | 505 | ||
384 | #ifdef __APPLE__ | 506 | FiTime_To_FILETIME (ST_CTIME(st), props->CTime); |
385 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctimespec, props->CTime); | 507 | FiTime_To_FILETIME (ST_ATIME(st), props->ATime); |
386 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atimespec, props->ATime); | 508 | FiTime_To_FILETIME (ST_MTIME(st), props->MTime); |
387 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtimespec, props->MTime); | ||
388 | #else | ||
389 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_ctim, props->CTime); | ||
390 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_atim, props->ATime); | ||
391 | NWindows::NFile::NFind::timespec_To_FILETIME(st.st_mtim, props->MTime); | ||
392 | #endif | ||
393 | 509 | ||
394 | /* | 510 | /* |
395 | printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" | 511 | printf("\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\n" |
@@ -402,8 +518,130 @@ STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) | |||
402 | return S_OK; | 518 | return S_OK; |
403 | } | 519 | } |
404 | 520 | ||
521 | STDMETHODIMP CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value) | ||
522 | { | ||
523 | if (!_info_WasLoaded) | ||
524 | RINOK(ReloadProps()); | ||
525 | |||
526 | if (!_info_WasLoaded) | ||
527 | return S_OK; | ||
528 | |||
529 | const struct stat &st = _info; | ||
530 | |||
531 | NWindows::NCOM::CPropVariant prop; | ||
532 | { | ||
533 | switch (propID) | ||
534 | { | ||
535 | case kpidSize: prop = (UInt64)st.st_size; break; | ||
536 | case kpidAttrib: | ||
537 | prop = (UInt32)NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode); | ||
538 | break; | ||
539 | case kpidCTime: PropVariant_SetFrom_FiTime(prop, ST_CTIME(st)); break; | ||
540 | case kpidATime: PropVariant_SetFrom_FiTime(prop, ST_ATIME(st)); break; | ||
541 | case kpidMTime: PropVariant_SetFrom_FiTime(prop, ST_MTIME(st)); break; | ||
542 | case kpidPosixAttrib: prop = (UInt32)st.st_mode; break; | ||
543 | |||
544 | case kpidDeviceMajor: | ||
545 | { | ||
546 | // printf("\nst.st_rdev = %d\n", st.st_rdev); | ||
547 | if (S_ISCHR(st.st_mode) || | ||
548 | S_ISBLK(st.st_mode)) | ||
549 | prop = (UInt32)(major(st.st_rdev)); // + 1000); | ||
550 | // prop = (UInt32)12345678; // for debug | ||
551 | break; | ||
552 | } | ||
553 | |||
554 | case kpidDeviceMinor: | ||
555 | if (S_ISCHR(st.st_mode) || | ||
556 | S_ISBLK(st.st_mode)) | ||
557 | prop = (UInt32)(minor(st.st_rdev)); // + 100); | ||
558 | // prop = (UInt32)(st.st_rdev); // for debug | ||
559 | // printf("\nst.st_rdev = %d\n", st.st_rdev); | ||
560 | // prop = (UInt32)123456789; // for debug | ||
561 | break; | ||
562 | |||
563 | /* | ||
564 | case kpidDevice: | ||
565 | if (S_ISCHR(st.st_mode) || | ||
566 | S_ISBLK(st.st_mode)) | ||
567 | prop = (UInt64)(st.st_rdev); | ||
568 | break; | ||
569 | */ | ||
570 | |||
571 | case kpidUserId: | ||
572 | { | ||
573 | if (StoreOwnerId) | ||
574 | prop = (UInt32)st.st_uid; | ||
575 | break; | ||
576 | } | ||
577 | case kpidGroupId: | ||
578 | { | ||
579 | if (StoreOwnerId) | ||
580 | prop = (UInt32)st.st_gid; | ||
581 | break; | ||
582 | } | ||
583 | case kpidUser: | ||
584 | { | ||
585 | if (StoreOwnerName) | ||
586 | { | ||
587 | const uid_t uid = st.st_uid; | ||
588 | { | ||
589 | if (!OwnerName.IsEmpty() && _uid == uid) | ||
590 | prop = OwnerName; | ||
591 | else | ||
592 | { | ||
593 | const passwd *pw = getpwuid(uid); | ||
594 | if (pw) | ||
595 | { | ||
596 | // we can use utf-8 here. | ||
597 | // prop = pw->pw_name; | ||
598 | } | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | break; | ||
603 | } | ||
604 | case kpidGroup: | ||
605 | { | ||
606 | if (StoreOwnerName) | ||
607 | { | ||
608 | const uid_t gid = st.st_gid; | ||
609 | { | ||
610 | if (!OwnerGroup.IsEmpty() && _gid == gid) | ||
611 | prop = OwnerGroup; | ||
612 | else | ||
613 | { | ||
614 | const group *gr = getgrgid(gid); | ||
615 | if (gr) | ||
616 | { | ||
617 | // we can use utf-8 here. | ||
618 | // prop = gr->gr_name; | ||
619 | } | ||
620 | } | ||
621 | } | ||
622 | } | ||
623 | break; | ||
624 | } | ||
625 | } | ||
626 | } | ||
627 | prop.Detach(value); | ||
628 | return S_OK; | ||
629 | } | ||
630 | |||
631 | |||
632 | STDMETHODIMP CInFileStream::ReloadProps() | ||
633 | { | ||
634 | _info_WasLoaded = (File.my_fstat(&_info) == 0); | ||
635 | if (!_info_WasLoaded) | ||
636 | return GetLastError_HRESULT(); | ||
637 | return S_OK; | ||
638 | } | ||
639 | |||
405 | #endif | 640 | #endif |
406 | 641 | ||
642 | |||
643 | |||
644 | |||
407 | ////////////////////////// | 645 | ////////////////////////// |
408 | // COutFileStream | 646 | // COutFileStream |
409 | 647 | ||