aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Common/FileStreams.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/Common/FileStreams.cpp292
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
19static inline HRESULT GetLastError_HRESULT() 31static inline HRESULT GetLastError_HRESULT()
@@ -37,12 +49,19 @@ static const UInt32 kClusterSize = 1 << 18;
37#endif 49#endif
38 50
39CInFileStream::CInFileStream(): 51CInFileStream::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
62STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) 81STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
@@ -306,8 +325,14 @@ STDMETHODIMP CInFileStream::GetSize(UInt64 *size)
306 325
307STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) 326STDMETHODIMP 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
322STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) 346STDMETHODIMP 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
370STDMETHODIMP 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
436STDMETHODIMP 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
343STDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib) 461STDMETHODIMP 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
366STDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props) 483STDMETHODIMP 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
521STDMETHODIMP 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
632STDMETHODIMP 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