diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-07-16 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-12-17 14:35:38 +0500 |
| commit | 93be7d4abfd4233228f58ee1fbbcd76d91be66a4 (patch) | |
| tree | 9b11631a70ca7150321838d9d6bd473e52d6684d | |
| parent | a3e1d227377188734b82f023f96f8e25dc40f3e6 (diff) | |
| download | 7zip-22.01.tar.gz 7zip-22.01.tar.bz2 7zip-22.01.zip | |
22.0122.01
Diffstat (limited to '')
47 files changed, 2468 insertions, 795 deletions
diff --git a/C/7zVersion.h b/C/7zVersion.h index 89fffd9..49ea81d 100644 --- a/C/7zVersion.h +++ b/C/7zVersion.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | #define MY_VER_MAJOR 22 | 1 | #define MY_VER_MAJOR 22 |
| 2 | #define MY_VER_MINOR 00 | 2 | #define MY_VER_MINOR 01 |
| 3 | #define MY_VER_BUILD 0 | 3 | #define MY_VER_BUILD 0 |
| 4 | #define MY_VERSION_NUMBERS "22.00" | 4 | #define MY_VERSION_NUMBERS "22.01" |
| 5 | #define MY_VERSION MY_VERSION_NUMBERS | 5 | #define MY_VERSION MY_VERSION_NUMBERS |
| 6 | 6 | ||
| 7 | #ifdef MY_CPU_NAME | 7 | #ifdef MY_CPU_NAME |
| @@ -10,7 +10,7 @@ | |||
| 10 | #define MY_VERSION_CPU MY_VERSION | 10 | #define MY_VERSION_CPU MY_VERSION |
| 11 | #endif | 11 | #endif |
| 12 | 12 | ||
| 13 | #define MY_DATE "2022-06-15" | 13 | #define MY_DATE "2022-07-15" |
| 14 | #undef MY_COPYRIGHT | 14 | #undef MY_COPYRIGHT |
| 15 | #undef MY_VERSION_COPYRIGHT_DATE | 15 | #undef MY_VERSION_COPYRIGHT_DATE |
| 16 | #define MY_AUTHOR_NAME "Igor Pavlov" | 16 | #define MY_AUTHOR_NAME "Igor Pavlov" |
diff --git a/C/7zip_gcc_c.mak b/C/7zip_gcc_c.mak index e884440..24505f3 100644 --- a/C/7zip_gcc_c.mak +++ b/C/7zip_gcc_c.mak | |||
| @@ -16,12 +16,32 @@ CFLAGS_BASE = $(MY_ARCH_2) -O2 $(CFLAGS_BASE_LIST) -Wall -Werror -Wextra $(CFLAG | |||
| 16 | -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE | 16 | -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | LDFLAGS_STATIC = -DNDEBUG | ||
| 20 | # -static | ||
| 21 | |||
| 22 | ifdef SystemDrive | 19 | ifdef SystemDrive |
| 23 | IS_MINGW = 1 | 20 | IS_MINGW = 1 |
| 21 | else | ||
| 22 | ifdef SYSTEMDRIVE | ||
| 23 | # ifdef OS | ||
| 24 | IS_MINGW = 1 | ||
| 25 | endif | ||
| 26 | endif | ||
| 27 | |||
| 28 | ifdef IS_MINGW | ||
| 29 | LDFLAGS_STATIC_2 = -static | ||
| 30 | else | ||
| 31 | ifndef DEF_FILE | ||
| 32 | ifndef IS_NOT_STANDALONE | ||
| 33 | ifndef MY_DYNAMIC_LINK | ||
| 34 | ifneq ($(CC), clang) | ||
| 35 | LDFLAGS_STATIC_2 = | ||
| 36 | # -static | ||
| 37 | # -static-libstdc++ -static-libgcc | ||
| 38 | endif | ||
| 39 | endif | ||
| 40 | endif | ||
| 24 | endif | 41 | endif |
| 42 | endif | ||
| 43 | |||
| 44 | LDFLAGS_STATIC = -DNDEBUG $(LDFLAGS_STATIC_2) | ||
| 25 | 45 | ||
| 26 | ifdef DEF_FILE | 46 | ifdef DEF_FILE |
| 27 | 47 | ||
| @@ -62,15 +82,22 @@ endif | |||
| 62 | 82 | ||
| 63 | ifdef IS_MINGW | 83 | ifdef IS_MINGW |
| 64 | 84 | ||
| 85 | ifdef MSYSTEM | ||
| 86 | RM = rm -f | ||
| 87 | MY_MKDIR=mkdir -p | ||
| 88 | DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) | ||
| 89 | else | ||
| 65 | RM = del | 90 | RM = del |
| 66 | MY_MKDIR=mkdir | 91 | MY_MKDIR=mkdir |
| 67 | LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 | 92 | DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll |
| 93 | endif | ||
| 94 | |||
| 68 | 95 | ||
| 96 | LIB2 = -lOle32 -loleaut32 -luuid -ladvapi32 -lUser32 | ||
| 69 | 97 | ||
| 70 | CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE | 98 | CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE |
| 71 | # -Wno-delete-non-virtual-dtor | 99 | # -Wno-delete-non-virtual-dtor |
| 72 | 100 | ||
| 73 | DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll | ||
| 74 | 101 | ||
| 75 | else | 102 | else |
| 76 | 103 | ||
| @@ -306,7 +333,10 @@ $O/7zMain.o: ../../../C/Util/7z/7zMain.c | |||
| 306 | $(CC) $(CFLAGS) $< | 333 | $(CC) $(CFLAGS) $< |
| 307 | $O/LzmaUtil.o: ../../../C/Util/Lzma/LzmaUtil.c | 334 | $O/LzmaUtil.o: ../../../C/Util/Lzma/LzmaUtil.c |
| 308 | $(CC) $(CFLAGS) $< | 335 | $(CC) $(CFLAGS) $< |
| 309 | 336 | $O/7zipInstall.o: ../../../C/Util/7zipInstall/7zipInstall.c | |
| 337 | $(CC) $(CFLAGS) $< | ||
| 338 | $O/7zipUninstall.o: ../../../C/Util/7zipUninstall/7zipUninstall.c | ||
| 339 | $(CC) $(CFLAGS) $< | ||
| 310 | 340 | ||
| 311 | 341 | ||
| 312 | clean: | 342 | clean: |
diff --git a/C/CpuArch.h b/C/CpuArch.h index 529d3a5..4856fbb 100644 --- a/C/CpuArch.h +++ b/C/CpuArch.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* CpuArch.h -- CPU specific code | 1 | /* CpuArch.h -- CPU specific code |
| 2 | 2021-07-13 : Igor Pavlov : Public domain */ | 2 | 2022-07-15 : Igor Pavlov : Public domain */ |
| 3 | 3 | ||
| 4 | #ifndef __CPU_ARCH_H | 4 | #ifndef __CPU_ARCH_H |
| 5 | #define __CPU_ARCH_H | 5 | #define __CPU_ARCH_H |
| @@ -123,12 +123,15 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. | |||
| 123 | #endif | 123 | #endif |
| 124 | 124 | ||
| 125 | 125 | ||
| 126 | #if defined(__sparc64__) | 126 | #if defined(__riscv) \ |
| 127 | #define MY_CPU_NAME "sparc64" | 127 | || defined(__riscv__) |
| 128 | #define MY_CPU_64BIT | 128 | #if __riscv_xlen == 32 |
| 129 | #elif defined(__sparc__) | 129 | #define MY_CPU_NAME "riscv32" |
| 130 | #define MY_CPU_NAME "sparc" | 130 | #elif __riscv_xlen == 64 |
| 131 | /* #define MY_CPU_32BIT */ | 131 | #define MY_CPU_NAME "riscv64" |
| 132 | #else | ||
| 133 | #define MY_CPU_NAME "riscv" | ||
| 134 | #endif | ||
| 132 | #endif | 135 | #endif |
| 133 | 136 | ||
| 134 | 137 | ||
diff --git a/C/DllSecur.c b/C/DllSecur.c index d81508c..dce0c96 100644 --- a/C/DllSecur.c +++ b/C/DllSecur.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* DllSecur.c -- DLL loading security | 1 | /* DllSecur.c -- DLL loading security |
| 2 | 2021-12-25 : Igor Pavlov : Public domain */ | 2 | 2022-07-15 : Igor Pavlov : Public domain */ |
| 3 | 3 | ||
| 4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
| 5 | 5 | ||
| @@ -11,6 +11,10 @@ | |||
| 11 | 11 | ||
| 12 | #ifndef UNDER_CE | 12 | #ifndef UNDER_CE |
| 13 | 13 | ||
| 14 | #if defined(__GNUC__) && (__GNUC__ >= 8) | ||
| 15 | #pragma GCC diagnostic ignored "-Wcast-function-type" | ||
| 16 | #endif | ||
| 17 | |||
| 14 | typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags); | 18 | typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags); |
| 15 | 19 | ||
| 16 | #define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400 | 20 | #define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400 |
| @@ -34,7 +38,7 @@ static const char * const g_Dlls = | |||
| 34 | #endif | 38 | #endif |
| 35 | 39 | ||
| 36 | // #define MY_CAST_FUNC (void(*)()) | 40 | // #define MY_CAST_FUNC (void(*)()) |
| 37 | #define MY_CAST_FUNC | 41 | #define MY_CAST_FUNC |
| 38 | 42 | ||
| 39 | void My_SetDefaultDllDirectories() | 43 | void My_SetDefaultDllDirectories() |
| 40 | { | 44 | { |
diff --git a/C/LzmaEnc.c b/C/LzmaEnc.c index b04a7b7..c8b31a1 100644 --- a/C/LzmaEnc.c +++ b/C/LzmaEnc.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* LzmaEnc.c -- LZMA Encoder | 1 | /* LzmaEnc.c -- LZMA Encoder |
| 2 | 2021-11-18: Igor Pavlov : Public domain */ | 2 | 2022-07-15: Igor Pavlov : Public domain */ |
| 3 | 3 | ||
| 4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
| 5 | 5 | ||
| @@ -2970,6 +2970,7 @@ const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) | |||
| 2970 | } | 2970 | } |
| 2971 | 2971 | ||
| 2972 | 2972 | ||
| 2973 | // (desiredPackSize == 0) is not allowed | ||
| 2973 | SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, | 2974 | SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, |
| 2974 | Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) | 2975 | Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) |
| 2975 | { | 2976 | { |
| @@ -2990,14 +2991,10 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, | |||
| 2990 | if (reInit) | 2991 | if (reInit) |
| 2991 | LzmaEnc_Init(p); | 2992 | LzmaEnc_Init(p); |
| 2992 | LzmaEnc_InitPrices(p); | 2993 | LzmaEnc_InitPrices(p); |
| 2993 | |||
| 2994 | nowPos64 = p->nowPos64; | ||
| 2995 | RangeEnc_Init(&p->rc); | 2994 | RangeEnc_Init(&p->rc); |
| 2996 | p->rc.outStream = &outStream.vt; | 2995 | p->rc.outStream = &outStream.vt; |
| 2997 | 2996 | nowPos64 = p->nowPos64; | |
| 2998 | if (desiredPackSize == 0) | 2997 | |
| 2999 | return SZ_ERROR_OUTPUT_EOF; | ||
| 3000 | |||
| 3001 | res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize); | 2998 | res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize); |
| 3002 | 2999 | ||
| 3003 | *unpackSize = (UInt32)(p->nowPos64 - nowPos64); | 3000 | *unpackSize = (UInt32)(p->nowPos64 - nowPos64); |
diff --git a/C/Util/7zipInstall/7zipInstall.c b/C/Util/7zipInstall/7zipInstall.c index 00d0f41..2649734 100644 --- a/C/Util/7zipInstall/7zipInstall.c +++ b/C/Util/7zipInstall/7zipInstall.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* 7zipInstall.c - 7-Zip Installer | 1 | /* 7zipInstall.c - 7-Zip Installer |
| 2 | 2021-09-02 : Igor Pavlov : Public domain */ | 2 | 2022-07-15 : Igor Pavlov : Public domain */ |
| 3 | 3 | ||
| 4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
| 5 | 5 | ||
| @@ -22,6 +22,10 @@ | |||
| 22 | 22 | ||
| 23 | #include "resource.h" | 23 | #include "resource.h" |
| 24 | 24 | ||
| 25 | #if defined(__GNUC__) && (__GNUC__ >= 8) | ||
| 26 | #pragma GCC diagnostic ignored "-Wcast-function-type" | ||
| 27 | #endif | ||
| 28 | |||
| 25 | #define LLL_(quote) L##quote | 29 | #define LLL_(quote) L##quote |
| 26 | #define LLL(quote) LLL_(quote) | 30 | #define LLL(quote) LLL_(quote) |
| 27 | 31 | ||
| @@ -70,7 +74,7 @@ static LPCWSTR const k_Reg_Software_7zip = L"Software\\7-Zip"; | |||
| 70 | #endif | 74 | #endif |
| 71 | #endif | 75 | #endif |
| 72 | 76 | ||
| 73 | #define k_7zip_with_Ver k_7zip_with_Ver_base k_Postfix | 77 | #define k_7zip_with_Ver k_7zip_with_Ver_base k_Postfix |
| 74 | 78 | ||
| 75 | 79 | ||
| 76 | static LPCWSTR const k_7zip_with_Ver_str = k_7zip_with_Ver; | 80 | static LPCWSTR const k_7zip_with_Ver_str = k_7zip_with_Ver; |
diff --git a/C/Util/7zipUninstall/7zipUninstall.c b/C/Util/7zipUninstall/7zipUninstall.c index b4c6ff5..c8e8a89 100644 --- a/C/Util/7zipUninstall/7zipUninstall.c +++ b/C/Util/7zipUninstall/7zipUninstall.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* 7zipUninstall.c - 7-Zip Uninstaller | 1 | /* 7zipUninstall.c - 7-Zip Uninstaller |
| 2 | 2021-11-24 : Igor Pavlov : Public domain */ | 2 | 2022-07-15 : Igor Pavlov : Public domain */ |
| 3 | 3 | ||
| 4 | #include "Precomp.h" | 4 | #include "Precomp.h" |
| 5 | 5 | ||
| @@ -17,6 +17,10 @@ | |||
| 17 | 17 | ||
| 18 | #include "resource.h" | 18 | #include "resource.h" |
| 19 | 19 | ||
| 20 | #if defined(__GNUC__) && (__GNUC__ >= 8) | ||
| 21 | #pragma GCC diagnostic ignored "-Wcast-function-type" | ||
| 22 | #endif | ||
| 23 | |||
| 20 | #define LLL_(quote) L##quote | 24 | #define LLL_(quote) L##quote |
| 21 | #define LLL(quote) LLL_(quote) | 25 | #define LLL(quote) LLL_(quote) |
| 22 | 26 | ||
diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak index b242459..f65cff2 100644 --- a/CPP/7zip/7zip_gcc.mak +++ b/CPP/7zip/7zip_gcc.mak | |||
| @@ -33,6 +33,11 @@ CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ | |||
| 33 | 33 | ||
| 34 | ifdef SystemDrive | 34 | ifdef SystemDrive |
| 35 | IS_MINGW = 1 | 35 | IS_MINGW = 1 |
| 36 | else | ||
| 37 | ifdef SYSTEMDRIVE | ||
| 38 | # ifdef OS | ||
| 39 | IS_MINGW = 1 | ||
| 40 | endif | ||
| 36 | endif | 41 | endif |
| 37 | 42 | ||
| 38 | ifdef IS_MINGW | 43 | ifdef IS_MINGW |
| @@ -97,20 +102,30 @@ PROGPATH_STATIC = $(O)/$(PROG)s$(SHARED_EXT) | |||
| 97 | 102 | ||
| 98 | ifdef IS_MINGW | 103 | ifdef IS_MINGW |
| 99 | 104 | ||
| 105 | ifdef MSYSTEM | ||
| 106 | RM = rm -f | ||
| 107 | MY_MKDIR=mkdir -p | ||
| 108 | DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) | ||
| 109 | LIB_HTMLHELP=-lhtmlhelp | ||
| 110 | else | ||
| 100 | RM = del | 111 | RM = del |
| 101 | MY_MKDIR=mkdir | 112 | MY_MKDIR=mkdir |
| 102 | LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 | 113 | DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll |
| 114 | endif | ||
| 115 | |||
| 116 | LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 $(LIB_HTMLHELP) | ||
| 103 | LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI) | 117 | LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI) |
| 104 | 118 | ||
| 105 | CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE | 119 | CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE |
| 106 | # -Wno-delete-non-virtual-dtor | 120 | # -Wno-delete-non-virtual-dtor |
| 107 | 121 | ||
| 108 | DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll | ||
| 109 | 122 | ||
| 110 | else | 123 | else |
| 111 | 124 | ||
| 112 | RM = rm -f | 125 | RM = rm -f |
| 113 | MY_MKDIR=mkdir -p | 126 | MY_MKDIR=mkdir -p |
| 127 | DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) | ||
| 128 | |||
| 114 | # CFLAGS_BASE := $(CFLAGS_BASE) -D_7ZIP_ST | 129 | # CFLAGS_BASE := $(CFLAGS_BASE) -D_7ZIP_ST |
| 115 | # CXXFLAGS_EXTRA = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE | 130 | # CXXFLAGS_EXTRA = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE |
| 116 | 131 | ||
| @@ -119,9 +134,6 @@ MY_MKDIR=mkdir -p | |||
| 119 | LIB2 = -lpthread -ldl | 134 | LIB2 = -lpthread -ldl |
| 120 | 135 | ||
| 121 | 136 | ||
| 122 | |||
| 123 | DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS) | ||
| 124 | |||
| 125 | endif | 137 | endif |
| 126 | 138 | ||
| 127 | 139 | ||
| @@ -130,9 +142,19 @@ CFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CFLAGS_BASE2) $(CFLAGS_BASE) $(CC_SHARED) | |||
| 130 | 142 | ||
| 131 | 143 | ||
| 132 | ifdef IS_MINGW | 144 | ifdef IS_MINGW |
| 145 | |||
| 146 | ifdef IS_X64 | ||
| 147 | AFLAGS_ABI = -win64 | ||
| 148 | else | ||
| 133 | AFLAGS_ABI = -coff -DABI_CDECL | 149 | AFLAGS_ABI = -coff -DABI_CDECL |
| 150 | # -DABI_CDECL | ||
| 151 | # -DABI_LINUX | ||
| 152 | # -DABI_CDECL | ||
| 153 | endif | ||
| 134 | AFLAGS = -nologo $(AFLAGS_ABI) -Fo$(O)/$(basename $(<F)).o | 154 | AFLAGS = -nologo $(AFLAGS_ABI) -Fo$(O)/$(basename $(<F)).o |
| 135 | else | 155 | |
| 156 | else # IS_MINGW | ||
| 157 | |||
| 136 | ifdef IS_X64 | 158 | ifdef IS_X64 |
| 137 | AFLAGS_ABI = -elf64 -DABI_LINUX | 159 | AFLAGS_ABI = -elf64 -DABI_LINUX |
| 138 | else | 160 | else |
| @@ -142,7 +164,10 @@ AFLAGS_ABI = -elf -DABI_LINUX -DABI_CDECL | |||
| 142 | # -DABI_CDECL | 164 | # -DABI_CDECL |
| 143 | endif | 165 | endif |
| 144 | AFLAGS = -nologo $(AFLAGS_ABI) -Fo$(O)/ | 166 | AFLAGS = -nologo $(AFLAGS_ABI) -Fo$(O)/ |
| 145 | endif | 167 | |
| 168 | endif # IS_MINGW | ||
| 169 | |||
| 170 | |||
| 146 | 171 | ||
| 147 | ifdef USE_ASM | 172 | ifdef USE_ASM |
| 148 | CONSOLE_ASM_FLAGS=-D_7ZIP_ASM | 173 | CONSOLE_ASM_FLAGS=-D_7ZIP_ASM |
diff --git a/CPP/7zip/Archive/ApfsHandler.cpp b/CPP/7zip/Archive/ApfsHandler.cpp index 8312456..2c16de1 100644 --- a/CPP/7zip/Archive/ApfsHandler.cpp +++ b/CPP/7zip/Archive/ApfsHandler.cpp | |||
| @@ -32,6 +32,8 @@ | |||
| 32 | 32 | ||
| 33 | #include "Common/ItemNameUtils.h" | 33 | #include "Common/ItemNameUtils.h" |
| 34 | 34 | ||
| 35 | #include "HfsHandler.h" | ||
| 36 | |||
| 35 | // if APFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files. | 37 | // if APFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files. |
| 36 | #define APFS_SHOW_ALT_STREAMS | 38 | #define APFS_SHOW_ALT_STREAMS |
| 37 | 39 | ||
| @@ -934,11 +936,12 @@ struct CItem | |||
| 934 | unsigned RefIndex; | 936 | unsigned RefIndex; |
| 935 | // unsigned iNode_Index; | 937 | // unsigned iNode_Index; |
| 936 | 938 | ||
| 937 | CItem(): | 939 | void Clear() |
| 938 | ParentItemIndex(VI_MINUS1), | 940 | { |
| 939 | RefIndex(VI_MINUS1) | 941 | Name.Empty(); |
| 940 | // iNode_Index(VI_MINUS1) | 942 | ParentItemIndex = VI_MINUS1; |
| 941 | {} | 943 | RefIndex = VI_MINUS1; |
| 944 | } | ||
| 942 | }; | 945 | }; |
| 943 | 946 | ||
| 944 | 947 | ||
| @@ -956,9 +959,9 @@ struct CItem | |||
| 956 | #define UNIFIED_ID_SPACE_MARK 0x0800000000000000 | 959 | #define UNIFIED_ID_SPACE_MARK 0x0800000000000000 |
| 957 | */ | 960 | */ |
| 958 | 961 | ||
| 959 | /* | ||
| 960 | typedef enum | 962 | typedef enum |
| 961 | { | 963 | { |
| 964 | /* | ||
| 962 | INODE_IS_APFS_PRIVATE = 0x00000001, | 965 | INODE_IS_APFS_PRIVATE = 0x00000001, |
| 963 | INODE_MAINTAIN_DIR_STATS = 0x00000002, | 966 | INODE_MAINTAIN_DIR_STATS = 0x00000002, |
| 964 | INODE_DIR_STATS_ORIGIN = 0x00000004, | 967 | INODE_DIR_STATS_ORIGIN = 0x00000004, |
| @@ -973,11 +976,15 @@ INODE_WAS_EVER_CLONED = 0x00000400, | |||
| 973 | INODE_ACTIVE_FILE_TRIMMED = 0x00000800, | 976 | INODE_ACTIVE_FILE_TRIMMED = 0x00000800, |
| 974 | INODE_PINNED_TO_MAIN = 0x00001000, | 977 | INODE_PINNED_TO_MAIN = 0x00001000, |
| 975 | INODE_PINNED_TO_TIER2 = 0x00002000, | 978 | INODE_PINNED_TO_TIER2 = 0x00002000, |
| 979 | */ | ||
| 976 | INODE_HAS_RSRC_FORK = 0x00004000, | 980 | INODE_HAS_RSRC_FORK = 0x00004000, |
| 981 | /* | ||
| 977 | INODE_NO_RSRC_FORK = 0x00008000, | 982 | INODE_NO_RSRC_FORK = 0x00008000, |
| 978 | INODE_ALLOCATION_SPILLEDOVER = 0x00010000, | 983 | INODE_ALLOCATION_SPILLEDOVER = 0x00010000, |
| 979 | INODE_FAST_PROMOTE = 0x00020000, | 984 | INODE_FAST_PROMOTE = 0x00020000, |
| 985 | */ | ||
| 980 | INODE_HAS_UNCOMPRESSED_SIZE = 0x00040000, | 986 | INODE_HAS_UNCOMPRESSED_SIZE = 0x00040000, |
| 987 | /* | ||
| 981 | INODE_IS_PURGEABLE = 0x00080000, | 988 | INODE_IS_PURGEABLE = 0x00080000, |
| 982 | INODE_WANTS_TO_BE_PURGEABLE = 0x00100000, | 989 | INODE_WANTS_TO_BE_PURGEABLE = 0x00100000, |
| 983 | INODE_IS_SYNC_ROOT = 0x00200000, | 990 | INODE_IS_SYNC_ROOT = 0x00200000, |
| @@ -993,10 +1000,12 @@ INODE_CLONED_INTERNAL_FLAGS = \ | |||
| 993 | | INODE_NO_RSRC_FORK \ | 1000 | | INODE_NO_RSRC_FORK \ |
| 994 | | INODE_HAS_FINDER_INFO \ | 1001 | | INODE_HAS_FINDER_INFO \ |
| 995 | | INODE_SNAPSHOT_COW_EXEMPTION), | 1002 | | INODE_SNAPSHOT_COW_EXEMPTION), |
| 1003 | */ | ||
| 996 | } | 1004 | } |
| 997 | j_inode_flags; | 1005 | j_inode_flags; |
| 998 | 1006 | ||
| 999 | 1007 | ||
| 1008 | /* | ||
| 1000 | #define APFS_VALID_INTERNAL_INODE_FLAGS \ | 1009 | #define APFS_VALID_INTERNAL_INODE_FLAGS \ |
| 1001 | ( INODE_IS_APFS_PRIVATE \ | 1010 | ( INODE_IS_APFS_PRIVATE \ |
| 1002 | | INODE_MAINTAIN_DIR_STATS \ | 1011 | | INODE_MAINTAIN_DIR_STATS \ |
| @@ -1192,22 +1201,34 @@ struct CAttr | |||
| 1192 | { | 1201 | { |
| 1193 | AString Name; | 1202 | AString Name; |
| 1194 | UInt32 flags; | 1203 | UInt32 flags; |
| 1204 | bool dstream_defined; | ||
| 1205 | bool NeedShow; | ||
| 1195 | CByteBuffer Data; | 1206 | CByteBuffer Data; |
| 1196 | 1207 | ||
| 1197 | j_dstream dstream; | 1208 | j_dstream dstream; |
| 1198 | bool dstream_defined; | ||
| 1199 | UInt64 Id; | 1209 | UInt64 Id; |
| 1200 | 1210 | ||
| 1201 | bool Is_dstream_OK_for_SymLink() const | 1211 | bool Is_dstream_OK_for_SymLink() const |
| 1202 | { | 1212 | { |
| 1203 | return dstream_defined && dstream.size <= (1 << 12) && dstream.size != 0; | 1213 | return dstream_defined && dstream.size <= (1 << 12) && dstream.size != 0; |
| 1204 | } | 1214 | } |
| 1215 | |||
| 1216 | UInt64 GetSize() const | ||
| 1217 | { | ||
| 1218 | if (dstream_defined) // dstream has more priority | ||
| 1219 | return dstream.size; | ||
| 1220 | return Data.Size(); | ||
| 1221 | } | ||
| 1205 | 1222 | ||
| 1206 | CAttr(): | 1223 | void Clear() |
| 1207 | dstream_defined(false) | 1224 | { |
| 1208 | {} | 1225 | dstream_defined = false; |
| 1226 | NeedShow = true; | ||
| 1227 | Data.Free(); | ||
| 1228 | Name.Empty(); | ||
| 1229 | } | ||
| 1209 | 1230 | ||
| 1210 | bool Is_STREAM() const { return (flags & XATTR_DATA_STREAM) != 0; } | 1231 | bool Is_STREAM() const { return (flags & XATTR_DATA_STREAM) != 0; } |
| 1211 | bool Is_EMBEDDED() const { return (flags & XATTR_DATA_EMBEDDED) != 0; } | 1232 | bool Is_EMBEDDED() const { return (flags & XATTR_DATA_EMBEDDED) != 0; } |
| 1212 | }; | 1233 | }; |
| 1213 | 1234 | ||
| @@ -1245,16 +1266,22 @@ struct CNode | |||
| 1245 | MY__gid_t group; | 1266 | MY__gid_t group; |
| 1246 | MY__mode_t mode; | 1267 | MY__mode_t mode; |
| 1247 | UInt16 pad1; | 1268 | UInt16 pad1; |
| 1248 | // UInt64 uncompressed_size; | 1269 | UInt64 uncompressed_size; |
| 1249 | 1270 | ||
| 1250 | j_dstream dstream; | 1271 | j_dstream dstream; |
| 1251 | AString PrimaryName; | 1272 | AString PrimaryName; |
| 1273 | |||
| 1252 | bool dstream_defined; | 1274 | bool dstream_defined; |
| 1253 | bool refcnt_defined; | 1275 | bool refcnt_defined; |
| 1276 | |||
| 1254 | UInt32 refcnt; // j_dstream_id_val_t | 1277 | UInt32 refcnt; // j_dstream_id_val_t |
| 1255 | CRecordVector<CExtent> Extents; | 1278 | CRecordVector<CExtent> Extents; |
| 1256 | CObjectVector<CAttr> Attrs; | 1279 | CObjectVector<CAttr> Attrs; |
| 1257 | unsigned SymLinkIndex; // index in Attrs | 1280 | unsigned SymLinkIndex; // index in Attrs |
| 1281 | unsigned DecmpfsIndex; // index in Attrs | ||
| 1282 | unsigned ResourceIndex; // index in Attrs | ||
| 1283 | |||
| 1284 | NHfs::CCompressHeader CompressHeader; | ||
| 1258 | 1285 | ||
| 1259 | CNode(): | 1286 | CNode(): |
| 1260 | ItemIndex(VI_MINUS1), | 1287 | ItemIndex(VI_MINUS1), |
| @@ -1262,11 +1289,16 @@ struct CNode | |||
| 1262 | // NumItems(0), | 1289 | // NumItems(0), |
| 1263 | dstream_defined(false), | 1290 | dstream_defined(false), |
| 1264 | refcnt_defined(false), | 1291 | refcnt_defined(false), |
| 1265 | SymLinkIndex(VI_MINUS1) | 1292 | SymLinkIndex(VI_MINUS1), |
| 1293 | DecmpfsIndex(VI_MINUS1), | ||
| 1294 | ResourceIndex(VI_MINUS1) | ||
| 1266 | {} | 1295 | {} |
| 1267 | 1296 | ||
| 1268 | bool IsDir() const { return MY_LIN_S_ISDIR(mode); } | 1297 | bool IsDir() const { return MY_LIN_S_ISDIR(mode); } |
| 1269 | bool IsSymLink() const { return MY_LIN_S_ISLNK(mode); } | 1298 | bool IsSymLink() const { return MY_LIN_S_ISLNK(mode); } |
| 1299 | |||
| 1300 | bool Has_UNCOMPRESSED_SIZE() const { return (internal_flags & INODE_HAS_UNCOMPRESSED_SIZE) != 0; } | ||
| 1301 | |||
| 1270 | unsigned Get_Type_From_mode() const { return mode >> 12; } | 1302 | unsigned Get_Type_From_mode() const { return mode >> 12; } |
| 1271 | 1303 | ||
| 1272 | bool GetSize(unsigned attrIndex, UInt64 &size) const | 1304 | bool GetSize(unsigned attrIndex, UInt64 &size) const |
| @@ -1278,6 +1310,12 @@ struct CNode | |||
| 1278 | size = dstream.size; | 1310 | size = dstream.size; |
| 1279 | return true; | 1311 | return true; |
| 1280 | } | 1312 | } |
| 1313 | size = 0; | ||
| 1314 | if (Has_UNCOMPRESSED_SIZE()) | ||
| 1315 | { | ||
| 1316 | size = uncompressed_size; | ||
| 1317 | return true; | ||
| 1318 | } | ||
| 1281 | if (!IsSymLink()) | 1319 | if (!IsSymLink()) |
| 1282 | return false; | 1320 | return false; |
| 1283 | attrIndex = SymLinkIndex; | 1321 | attrIndex = SymLinkIndex; |
| @@ -1301,9 +1339,23 @@ struct CNode | |||
| 1301 | size = dstream.alloced_size; | 1339 | size = dstream.alloced_size; |
| 1302 | return true; | 1340 | return true; |
| 1303 | } | 1341 | } |
| 1304 | if (!IsSymLink()) | 1342 | size = 0; |
| 1305 | return false; | 1343 | |
| 1306 | attrIndex = SymLinkIndex; | 1344 | if (IsSymLink()) |
| 1345 | attrIndex = SymLinkIndex; | ||
| 1346 | else | ||
| 1347 | { | ||
| 1348 | if (!CompressHeader.IsCorrect || | ||
| 1349 | !CompressHeader.IsSupported) | ||
| 1350 | return false; | ||
| 1351 | const CAttr &attr = Attrs[DecmpfsIndex]; | ||
| 1352 | if (!CompressHeader.IsMethod_Resource()) | ||
| 1353 | { | ||
| 1354 | size = attr.Data.Size() - CompressHeader.DataPos; | ||
| 1355 | return true; | ||
| 1356 | } | ||
| 1357 | attrIndex = ResourceIndex; | ||
| 1358 | } | ||
| 1307 | if (IsViNotDef(attrIndex)) | 1359 | if (IsViNotDef(attrIndex)) |
| 1308 | return false; | 1360 | return false; |
| 1309 | } | 1361 | } |
| @@ -1339,17 +1391,17 @@ void CNode::Parse(const Byte *p) | |||
| 1339 | G64 (0x28, access_time); | 1391 | G64 (0x28, access_time); |
| 1340 | G64 (0x30, internal_flags); | 1392 | G64 (0x30, internal_flags); |
| 1341 | { | 1393 | { |
| 1342 | G32(0x38, nchildren); | 1394 | G32 (0x38, nchildren); |
| 1343 | // G32(0x38, nlink); | 1395 | // G32 (0x38, nlink); |
| 1344 | } | 1396 | } |
| 1345 | // G32(0x3c, default_protection_class); | 1397 | // G32 (0x3c, default_protection_class); |
| 1346 | G32(0x40, write_generation_counter); | 1398 | G32 (0x40, write_generation_counter); |
| 1347 | G32(0x44, bsd_flags); | 1399 | G32 (0x44, bsd_flags); |
| 1348 | G32(0x48, owner); | 1400 | G32 (0x48, owner); |
| 1349 | G32(0x4c, group); | 1401 | G32 (0x4c, group); |
| 1350 | G16(0x50, mode); | 1402 | G16 (0x50, mode); |
| 1351 | // G16(0x52, pad1); | 1403 | // G16 (0x52, pad1); |
| 1352 | // G64 (0x54, uncompressed_size); | 1404 | G64 (0x54, uncompressed_size); |
| 1353 | } | 1405 | } |
| 1354 | 1406 | ||
| 1355 | 1407 | ||
| @@ -1364,6 +1416,7 @@ struct CRef | |||
| 1364 | bool IsAltStream() const { return IsViDef(AttrIndex); } | 1416 | bool IsAltStream() const { return IsViDef(AttrIndex); } |
| 1365 | unsigned GetAttrIndex() const { return AttrIndex; }; | 1417 | unsigned GetAttrIndex() const { return AttrIndex; }; |
| 1366 | #else | 1418 | #else |
| 1419 | // bool IsAltStream() const { return false; } | ||
| 1367 | unsigned GetAttrIndex() const { return VI_MINUS1; }; | 1420 | unsigned GetAttrIndex() const { return VI_MINUS1; }; |
| 1368 | #endif | 1421 | #endif |
| 1369 | }; | 1422 | }; |
| @@ -1667,6 +1720,7 @@ struct CDatabase | |||
| 1667 | UInt64 ProgressVal_NumFilesTotal; | 1720 | UInt64 ProgressVal_NumFilesTotal; |
| 1668 | CObjectVector<CByteBuffer> Buffers; | 1721 | CObjectVector<CByteBuffer> Buffers; |
| 1669 | 1722 | ||
| 1723 | UInt32 MethodsMask; | ||
| 1670 | UInt64 GetSize(const UInt32 index) const; | 1724 | UInt64 GetSize(const UInt32 index) const; |
| 1671 | 1725 | ||
| 1672 | void Clear() | 1726 | void Clear() |
| @@ -1678,6 +1732,8 @@ struct CDatabase | |||
| 1678 | ProgressVal_Cur = 0; | 1732 | ProgressVal_Cur = 0; |
| 1679 | ProgressVal_Prev = 0; | 1733 | ProgressVal_Prev = 0; |
| 1680 | ProgressVal_NumFilesTotal = 0; | 1734 | ProgressVal_NumFilesTotal = 0; |
| 1735 | |||
| 1736 | MethodsMask = 0; | ||
| 1681 | 1737 | ||
| 1682 | Vols.Clear(); | 1738 | Vols.Clear(); |
| 1683 | Refs2.Clear(); | 1739 | Refs2.Clear(); |
| @@ -1691,6 +1747,12 @@ struct CDatabase | |||
| 1691 | HRESULT OpenVolume(const CObjectMap &omap, const oid_t fs_oid); | 1747 | HRESULT OpenVolume(const CObjectMap &omap, const oid_t fs_oid); |
| 1692 | HRESULT Open2(); | 1748 | HRESULT Open2(); |
| 1693 | 1749 | ||
| 1750 | HRESULT GetAttrStream(IInStream *apfsInStream, const CVol &vol, | ||
| 1751 | const CAttr &attr, ISequentialInStream **stream); | ||
| 1752 | |||
| 1753 | HRESULT GetAttrStream_dstream(IInStream *apfsInStream, const CVol &vol, | ||
| 1754 | const CAttr &attr, ISequentialInStream **stream); | ||
| 1755 | |||
| 1694 | HRESULT GetStream2( | 1756 | HRESULT GetStream2( |
| 1695 | IInStream *apfsInStream, | 1757 | IInStream *apfsInStream, |
| 1696 | const CRecordVector<CExtent> *extents, UInt64 rem, | 1758 | const CRecordVector<CExtent> *extents, UInt64 rem, |
| @@ -2070,7 +2132,7 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid) | |||
| 2070 | RINOK(ReadMap(ov.paddr, map, 0)); | 2132 | RINOK(ReadMap(ov.paddr, map, 0)); |
| 2071 | } | 2133 | } |
| 2072 | 2134 | ||
| 2073 | bool NeedReadSymLink = false; | 2135 | bool needParseAttr = false; |
| 2074 | 2136 | ||
| 2075 | { | 2137 | { |
| 2076 | const bool isHashed = apfs.IsHashedName(); | 2138 | const bool isHashed = apfs.IsHashedName(); |
| @@ -2094,6 +2156,9 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid) | |||
| 2094 | } | 2156 | } |
| 2095 | } | 2157 | } |
| 2096 | 2158 | ||
| 2159 | CAttr attr; | ||
| 2160 | CItem item; | ||
| 2161 | |||
| 2097 | FOR_VECTOR (i, map.Pairs) | 2162 | FOR_VECTOR (i, map.Pairs) |
| 2098 | { | 2163 | { |
| 2099 | if (OpenCallback && (i & 0xffff) == 1) | 2164 | if (OpenCallback && (i & 0xffff) == 1) |
| @@ -2232,7 +2297,7 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid) | |||
| 2232 | if (nameOffset + len != pair.Key.Size()) | 2297 | if (nameOffset + len != pair.Key.Size()) |
| 2233 | return S_FALSE; | 2298 | return S_FALSE; |
| 2234 | 2299 | ||
| 2235 | CAttr attr; | 2300 | attr.Clear(); |
| 2236 | attr.Name.SetFrom_CalcLen((const char *)p + nameOffset, len); | 2301 | attr.Name.SetFrom_CalcLen((const char *)p + nameOffset, len); |
| 2237 | if (attr.Name.Len() != len - 1) | 2302 | if (attr.Name.Len() != len - 1) |
| 2238 | return S_FALSE; | 2303 | return S_FALSE; |
| @@ -2287,15 +2352,25 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid) | |||
| 2287 | // UnsupportedFeature = true; | 2352 | // UnsupportedFeature = true; |
| 2288 | // continue; | 2353 | // continue; |
| 2289 | } | 2354 | } |
| 2355 | |||
| 2290 | CNode &inode = vol.Nodes.Back(); | 2356 | CNode &inode = vol.Nodes.Back(); |
| 2357 | |||
| 2291 | if (attr.Name.IsEqualTo("com.apple.fs.symlink")) | 2358 | if (attr.Name.IsEqualTo("com.apple.fs.symlink")) |
| 2292 | { | 2359 | { |
| 2293 | inode.SymLinkIndex = inode.Attrs.Size(); | 2360 | inode.SymLinkIndex = inode.Attrs.Size(); |
| 2294 | if (attr.Is_dstream_OK_for_SymLink()) | 2361 | if (attr.Is_dstream_OK_for_SymLink()) |
| 2295 | NeedReadSymLink = true; | 2362 | needParseAttr = true; |
| 2363 | } | ||
| 2364 | else if (attr.Name.IsEqualTo("com.apple.decmpfs")) | ||
| 2365 | { | ||
| 2366 | inode.DecmpfsIndex = inode.Attrs.Size(); | ||
| 2367 | // if (attr.dstream_defined) | ||
| 2368 | needParseAttr = true; | ||
| 2369 | } | ||
| 2370 | else if (attr.Name.IsEqualTo("com.apple.ResourceFork")) | ||
| 2371 | { | ||
| 2372 | inode.ResourceIndex = inode.Attrs.Size(); | ||
| 2296 | } | 2373 | } |
| 2297 | else | ||
| 2298 | vol.NumAltStreams++; | ||
| 2299 | inode.Attrs.Add(attr); | 2374 | inode.Attrs.Add(attr); |
| 2300 | continue; | 2375 | continue; |
| 2301 | } | 2376 | } |
| @@ -2431,7 +2506,10 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid) | |||
| 2431 | } | 2506 | } |
| 2432 | if (nameOffset + len != pair.Key.Size()) | 2507 | if (nameOffset + len != pair.Key.Size()) |
| 2433 | return S_FALSE; | 2508 | return S_FALSE; |
| 2434 | CItem item; | 2509 | |
| 2510 | // CItem item; | ||
| 2511 | item.Clear(); | ||
| 2512 | |||
| 2435 | item.ParentId = id; | 2513 | item.ParentId = id; |
| 2436 | item.Name.SetFrom_CalcLen((const char *)p + nameOffset, len); | 2514 | item.Name.SetFrom_CalcLen((const char *)p + nameOffset, len); |
| 2437 | if (item.Name.Len() != len - 1) | 2515 | if (item.Name.Len() != len - 1) |
| @@ -2471,39 +2549,86 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid) | |||
| 2471 | ProgressVal_NumFilesTotal += vol.Items.Size(); | 2549 | ProgressVal_NumFilesTotal += vol.Items.Size(); |
| 2472 | } | 2550 | } |
| 2473 | 2551 | ||
| 2474 | if (NeedReadSymLink) | 2552 | |
| 2553 | if (needParseAttr) | ||
| 2475 | { | 2554 | { |
| 2476 | /* we read external streams for SymLinks to CAttr.Data | 2555 | /* we read external streams for attributes |
| 2477 | So we can get SymLink for GetProperty(kpidSymLink) later */ | 2556 | So we can get SymLink for GetProperty(kpidSymLink) later */ |
| 2478 | FOR_VECTOR (i, vol.Nodes) | 2557 | FOR_VECTOR (i, vol.Nodes) |
| 2479 | { | 2558 | { |
| 2480 | CNode &node = vol.Nodes[i]; | 2559 | CNode &node = vol.Nodes[i]; |
| 2481 | if (IsViNotDef(node.SymLinkIndex)) | 2560 | |
| 2482 | continue; | 2561 | FOR_VECTOR (a, node.Attrs) |
| 2483 | CAttr &attr = node.Attrs[(unsigned)node.SymLinkIndex]; | 2562 | { |
| 2484 | // FOR_VECTOR (k, node.Attrs) { CAttr &attr = node.Attrs[(unsigned)k]; // for debug | 2563 | CAttr &attr = node.Attrs[a]; |
| 2485 | if (attr.Data.Size() != 0 | 2564 | if (attr.Data.Size() != 0 || !attr.dstream_defined) |
| 2486 | || !attr.Is_dstream_OK_for_SymLink()) | 2565 | continue; |
| 2487 | continue; | 2566 | if (a == node.SymLinkIndex) |
| 2488 | const UInt32 size = (UInt32)attr.dstream.size; | 2567 | { |
| 2489 | const int idIndex = vol.SmallNodeIDs.FindInSorted(attr.Id); | 2568 | if (!attr.Is_dstream_OK_for_SymLink()) |
| 2490 | if (idIndex == -1) | 2569 | continue; |
| 2491 | continue; | 2570 | } |
| 2492 | CMyComPtr<ISequentialInStream> inStream; | 2571 | else |
| 2493 | const HRESULT res = GetStream2( | 2572 | { |
| 2494 | OpenInStream, | 2573 | if (a != node.DecmpfsIndex |
| 2495 | &vol.SmallNodes[(unsigned)idIndex].Extents, | 2574 | // && a != node.ResourceIndex |
| 2496 | size, &inStream); | 2575 | ) |
| 2497 | if (res == S_OK && inStream) | 2576 | continue; |
| 2577 | } | ||
| 2578 | // we don't expect big streams here | ||
| 2579 | // largest dstream for Decmpfs attribute is (2Kib+17) | ||
| 2580 | if (attr.dstream.size > ((UInt32)1 << 16)) | ||
| 2581 | continue; | ||
| 2582 | CMyComPtr<ISequentialInStream> inStream; | ||
| 2583 | const HRESULT res = GetAttrStream_dstream(OpenInStream, vol, attr, &inStream); | ||
| 2584 | if (res == S_OK && inStream) | ||
| 2585 | { | ||
| 2586 | CByteBuffer buf2; | ||
| 2587 | const size_t size = (size_t)attr.dstream.size; | ||
| 2588 | buf2.Alloc(size); | ||
| 2589 | if (ReadStream_FAIL(inStream, buf2, size) == S_OK) | ||
| 2590 | attr.Data = buf2; | ||
| 2591 | |||
| 2592 | ProgressVal_Cur += size; | ||
| 2593 | if (OpenCallback) | ||
| 2594 | if (ProgressVal_Cur - ProgressVal_Prev >= (1 << 22)) | ||
| 2595 | { | ||
| 2596 | |||
| 2597 | RINOK(OpenCallback->SetCompleted( | ||
| 2598 | &ProgressVal_NumFilesTotal, | ||
| 2599 | &ProgressVal_Cur)); | ||
| 2600 | ProgressVal_Prev = ProgressVal_Cur; | ||
| 2601 | } | ||
| 2602 | } | ||
| 2603 | } | ||
| 2604 | |||
| 2605 | if (node.Has_UNCOMPRESSED_SIZE()) | ||
| 2606 | if (IsViDef(node.DecmpfsIndex)) | ||
| 2498 | { | 2607 | { |
| 2499 | CByteBuffer buf2; | 2608 | CAttr &attr = node.Attrs[node.DecmpfsIndex]; |
| 2500 | buf2.Alloc(size); | 2609 | node.CompressHeader.Parse(attr.Data, attr.Data.Size()); |
| 2501 | if (ReadStream_FAIL(inStream, buf2, size) == S_OK) | 2610 | |
| 2502 | attr.Data = buf2; | 2611 | if (node.CompressHeader.IsCorrect) |
| 2612 | if (node.CompressHeader.Method < sizeof(MethodsMask) * 8) | ||
| 2613 | MethodsMask |= ((UInt32)1 << node.CompressHeader.Method); | ||
| 2614 | |||
| 2615 | if (node.CompressHeader.IsCorrect | ||
| 2616 | && node.CompressHeader.IsSupported | ||
| 2617 | && node.CompressHeader.UnpackSize == node.uncompressed_size) | ||
| 2618 | { | ||
| 2619 | attr.NeedShow = false; | ||
| 2620 | if (node.CompressHeader.IsMethod_Resource() | ||
| 2621 | && IsViDef(node.ResourceIndex)) | ||
| 2622 | node.Attrs[node.ResourceIndex].NeedShow = false; | ||
| 2623 | } | ||
| 2624 | else | ||
| 2625 | { | ||
| 2626 | vol.UnsupportedFeature = true; | ||
| 2627 | } | ||
| 2503 | } | 2628 | } |
| 2504 | } | 2629 | } |
| 2505 | } | 2630 | } |
| 2506 | 2631 | ||
| 2507 | const HRESULT res = vol.FillRefs(); | 2632 | const HRESULT res = vol.FillRefs(); |
| 2508 | 2633 | ||
| 2509 | if (vol.ThereAreErrors()) | 2634 | if (vol.ThereAreErrors()) |
| @@ -2521,9 +2646,10 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid) | |||
| 2521 | HRESULT CVol::FillRefs() | 2646 | HRESULT CVol::FillRefs() |
| 2522 | { | 2647 | { |
| 2523 | { | 2648 | { |
| 2649 | Refs.Reserve(Items.Size()); | ||
| 2524 | // we fill Refs[*] | 2650 | // we fill Refs[*] |
| 2525 | // we | 2651 | // we |
| 2526 | // and set Nodes[*].ItemIndex for Nodes that are dictories; | 2652 | // and set Nodes[*].ItemIndex for Nodes that are directories; |
| 2527 | FOR_VECTOR (i, Items) | 2653 | FOR_VECTOR (i, Items) |
| 2528 | { | 2654 | { |
| 2529 | CItem &item = Items[i]; | 2655 | CItem &item = Items[i]; |
| @@ -2593,12 +2719,17 @@ HRESULT CVol::FillRefs() | |||
| 2593 | ref.ParentRefIndex = item.RefIndex; | 2719 | ref.ParentRefIndex = item.RefIndex; |
| 2594 | for (unsigned k = 0; k < numAttrs; k++) | 2720 | for (unsigned k = 0; k < numAttrs; k++) |
| 2595 | { | 2721 | { |
| 2722 | // comment it for debug | ||
| 2723 | const CAttr &attr = inode.Attrs[k]; | ||
| 2724 | if (!attr.NeedShow) | ||
| 2725 | continue; | ||
| 2726 | |||
| 2596 | if (k == inode.SymLinkIndex) | 2727 | if (k == inode.SymLinkIndex) |
| 2597 | continue; | 2728 | continue; |
| 2598 | ref.AttrIndex = k; | 2729 | ref.AttrIndex = k; |
| 2730 | NumAltStreams++; | ||
| 2599 | Refs.Add(ref); | 2731 | Refs.Add(ref); |
| 2600 | /* | 2732 | /* |
| 2601 | const CAttr &attr = inode.Attrs[k]; | ||
| 2602 | if (attr.dstream_defined) | 2733 | if (attr.dstream_defined) |
| 2603 | { | 2734 | { |
| 2604 | const int idIndex = SmallNodeIDs.FindInSorted(attr.Id); | 2735 | const int idIndex = SmallNodeIDs.FindInSorted(attr.Id); |
| @@ -2780,6 +2911,7 @@ enum | |||
| 2780 | kpidAddTime, | 2911 | kpidAddTime, |
| 2781 | kpidGeneration, | 2912 | kpidGeneration, |
| 2782 | kpidBsdFlags | 2913 | kpidBsdFlags |
| 2914 | // kpidUncompressedSize | ||
| 2783 | }; | 2915 | }; |
| 2784 | 2916 | ||
| 2785 | static const CStatProp kProps[] = | 2917 | static const CStatProp kProps[] = |
| @@ -2793,11 +2925,13 @@ static const CStatProp kProps[] = | |||
| 2793 | { NULL, kpidATime, VT_FILETIME }, | 2925 | { NULL, kpidATime, VT_FILETIME }, |
| 2794 | { NULL, kpidChangeTime, VT_FILETIME }, | 2926 | { NULL, kpidChangeTime, VT_FILETIME }, |
| 2795 | { "Added Time", kpidAddTime, VT_FILETIME }, | 2927 | { "Added Time", kpidAddTime, VT_FILETIME }, |
| 2928 | { NULL, kpidMethod, VT_BSTR }, | ||
| 2796 | { NULL, kpidINode, VT_UI8 }, | 2929 | { NULL, kpidINode, VT_UI8 }, |
| 2797 | { NULL, kpidLinks, VT_UI4 }, | 2930 | { NULL, kpidLinks, VT_UI4 }, |
| 2798 | { NULL, kpidSymLink, VT_BSTR }, | 2931 | { NULL, kpidSymLink, VT_BSTR }, |
| 2799 | { NULL, kpidUserId, VT_UI4 }, | 2932 | { NULL, kpidUserId, VT_UI4 }, |
| 2800 | { NULL, kpidGroupId, VT_UI4 }, | 2933 | { NULL, kpidGroupId, VT_UI4 }, |
| 2934 | { NULL, kpidCharacts, VT_BSTR }, | ||
| 2801 | #ifdef APFS_SHOW_ALT_STREAMS | 2935 | #ifdef APFS_SHOW_ALT_STREAMS |
| 2802 | { NULL, kpidIsAltStream, VT_BOOL }, | 2936 | { NULL, kpidIsAltStream, VT_BOOL }, |
| 2803 | #endif | 2937 | #endif |
| @@ -2807,12 +2941,14 @@ static const CStatProp kProps[] = | |||
| 2807 | { "Written Size", kpidBytesWritten, VT_UI8 }, | 2941 | { "Written Size", kpidBytesWritten, VT_UI8 }, |
| 2808 | { "Read Size", kpidBytesRead, VT_UI8 }, | 2942 | { "Read Size", kpidBytesRead, VT_UI8 }, |
| 2809 | { "BSD Flags", kpidBsdFlags, VT_UI4 } | 2943 | { "BSD Flags", kpidBsdFlags, VT_UI4 } |
| 2944 | // , { "Uncompressed Size", kpidUncompressedSize, VT_UI8 } | ||
| 2810 | }; | 2945 | }; |
| 2811 | 2946 | ||
| 2812 | 2947 | ||
| 2813 | static const Byte kArcProps[] = | 2948 | static const Byte kArcProps[] = |
| 2814 | { | 2949 | { |
| 2815 | kpidName, | 2950 | kpidName, |
| 2951 | kpidCharacts, | ||
| 2816 | kpidId, | 2952 | kpidId, |
| 2817 | kpidClusterSize, | 2953 | kpidClusterSize, |
| 2818 | kpidCTime, | 2954 | kpidCTime, |
| @@ -2848,6 +2984,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
| 2848 | prop = (UInt64)sb.block_count << sb.block_size_Log; | 2984 | prop = (UInt64)sb.block_count << sb.block_size_Log; |
| 2849 | break; | 2985 | break; |
| 2850 | case kpidClusterSize: prop = (UInt32)(sb.block_size); break; | 2986 | case kpidClusterSize: prop = (UInt32)(sb.block_size); break; |
| 2987 | case kpidCharacts: NHfs::MethodsMaskToProp(MethodsMask, prop); break; | ||
| 2851 | case kpidMTime: | 2988 | case kpidMTime: |
| 2852 | if (apfs) | 2989 | if (apfs) |
| 2853 | ApfsTimeToProp(apfs->modified_by[0].timestamp, prop); | 2990 | ApfsTimeToProp(apfs->modified_by[0].timestamp, prop); |
| @@ -2953,7 +3090,6 @@ STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentTyp | |||
| 2953 | const CRef2 &ref2 = Refs2[index]; | 3090 | const CRef2 &ref2 = Refs2[index]; |
| 2954 | const CVol &vol = Vols[ref2.VolIndex]; | 3091 | const CVol &vol = Vols[ref2.VolIndex]; |
| 2955 | UInt32 parentIndex = (UInt32)(Int32)-1; | 3092 | UInt32 parentIndex = (UInt32)(Int32)-1; |
| 2956 | *parentType = NParentType::kDir; | ||
| 2957 | 3093 | ||
| 2958 | if (IsViDef(ref2.RefIndex)) | 3094 | if (IsViDef(ref2.RefIndex)) |
| 2959 | { | 3095 | { |
| @@ -3017,6 +3153,7 @@ void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM:: | |||
| 3017 | { | 3153 | { |
| 3018 | const CRef &ref = vol.Refs[ref2.RefIndex]; | 3154 | const CRef &ref = vol.Refs[ref2.RefIndex]; |
| 3019 | unsigned cur = ref.ItemIndex; | 3155 | unsigned cur = ref.ItemIndex; |
| 3156 | UString s2; | ||
| 3020 | if (IsViNotDef(cur)) | 3157 | if (IsViNotDef(cur)) |
| 3021 | { | 3158 | { |
| 3022 | if (inode) | 3159 | if (inode) |
| @@ -3032,14 +3169,13 @@ void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM:: | |||
| 3032 | break; | 3169 | break; |
| 3033 | } | 3170 | } |
| 3034 | const CItem &item = vol.Items[(unsigned)cur]; | 3171 | const CItem &item = vol.Items[(unsigned)cur]; |
| 3035 | UString s2; | ||
| 3036 | Utf8Name_to_InterName(item.Name, s2); | 3172 | Utf8Name_to_InterName(item.Name, s2); |
| 3037 | // s2 += "a\\b"; // for debug | 3173 | // s2 += "a\\b"; // for debug |
| 3038 | s.Insert(0, s2); | 3174 | s.Insert(0, s2); |
| 3039 | cur = item.ParentItemIndex; | 3175 | cur = item.ParentItemIndex; |
| 3040 | if (IsViNotDef(cur)) | 3176 | if (IsViNotDef(cur)) |
| 3041 | break; | 3177 | break; |
| 3042 | // ParentItemIndex was not set for sch items | 3178 | // ParentItemIndex was not set for such items |
| 3043 | // if (item.ParentId == ROOT_DIR_INO_NUM) break; | 3179 | // if (item.ParentId == ROOT_DIR_INO_NUM) break; |
| 3044 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); | 3180 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); |
| 3045 | } | 3181 | } |
| @@ -3049,7 +3185,6 @@ void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM:: | |||
| 3049 | if (IsViDef(ref.AttrIndex) && inode) | 3185 | if (IsViDef(ref.AttrIndex) && inode) |
| 3050 | { | 3186 | { |
| 3051 | s += ':'; | 3187 | s += ':'; |
| 3052 | UString s2; | ||
| 3053 | Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2); | 3188 | Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2); |
| 3054 | // s2 += "a\\b"; // for debug | 3189 | // s2 += "a\\b"; // for debug |
| 3055 | s += s2; | 3190 | s += s2; |
| @@ -3110,11 +3245,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3110 | break; | 3245 | break; |
| 3111 | case kpidPrimeName: | 3246 | case kpidPrimeName: |
| 3112 | { | 3247 | { |
| 3113 | if (inode | 3248 | #ifdef APFS_SHOW_ALT_STREAMS |
| 3114 | #ifdef APFS_SHOW_ALT_STREAMS | 3249 | if (!ref.IsAltStream()) |
| 3115 | && !ref.IsAltStream() | 3250 | #endif |
| 3116 | #endif | 3251 | if (inode && !inode->PrimaryName.IsEmpty()) |
| 3117 | && !inode->PrimaryName.IsEmpty()) | ||
| 3118 | { | 3252 | { |
| 3119 | UString s; | 3253 | UString s; |
| 3120 | ConvertUTF8ToUnicode(inode->PrimaryName, s); | 3254 | ConvertUTF8ToUnicode(inode->PrimaryName, s); |
| @@ -3155,6 +3289,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3155 | } | 3289 | } |
| 3156 | 3290 | ||
| 3157 | case kpidSymLink: | 3291 | case kpidSymLink: |
| 3292 | #ifdef APFS_SHOW_ALT_STREAMS | ||
| 3293 | if (!ref.IsAltStream()) | ||
| 3294 | #endif | ||
| 3158 | if (inode) | 3295 | if (inode) |
| 3159 | { | 3296 | { |
| 3160 | if (inode->IsSymLink() && IsViDef(inode->SymLinkIndex)) | 3297 | if (inode->IsSymLink() && IsViDef(inode->SymLinkIndex)) |
| @@ -3178,8 +3315,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3178 | case kpidSize: | 3315 | case kpidSize: |
| 3179 | if (inode) | 3316 | if (inode) |
| 3180 | { | 3317 | { |
| 3181 | UInt64 size; | 3318 | UInt64 size = 0; |
| 3182 | if (inode->GetSize(ref.GetAttrIndex(), size)) | 3319 | if (inode->GetSize(ref.GetAttrIndex(), size) || |
| 3320 | !inode->IsDir()) | ||
| 3183 | prop = size; | 3321 | prop = size; |
| 3184 | } | 3322 | } |
| 3185 | break; | 3323 | break; |
| @@ -3188,18 +3326,53 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3188 | if (inode) | 3326 | if (inode) |
| 3189 | { | 3327 | { |
| 3190 | UInt64 size; | 3328 | UInt64 size; |
| 3191 | if (inode->GetPackSize(ref.GetAttrIndex(), size)) | 3329 | if (inode->GetPackSize(ref.GetAttrIndex(), size) || |
| 3330 | !inode->IsDir()) | ||
| 3192 | prop = size; | 3331 | prop = size; |
| 3193 | } | 3332 | } |
| 3194 | break; | 3333 | break; |
| 3195 | 3334 | ||
| 3335 | case kpidMethod: | ||
| 3336 | #ifdef APFS_SHOW_ALT_STREAMS | ||
| 3337 | if (!ref.IsAltStream()) | ||
| 3338 | #endif | ||
| 3339 | if (inode) | ||
| 3340 | { | ||
| 3341 | if (inode->CompressHeader.IsCorrect) | ||
| 3342 | inode->CompressHeader.MethodToProp(prop); | ||
| 3343 | else if (IsViDef(inode->DecmpfsIndex)) | ||
| 3344 | prop = "decmpfs"; | ||
| 3345 | else if (!inode->IsDir() && !inode->dstream_defined) | ||
| 3346 | { | ||
| 3347 | if (inode->IsSymLink()) | ||
| 3348 | { | ||
| 3349 | if (IsViDef(inode->SymLinkIndex)) | ||
| 3350 | prop = "symlink"; | ||
| 3351 | } | ||
| 3352 | // else prop = "no_dstream"; | ||
| 3353 | } | ||
| 3354 | } | ||
| 3355 | break; | ||
| 3356 | |||
| 3357 | /* | ||
| 3358 | case kpidUncompressedSize: | ||
| 3359 | if (inode && inode->Has_UNCOMPRESSED_SIZE()) | ||
| 3360 | prop = inode->uncompressed_size; | ||
| 3361 | break; | ||
| 3362 | */ | ||
| 3363 | |||
| 3196 | case kpidIsDir: | 3364 | case kpidIsDir: |
| 3197 | { | 3365 | { |
| 3198 | bool isDir = false; | 3366 | bool isDir = false; |
| 3199 | if (inode) | 3367 | #ifdef APFS_SHOW_ALT_STREAMS |
| 3200 | isDir = inode->IsDir(); | 3368 | if (!ref.IsAltStream()) |
| 3201 | else if (item) | 3369 | #endif |
| 3202 | isDir = item->Val.IsFlags_Dir(); | 3370 | { |
| 3371 | if (inode) | ||
| 3372 | isDir = inode->IsDir(); | ||
| 3373 | else if (item) | ||
| 3374 | isDir = item->Val.IsFlags_Dir(); | ||
| 3375 | } | ||
| 3203 | prop = isDir; | 3376 | prop = isDir; |
| 3204 | break; | 3377 | break; |
| 3205 | } | 3378 | } |
| @@ -3251,6 +3424,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3251 | #endif | 3424 | #endif |
| 3252 | 3425 | ||
| 3253 | case kpidCharacts: | 3426 | case kpidCharacts: |
| 3427 | #ifdef APFS_SHOW_ALT_STREAMS | ||
| 3428 | if (!ref.IsAltStream()) | ||
| 3429 | #endif | ||
| 3254 | if (inode) | 3430 | if (inode) |
| 3255 | { | 3431 | { |
| 3256 | FLAGS_TO_PROP(g_INODE_Flags, (UInt32)inode->internal_flags, prop); | 3432 | FLAGS_TO_PROP(g_INODE_Flags, (UInt32)inode->internal_flags, prop); |
| @@ -3258,6 +3434,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3258 | break; | 3434 | break; |
| 3259 | 3435 | ||
| 3260 | case kpidBsdFlags: | 3436 | case kpidBsdFlags: |
| 3437 | #ifdef APFS_SHOW_ALT_STREAMS | ||
| 3438 | if (!ref.IsAltStream()) | ||
| 3439 | #endif | ||
| 3261 | if (inode) | 3440 | if (inode) |
| 3262 | { | 3441 | { |
| 3263 | FLAGS_TO_PROP(g_INODE_BSD_Flags, inode->bsd_flags, prop); | 3442 | FLAGS_TO_PROP(g_INODE_BSD_Flags, inode->bsd_flags, prop); |
| @@ -3265,6 +3444,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3265 | break; | 3444 | break; |
| 3266 | 3445 | ||
| 3267 | case kpidGeneration: | 3446 | case kpidGeneration: |
| 3447 | #ifdef APFS_SHOW_ALT_STREAMS | ||
| 3448 | // if (!ref.IsAltStream()) | ||
| 3449 | #endif | ||
| 3268 | if (inode) | 3450 | if (inode) |
| 3269 | prop = inode->write_generation_counter; | 3451 | prop = inode->write_generation_counter; |
| 3270 | break; | 3452 | break; |
| @@ -3280,6 +3462,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3280 | break; | 3462 | break; |
| 3281 | 3463 | ||
| 3282 | case kpidLinks: | 3464 | case kpidLinks: |
| 3465 | #ifdef APFS_SHOW_ALT_STREAMS | ||
| 3466 | if (!ref.IsAltStream()) | ||
| 3467 | #endif | ||
| 3283 | if (inode && !inode->IsDir()) | 3468 | if (inode && !inode->IsDir()) |
| 3284 | prop = (UInt32)inode->nlink; | 3469 | prop = (UInt32)inode->nlink; |
| 3285 | break; | 3470 | break; |
| @@ -3287,13 +3472,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 3287 | case kpidINode: | 3472 | case kpidINode: |
| 3288 | #ifdef APFS_SHOW_ALT_STREAMS | 3473 | #ifdef APFS_SHOW_ALT_STREAMS |
| 3289 | // here we can disable iNode for alt stream. | 3474 | // here we can disable iNode for alt stream. |
| 3290 | // if (!ref.IsAltStream()) | 3475 | if (!ref.IsAltStream()) |
| 3291 | #endif | 3476 | #endif |
| 3292 | if (IsViDef(ref.NodeIndex)) | 3477 | if (IsViDef(ref.NodeIndex)) |
| 3293 | prop = (UInt32)vol.NodeIDs[ref.NodeIndex]; | 3478 | prop = (UInt32)vol.NodeIDs[ref.NodeIndex]; |
| 3294 | break; | 3479 | break; |
| 3295 | 3480 | ||
| 3296 | case kpidParentINode: | 3481 | case kpidParentINode: |
| 3482 | #ifdef APFS_SHOW_ALT_STREAMS | ||
| 3483 | if (!ref.IsAltStream()) | ||
| 3484 | #endif | ||
| 3297 | if (inode) | 3485 | if (inode) |
| 3298 | prop = (UInt32)inode->parent_id; | 3486 | prop = (UInt32)inode->parent_id; |
| 3299 | break; | 3487 | break; |
| @@ -3351,6 +3539,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 3351 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); | 3539 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); |
| 3352 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | 3540 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; |
| 3353 | 3541 | ||
| 3542 | NHfs::CDecoder decoder; | ||
| 3543 | |||
| 3354 | for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) | 3544 | for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) |
| 3355 | { | 3545 | { |
| 3356 | lps->InSize = currentTotalSize; | 3546 | lps->InSize = currentTotalSize; |
| @@ -3399,15 +3589,68 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 3399 | RINOK(extractCallback->PrepareOperation(askMode)); | 3589 | RINOK(extractCallback->PrepareOperation(askMode)); |
| 3400 | int opRes = NExtract::NOperationResult::kDataError; | 3590 | int opRes = NExtract::NOperationResult::kDataError; |
| 3401 | 3591 | ||
| 3402 | CMyComPtr<ISequentialInStream> inStream; | 3592 | if (IsViDef(ref.NodeIndex)) |
| 3403 | if (GetStream(index, &inStream) == S_OK && inStream) | ||
| 3404 | { | 3593 | { |
| 3405 | RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); | 3594 | const CNode &inode = vol.Nodes[ref.NodeIndex]; |
| 3406 | opRes = NExtract::NOperationResult::kDataError; | 3595 | if ( |
| 3407 | if (copyCoderSpec->TotalSize == currentItemSize) | 3596 | #ifdef APFS_SHOW_ALT_STREAMS |
| 3408 | opRes = NExtract::NOperationResult::kOK; | 3597 | !ref.IsAltStream() && |
| 3409 | else if (copyCoderSpec->TotalSize < currentItemSize) | 3598 | #endif |
| 3410 | opRes = NExtract::NOperationResult::kUnexpectedEnd; | 3599 | !inode.dstream_defined |
| 3600 | && inode.Extents.IsEmpty() | ||
| 3601 | && inode.Has_UNCOMPRESSED_SIZE() | ||
| 3602 | && inode.uncompressed_size == inode.CompressHeader.UnpackSize) | ||
| 3603 | { | ||
| 3604 | if (inode.CompressHeader.IsSupported) | ||
| 3605 | { | ||
| 3606 | CMyComPtr<ISequentialInStream> inStreamFork; | ||
| 3607 | UInt64 forkSize = 0; | ||
| 3608 | const CByteBuffer *decmpfs_Data = NULL; | ||
| 3609 | |||
| 3610 | if (inode.CompressHeader.IsMethod_Resource()) | ||
| 3611 | { | ||
| 3612 | if (IsViDef(inode.ResourceIndex)) | ||
| 3613 | { | ||
| 3614 | const CAttr &attr = inode.Attrs[inode.ResourceIndex]; | ||
| 3615 | forkSize = attr.GetSize(); | ||
| 3616 | GetAttrStream(_stream, vol, attr, &inStreamFork); | ||
| 3617 | } | ||
| 3618 | } | ||
| 3619 | else | ||
| 3620 | { | ||
| 3621 | const CAttr &attr = inode.Attrs[inode.DecmpfsIndex]; | ||
| 3622 | decmpfs_Data = &attr.Data; | ||
| 3623 | } | ||
| 3624 | |||
| 3625 | if (inStreamFork || decmpfs_Data) | ||
| 3626 | { | ||
| 3627 | const HRESULT hres = decoder.Extract( | ||
| 3628 | inStreamFork, realOutStream, | ||
| 3629 | forkSize, | ||
| 3630 | inode.CompressHeader, | ||
| 3631 | decmpfs_Data, | ||
| 3632 | currentTotalSize, extractCallback, | ||
| 3633 | opRes); | ||
| 3634 | if (hres != S_FALSE && hres != S_OK) | ||
| 3635 | return hres; | ||
| 3636 | } | ||
| 3637 | } | ||
| 3638 | else | ||
| 3639 | opRes = NExtract::NOperationResult::kUnsupportedMethod; | ||
| 3640 | } | ||
| 3641 | else | ||
| 3642 | { | ||
| 3643 | CMyComPtr<ISequentialInStream> inStream; | ||
| 3644 | if (GetStream(index, &inStream) == S_OK && inStream) | ||
| 3645 | { | ||
| 3646 | RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); | ||
| 3647 | opRes = NExtract::NOperationResult::kDataError; | ||
| 3648 | if (copyCoderSpec->TotalSize == currentItemSize) | ||
| 3649 | opRes = NExtract::NOperationResult::kOK; | ||
| 3650 | else if (copyCoderSpec->TotalSize < currentItemSize) | ||
| 3651 | opRes = NExtract::NOperationResult::kUnexpectedEnd; | ||
| 3652 | } | ||
| 3653 | } | ||
| 3411 | } | 3654 | } |
| 3412 | 3655 | ||
| 3413 | realOutStream.Release(); | 3656 | realOutStream.Release(); |
| @@ -3478,7 +3721,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | |||
| 3478 | if (inode.IsDir()) | 3721 | if (inode.IsDir()) |
| 3479 | return S_FALSE; | 3722 | return S_FALSE; |
| 3480 | if (inode.dstream_defined) | 3723 | if (inode.dstream_defined) |
| 3724 | { | ||
| 3481 | rem = inode.dstream.size; | 3725 | rem = inode.dstream.size; |
| 3726 | } | ||
| 3727 | else | ||
| 3728 | { | ||
| 3729 | // return S_FALSE; // check it !!! How zero size files are stored with dstream_defined? | ||
| 3730 | } | ||
| 3731 | |||
| 3482 | extents = &inode.Extents; | 3732 | extents = &inode.Extents; |
| 3483 | } | 3733 | } |
| 3484 | return GetStream2(_stream, extents, rem, stream); | 3734 | return GetStream2(_stream, extents, rem, stream); |
| @@ -3486,6 +3736,35 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | |||
| 3486 | 3736 | ||
| 3487 | 3737 | ||
| 3488 | 3738 | ||
| 3739 | HRESULT CDatabase::GetAttrStream(IInStream *apfsInStream, const CVol &vol, | ||
| 3740 | const CAttr &attr, ISequentialInStream **stream) | ||
| 3741 | { | ||
| 3742 | *stream = NULL; | ||
| 3743 | if (!attr.dstream_defined) | ||
| 3744 | { | ||
| 3745 | CBufInStream *streamSpec = new CBufInStream; | ||
| 3746 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; | ||
| 3747 | streamSpec->Init(attr.Data, attr.Data.Size(), (IInArchive *)this); | ||
| 3748 | *stream = streamTemp.Detach(); | ||
| 3749 | return S_OK; | ||
| 3750 | } | ||
| 3751 | return GetAttrStream_dstream(apfsInStream, vol, attr, stream); | ||
| 3752 | } | ||
| 3753 | |||
| 3754 | |||
| 3755 | HRESULT CDatabase::GetAttrStream_dstream( IInStream *apfsInStream, const CVol &vol, | ||
| 3756 | const CAttr &attr, ISequentialInStream **stream) | ||
| 3757 | { | ||
| 3758 | const int idIndex = vol.SmallNodeIDs.FindInSorted(attr.Id); | ||
| 3759 | if (idIndex == -1) | ||
| 3760 | return S_FALSE; | ||
| 3761 | return GetStream2(apfsInStream, | ||
| 3762 | &vol.SmallNodes[(unsigned)idIndex].Extents, | ||
| 3763 | attr.dstream.size, | ||
| 3764 | stream); | ||
| 3765 | } | ||
| 3766 | |||
| 3767 | |||
| 3489 | HRESULT CDatabase::GetStream2( | 3768 | HRESULT CDatabase::GetStream2( |
| 3490 | IInStream *apfsInStream, | 3769 | IInStream *apfsInStream, |
| 3491 | const CRecordVector<CExtent> *extents, UInt64 rem, | 3770 | const CRecordVector<CExtent> *extents, UInt64 rem, |
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h index 7cba0c7..2d77366 100644 --- a/CPP/7zip/Archive/Chm/ChmIn.h +++ b/CPP/7zip/Archive/Chm/ChmIn.h | |||
| @@ -126,6 +126,7 @@ struct CLzxInfo | |||
| 126 | CLzxInfo(): | 126 | CLzxInfo(): |
| 127 | Version(0), | 127 | Version(0), |
| 128 | ResetIntervalBits(0), | 128 | ResetIntervalBits(0), |
| 129 | WindowSizeBits(0), | ||
| 129 | CacheSize(0) | 130 | CacheSize(0) |
| 130 | {} | 131 | {} |
| 131 | 132 | ||
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp index 1f2ca26..e6166f1 100644 --- a/CPP/7zip/Archive/DmgHandler.cpp +++ b/CPP/7zip/Archive/DmgHandler.cpp | |||
| @@ -1063,6 +1063,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 1063 | subName.DeleteFrom(pos1); | 1063 | subName.DeleteFrom(pos1); |
| 1064 | } | 1064 | } |
| 1065 | } | 1065 | } |
| 1066 | else | ||
| 1067 | subName = item.Name; // new apfs dmg can be without braces | ||
| 1066 | subName.Trim(); | 1068 | subName.Trim(); |
| 1067 | if (!subName.IsEmpty()) | 1069 | if (!subName.IsEmpty()) |
| 1068 | { | 1070 | { |
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index f0a85f1..fa96b73 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp | |||
| @@ -7,19 +7,19 @@ | |||
| 7 | #include "../../Common/ComTry.h" | 7 | #include "../../Common/ComTry.h" |
| 8 | #include "../../Common/MyString.h" | 8 | #include "../../Common/MyString.h" |
| 9 | 9 | ||
| 10 | #include "../../Windows/PropVariant.h" | 10 | #include "../../Windows/PropVariantUtils.h" |
| 11 | 11 | ||
| 12 | #include "../Common/LimitedStreams.h" | 12 | #include "../Common/LimitedStreams.h" |
| 13 | #include "../Common/RegisterArc.h" | 13 | #include "../Common/RegisterArc.h" |
| 14 | #include "../Common/StreamObjects.h" | 14 | #include "../Common/StreamObjects.h" |
| 15 | #include "../Common/StreamUtils.h" | 15 | #include "../Common/StreamUtils.h" |
| 16 | 16 | ||
| 17 | #include "../Compress/ZlibDecoder.h" | 17 | #include "HfsHandler.h" |
| 18 | 18 | ||
| 19 | /* if HFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files | 19 | /* if HFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files |
| 20 | and resource forks. In most cases it looks useless. So we disable it. */ | 20 | and resource forks. In most cases it looks useless. So we disable it. */ |
| 21 | 21 | ||
| 22 | // #define HFS_SHOW_ALT_STREAMS | 22 | #define HFS_SHOW_ALT_STREAMS |
| 23 | 23 | ||
| 24 | #define Get16(p) GetBe16(p) | 24 | #define Get16(p) GetBe16(p) |
| 25 | #define Get32(p) GetBe32(p) | 25 | #define Get32(p) GetBe32(p) |
| @@ -80,6 +80,8 @@ struct CFork | |||
| 80 | }; | 80 | }; |
| 81 | 81 | ||
| 82 | static const unsigned kNumFixedExtents = 8; | 82 | static const unsigned kNumFixedExtents = 8; |
| 83 | static const unsigned kForkRecSize = 16 + kNumFixedExtents * 8; | ||
| 84 | |||
| 83 | 85 | ||
| 84 | void CFork::Parse(const Byte *p) | 86 | void CFork::Parse(const Byte *p) |
| 85 | { | 87 | { |
| @@ -227,6 +229,121 @@ enum ERecordType | |||
| 227 | RECORD_TYPE_FILE_THREAD | 229 | RECORD_TYPE_FILE_THREAD |
| 228 | }; | 230 | }; |
| 229 | 231 | ||
| 232 | |||
| 233 | |||
| 234 | // static const UInt32 kMethod_1_NO_COMPRESSION = 1; // in xattr | ||
| 235 | static const UInt32 kMethod_ZLIB_ATTR = 3; | ||
| 236 | static const UInt32 kMethod_ZLIB_RSRC = 4; | ||
| 237 | // static const UInt32 kMethod_DEDUP = 5; // de-dup within the generation store | ||
| 238 | // macos 10.10 | ||
| 239 | static const UInt32 kMethod_LZVN_ATTR = 7; | ||
| 240 | static const UInt32 kMethod_LZVN_RSRC = 8; | ||
| 241 | static const UInt32 kMethod_COPY_ATTR = 9; | ||
| 242 | static const UInt32 kMethod_COPY_RSRC = 10; | ||
| 243 | // macos 10.11 | ||
| 244 | // static const UInt32 kMethod_LZFSE_ATTR = 11; | ||
| 245 | static const UInt32 kMethod_LZFSE_RSRC = 12; | ||
| 246 | |||
| 247 | static const char * const g_Methods[] = | ||
| 248 | { | ||
| 249 | NULL | ||
| 250 | , NULL | ||
| 251 | , NULL | ||
| 252 | , "ZLIB-attr" | ||
| 253 | , "ZLIB-rsrc" | ||
| 254 | , NULL | ||
| 255 | , NULL | ||
| 256 | , "LZVN-attr" | ||
| 257 | , "LZVN-rsrc" | ||
| 258 | , "COPY-attr" | ||
| 259 | , "COPY-rsrc" | ||
| 260 | , "LZFSE-attr" | ||
| 261 | , "LZFSE-rsrc" | ||
| 262 | }; | ||
| 263 | |||
| 264 | |||
| 265 | static const Byte k_COPY_Uncompressed_Marker = 0xcc; | ||
| 266 | static const Byte k_LZVN_Uncompressed_Marker = 6; | ||
| 267 | |||
| 268 | void CCompressHeader::Parse(const Byte *p, size_t dataSize) | ||
| 269 | { | ||
| 270 | Clear(); | ||
| 271 | |||
| 272 | if (dataSize < k_decmpfs_HeaderSize) | ||
| 273 | return; | ||
| 274 | if (GetUi32(p) != 0x636D7066) // magic == "fpmc" | ||
| 275 | return; | ||
| 276 | Method = GetUi32(p + 4); | ||
| 277 | UnpackSize = GetUi64(p + 8); | ||
| 278 | dataSize -= k_decmpfs_HeaderSize; | ||
| 279 | IsCorrect = true; | ||
| 280 | |||
| 281 | if ( Method == kMethod_ZLIB_RSRC | ||
| 282 | || Method == kMethod_COPY_RSRC | ||
| 283 | || Method == kMethod_LZVN_RSRC | ||
| 284 | || Method == kMethod_LZFSE_RSRC) | ||
| 285 | { | ||
| 286 | IsResource = true; | ||
| 287 | if (dataSize == 0) | ||
| 288 | IsSupported = ( | ||
| 289 | Method != kMethod_LZFSE_RSRC && | ||
| 290 | Method != kMethod_COPY_RSRC); | ||
| 291 | return; | ||
| 292 | } | ||
| 293 | |||
| 294 | if ( Method == kMethod_ZLIB_ATTR | ||
| 295 | || Method == kMethod_COPY_ATTR | ||
| 296 | || Method == kMethod_LZVN_ATTR | ||
| 297 | // || Method == kMethod_LZFSE_ATTR | ||
| 298 | ) | ||
| 299 | { | ||
| 300 | if (dataSize == 0) | ||
| 301 | return; | ||
| 302 | const Byte b = p[k_decmpfs_HeaderSize]; | ||
| 303 | if ( (Method == kMethod_ZLIB_ATTR && (b & 0xf) == 0xf) | ||
| 304 | || (Method == kMethod_COPY_ATTR && b == k_COPY_Uncompressed_Marker) | ||
| 305 | || (Method == kMethod_LZVN_ATTR && b == k_LZVN_Uncompressed_Marker)) | ||
| 306 | { | ||
| 307 | dataSize--; | ||
| 308 | // if (UnpackSize > dataSize) | ||
| 309 | if (UnpackSize != dataSize) | ||
| 310 | return; | ||
| 311 | DataPos = k_decmpfs_HeaderSize + 1; | ||
| 312 | IsSupported = true; | ||
| 313 | } | ||
| 314 | else | ||
| 315 | { | ||
| 316 | if (Method != kMethod_COPY_ATTR) | ||
| 317 | IsSupported = true; | ||
| 318 | DataPos = k_decmpfs_HeaderSize; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | |||
| 324 | void CCompressHeader::MethodToProp(NWindows::NCOM::CPropVariant &prop) const | ||
| 325 | { | ||
| 326 | if (!IsCorrect) | ||
| 327 | return; | ||
| 328 | const UInt32 method = Method; | ||
| 329 | const char *p = NULL; | ||
| 330 | if (method < ARRAY_SIZE(g_Methods)) | ||
| 331 | p = g_Methods[method]; | ||
| 332 | AString s; | ||
| 333 | if (p) | ||
| 334 | s = p; | ||
| 335 | else | ||
| 336 | s.Add_UInt32(method); | ||
| 337 | // if (!IsSupported) s += "-unsuported"; | ||
| 338 | prop = s; | ||
| 339 | } | ||
| 340 | |||
| 341 | void MethodsMaskToProp(UInt32 methodsMask, NWindows::NCOM::CPropVariant &prop) | ||
| 342 | { | ||
| 343 | FLAGS_TO_PROP(g_Methods, methodsMask, prop); | ||
| 344 | } | ||
| 345 | |||
| 346 | |||
| 230 | struct CItem | 347 | struct CItem |
| 231 | { | 348 | { |
| 232 | UString Name; | 349 | UString Name; |
| @@ -265,54 +382,79 @@ struct CItem | |||
| 265 | CFork DataFork; | 382 | CFork DataFork; |
| 266 | CFork ResourceFork; | 383 | CFork ResourceFork; |
| 267 | 384 | ||
| 268 | // for compressed attribute | 385 | // for compressed attribute (decmpfs) |
| 269 | UInt64 UnpackSize; | 386 | int decmpfs_AttrIndex; |
| 270 | size_t DataPos; | 387 | CCompressHeader CompressHeader; |
| 271 | UInt32 PackSize; | ||
| 272 | unsigned Method; | ||
| 273 | bool UseAttr; | ||
| 274 | bool UseInlineData; | ||
| 275 | 388 | ||
| 276 | CItem(): UseAttr(false), UseInlineData(false) {} | 389 | CItem(): |
| 390 | decmpfs_AttrIndex(-1) | ||
| 391 | {} | ||
| 277 | bool IsDir() const { return Type == RECORD_TYPE_FOLDER; } | 392 | bool IsDir() const { return Type == RECORD_TYPE_FOLDER; } |
| 278 | const CFork &GetFork(bool isResource) const { return (const CFork & )*(isResource ? &ResourceFork: &DataFork ); } | 393 | // const CFork *GetFork(bool isResource) const { return (isResource ? &ResourceFork: &DataFork); } |
| 279 | }; | 394 | }; |
| 280 | 395 | ||
| 396 | |||
| 281 | struct CAttr | 397 | struct CAttr |
| 282 | { | 398 | { |
| 283 | UInt32 ID; | 399 | UInt32 ID; |
| 284 | UInt32 Size; | 400 | bool Fork_defined; |
| 285 | size_t Pos; | 401 | |
| 402 | // UInt32 Size; // for (Fork_defined == false) case | ||
| 403 | // size_t DataPos; // for (Fork_defined == false) case | ||
| 404 | CByteBuffer Data; | ||
| 405 | |||
| 406 | CFork Fork; | ||
| 407 | |||
| 286 | UString Name; | 408 | UString Name; |
| 409 | |||
| 410 | UInt64 GetSize() const | ||
| 411 | { | ||
| 412 | if (Fork_defined) | ||
| 413 | return Fork.Size; | ||
| 414 | return Data.Size(); | ||
| 415 | } | ||
| 416 | |||
| 417 | CAttr(): | ||
| 418 | Fork_defined(false) | ||
| 419 | // Size(0), | ||
| 420 | // DataPos(0), | ||
| 421 | {} | ||
| 287 | }; | 422 | }; |
| 288 | 423 | ||
| 424 | |||
| 425 | static const int kAttrIndex_Item = -1; | ||
| 426 | static const int kAttrIndex_Resource = -2; | ||
| 427 | |||
| 289 | struct CRef | 428 | struct CRef |
| 290 | { | 429 | { |
| 291 | unsigned ItemIndex; | 430 | unsigned ItemIndex; |
| 292 | int AttrIndex; | 431 | int AttrIndex; |
| 293 | int Parent; | 432 | int Parent; |
| 294 | bool IsResource; | ||
| 295 | 433 | ||
| 296 | bool IsAltStream() const { return IsResource || AttrIndex >= 0; } | 434 | CRef(): AttrIndex(kAttrIndex_Item), Parent(-1) {} |
| 297 | CRef(): AttrIndex(-1), Parent(-1), IsResource(false) {} | 435 | bool IsResource() const { return AttrIndex == kAttrIndex_Resource; } |
| 436 | bool IsAltStream() const { return AttrIndex != kAttrIndex_Item; } | ||
| 437 | bool IsItem() const { return AttrIndex == kAttrIndex_Item; } | ||
| 298 | }; | 438 | }; |
| 299 | 439 | ||
| 440 | |||
| 300 | class CDatabase | 441 | class CDatabase |
| 301 | { | 442 | { |
| 302 | HRESULT ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream); | 443 | HRESULT ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream); |
| 303 | HRESULT LoadExtentFile(const CFork &fork, IInStream *inStream, CObjectVector<CIdExtents> *overflowExtentsArray); | 444 | HRESULT LoadExtentFile(const CFork &fork, IInStream *inStream, CObjectVector<CIdExtents> *overflowExtentsArray); |
| 304 | HRESULT LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress); | 445 | HRESULT LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress); |
| 305 | HRESULT LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress); | 446 | HRESULT LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress); |
| 306 | bool Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip); | 447 | bool Parse_decmpgfs(unsigned attrIndex, CItem &item, bool &skip); |
| 307 | public: | 448 | public: |
| 308 | CRecordVector<CRef> Refs; | 449 | CRecordVector<CRef> Refs; |
| 309 | CObjectVector<CItem> Items; | 450 | CObjectVector<CItem> Items; |
| 310 | CObjectVector<CAttr> Attrs; | 451 | CObjectVector<CAttr> Attrs; |
| 311 | 452 | ||
| 312 | CByteBuffer AttrBuf; | 453 | // CByteBuffer AttrBuf; |
| 313 | 454 | ||
| 314 | CVolHeader Header; | 455 | CVolHeader Header; |
| 315 | bool HeadersError; | 456 | bool HeadersError; |
| 457 | bool UnsupportedFeature; | ||
| 316 | bool ThereAreAltStreams; | 458 | bool ThereAreAltStreams; |
| 317 | // bool CaseSensetive; | 459 | // bool CaseSensetive; |
| 318 | UString ResFileName; | 460 | UString ResFileName; |
| @@ -321,6 +463,7 @@ public: | |||
| 321 | UInt64 PhySize; | 463 | UInt64 PhySize; |
| 322 | UInt64 PhySize2; | 464 | UInt64 PhySize2; |
| 323 | UInt64 ArcFileSize; | 465 | UInt64 ArcFileSize; |
| 466 | UInt32 MethodsMask; | ||
| 324 | 467 | ||
| 325 | void Clear() | 468 | void Clear() |
| 326 | { | 469 | { |
| @@ -328,25 +471,30 @@ public: | |||
| 328 | PhySize = 0; | 471 | PhySize = 0; |
| 329 | PhySize2 = 0; | 472 | PhySize2 = 0; |
| 330 | ArcFileSize = 0; | 473 | ArcFileSize = 0; |
| 474 | MethodsMask = 0; | ||
| 331 | HeadersError = false; | 475 | HeadersError = false; |
| 476 | UnsupportedFeature = false; | ||
| 332 | ThereAreAltStreams = false; | 477 | ThereAreAltStreams = false; |
| 333 | // CaseSensetive = false; | 478 | // CaseSensetive = false; |
| 479 | |||
| 334 | Refs.Clear(); | 480 | Refs.Clear(); |
| 335 | Items.Clear(); | 481 | Items.Clear(); |
| 336 | Attrs.Clear(); | 482 | Attrs.Clear(); |
| 337 | AttrBuf.Free(); | 483 | // AttrBuf.Free(); |
| 338 | } | 484 | } |
| 339 | 485 | ||
| 340 | UInt64 Get_UnpackSize_of_Ref(const CRef &ref) const | 486 | UInt64 Get_UnpackSize_of_Ref(const CRef &ref) const |
| 341 | { | 487 | { |
| 342 | if (ref.AttrIndex >= 0) | 488 | if (ref.AttrIndex >= 0) |
| 343 | return Attrs[ref.AttrIndex].Size; | 489 | return Attrs[ref.AttrIndex].GetSize(); |
| 344 | const CItem &item = Items[ref.ItemIndex]; | 490 | const CItem &item = Items[ref.ItemIndex]; |
| 491 | if (ref.IsResource()) | ||
| 492 | return item.ResourceFork.Size; | ||
| 345 | if (item.IsDir()) | 493 | if (item.IsDir()) |
| 346 | return 0; | 494 | return 0; |
| 347 | if (item.UseAttr) | 495 | else if (item.CompressHeader.IsCorrect) |
| 348 | return item.UnpackSize; | 496 | return item.CompressHeader.UnpackSize; |
| 349 | return item.GetFork(ref.IsResource).Size; | 497 | return item.DataFork.Size; |
| 350 | } | 498 | } |
| 351 | 499 | ||
| 352 | void GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path) const; | 500 | void GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path) const; |
| @@ -380,7 +528,7 @@ void CDatabase::GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path) | |||
| 380 | const CRef &ref = Refs[cur]; | 528 | const CRef &ref = Refs[cur]; |
| 381 | const UString *s; | 529 | const UString *s; |
| 382 | 530 | ||
| 383 | if (ref.IsResource) | 531 | if (ref.IsResource()) |
| 384 | s = &ResFileName; | 532 | s = &ResFileName; |
| 385 | else if (ref.AttrIndex >= 0) | 533 | else if (ref.AttrIndex >= 0) |
| 386 | s = &Attrs[ref.AttrIndex].Name; | 534 | s = &Attrs[ref.AttrIndex].Name; |
| @@ -405,7 +553,7 @@ void CDatabase::GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path) | |||
| 405 | const UString *s; | 553 | const UString *s; |
| 406 | wchar_t delimChar = L':'; | 554 | wchar_t delimChar = L':'; |
| 407 | 555 | ||
| 408 | if (ref.IsResource) | 556 | if (ref.IsResource()) |
| 409 | s = &ResFileName; | 557 | s = &ResFileName; |
| 410 | else if (ref.AttrIndex >= 0) | 558 | else if (ref.AttrIndex >= 0) |
| 411 | s = &Attrs[ref.AttrIndex].Name; | 559 | s = &Attrs[ref.AttrIndex].Name; |
| @@ -596,6 +744,8 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec | |||
| 596 | UInt32 node = hr.FirstLeafNode; | 744 | UInt32 node = hr.FirstLeafNode; |
| 597 | if (node == 0) | 745 | if (node == 0) |
| 598 | return S_OK; | 746 | return S_OK; |
| 747 | if (hr.TotalNodes == 0) | ||
| 748 | return S_FALSE; | ||
| 599 | 749 | ||
| 600 | CByteArr usedBuf(hr.TotalNodes); | 750 | CByteArr usedBuf(hr.TotalNodes); |
| 601 | memset(usedBuf, 0, hr.TotalNodes); | 751 | memset(usedBuf, 0, hr.TotalNodes); |
| @@ -617,7 +767,7 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec | |||
| 617 | 767 | ||
| 618 | for (unsigned i = 0; i < desc.NumRecords; i++) | 768 | for (unsigned i = 0; i < desc.NumRecords; i++) |
| 619 | { | 769 | { |
| 620 | const UInt32 nodeSize = (1 << hr.NodeSizeLog); | 770 | const UInt32 nodeSize = ((UInt32)1 << hr.NodeSizeLog); |
| 621 | const Byte *r = p + nodeOffset + nodeSize - i * 2; | 771 | const Byte *r = p + nodeOffset + nodeSize - i * 2; |
| 622 | const UInt32 offs = Get16(r - 2); | 772 | const UInt32 offs = Get16(r - 2); |
| 623 | UInt32 recSize = Get16(r - 4) - offs; | 773 | UInt32 recSize = Get16(r - 4) - offs; |
| @@ -630,7 +780,7 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec | |||
| 630 | if (Get16(r) != kKeyLen) | 780 | if (Get16(r) != kKeyLen) |
| 631 | return S_FALSE; | 781 | return S_FALSE; |
| 632 | 782 | ||
| 633 | Byte forkType = r[2]; | 783 | const Byte forkType = r[2]; |
| 634 | unsigned forkTypeIndex; | 784 | unsigned forkTypeIndex; |
| 635 | if (forkType == kExtentForkType_Data) | 785 | if (forkType == kExtentForkType_Data) |
| 636 | forkTypeIndex = 0; | 786 | forkTypeIndex = 0; |
| @@ -640,8 +790,8 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec | |||
| 640 | continue; | 790 | continue; |
| 641 | CObjectVector<CIdExtents> &overflowExtents = overflowExtentsArray[forkTypeIndex]; | 791 | CObjectVector<CIdExtents> &overflowExtents = overflowExtentsArray[forkTypeIndex]; |
| 642 | 792 | ||
| 643 | UInt32 id = Get32(r + 4); | 793 | const UInt32 id = Get32(r + 4); |
| 644 | UInt32 startBlock = Get32(r + 8); | 794 | const UInt32 startBlock = Get32(r + 8); |
| 645 | r += 2 + kKeyLen; | 795 | r += 2 + kKeyLen; |
| 646 | 796 | ||
| 647 | bool needNew = true; | 797 | bool needNew = true; |
| @@ -691,7 +841,7 @@ static void LoadName(const Byte *data, unsigned len, UString &dest) | |||
| 691 | unsigned i; | 841 | unsigned i; |
| 692 | for (i = 0; i < len; i++) | 842 | for (i = 0; i < len; i++) |
| 693 | { | 843 | { |
| 694 | wchar_t c = Get16(data + i * 2); | 844 | const wchar_t c = Get16(data + i * 2); |
| 695 | if (c == 0) | 845 | if (c == 0) |
| 696 | break; | 846 | break; |
| 697 | p[i] = c; | 847 | p[i] = c; |
| @@ -704,7 +854,7 @@ static bool IsNameEqualTo(const Byte *data, const char *name) | |||
| 704 | { | 854 | { |
| 705 | for (unsigned i = 0;; i++) | 855 | for (unsigned i = 0;; i++) |
| 706 | { | 856 | { |
| 707 | char c = name[i]; | 857 | const char c = name[i]; |
| 708 | if (c == 0) | 858 | if (c == 0) |
| 709 | return true; | 859 | return true; |
| 710 | if (Get16(data + i * 2) != (Byte)c) | 860 | if (Get16(data + i * 2) != (Byte)c) |
| @@ -713,7 +863,7 @@ static bool IsNameEqualTo(const Byte *data, const char *name) | |||
| 713 | } | 863 | } |
| 714 | 864 | ||
| 715 | static const UInt32 kAttrRecordType_Inline = 0x10; | 865 | static const UInt32 kAttrRecordType_Inline = 0x10; |
| 716 | // static const UInt32 kAttrRecordType_Fork = 0x20; | 866 | static const UInt32 kAttrRecordType_Fork = 0x20; |
| 717 | // static const UInt32 kAttrRecordType_Extents = 0x30; | 867 | // static const UInt32 kAttrRecordType_Extents = 0x30; |
| 718 | 868 | ||
| 719 | HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress) | 869 | HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress) |
| @@ -721,6 +871,7 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe | |||
| 721 | if (fork.NumBlocks == 0) | 871 | if (fork.NumBlocks == 0) |
| 722 | return S_OK; | 872 | return S_OK; |
| 723 | 873 | ||
| 874 | CByteBuffer AttrBuf; | ||
| 724 | RINOK(ReadFile(fork, AttrBuf, inStream)); | 875 | RINOK(ReadFile(fork, AttrBuf, inStream)); |
| 725 | const Byte *p = (const Byte *)AttrBuf; | 876 | const Byte *p = (const Byte *)AttrBuf; |
| 726 | 877 | ||
| @@ -734,7 +885,9 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe | |||
| 734 | UInt32 node = hr.FirstLeafNode; | 885 | UInt32 node = hr.FirstLeafNode; |
| 735 | if (node == 0) | 886 | if (node == 0) |
| 736 | return S_OK; | 887 | return S_OK; |
| 737 | 888 | if (hr.TotalNodes == 0) | |
| 889 | return S_FALSE; | ||
| 890 | |||
| 738 | CByteArr usedBuf(hr.TotalNodes); | 891 | CByteArr usedBuf(hr.TotalNodes); |
| 739 | memset(usedBuf, 0, hr.TotalNodes); | 892 | memset(usedBuf, 0, hr.TotalNodes); |
| 740 | 893 | ||
| @@ -755,7 +908,7 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe | |||
| 755 | 908 | ||
| 756 | for (unsigned i = 0; i < desc.NumRecords; i++) | 909 | for (unsigned i = 0; i < desc.NumRecords; i++) |
| 757 | { | 910 | { |
| 758 | const UInt32 nodeSize = (1 << hr.NodeSizeLog); | 911 | const UInt32 nodeSize = ((UInt32)1 << hr.NodeSizeLog); |
| 759 | const Byte *r = p + nodeOffset + nodeSize - i * 2; | 912 | const Byte *r = p + nodeOffset + nodeSize - i * 2; |
| 760 | const UInt32 offs = Get16(r - 2); | 913 | const UInt32 offs = Get16(r - 2); |
| 761 | UInt32 recSize = Get16(r - 4) - offs; | 914 | UInt32 recSize = Get16(r - 4) - offs; |
| @@ -764,18 +917,18 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe | |||
| 764 | return S_FALSE; | 917 | return S_FALSE; |
| 765 | 918 | ||
| 766 | r = p + nodeOffset + offs; | 919 | r = p + nodeOffset + offs; |
| 767 | UInt32 keyLen = Get16(r); | 920 | const UInt32 keyLen = Get16(r); |
| 768 | 921 | ||
| 769 | // UInt16 pad = Get16(r + 2); | 922 | // UInt16 pad = Get16(r + 2); |
| 770 | UInt32 fileID = Get32(r + 4); | 923 | const UInt32 fileID = Get32(r + 4); |
| 771 | unsigned startBlock = Get32(r + 8); | 924 | const unsigned startBlock = Get32(r + 8); |
| 772 | if (startBlock != 0) | 925 | if (startBlock != 0) |
| 773 | { | 926 | { |
| 774 | // that case is still unsupported | 927 | // that case is still unsupported |
| 775 | HeadersError = true; | 928 | UnsupportedFeature = true; |
| 776 | continue; | 929 | continue; |
| 777 | } | 930 | } |
| 778 | unsigned nameLen = Get16(r + 12); | 931 | const unsigned nameLen = Get16(r + 12); |
| 779 | 932 | ||
| 780 | if (keyLen + 2 > recSize || | 933 | if (keyLen + 2 > recSize || |
| 781 | keyLen != kHeadSize - 2 + nameLen * 2) | 934 | keyLen != kHeadSize - 2 + nameLen * 2) |
| @@ -790,36 +943,56 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe | |||
| 790 | if (recSize < 4) | 943 | if (recSize < 4) |
| 791 | return S_FALSE; | 944 | return S_FALSE; |
| 792 | 945 | ||
| 793 | UInt32 recordType = Get32(r); | 946 | const UInt32 recordType = Get32(r); |
| 794 | if (recordType != kAttrRecordType_Inline) | 947 | |
| 948 | if (progress && (Attrs.Size() & 0xFFF) == 0) | ||
| 795 | { | 949 | { |
| 796 | // Probably only kAttrRecordType_Inline now is used in real HFS files | 950 | const UInt64 numFiles = 0; |
| 797 | HeadersError = true; | 951 | RINOK(progress->SetCompleted(&numFiles, NULL)); |
| 798 | continue; | ||
| 799 | } | 952 | } |
| 800 | 953 | ||
| 801 | const UInt32 kRecordHeaderSize = 16; | 954 | if (Attrs.Size() >= ((UInt32)1 << 31)) |
| 802 | if (recSize < kRecordHeaderSize) | ||
| 803 | return S_FALSE; | ||
| 804 | UInt32 dataSize = Get32(r + 12); | ||
| 805 | |||
| 806 | r += kRecordHeaderSize; | ||
| 807 | recSize -= kRecordHeaderSize; | ||
| 808 | |||
| 809 | if (recSize < dataSize) | ||
| 810 | return S_FALSE; | 955 | return S_FALSE; |
| 811 | 956 | ||
| 812 | CAttr &attr = Attrs.AddNew(); | 957 | CAttr &attr = Attrs.AddNew(); |
| 813 | attr.ID = fileID; | 958 | attr.ID = fileID; |
| 814 | attr.Pos = nodeOffset + offs + 2 + keyLen + kRecordHeaderSize; | ||
| 815 | attr.Size = dataSize; | ||
| 816 | LoadName(name, nameLen, attr.Name); | 959 | LoadName(name, nameLen, attr.Name); |
| 817 | 960 | ||
| 818 | if (progress && (i & 0xFFF) == 0) | 961 | if (recordType == kAttrRecordType_Fork) |
| 819 | { | 962 | { |
| 820 | const UInt64 numFiles = 0; | 963 | // 22.00 : some hfs files contain it; |
| 821 | RINOK(progress->SetCompleted(&numFiles, NULL)); | 964 | /* spec: If the attribute has more than 8 extents, there will be additional |
| 965 | records (of type kAttrRecordType_Extents) for this attribute. */ | ||
| 966 | if (recSize != 8 + kForkRecSize) | ||
| 967 | return S_FALSE; | ||
| 968 | if (Get32(r + 4) != 0) // reserved | ||
| 969 | return S_FALSE; | ||
| 970 | attr.Fork.Parse(r + 8); | ||
| 971 | attr.Fork_defined = true; | ||
| 972 | continue; | ||
| 973 | } | ||
| 974 | else if (recordType != kAttrRecordType_Inline) | ||
| 975 | { | ||
| 976 | UnsupportedFeature = true; | ||
| 977 | continue; | ||
| 822 | } | 978 | } |
| 979 | |||
| 980 | const unsigned kRecordHeaderSize = 16; | ||
| 981 | if (recSize < kRecordHeaderSize) | ||
| 982 | return S_FALSE; | ||
| 983 | if (Get32(r + 4) != 0 || Get32(r + 8) != 0) // reserved | ||
| 984 | return S_FALSE; | ||
| 985 | const UInt32 dataSize = Get32(r + 12); | ||
| 986 | |||
| 987 | r += kRecordHeaderSize; | ||
| 988 | recSize -= kRecordHeaderSize; | ||
| 989 | |||
| 990 | if (recSize < dataSize) | ||
| 991 | return S_FALSE; | ||
| 992 | |||
| 993 | attr.Data.CopyFrom(r, dataSize); | ||
| 994 | // attr.DataPos = nodeOffset + offs + 2 + keyLen + kRecordHeaderSize; | ||
| 995 | // attr.Size = dataSize; | ||
| 823 | } | 996 | } |
| 824 | 997 | ||
| 825 | node = desc.fLink; | 998 | node = desc.fLink; |
| @@ -827,62 +1000,28 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe | |||
| 827 | return S_OK; | 1000 | return S_OK; |
| 828 | } | 1001 | } |
| 829 | 1002 | ||
| 830 | static const UInt32 kMethod_Attr = 3; // data stored in attribute file | ||
| 831 | static const UInt32 kMethod_Resource = 4; // data stored in resource fork | ||
| 832 | 1003 | ||
| 833 | bool CDatabase::Parse_decmpgfs(const CAttr &attr, CItem &item, bool &skip) | 1004 | bool CDatabase::Parse_decmpgfs(unsigned attrIndex, CItem &item, bool &skip) |
| 834 | { | 1005 | { |
| 1006 | const CAttr &attr = Attrs[attrIndex]; | ||
| 835 | skip = false; | 1007 | skip = false; |
| 836 | if (!attr.Name.IsEqualTo("com.apple.decmpfs")) | 1008 | if (item.CompressHeader.IsCorrect || !item.DataFork.IsEmpty()) |
| 837 | return true; | ||
| 838 | if (item.UseAttr || !item.DataFork.IsEmpty()) | ||
| 839 | return false; | 1009 | return false; |
| 840 | 1010 | ||
| 841 | const UInt32 k_decmpfs_headerSize = 16; | 1011 | item.CompressHeader.Parse(attr.Data, attr.Data.Size()); |
| 842 | UInt32 dataSize = attr.Size; | 1012 | |
| 843 | if (dataSize < k_decmpfs_headerSize) | 1013 | if (item.CompressHeader.IsCorrect) |
| 844 | return false; | ||
| 845 | const Byte *r = AttrBuf + attr.Pos; | ||
| 846 | if (GetUi32(r) != 0x636D7066) // magic == "fpmc" | ||
| 847 | return false; | ||
| 848 | item.Method = GetUi32(r + 4); | ||
| 849 | item.UnpackSize = GetUi64(r + 8); | ||
| 850 | dataSize -= k_decmpfs_headerSize; | ||
| 851 | r += k_decmpfs_headerSize; | ||
| 852 | if (item.Method == kMethod_Resource) | ||
| 853 | { | 1014 | { |
| 854 | if (dataSize != 0) | 1015 | item.decmpfs_AttrIndex = attrIndex; |
| 855 | return false; | 1016 | skip = true; |
| 856 | item.UseAttr = true; | 1017 | if (item.CompressHeader.Method < sizeof(MethodsMask) * 8) |
| 1018 | MethodsMask |= ((UInt32)1 << item.CompressHeader.Method); | ||
| 857 | } | 1019 | } |
| 858 | else if (item.Method == kMethod_Attr) | 1020 | |
| 859 | { | ||
| 860 | if (dataSize == 0) | ||
| 861 | return false; | ||
| 862 | Byte b = r[0]; | ||
| 863 | if ((b & 0xF) == 0xF) | ||
| 864 | { | ||
| 865 | dataSize--; | ||
| 866 | if (item.UnpackSize > dataSize) | ||
| 867 | return false; | ||
| 868 | item.DataPos = attr.Pos + k_decmpfs_headerSize + 1; | ||
| 869 | item.PackSize = dataSize; | ||
| 870 | item.UseAttr = true; | ||
| 871 | item.UseInlineData = true; | ||
| 872 | } | ||
| 873 | else | ||
| 874 | { | ||
| 875 | item.DataPos = attr.Pos + k_decmpfs_headerSize; | ||
| 876 | item.PackSize = dataSize; | ||
| 877 | item.UseAttr = true; | ||
| 878 | } | ||
| 879 | } | ||
| 880 | else | ||
| 881 | return false; | ||
| 882 | skip = true; | ||
| 883 | return true; | 1021 | return true; |
| 884 | } | 1022 | } |
| 885 | 1023 | ||
| 1024 | |||
| 886 | HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress) | 1025 | HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress) |
| 887 | { | 1026 | { |
| 888 | CByteBuffer buf; | 1027 | CByteBuffer buf; |
| @@ -911,7 +1050,8 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
| 911 | // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); | 1050 | // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC); |
| 912 | 1051 | ||
| 913 | CByteArr usedBuf(hr.TotalNodes); | 1052 | CByteArr usedBuf(hr.TotalNodes); |
| 914 | memset(usedBuf, 0, hr.TotalNodes); | 1053 | if (hr.TotalNodes != 0) |
| 1054 | memset(usedBuf, 0, hr.TotalNodes); | ||
| 915 | 1055 | ||
| 916 | CFork resFork; | 1056 | CFork resFork; |
| 917 | 1057 | ||
| @@ -1037,7 +1177,6 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
| 1037 | else | 1177 | else |
| 1038 | { | 1178 | { |
| 1039 | numFiles++; | 1179 | numFiles++; |
| 1040 | const unsigned kForkRecSize = 16 + kNumFixedExtents * 8; | ||
| 1041 | if (recSize != kForkRecSize * 2) | 1180 | if (recSize != kForkRecSize * 2) |
| 1042 | return S_FALSE; | 1181 | return S_FALSE; |
| 1043 | 1182 | ||
| @@ -1051,7 +1190,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
| 1051 | { | 1190 | { |
| 1052 | if (!item.ResourceFork.UpgradeAndTest(overflowExtentsArray[1], item.ID, Header.BlockSizeLog)) | 1191 | if (!item.ResourceFork.UpgradeAndTest(overflowExtentsArray[1], item.ID, Header.BlockSizeLog)) |
| 1053 | HeadersError = true; | 1192 | HeadersError = true; |
| 1054 | ThereAreAltStreams = true; | 1193 | // ThereAreAltStreams = true; |
| 1055 | } | 1194 | } |
| 1056 | } | 1195 | } |
| 1057 | if (progress && (Items.Size() & 0xFFF) == 0) | 1196 | if (progress && (Items.Size() & 0xFFF) == 0) |
| @@ -1086,14 +1225,18 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
| 1086 | { | 1225 | { |
| 1087 | const CAttr &attr = Attrs[i]; | 1226 | const CAttr &attr = Attrs[i]; |
| 1088 | 1227 | ||
| 1089 | int itemIndex = FindItemIndex(IdToIndexMap, attr.ID); | 1228 | const int itemIndex = FindItemIndex(IdToIndexMap, attr.ID); |
| 1090 | if (itemIndex < 0) | 1229 | if (itemIndex < 0) |
| 1091 | { | 1230 | { |
| 1092 | HeadersError = true; | 1231 | HeadersError = true; |
| 1093 | continue; | 1232 | continue; |
| 1094 | } | 1233 | } |
| 1095 | if (!Parse_decmpgfs(attr, Items[itemIndex], skipAttr[i])) | 1234 | |
| 1096 | HeadersError = true; | 1235 | if (attr.Name.IsEqualTo("com.apple.decmpfs")) |
| 1236 | { | ||
| 1237 | if (!Parse_decmpgfs(i, Items[itemIndex], skipAttr[i])) | ||
| 1238 | HeadersError = true; | ||
| 1239 | } | ||
| 1097 | } | 1240 | } |
| 1098 | } | 1241 | } |
| 1099 | 1242 | ||
| @@ -1117,13 +1260,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
| 1117 | 1260 | ||
| 1118 | if (item.ResourceFork.IsEmpty()) | 1261 | if (item.ResourceFork.IsEmpty()) |
| 1119 | continue; | 1262 | continue; |
| 1120 | if (item.UseAttr && item.Method == kMethod_Resource) | 1263 | if (item.CompressHeader.IsSupported && item.CompressHeader.IsMethod_Resource()) |
| 1121 | continue; | 1264 | continue; |
| 1122 | CRef resRef; | 1265 | |
| 1123 | resRef.ItemIndex = i; | 1266 | ThereAreAltStreams = true; |
| 1124 | resRef.IsResource = true; | 1267 | ref.AttrIndex = kAttrIndex_Resource; |
| 1125 | resRef.Parent = Refs.Size() - 1; | 1268 | ref.Parent = Refs.Size() - 1; |
| 1126 | Refs.Add(resRef); | 1269 | Refs.Add(ref); |
| 1127 | 1270 | ||
| 1128 | #endif | 1271 | #endif |
| 1129 | } | 1272 | } |
| @@ -1135,9 +1278,9 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
| 1135 | FOR_VECTOR (i, Refs) | 1278 | FOR_VECTOR (i, Refs) |
| 1136 | { | 1279 | { |
| 1137 | CRef &ref = Refs[i]; | 1280 | CRef &ref = Refs[i]; |
| 1138 | if (ref.IsResource) | 1281 | if (ref.IsResource()) |
| 1139 | continue; | 1282 | continue; |
| 1140 | CItem &item = Items[ref.ItemIndex]; | 1283 | const CItem &item = Items[ref.ItemIndex]; |
| 1141 | ref.Parent = FindItemIndex(IdToIndexMap, item.ParentID); | 1284 | ref.Parent = FindItemIndex(IdToIndexMap, item.ParentID); |
| 1142 | if (ref.Parent >= 0) | 1285 | if (ref.Parent >= 0) |
| 1143 | { | 1286 | { |
| @@ -1158,13 +1301,15 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents | |||
| 1158 | continue; | 1301 | continue; |
| 1159 | const CAttr &attr = Attrs[i]; | 1302 | const CAttr &attr = Attrs[i]; |
| 1160 | 1303 | ||
| 1161 | int refIndex = FindItemIndex(IdToIndexMap, attr.ID); | 1304 | const int refIndex = FindItemIndex(IdToIndexMap, attr.ID); |
| 1162 | if (refIndex < 0) | 1305 | if (refIndex < 0) |
| 1163 | { | 1306 | { |
| 1164 | HeadersError = true; | 1307 | HeadersError = true; |
| 1165 | continue; | 1308 | continue; |
| 1166 | } | 1309 | } |
| 1167 | 1310 | ||
| 1311 | ThereAreAltStreams = true; | ||
| 1312 | |||
| 1168 | CRef ref; | 1313 | CRef ref; |
| 1169 | ref.AttrIndex = i; | 1314 | ref.AttrIndex = i; |
| 1170 | ref.Parent = refIndex; | 1315 | ref.Parent = refIndex; |
| @@ -1381,13 +1526,6 @@ class CHandler: | |||
| 1381 | 1526 | ||
| 1382 | HRESULT GetForkStream(const CFork &fork, ISequentialInStream **stream); | 1527 | HRESULT GetForkStream(const CFork &fork, ISequentialInStream **stream); |
| 1383 | 1528 | ||
| 1384 | HRESULT ExtractZlibFile( | ||
| 1385 | ISequentialOutStream *realOutStream, | ||
| 1386 | const CItem &item, | ||
| 1387 | NCompress::NZlib::CDecoder *_zlibDecoderSpec, | ||
| 1388 | CByteBuffer &buf, | ||
| 1389 | UInt64 progressStart, | ||
| 1390 | IArchiveExtractCallback *extractCallback); | ||
| 1391 | public: | 1529 | public: |
| 1392 | MY_UNKNOWN_IMP3(IInArchive, IArchiveGetRawProps, IInArchiveGetStream) | 1530 | MY_UNKNOWN_IMP3(IInArchive, IArchiveGetRawProps, IInArchiveGetStream) |
| 1393 | INTERFACE_IInArchive(;) | 1531 | INTERFACE_IInArchive(;) |
| @@ -1405,12 +1543,21 @@ static const Byte kProps[] = | |||
| 1405 | kpidMTime, | 1543 | kpidMTime, |
| 1406 | kpidATime, | 1544 | kpidATime, |
| 1407 | kpidChangeTime, | 1545 | kpidChangeTime, |
| 1408 | kpidPosixAttrib | 1546 | kpidPosixAttrib, |
| 1547 | /* | ||
| 1548 | kpidUserId, | ||
| 1549 | kpidGroupId, | ||
| 1550 | */ | ||
| 1551 | #ifdef HFS_SHOW_ALT_STREAMS | ||
| 1552 | kpidIsAltStream, | ||
| 1553 | #endif | ||
| 1554 | kpidMethod | ||
| 1409 | }; | 1555 | }; |
| 1410 | 1556 | ||
| 1411 | static const Byte kArcProps[] = | 1557 | static const Byte kArcProps[] = |
| 1412 | { | 1558 | { |
| 1413 | kpidMethod, | 1559 | kpidMethod, |
| 1560 | kpidCharacts, | ||
| 1414 | kpidClusterSize, | 1561 | kpidClusterSize, |
| 1415 | kpidFreeSpace, | 1562 | kpidFreeSpace, |
| 1416 | kpidCTime, | 1563 | kpidCTime, |
| @@ -1437,6 +1584,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
| 1437 | { | 1584 | { |
| 1438 | case kpidExtension: prop = Header.IsHfsX() ? "hfsx" : "hfs"; break; | 1585 | case kpidExtension: prop = Header.IsHfsX() ? "hfsx" : "hfs"; break; |
| 1439 | case kpidMethod: prop = Header.IsHfsX() ? "HFSX" : "HFS+"; break; | 1586 | case kpidMethod: prop = Header.IsHfsX() ? "HFSX" : "HFS+"; break; |
| 1587 | case kpidCharacts: MethodsMaskToProp(MethodsMask, prop); break; | ||
| 1440 | case kpidPhySize: | 1588 | case kpidPhySize: |
| 1441 | { | 1589 | { |
| 1442 | UInt64 v = SpecOffset + PhySize; | 1590 | UInt64 v = SpecOffset + PhySize; |
| @@ -1464,6 +1612,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
| 1464 | { | 1612 | { |
| 1465 | UInt32 flags = 0; | 1613 | UInt32 flags = 0; |
| 1466 | if (HeadersError) flags |= kpv_ErrorFlags_HeadersError; | 1614 | if (HeadersError) flags |= kpv_ErrorFlags_HeadersError; |
| 1615 | if (UnsupportedFeature) flags |= kpv_ErrorFlags_UnsupportedFeature; | ||
| 1467 | if (flags != 0) | 1616 | if (flags != 0) |
| 1468 | prop = flags; | 1617 | prop = flags; |
| 1469 | break; | 1618 | break; |
| @@ -1508,7 +1657,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data | |||
| 1508 | { | 1657 | { |
| 1509 | const CRef &ref = Refs[index]; | 1658 | const CRef &ref = Refs[index]; |
| 1510 | const UString *s; | 1659 | const UString *s; |
| 1511 | if (ref.IsResource) | 1660 | if (ref.IsResource()) |
| 1512 | s = &ResFileName; | 1661 | s = &ResFileName; |
| 1513 | else if (ref.AttrIndex >= 0) | 1662 | else if (ref.AttrIndex >= 0) |
| 1514 | s = &Attrs[ref.AttrIndex].Name; | 1663 | s = &Attrs[ref.AttrIndex].Name; |
| @@ -1536,8 +1685,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 1536 | { | 1685 | { |
| 1537 | case kpidPath: GetItemPath(index, prop); break; | 1686 | case kpidPath: GetItemPath(index, prop); break; |
| 1538 | case kpidName: | 1687 | case kpidName: |
| 1688 | { | ||
| 1539 | const UString *s; | 1689 | const UString *s; |
| 1540 | if (ref.IsResource) | 1690 | if (ref.IsResource()) |
| 1541 | s = &ResFileName; | 1691 | s = &ResFileName; |
| 1542 | else if (ref.AttrIndex >= 0) | 1692 | else if (ref.AttrIndex >= 0) |
| 1543 | s = &Attrs[ref.AttrIndex].Name; | 1693 | s = &Attrs[ref.AttrIndex].Name; |
| @@ -1545,22 +1695,31 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 1545 | s = &item.Name; | 1695 | s = &item.Name; |
| 1546 | prop = *s; | 1696 | prop = *s; |
| 1547 | break; | 1697 | break; |
| 1698 | } | ||
| 1548 | case kpidPackSize: | 1699 | case kpidPackSize: |
| 1549 | { | 1700 | { |
| 1550 | UInt64 size; | 1701 | UInt64 size; |
| 1551 | if (ref.AttrIndex >= 0) | 1702 | if (ref.AttrIndex >= 0) |
| 1552 | size = Attrs[ref.AttrIndex].Size; | 1703 | size = Attrs[ref.AttrIndex].GetSize(); |
| 1704 | else if (ref.IsResource()) | ||
| 1705 | size = (UInt64)item.ResourceFork.NumBlocks << Header.BlockSizeLog; | ||
| 1553 | else if (item.IsDir()) | 1706 | else if (item.IsDir()) |
| 1554 | break; | 1707 | break; |
| 1555 | else if (item.UseAttr) | 1708 | else if (item.CompressHeader.IsCorrect) |
| 1556 | { | 1709 | { |
| 1557 | if (item.Method == kMethod_Resource) | 1710 | if (item.CompressHeader.IsMethod_Resource()) |
| 1558 | size = item.ResourceFork.NumBlocks << Header.BlockSizeLog; | 1711 | size = (UInt64)item.ResourceFork.NumBlocks << Header.BlockSizeLog; |
| 1712 | else if (item.decmpfs_AttrIndex >= 0) | ||
| 1713 | { | ||
| 1714 | // size = item.PackSize; | ||
| 1715 | const CAttr &attr = Attrs[item.decmpfs_AttrIndex]; | ||
| 1716 | size = attr.Data.Size() - item.CompressHeader.DataPos; | ||
| 1717 | } | ||
| 1559 | else | 1718 | else |
| 1560 | size = item.PackSize; | 1719 | size = 0; |
| 1561 | } | 1720 | } |
| 1562 | else | 1721 | else |
| 1563 | size = item.GetFork(ref.IsResource).NumBlocks << Header.BlockSizeLog; | 1722 | size = (UInt64)item.DataFork.NumBlocks << Header.BlockSizeLog; |
| 1564 | prop = size; | 1723 | prop = size; |
| 1565 | break; | 1724 | break; |
| 1566 | } | 1725 | } |
| @@ -1568,25 +1727,34 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 1568 | { | 1727 | { |
| 1569 | UInt64 size; | 1728 | UInt64 size; |
| 1570 | if (ref.AttrIndex >= 0) | 1729 | if (ref.AttrIndex >= 0) |
| 1571 | size = Attrs[ref.AttrIndex].Size; | 1730 | size = Attrs[ref.AttrIndex].GetSize(); |
| 1731 | else if (ref.IsResource()) | ||
| 1732 | size = item.ResourceFork.Size; | ||
| 1572 | else if (item.IsDir()) | 1733 | else if (item.IsDir()) |
| 1573 | break; | 1734 | break; |
| 1574 | else if (item.UseAttr) | 1735 | else if (item.CompressHeader.IsCorrect) |
| 1575 | size = item.UnpackSize; | 1736 | size = item.CompressHeader.UnpackSize; |
| 1576 | else | 1737 | else |
| 1577 | size = item.GetFork(ref.IsResource).Size; | 1738 | size = item.DataFork.Size; |
| 1578 | prop = size; | 1739 | prop = size; |
| 1579 | break; | 1740 | break; |
| 1580 | } | 1741 | } |
| 1581 | case kpidIsDir: prop = item.IsDir(); break; | 1742 | case kpidIsDir: prop = (ref.IsItem() && item.IsDir()); break; |
| 1582 | case kpidIsAltStream: prop = ref.IsAltStream(); break; | 1743 | case kpidIsAltStream: prop = ref.IsAltStream(); break; |
| 1583 | |||
| 1584 | case kpidCTime: HfsTimeToProp(item.CTime, prop); break; | 1744 | case kpidCTime: HfsTimeToProp(item.CTime, prop); break; |
| 1585 | case kpidMTime: HfsTimeToProp(item.MTime, prop); break; | 1745 | case kpidMTime: HfsTimeToProp(item.MTime, prop); break; |
| 1586 | case kpidATime: HfsTimeToProp(item.ATime, prop); break; | 1746 | case kpidATime: HfsTimeToProp(item.ATime, prop); break; |
| 1587 | case kpidChangeTime: HfsTimeToProp(item.AttrMTime, prop); break; | 1747 | case kpidChangeTime: HfsTimeToProp(item.AttrMTime, prop); break; |
| 1748 | case kpidPosixAttrib: if (ref.IsItem()) prop = (UInt32)item.FileMode; break; | ||
| 1749 | /* | ||
| 1750 | case kpidUserId: prop = (UInt32)item.OwnerID; break; | ||
| 1751 | case kpidGroupId: prop = (UInt32)item.GroupID; break; | ||
| 1752 | */ | ||
| 1588 | 1753 | ||
| 1589 | case kpidPosixAttrib: if (ref.AttrIndex < 0) prop = (UInt32)item.FileMode; break; | 1754 | case kpidMethod: |
| 1755 | if (ref.IsItem()) | ||
| 1756 | item.CompressHeader.MethodToProp(prop); | ||
| 1757 | break; | ||
| 1590 | } | 1758 | } |
| 1591 | prop.Detach(value); | 1759 | prop.Detach(value); |
| 1592 | return S_OK; | 1760 | return S_OK; |
| @@ -1614,65 +1782,77 @@ STDMETHODIMP CHandler::Close() | |||
| 1614 | 1782 | ||
| 1615 | static const UInt32 kCompressionBlockSize = 1 << 16; | 1783 | static const UInt32 kCompressionBlockSize = 1 << 16; |
| 1616 | 1784 | ||
| 1617 | HRESULT CHandler::ExtractZlibFile( | 1785 | CDecoder::CDecoder() |
| 1618 | ISequentialOutStream *outStream, | 1786 | { |
| 1619 | const CItem &item, | 1787 | _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); |
| 1620 | NCompress::NZlib::CDecoder *_zlibDecoderSpec, | 1788 | _zlibDecoder = _zlibDecoderSpec; |
| 1621 | CByteBuffer &buf, | 1789 | |
| 1622 | UInt64 progressStart, | 1790 | _lzfseDecoderSpec = new NCompress::NLzfse::CDecoder(); |
| 1623 | IArchiveExtractCallback *extractCallback) | 1791 | _lzfseDecoder = _lzfseDecoderSpec; |
| 1792 | _lzfseDecoderSpec->LzvnMode = true; | ||
| 1793 | } | ||
| 1794 | |||
| 1795 | HRESULT CDecoder::ExtractResourceFork_ZLIB( | ||
| 1796 | ISequentialInStream *inStream, ISequentialOutStream *outStream, | ||
| 1797 | UInt64 forkSize, UInt64 unpackSize, | ||
| 1798 | UInt64 progressStart, IArchiveExtractCallback *extractCallback) | ||
| 1624 | { | 1799 | { |
| 1625 | CMyComPtr<ISequentialInStream> inStream; | ||
| 1626 | const CFork &fork = item.ResourceFork; | ||
| 1627 | RINOK(GetForkStream(fork, &inStream)); | ||
| 1628 | const unsigned kHeaderSize = 0x100 + 8; | 1800 | const unsigned kHeaderSize = 0x100 + 8; |
| 1629 | RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize)); | 1801 | |
| 1630 | UInt32 dataPos = Get32(buf); | 1802 | const size_t kBufSize = kCompressionBlockSize; |
| 1631 | UInt32 mapPos = Get32(buf + 4); | 1803 | _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header |
| 1632 | UInt32 dataSize = Get32(buf + 8); | 1804 | |
| 1633 | UInt32 mapSize = Get32(buf + 12); | 1805 | RINOK(ReadStream_FALSE(inStream, _buf, kHeaderSize)); |
| 1806 | Byte *buf = _buf; | ||
| 1807 | const UInt32 dataPos = Get32(buf); | ||
| 1808 | const UInt32 mapPos = Get32(buf + 4); | ||
| 1809 | const UInt32 dataSize = Get32(buf + 8); | ||
| 1810 | const UInt32 mapSize = Get32(buf + 12); | ||
| 1634 | 1811 | ||
| 1635 | const UInt32 kResMapSize = 50; | 1812 | const UInt32 kResMapSize = 50; |
| 1636 | 1813 | ||
| 1637 | if (mapSize != kResMapSize | 1814 | if (mapSize != kResMapSize |
| 1638 | || dataPos + dataSize != mapPos | 1815 | || dataPos > mapPos |
| 1639 | || mapPos + mapSize != fork.Size) | 1816 | || dataSize != mapPos - dataPos |
| 1817 | || mapSize > forkSize | ||
| 1818 | || mapPos != forkSize - mapSize) | ||
| 1640 | return S_FALSE; | 1819 | return S_FALSE; |
| 1641 | 1820 | ||
| 1642 | UInt32 dataSize2 = Get32(buf + 0x100); | 1821 | const UInt32 dataSize2 = Get32(buf + 0x100); |
| 1643 | if (4 + dataSize2 != dataSize || dataSize2 < 8) | 1822 | if (4 + dataSize2 != dataSize |
| 1823 | || dataSize2 < 8 | ||
| 1824 | || dataSize2 > dataSize) | ||
| 1644 | return S_FALSE; | 1825 | return S_FALSE; |
| 1645 | 1826 | ||
| 1646 | UInt32 numBlocks = GetUi32(buf + 0x100 + 4); | 1827 | const UInt32 numBlocks = GetUi32(buf + 0x100 + 4); |
| 1647 | if (((dataSize2 - 4) >> 3) < numBlocks) | 1828 | if (((dataSize2 - 4) >> 3) < numBlocks) |
| 1648 | return S_FALSE; | 1829 | return S_FALSE; |
| 1649 | if (item.UnpackSize > (UInt64)numBlocks * kCompressionBlockSize) | 1830 | { |
| 1650 | return S_FALSE; | 1831 | const UInt64 up = unpackSize + kCompressionBlockSize - 1; |
| 1651 | 1832 | if (up < unpackSize || up / kCompressionBlockSize != numBlocks) | |
| 1652 | if (item.UnpackSize + kCompressionBlockSize < (UInt64)numBlocks * kCompressionBlockSize) | 1833 | return S_FALSE; |
| 1653 | return S_FALSE; | 1834 | } |
| 1654 | 1835 | ||
| 1655 | UInt32 tableSize = (numBlocks << 3); | 1836 | const UInt32 tableSize = (numBlocks << 3); |
| 1656 | 1837 | ||
| 1657 | CByteBuffer tableBuf(tableSize); | 1838 | _tableBuf.AllocAtLeast(tableSize); |
| 1658 | 1839 | ||
| 1659 | RINOK(ReadStream_FALSE(inStream, tableBuf, tableSize)); | 1840 | RINOK(ReadStream_FALSE(inStream, _tableBuf, tableSize)); |
| 1841 | const Byte *tableBuf = _tableBuf; | ||
| 1660 | 1842 | ||
| 1661 | UInt32 prev = 4 + tableSize; | 1843 | UInt32 prev = 4 + tableSize; |
| 1662 | 1844 | ||
| 1663 | UInt32 i; | 1845 | UInt32 i; |
| 1664 | for (i = 0; i < numBlocks; i++) | 1846 | for (i = 0; i < numBlocks; i++) |
| 1665 | { | 1847 | { |
| 1666 | UInt32 offset = GetUi32(tableBuf + i * 8); | 1848 | const UInt32 offs = GetUi32(tableBuf + i * 8); |
| 1667 | UInt32 size = GetUi32(tableBuf + i * 8 + 4); | 1849 | const UInt32 size = GetUi32(tableBuf + i * 8 + 4); |
| 1668 | if (size == 0) | 1850 | if (size == 0 |
| 1669 | return S_FALSE; | 1851 | || prev != offs |
| 1670 | if (prev != offset) | 1852 | || offs > dataSize2 |
| 1853 | || size > dataSize2 - offs) | ||
| 1671 | return S_FALSE; | 1854 | return S_FALSE; |
| 1672 | if (offset > dataSize2 || | 1855 | prev = offs + size; |
| 1673 | size > dataSize2 - offset) | ||
| 1674 | return S_FALSE; | ||
| 1675 | prev = offset + size; | ||
| 1676 | } | 1856 | } |
| 1677 | 1857 | ||
| 1678 | if (prev != dataSize2) | 1858 | if (prev != dataSize2) |
| @@ -1681,26 +1861,29 @@ HRESULT CHandler::ExtractZlibFile( | |||
| 1681 | CBufInStream *bufInStreamSpec = new CBufInStream; | 1861 | CBufInStream *bufInStreamSpec = new CBufInStream; |
| 1682 | CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec; | 1862 | CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec; |
| 1683 | 1863 | ||
| 1864 | // bool padError = false; | ||
| 1684 | UInt64 outPos = 0; | 1865 | UInt64 outPos = 0; |
| 1866 | |||
| 1685 | for (i = 0; i < numBlocks; i++) | 1867 | for (i = 0; i < numBlocks; i++) |
| 1686 | { | 1868 | { |
| 1687 | UInt64 rem = item.UnpackSize - outPos; | 1869 | const UInt64 rem = unpackSize - outPos; |
| 1688 | if (rem == 0) | 1870 | if (rem == 0) |
| 1689 | return S_FALSE; | 1871 | return S_FALSE; |
| 1690 | UInt32 blockSize = kCompressionBlockSize; | 1872 | UInt32 blockSize = kCompressionBlockSize; |
| 1691 | if (rem < kCompressionBlockSize) | 1873 | if (rem < kCompressionBlockSize) |
| 1692 | blockSize = (UInt32)rem; | 1874 | blockSize = (UInt32)rem; |
| 1693 | 1875 | ||
| 1694 | UInt32 size = GetUi32(tableBuf + i * 8 + 4); | 1876 | const UInt32 size = GetUi32(tableBuf + i * 8 + 4); |
| 1695 | 1877 | ||
| 1696 | if (size > buf.Size() || size > kCompressionBlockSize + 1) | 1878 | if (size > kCompressionBlockSize + 1) |
| 1697 | return S_FALSE; | 1879 | return S_FALSE; |
| 1698 | 1880 | ||
| 1699 | RINOK(ReadStream_FALSE(inStream, buf, size)); | 1881 | RINOK(ReadStream_FALSE(inStream, buf, size)); |
| 1700 | 1882 | ||
| 1701 | if ((buf[0] & 0xF) == 0xF) | 1883 | if ((buf[0] & 0xF) == 0xF) |
| 1702 | { | 1884 | { |
| 1703 | // that code was not tested. Are there HFS archives with uncompressed block | 1885 | // (buf[0] = 0xff) is marker of uncompressed block in APFS |
| 1886 | // that code was not tested in HFS | ||
| 1704 | if (size - 1 != blockSize) | 1887 | if (size - 1 != blockSize) |
| 1705 | return S_FALSE; | 1888 | return S_FALSE; |
| 1706 | 1889 | ||
| @@ -1711,54 +1894,251 @@ HRESULT CHandler::ExtractZlibFile( | |||
| 1711 | } | 1894 | } |
| 1712 | else | 1895 | else |
| 1713 | { | 1896 | { |
| 1714 | UInt64 blockSize64 = blockSize; | 1897 | const UInt64 blockSize64 = blockSize; |
| 1715 | bufInStreamSpec->Init(buf, size); | 1898 | bufInStreamSpec->Init(buf, size); |
| 1716 | RINOK(_zlibDecoderSpec->Code(bufInStream, outStream, NULL, &blockSize64, NULL)); | 1899 | RINOK(_zlibDecoderSpec->Code(bufInStream, outStream, NULL, &blockSize64, NULL)); |
| 1717 | if (_zlibDecoderSpec->GetOutputProcessedSize() != blockSize || | 1900 | if (_zlibDecoderSpec->GetOutputProcessedSize() != blockSize) |
| 1718 | _zlibDecoderSpec->GetInputProcessedSize() != size) | ||
| 1719 | return S_FALSE; | 1901 | return S_FALSE; |
| 1902 | const UInt64 inSize = _zlibDecoderSpec->GetInputProcessedSize(); | ||
| 1903 | if (inSize != size) | ||
| 1904 | { | ||
| 1905 | if (inSize > size) | ||
| 1906 | return S_FALSE; | ||
| 1907 | // apfs file can contain junk (non-zeros) after data block. | ||
| 1908 | /* | ||
| 1909 | if (!padError) | ||
| 1910 | { | ||
| 1911 | const Byte *p = buf + (UInt32)inSize; | ||
| 1912 | const Byte *e = p + (size - (UInt32)inSize); | ||
| 1913 | do | ||
| 1914 | { | ||
| 1915 | if (*p != 0) | ||
| 1916 | { | ||
| 1917 | padError = true; | ||
| 1918 | break; | ||
| 1919 | } | ||
| 1920 | } | ||
| 1921 | while (++p != e); | ||
| 1922 | } | ||
| 1923 | */ | ||
| 1924 | } | ||
| 1720 | } | 1925 | } |
| 1721 | 1926 | ||
| 1722 | outPos += blockSize; | 1927 | outPos += blockSize; |
| 1723 | const UInt64 progressPos = progressStart + outPos; | 1928 | if ((i & 0xFF) == 0) |
| 1724 | RINOK(extractCallback->SetCompleted(&progressPos)); | 1929 | { |
| 1930 | const UInt64 progressPos = progressStart + outPos; | ||
| 1931 | RINOK(extractCallback->SetCompleted(&progressPos)); | ||
| 1932 | } | ||
| 1725 | } | 1933 | } |
| 1726 | 1934 | ||
| 1727 | if (outPos != item.UnpackSize) | 1935 | if (outPos != unpackSize) |
| 1728 | return S_FALSE; | 1936 | return S_FALSE; |
| 1729 | 1937 | ||
| 1938 | // if (padError) return S_FALSE; | ||
| 1939 | |||
| 1730 | /* We check Resource Map | 1940 | /* We check Resource Map |
| 1731 | Are there HFS files with another values in Resource Map ??? */ | 1941 | Are there HFS files with another values in Resource Map ??? */ |
| 1732 | 1942 | ||
| 1733 | RINOK(ReadStream_FALSE(inStream, buf, mapSize)); | 1943 | RINOK(ReadStream_FALSE(inStream, buf, mapSize)); |
| 1734 | UInt32 types = Get16(buf + 24); | 1944 | const UInt32 types = Get16(buf + 24); |
| 1735 | UInt32 names = Get16(buf + 26); | 1945 | const UInt32 names = Get16(buf + 26); |
| 1736 | UInt32 numTypes = Get16(buf + 28); | 1946 | const UInt32 numTypes = Get16(buf + 28); |
| 1737 | if (numTypes != 0 || types != 28 || names != kResMapSize) | 1947 | if (numTypes != 0 || types != 28 || names != kResMapSize) |
| 1738 | return S_FALSE; | 1948 | return S_FALSE; |
| 1739 | UInt32 resType = Get32(buf + 30); | 1949 | const UInt32 resType = Get32(buf + 30); |
| 1740 | UInt32 numResources = Get16(buf + 34); | 1950 | const UInt32 numResources = Get16(buf + 34); |
| 1741 | UInt32 resListOffset = Get16(buf + 36); | 1951 | const UInt32 resListOffset = Get16(buf + 36); |
| 1742 | if (resType != 0x636D7066) // cmpf | 1952 | if (resType != 0x636D7066) // cmpf |
| 1743 | return S_FALSE; | 1953 | return S_FALSE; |
| 1744 | if (numResources != 0 || resListOffset != 10) | 1954 | if (numResources != 0 || resListOffset != 10) |
| 1745 | return S_FALSE; | 1955 | return S_FALSE; |
| 1746 | 1956 | ||
| 1747 | UInt32 entryId = Get16(buf + 38); | 1957 | const UInt32 entryId = Get16(buf + 38); |
| 1748 | UInt32 nameOffset = Get16(buf + 40); | 1958 | const UInt32 nameOffset = Get16(buf + 40); |
| 1749 | // Byte attrib = buf[42]; | 1959 | // Byte attrib = buf[42]; |
| 1750 | UInt32 resourceOffset = Get32(buf + 42) & 0xFFFFFF; | 1960 | const UInt32 resourceOffset = Get32(buf + 42) & 0xFFFFFF; |
| 1751 | if (entryId != 1 || nameOffset != 0xFFFF || resourceOffset != 0) | 1961 | if (entryId != 1 || nameOffset != 0xFFFF || resourceOffset != 0) |
| 1752 | return S_FALSE; | 1962 | return S_FALSE; |
| 1753 | 1963 | ||
| 1754 | return S_OK; | 1964 | return S_OK; |
| 1755 | } | 1965 | } |
| 1756 | 1966 | ||
| 1967 | |||
| 1968 | |||
| 1969 | HRESULT CDecoder::ExtractResourceFork_LZFSE( | ||
| 1970 | ISequentialInStream *inStream, ISequentialOutStream *outStream, | ||
| 1971 | UInt64 forkSize, UInt64 unpackSize, | ||
| 1972 | UInt64 progressStart, IArchiveExtractCallback *extractCallback) | ||
| 1973 | { | ||
| 1974 | const UInt32 kNumBlocksMax = (UInt32)1 << 29; | ||
| 1975 | if (unpackSize >= (UInt64)kNumBlocksMax * kCompressionBlockSize) | ||
| 1976 | return S_FALSE; | ||
| 1977 | const UInt32 numBlocks = (UInt32)((unpackSize + kCompressionBlockSize - 1) / kCompressionBlockSize); | ||
| 1978 | const UInt32 numBlocks2 = numBlocks + 1; | ||
| 1979 | const UInt32 tableSize = (numBlocks2 << 2); | ||
| 1980 | if (tableSize > forkSize) | ||
| 1981 | return S_FALSE; | ||
| 1982 | _tableBuf.AllocAtLeast(tableSize); | ||
| 1983 | RINOK(ReadStream_FALSE(inStream, _tableBuf, tableSize)); | ||
| 1984 | const Byte *tableBuf = _tableBuf; | ||
| 1985 | |||
| 1986 | { | ||
| 1987 | UInt32 prev = GetUi32(tableBuf); | ||
| 1988 | if (prev != tableSize) | ||
| 1989 | return S_FALSE; | ||
| 1990 | for (UInt32 i = 1; i < numBlocks2; i++) | ||
| 1991 | { | ||
| 1992 | const UInt32 offs = GetUi32(tableBuf + i * 4); | ||
| 1993 | if (offs <= prev) | ||
| 1994 | return S_FALSE; | ||
| 1995 | prev = offs; | ||
| 1996 | } | ||
| 1997 | if (prev != forkSize) | ||
| 1998 | return S_FALSE; | ||
| 1999 | } | ||
| 2000 | |||
| 2001 | const size_t kBufSize = kCompressionBlockSize; | ||
| 2002 | _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header | ||
| 2003 | |||
| 2004 | CBufInStream *bufInStreamSpec = new CBufInStream; | ||
| 2005 | CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec; | ||
| 2006 | |||
| 2007 | UInt64 outPos = 0; | ||
| 2008 | |||
| 2009 | for (UInt32 i = 0; i < numBlocks; i++) | ||
| 2010 | { | ||
| 2011 | const UInt64 rem = unpackSize - outPos; | ||
| 2012 | if (rem == 0) | ||
| 2013 | return S_FALSE; | ||
| 2014 | UInt32 blockSize = kCompressionBlockSize; | ||
| 2015 | if (rem < kCompressionBlockSize) | ||
| 2016 | blockSize = (UInt32)rem; | ||
| 2017 | |||
| 2018 | const UInt32 size = | ||
| 2019 | GetUi32(tableBuf + i * 4 + 4) - | ||
| 2020 | GetUi32(tableBuf + i * 4); | ||
| 2021 | |||
| 2022 | if (size > kCompressionBlockSize + 1) | ||
| 2023 | return S_FALSE; | ||
| 2024 | |||
| 2025 | RINOK(ReadStream_FALSE(inStream, _buf, size)); | ||
| 2026 | const Byte *buf = _buf; | ||
| 2027 | |||
| 2028 | if (buf[0] == k_LZVN_Uncompressed_Marker) | ||
| 2029 | { | ||
| 2030 | if (size - 1 != blockSize) | ||
| 2031 | return S_FALSE; | ||
| 2032 | if (outStream) | ||
| 2033 | { | ||
| 2034 | RINOK(WriteStream(outStream, buf, blockSize)); | ||
| 2035 | } | ||
| 2036 | } | ||
| 2037 | else | ||
| 2038 | { | ||
| 2039 | const UInt64 blockSize64 = blockSize; | ||
| 2040 | const UInt64 packSize64 = size; | ||
| 2041 | bufInStreamSpec->Init(buf, size); | ||
| 2042 | RINOK(_lzfseDecoderSpec->Code(bufInStream, outStream, &packSize64, &blockSize64, NULL)); | ||
| 2043 | // in/out sizes were checked in Code() | ||
| 2044 | } | ||
| 2045 | |||
| 2046 | outPos += blockSize; | ||
| 2047 | if ((i & 0xFF) == 0) | ||
| 2048 | { | ||
| 2049 | const UInt64 progressPos = progressStart + outPos; | ||
| 2050 | RINOK(extractCallback->SetCompleted(&progressPos)); | ||
| 2051 | } | ||
| 2052 | } | ||
| 2053 | |||
| 2054 | return S_OK; | ||
| 2055 | } | ||
| 2056 | |||
| 2057 | |||
| 2058 | HRESULT CDecoder::Extract( | ||
| 2059 | ISequentialInStream *inStreamFork, ISequentialOutStream *realOutStream, | ||
| 2060 | UInt64 forkSize, | ||
| 2061 | const CCompressHeader &compressHeader, | ||
| 2062 | const CByteBuffer *data, | ||
| 2063 | UInt64 progressStart, IArchiveExtractCallback *extractCallback, | ||
| 2064 | int &opRes) | ||
| 2065 | { | ||
| 2066 | opRes = NExtract::NOperationResult::kDataError; | ||
| 2067 | |||
| 2068 | if (compressHeader.IsMethod_Uncompressed_Inline()) | ||
| 2069 | { | ||
| 2070 | const size_t packSize = data->Size() - compressHeader.DataPos; | ||
| 2071 | if (realOutStream) | ||
| 2072 | { | ||
| 2073 | RINOK(WriteStream(realOutStream, *data + compressHeader.DataPos, packSize)); | ||
| 2074 | } | ||
| 2075 | opRes = NExtract::NOperationResult::kOK; | ||
| 2076 | return S_OK; | ||
| 2077 | } | ||
| 2078 | |||
| 2079 | if (compressHeader.Method == kMethod_ZLIB_ATTR || | ||
| 2080 | compressHeader.Method == kMethod_LZVN_ATTR) | ||
| 2081 | { | ||
| 2082 | CBufInStream *bufInStreamSpec = new CBufInStream; | ||
| 2083 | CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec; | ||
| 2084 | const size_t packSize = data->Size() - compressHeader.DataPos; | ||
| 2085 | bufInStreamSpec->Init(*data + compressHeader.DataPos, packSize); | ||
| 2086 | |||
| 2087 | if (compressHeader.Method == kMethod_ZLIB_ATTR) | ||
| 2088 | { | ||
| 2089 | const HRESULT hres = _zlibDecoder->Code(bufInStream, realOutStream, | ||
| 2090 | NULL, &compressHeader.UnpackSize, NULL); | ||
| 2091 | if (hres == S_OK) | ||
| 2092 | if (_zlibDecoderSpec->GetOutputProcessedSize() == compressHeader.UnpackSize | ||
| 2093 | && _zlibDecoderSpec->GetInputProcessedSize() == packSize) | ||
| 2094 | opRes = NExtract::NOperationResult::kOK; | ||
| 2095 | return hres; | ||
| 2096 | } | ||
| 2097 | { | ||
| 2098 | const UInt64 packSize64 = packSize; | ||
| 2099 | const HRESULT hres = _lzfseDecoder->Code(bufInStream, realOutStream, | ||
| 2100 | &packSize64, &compressHeader.UnpackSize, NULL); | ||
| 2101 | if (hres == S_OK) | ||
| 2102 | { | ||
| 2103 | // in/out sizes were checked in Code() | ||
| 2104 | opRes = NExtract::NOperationResult::kOK; | ||
| 2105 | } | ||
| 2106 | return hres; | ||
| 2107 | } | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | HRESULT hres; | ||
| 2111 | if (compressHeader.Method == NHfs::kMethod_ZLIB_RSRC) | ||
| 2112 | { | ||
| 2113 | hres = ExtractResourceFork_ZLIB( | ||
| 2114 | inStreamFork, realOutStream, | ||
| 2115 | forkSize, compressHeader.UnpackSize, | ||
| 2116 | progressStart, extractCallback); | ||
| 2117 | } | ||
| 2118 | else if (compressHeader.Method == NHfs::kMethod_LZVN_RSRC) | ||
| 2119 | { | ||
| 2120 | hres = ExtractResourceFork_LZFSE( | ||
| 2121 | inStreamFork, realOutStream, | ||
| 2122 | forkSize, compressHeader.UnpackSize, | ||
| 2123 | progressStart, extractCallback); | ||
| 2124 | } | ||
| 2125 | else | ||
| 2126 | { | ||
| 2127 | opRes = NExtract::NOperationResult::kUnsupportedMethod; | ||
| 2128 | hres = S_FALSE; | ||
| 2129 | } | ||
| 2130 | |||
| 2131 | if (hres == S_OK) | ||
| 2132 | opRes = NExtract::NOperationResult::kOK; | ||
| 2133 | return hres; | ||
| 2134 | } | ||
| 2135 | |||
| 2136 | |||
| 1757 | STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | 2137 | STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, |
| 1758 | Int32 testMode, IArchiveExtractCallback *extractCallback) | 2138 | Int32 testMode, IArchiveExtractCallback *extractCallback) |
| 1759 | { | 2139 | { |
| 1760 | COM_TRY_BEGIN | 2140 | COM_TRY_BEGIN |
| 1761 | bool allFilesMode = (numItems == (UInt32)(Int32)-1); | 2141 | const bool allFilesMode = (numItems == (UInt32)(Int32)-1); |
| 1762 | if (allFilesMode) | 2142 | if (allFilesMode) |
| 1763 | numItems = Refs.Size(); | 2143 | numItems = Refs.Size(); |
| 1764 | if (numItems == 0) | 2144 | if (numItems == 0) |
| @@ -1777,12 +2157,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1777 | const size_t kBufSize = kCompressionBlockSize; | 2157 | const size_t kBufSize = kCompressionBlockSize; |
| 1778 | CByteBuffer buf(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header | 2158 | CByteBuffer buf(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header |
| 1779 | 2159 | ||
| 1780 | NCompress::NZlib::CDecoder *_zlibDecoderSpec = NULL; | 2160 | CDecoder decoder; |
| 1781 | CMyComPtr<ICompressCoder> _zlibDecoder; | ||
| 1782 | 2161 | ||
| 1783 | for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) | 2162 | for (i = 0;; i++, currentTotalSize += currentItemSize) |
| 1784 | { | 2163 | { |
| 1785 | RINOK(extractCallback->SetCompleted(¤tTotalSize)); | 2164 | RINOK(extractCallback->SetCompleted(¤tTotalSize)); |
| 2165 | if (i == numItems) | ||
| 2166 | break; | ||
| 1786 | UInt32 index = allFilesMode ? i : indices[i]; | 2167 | UInt32 index = allFilesMode ? i : indices[i]; |
| 1787 | const CRef &ref = Refs[index]; | 2168 | const CRef &ref = Refs[index]; |
| 1788 | const CItem &item = Items[ref.ItemIndex]; | 2169 | const CItem &item = Items[ref.ItemIndex]; |
| @@ -1794,7 +2175,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1794 | NExtract::NAskMode::kExtract; | 2175 | NExtract::NAskMode::kExtract; |
| 1795 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); | 2176 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); |
| 1796 | 2177 | ||
| 1797 | if (ref.AttrIndex < 0 && item.IsDir()) | 2178 | if (ref.IsItem() && item.IsDir()) |
| 1798 | { | 2179 | { |
| 1799 | RINOK(extractCallback->PrepareOperation(askMode)); | 2180 | RINOK(extractCallback->PrepareOperation(askMode)); |
| 1800 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); | 2181 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); |
| @@ -1802,89 +2183,91 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1802 | } | 2183 | } |
| 1803 | if (!testMode && !realOutStream) | 2184 | if (!testMode && !realOutStream) |
| 1804 | continue; | 2185 | continue; |
| 2186 | |||
| 1805 | RINOK(extractCallback->PrepareOperation(askMode)); | 2187 | RINOK(extractCallback->PrepareOperation(askMode)); |
| 2188 | |||
| 1806 | UInt64 pos = 0; | 2189 | UInt64 pos = 0; |
| 1807 | int res = NExtract::NOperationResult::kDataError; | 2190 | int opRes = NExtract::NOperationResult::kDataError; |
| 2191 | const CFork *fork = NULL; | ||
| 2192 | |||
| 1808 | if (ref.AttrIndex >= 0) | 2193 | if (ref.AttrIndex >= 0) |
| 1809 | { | 2194 | { |
| 1810 | res = NExtract::NOperationResult::kOK; | 2195 | const CAttr &attr = Attrs[ref.AttrIndex]; |
| 1811 | if (realOutStream) | 2196 | if (attr.Fork_defined && attr.Data.Size() == 0) |
| 2197 | fork = &attr.Fork; | ||
| 2198 | else | ||
| 1812 | { | 2199 | { |
| 1813 | const CAttr &attr = Attrs[ref.AttrIndex]; | 2200 | opRes = NExtract::NOperationResult::kOK; |
| 1814 | RINOK(WriteStream(realOutStream, AttrBuf + attr.Pos, attr.Size)); | 2201 | if (realOutStream) |
| 2202 | { | ||
| 2203 | RINOK(WriteStream(realOutStream, | ||
| 2204 | // AttrBuf + attr.Pos, attr.Size | ||
| 2205 | attr.Data, attr.Data.Size() | ||
| 2206 | )); | ||
| 2207 | } | ||
| 1815 | } | 2208 | } |
| 1816 | } | 2209 | } |
| 1817 | else if (item.UseAttr) | 2210 | else if (ref.IsResource()) |
| 2211 | fork = &item.ResourceFork; | ||
| 2212 | else if (item.CompressHeader.IsSupported) | ||
| 1818 | { | 2213 | { |
| 1819 | if (item.UseInlineData) | 2214 | CMyComPtr<ISequentialInStream> inStreamFork; |
| 2215 | UInt64 forkSize = 0; | ||
| 2216 | const CByteBuffer *decmpfs_Data = NULL; | ||
| 2217 | |||
| 2218 | if (item.CompressHeader.IsMethod_Resource()) | ||
| 1820 | { | 2219 | { |
| 1821 | res = NExtract::NOperationResult::kOK; | 2220 | const CFork &resourceFork = item.ResourceFork; |
| 1822 | if (realOutStream) | 2221 | forkSize = resourceFork.Size; |
| 1823 | { | 2222 | GetForkStream(resourceFork, &inStreamFork); |
| 1824 | RINOK(WriteStream(realOutStream, AttrBuf + item.DataPos, (size_t)item.UnpackSize)); | ||
| 1825 | } | ||
| 1826 | } | 2223 | } |
| 1827 | else | 2224 | else |
| 1828 | { | 2225 | { |
| 1829 | if (!_zlibDecoder) | 2226 | const CAttr &attr = Attrs[item.decmpfs_AttrIndex]; |
| 1830 | { | 2227 | decmpfs_Data = &attr.Data; |
| 1831 | _zlibDecoderSpec = new NCompress::NZlib::CDecoder(); | 2228 | } |
| 1832 | _zlibDecoder = _zlibDecoderSpec; | 2229 | |
| 1833 | } | 2230 | if (inStreamFork || decmpfs_Data) |
| 1834 | 2231 | { | |
| 1835 | if (item.Method == kMethod_Attr) | 2232 | const HRESULT hres = decoder.Extract( |
| 1836 | { | 2233 | inStreamFork, realOutStream, |
| 1837 | CBufInStream *bufInStreamSpec = new CBufInStream; | 2234 | forkSize, |
| 1838 | CMyComPtr<ISequentialInStream> bufInStream = bufInStreamSpec; | 2235 | item.CompressHeader, |
| 1839 | bufInStreamSpec->Init(AttrBuf + item.DataPos, item.PackSize); | 2236 | decmpfs_Data, |
| 1840 | 2237 | currentTotalSize, extractCallback, | |
| 1841 | HRESULT hres = _zlibDecoder->Code(bufInStream, realOutStream, NULL, &item.UnpackSize, NULL); | 2238 | opRes); |
| 1842 | if (hres != S_FALSE) | 2239 | if (hres != S_FALSE && hres != S_OK) |
| 1843 | { | 2240 | return hres; |
| 1844 | if (hres != S_OK) | ||
| 1845 | return hres; | ||
| 1846 | if (_zlibDecoderSpec->GetOutputProcessedSize() == item.UnpackSize && | ||
| 1847 | _zlibDecoderSpec->GetInputProcessedSize() == item.PackSize) | ||
| 1848 | res = NExtract::NOperationResult::kOK; | ||
| 1849 | } | ||
| 1850 | } | ||
| 1851 | else | ||
| 1852 | { | ||
| 1853 | HRESULT hres = ExtractZlibFile(realOutStream, item, _zlibDecoderSpec, buf, | ||
| 1854 | currentTotalSize, extractCallback); | ||
| 1855 | if (hres != S_FALSE) | ||
| 1856 | { | ||
| 1857 | if (hres != S_OK) | ||
| 1858 | return hres; | ||
| 1859 | res = NExtract::NOperationResult::kOK; | ||
| 1860 | } | ||
| 1861 | } | ||
| 1862 | } | 2241 | } |
| 1863 | } | 2242 | } |
| 2243 | else if (item.CompressHeader.IsCorrect) | ||
| 2244 | opRes = NExtract::NOperationResult::kUnsupportedMethod; | ||
| 1864 | else | 2245 | else |
| 2246 | fork = &item.DataFork; | ||
| 2247 | |||
| 2248 | if (fork) | ||
| 1865 | { | 2249 | { |
| 1866 | const CFork &fork = item.GetFork(ref.IsResource); | 2250 | if (fork->IsOk(Header.BlockSizeLog)) |
| 1867 | if (fork.IsOk(Header.BlockSizeLog)) | ||
| 1868 | { | 2251 | { |
| 1869 | res = NExtract::NOperationResult::kOK; | 2252 | opRes = NExtract::NOperationResult::kOK; |
| 1870 | unsigned extentIndex; | 2253 | unsigned extentIndex; |
| 1871 | for (extentIndex = 0; extentIndex < fork.Extents.Size(); extentIndex++) | 2254 | for (extentIndex = 0; extentIndex < fork->Extents.Size(); extentIndex++) |
| 1872 | { | 2255 | { |
| 1873 | if (res != NExtract::NOperationResult::kOK) | 2256 | if (opRes != NExtract::NOperationResult::kOK) |
| 1874 | break; | 2257 | break; |
| 1875 | if (fork.Size == pos) | 2258 | if (fork->Size == pos) |
| 1876 | break; | 2259 | break; |
| 1877 | const CExtent &e = fork.Extents[extentIndex]; | 2260 | const CExtent &e = fork->Extents[extentIndex]; |
| 1878 | RINOK(_stream->Seek(SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog), STREAM_SEEK_SET, NULL)); | 2261 | RINOK(_stream->Seek(SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog), STREAM_SEEK_SET, NULL)); |
| 1879 | UInt64 extentRem = (UInt64)e.NumBlocks << Header.BlockSizeLog; | 2262 | UInt64 extentRem = (UInt64)e.NumBlocks << Header.BlockSizeLog; |
| 1880 | while (extentRem != 0) | 2263 | while (extentRem != 0) |
| 1881 | { | 2264 | { |
| 1882 | UInt64 rem = fork.Size - pos; | 2265 | const UInt64 rem = fork->Size - pos; |
| 1883 | if (rem == 0) | 2266 | if (rem == 0) |
| 1884 | { | 2267 | { |
| 1885 | // Here we check that there are no extra (empty) blocks in last extent. | 2268 | // Here we check that there are no extra (empty) blocks in last extent. |
| 1886 | if (extentRem >= ((UInt64)1 << Header.BlockSizeLog)) | 2269 | if (extentRem >= ((UInt64)1 << Header.BlockSizeLog)) |
| 1887 | res = NExtract::NOperationResult::kDataError; | 2270 | opRes = NExtract::NOperationResult::kDataError; |
| 1888 | break; | 2271 | break; |
| 1889 | } | 2272 | } |
| 1890 | size_t cur = kBufSize; | 2273 | size_t cur = kBufSize; |
| @@ -1895,7 +2278,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1895 | RINOK(ReadStream(_stream, buf, &cur)); | 2278 | RINOK(ReadStream(_stream, buf, &cur)); |
| 1896 | if (cur == 0) | 2279 | if (cur == 0) |
| 1897 | { | 2280 | { |
| 1898 | res = NExtract::NOperationResult::kDataError; | 2281 | opRes = NExtract::NOperationResult::kDataError; |
| 1899 | break; | 2282 | break; |
| 1900 | } | 2283 | } |
| 1901 | if (realOutStream) | 2284 | if (realOutStream) |
| @@ -1908,12 +2291,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 1908 | RINOK(extractCallback->SetCompleted(&processed)); | 2291 | RINOK(extractCallback->SetCompleted(&processed)); |
| 1909 | } | 2292 | } |
| 1910 | } | 2293 | } |
| 1911 | if (extentIndex != fork.Extents.Size() || fork.Size != pos) | 2294 | if (extentIndex != fork->Extents.Size() || fork->Size != pos) |
| 1912 | res = NExtract::NOperationResult::kDataError; | 2295 | opRes = NExtract::NOperationResult::kDataError; |
| 1913 | } | 2296 | } |
| 1914 | } | 2297 | } |
| 1915 | realOutStream.Release(); | 2298 | realOutStream.Release(); |
| 1916 | RINOK(extractCallback->SetOperationResult(res)); | 2299 | RINOK(extractCallback->SetOperationResult(opRes)); |
| 1917 | } | 2300 | } |
| 1918 | return S_OK; | 2301 | return S_OK; |
| 1919 | COM_TRY_END | 2302 | COM_TRY_END |
| @@ -1976,13 +2359,27 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | |||
| 1976 | *stream = 0; | 2359 | *stream = 0; |
| 1977 | 2360 | ||
| 1978 | const CRef &ref = Refs[index]; | 2361 | const CRef &ref = Refs[index]; |
| 2362 | const CFork *fork = NULL; | ||
| 1979 | if (ref.AttrIndex >= 0) | 2363 | if (ref.AttrIndex >= 0) |
| 1980 | return S_FALSE; | 2364 | { |
| 1981 | const CItem &item = Items[ref.ItemIndex]; | 2365 | const CAttr &attr = Attrs[ref.AttrIndex]; |
| 1982 | if (item.IsDir() || item.UseAttr) | 2366 | if (!attr.Fork_defined || attr.Data.Size() != 0) |
| 1983 | return S_FALSE; | 2367 | return S_FALSE; |
| 1984 | 2368 | fork = &attr.Fork; | |
| 1985 | return GetForkStream(item.GetFork(ref.IsResource), stream); | 2369 | } |
| 2370 | else | ||
| 2371 | { | ||
| 2372 | const CItem &item = Items[ref.ItemIndex]; | ||
| 2373 | if (ref.IsResource()) | ||
| 2374 | fork = &item.ResourceFork; | ||
| 2375 | else if (item.IsDir()) | ||
| 2376 | return S_FALSE; | ||
| 2377 | else if (item.CompressHeader.IsCorrect) | ||
| 2378 | return S_FALSE; | ||
| 2379 | else | ||
| 2380 | fork = &item.DataFork; | ||
| 2381 | } | ||
| 2382 | return GetForkStream(*fork, stream); | ||
| 1986 | } | 2383 | } |
| 1987 | 2384 | ||
| 1988 | static const Byte k_Signature[] = { | 2385 | static const Byte k_Signature[] = { |
diff --git a/CPP/7zip/Archive/HfsHandler.h b/CPP/7zip/Archive/HfsHandler.h new file mode 100644 index 0000000..2461f6b --- /dev/null +++ b/CPP/7zip/Archive/HfsHandler.h | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | // HfsHandler.h | ||
| 2 | |||
| 3 | #ifndef __HFS_HANDLER_H | ||
| 4 | #define __HFS_HANDLER_H | ||
| 5 | |||
| 6 | #include "../../Windows/PropVariant.h" | ||
| 7 | |||
| 8 | #include "../Compress/LzfseDecoder.h" | ||
| 9 | #include "../Compress/ZlibDecoder.h" | ||
| 10 | |||
| 11 | namespace NArchive { | ||
| 12 | namespace NHfs { | ||
| 13 | |||
| 14 | static const UInt32 k_decmpfs_HeaderSize = 16; | ||
| 15 | |||
| 16 | struct CCompressHeader | ||
| 17 | { | ||
| 18 | UInt64 UnpackSize; | ||
| 19 | UInt32 Method; | ||
| 20 | Byte DataPos; | ||
| 21 | bool IsCorrect; | ||
| 22 | bool IsSupported; | ||
| 23 | bool IsResource; | ||
| 24 | |||
| 25 | bool IsMethod_Compressed_Inline() const { return DataPos == k_decmpfs_HeaderSize; } | ||
| 26 | bool IsMethod_Uncompressed_Inline() const { return DataPos == k_decmpfs_HeaderSize + 1; } | ||
| 27 | bool IsMethod_Resource() const { return IsResource; } | ||
| 28 | |||
| 29 | void Parse(const Byte *p, size_t size); | ||
| 30 | |||
| 31 | void Clear() | ||
| 32 | { | ||
| 33 | UnpackSize = 0; | ||
| 34 | Method = 0; | ||
| 35 | DataPos = 0; | ||
| 36 | IsCorrect = false; | ||
| 37 | IsSupported = false; | ||
| 38 | IsResource = false; | ||
| 39 | } | ||
| 40 | |||
| 41 | CCompressHeader() { Clear(); } | ||
| 42 | |||
| 43 | void MethodToProp(NWindows::NCOM::CPropVariant &prop) const; | ||
| 44 | }; | ||
| 45 | |||
| 46 | void MethodsMaskToProp(UInt32 methodsMask, NWindows::NCOM::CPropVariant &prop); | ||
| 47 | |||
| 48 | |||
| 49 | class CDecoder | ||
| 50 | { | ||
| 51 | NCompress::NZlib::CDecoder *_zlibDecoderSpec; | ||
| 52 | CMyComPtr<ICompressCoder> _zlibDecoder; | ||
| 53 | |||
| 54 | NCompress::NLzfse::CDecoder *_lzfseDecoderSpec; | ||
| 55 | CMyComPtr<ICompressCoder> _lzfseDecoder; | ||
| 56 | |||
| 57 | CByteBuffer _tableBuf; | ||
| 58 | CByteBuffer _buf; | ||
| 59 | |||
| 60 | HRESULT ExtractResourceFork_ZLIB( | ||
| 61 | ISequentialInStream *inStream, ISequentialOutStream *realOutStream, | ||
| 62 | UInt64 forkSize, UInt64 unpackSize, | ||
| 63 | UInt64 progressStart, IArchiveExtractCallback *extractCallback); | ||
| 64 | |||
| 65 | HRESULT ExtractResourceFork_LZFSE( | ||
| 66 | ISequentialInStream *inStream, ISequentialOutStream *realOutStream, | ||
| 67 | UInt64 forkSize, UInt64 unpackSize, | ||
| 68 | UInt64 progressStart, IArchiveExtractCallback *extractCallback); | ||
| 69 | |||
| 70 | public: | ||
| 71 | |||
| 72 | HRESULT Extract( | ||
| 73 | ISequentialInStream *inStreamFork, ISequentialOutStream *realOutStream, | ||
| 74 | UInt64 forkSize, | ||
| 75 | const CCompressHeader &compressHeader, | ||
| 76 | const CByteBuffer *data, | ||
| 77 | UInt64 progressStart, IArchiveExtractCallback *extractCallback, | ||
| 78 | int &opRes); | ||
| 79 | |||
| 80 | CDecoder(); | ||
| 81 | }; | ||
| 82 | |||
| 83 | }} | ||
| 84 | |||
| 85 | #endif | ||
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp index 2232c64..691199e 100644 --- a/CPP/7zip/Archive/Udf/UdfHandler.cpp +++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp | |||
| @@ -48,14 +48,22 @@ static const Byte kProps[] = | |||
| 48 | kpidPackSize, | 48 | kpidPackSize, |
| 49 | kpidMTime, | 49 | kpidMTime, |
| 50 | kpidATime, | 50 | kpidATime, |
| 51 | kpidChangeTime | 51 | kpidCTime, |
| 52 | kpidChangeTime, | ||
| 53 | // kpidUserId, | ||
| 54 | // kpidGroupId, | ||
| 55 | // kpidPosixAttrib, | ||
| 56 | kpidLinks | ||
| 52 | }; | 57 | }; |
| 53 | 58 | ||
| 54 | static const Byte kArcProps[] = | 59 | static const Byte kArcProps[] = |
| 55 | { | 60 | { |
| 56 | kpidComment, | 61 | kpidUnpackVer, |
| 57 | kpidClusterSize, | 62 | kpidClusterSize, |
| 58 | kpidCTime | 63 | kpidSectorSize, |
| 64 | kpidCTime, | ||
| 65 | kpidMTime, | ||
| 66 | kpidComment | ||
| 59 | }; | 67 | }; |
| 60 | 68 | ||
| 61 | IMP_IInArchive_Props | 69 | IMP_IInArchive_Props |
| @@ -69,6 +77,18 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
| 69 | { | 77 | { |
| 70 | case kpidPhySize: prop = _archive.PhySize; break; | 78 | case kpidPhySize: prop = _archive.PhySize; break; |
| 71 | 79 | ||
| 80 | case kpidUnpackVer: | ||
| 81 | { | ||
| 82 | if (_archive.LogVols.Size() == 1) | ||
| 83 | { | ||
| 84 | UString s; | ||
| 85 | const CLogVol &vol = _archive.LogVols[0]; | ||
| 86 | vol.DomainId.AddUdfVersionTo(s); | ||
| 87 | if (!s.IsEmpty()) | ||
| 88 | prop = s; | ||
| 89 | } | ||
| 90 | break; | ||
| 91 | } | ||
| 72 | case kpidComment: | 92 | case kpidComment: |
| 73 | { | 93 | { |
| 74 | UString comment = _archive.GetComment(); | 94 | UString comment = _archive.GetComment(); |
| @@ -90,12 +110,21 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |||
| 90 | } | 110 | } |
| 91 | break; | 111 | break; |
| 92 | 112 | ||
| 113 | case kpidSectorSize: prop = ((UInt32)1 << _archive.SecLogSize); break; | ||
| 114 | |||
| 93 | case kpidCTime: | 115 | case kpidCTime: |
| 94 | if (_archive.LogVols.Size() == 1) | 116 | if (_archive.LogVols.Size() == 1) |
| 95 | { | 117 | { |
| 96 | const CLogVol &vol = _archive.LogVols[0]; | 118 | const CLogVol &vol = _archive.LogVols[0]; |
| 97 | if (vol.FileSets.Size() >= 1) | 119 | if (vol.FileSets.Size() >= 1) |
| 98 | UdfTimeToFileTime(vol.FileSets[0].RecodringTime, prop); | 120 | UdfTimeToFileTime(vol.FileSets[0].RecordingTime, prop); |
| 121 | } | ||
| 122 | break; | ||
| 123 | case kpidMTime: | ||
| 124 | if (_archive.PrimeVols.Size() == 1) | ||
| 125 | { | ||
| 126 | const CPrimeVol &pv = _archive.PrimeVols[0]; | ||
| 127 | UdfTimeToFileTime(pv.RecordingTime, prop); | ||
| 99 | } | 128 | } |
| 100 | break; | 129 | break; |
| 101 | 130 | ||
| @@ -160,6 +189,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
| 160 | { | 189 | { |
| 161 | const CLogVol &vol = _archive.LogVols[volIndex]; | 190 | const CLogVol &vol = _archive.LogVols[volIndex]; |
| 162 | bool showFileSetName = (vol.FileSets.Size() > 1); | 191 | bool showFileSetName = (vol.FileSets.Size() > 1); |
| 192 | // showFileSetName = true; // for debug | ||
| 163 | FOR_VECTOR (fsIndex, vol.FileSets) | 193 | FOR_VECTOR (fsIndex, vol.FileSets) |
| 164 | { | 194 | { |
| 165 | const CFileSet &fs = vol.FileSets[fsIndex]; | 195 | const CFileSet &fs = vol.FileSets[fsIndex]; |
| @@ -212,7 +242,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 212 | case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break; | 242 | case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break; |
| 213 | case kpidMTime: UdfTimeToFileTime(item.MTime, prop); break; | 243 | case kpidMTime: UdfTimeToFileTime(item.MTime, prop); break; |
| 214 | case kpidATime: UdfTimeToFileTime(item.ATime, prop); break; | 244 | case kpidATime: UdfTimeToFileTime(item.ATime, prop); break; |
| 245 | case kpidCTime: | ||
| 246 | if (item.IsExtended) | ||
| 247 | UdfTimeToFileTime(item.CreateTime, prop); | ||
| 248 | break; | ||
| 215 | case kpidChangeTime: UdfTimeToFileTime(item.AttribTime, prop); break; | 249 | case kpidChangeTime: UdfTimeToFileTime(item.AttribTime, prop); break; |
| 250 | // case kpidUserId: prop = item.Uid; break; | ||
| 251 | // case kpidGroupId: prop = item.Gid; break; | ||
| 252 | // case kpidPosixAttrib: prop = (UInt32)item.Permissions; break; | ||
| 253 | case kpidLinks: prop = (UInt32)item.FileLinkCount; break; | ||
| 216 | } | 254 | } |
| 217 | } | 255 | } |
| 218 | prop.Detach(value); | 256 | prop.Detach(value); |
| @@ -255,7 +293,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | |||
| 255 | if (size < len) | 293 | if (size < len) |
| 256 | return S_FALSE; | 294 | return S_FALSE; |
| 257 | 295 | ||
| 258 | int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; | 296 | const unsigned partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; |
| 259 | UInt32 logBlockNumber = extent.Pos; | 297 | UInt32 logBlockNumber = extent.Pos; |
| 260 | const CPartition &partition = _archive.Partitions[partitionIndex]; | 298 | const CPartition &partition = _archive.Partitions[partitionIndex]; |
| 261 | UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) + | 299 | UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) + |
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.h b/CPP/7zip/Archive/Udf/UdfHandler.h index da44b23..462faee 100644 --- a/CPP/7zip/Archive/Udf/UdfHandler.h +++ b/CPP/7zip/Archive/Udf/UdfHandler.h | |||
| @@ -24,9 +24,9 @@ class CHandler: | |||
| 24 | public IInArchiveGetStream, | 24 | public IInArchiveGetStream, |
| 25 | public CMyUnknownImp | 25 | public CMyUnknownImp |
| 26 | { | 26 | { |
| 27 | CRecordVector<CRef2> _refs2; | ||
| 27 | CMyComPtr<IInStream> _inStream; | 28 | CMyComPtr<IInStream> _inStream; |
| 28 | CInArchive _archive; | 29 | CInArchive _archive; |
| 29 | CRecordVector<CRef2> _refs2; | ||
| 30 | public: | 30 | public: |
| 31 | MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) | 31 | MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) |
| 32 | INTERFACE_IInArchive(;) | 32 | INTERFACE_IInArchive(;) |
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index d2d2b20..70496e4 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | #include "../../../../C/CpuArch.h" | 11 | #include "../../../../C/CpuArch.h" |
| 12 | 12 | ||
| 13 | #include "../../../Windows/PropVariantUtils.h" | ||
| 14 | |||
| 13 | #include "../../Common/RegisterArc.h" | 15 | #include "../../Common/RegisterArc.h" |
| 14 | #include "../../Common/StreamUtils.h" | 16 | #include "../../Common/StreamUtils.h" |
| 15 | 17 | ||
| @@ -25,6 +27,10 @@ | |||
| 25 | #define Get32(p) GetUi32(p) | 27 | #define Get32(p) GetUi32(p) |
| 26 | #define Get64(p) GetUi64(p) | 28 | #define Get64(p) GetUi64(p) |
| 27 | 29 | ||
| 30 | #define G16(_offs_, dest) dest = Get16(p + (_offs_)); | ||
| 31 | #define G32(_offs_, dest) dest = Get32(p + (_offs_)); | ||
| 32 | #define G64(_offs_, dest) dest = Get64(p + (_offs_)); | ||
| 33 | |||
| 28 | namespace NArchive { | 34 | namespace NArchive { |
| 29 | namespace NUdf { | 35 | namespace NUdf { |
| 30 | 36 | ||
| @@ -39,7 +45,6 @@ static const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33; | |||
| 39 | static const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33; | 45 | static const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33; |
| 40 | 46 | ||
| 41 | #define CRC16_INIT_VAL 0 | 47 | #define CRC16_INIT_VAL 0 |
| 42 | // #define CRC16_GET_DIGEST(crc) (crc) | ||
| 43 | #define CRC16_UPDATE_BYTE(crc, b) ((UInt16)(g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8))) | 48 | #define CRC16_UPDATE_BYTE(crc, b) ((UInt16)(g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8))) |
| 44 | 49 | ||
| 45 | #define kCrc16Poly 0x1021 | 50 | #define kCrc16Poly 0x1021 |
| @@ -57,22 +62,20 @@ static void MY_FAST_CALL Crc16GenerateTable(void) | |||
| 57 | } | 62 | } |
| 58 | } | 63 | } |
| 59 | 64 | ||
| 60 | static UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size) | 65 | static UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size) |
| 61 | { | 66 | { |
| 67 | UInt32 v = CRC16_INIT_VAL; | ||
| 62 | const Byte *p = (const Byte *)data; | 68 | const Byte *p = (const Byte *)data; |
| 63 | for (; size > 0 ; size--, p++) | 69 | const Byte *pEnd = p + size; |
| 70 | for (; p != pEnd; p++) | ||
| 64 | v = CRC16_UPDATE_BYTE(v, *p); | 71 | v = CRC16_UPDATE_BYTE(v, *p); |
| 65 | return v; | 72 | return v; |
| 66 | } | 73 | } |
| 67 | 74 | ||
| 68 | static UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size) | ||
| 69 | { | ||
| 70 | return Crc16_Update(CRC16_INIT_VAL, data, size); | ||
| 71 | } | ||
| 72 | |||
| 73 | static struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit; | 75 | static struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit; |
| 74 | 76 | ||
| 75 | 77 | ||
| 78 | // ---------- ECMA Part 1 ---------- | ||
| 76 | 79 | ||
| 77 | void CDString::Parse(const Byte *p, unsigned size) | 80 | void CDString::Parse(const Byte *p, unsigned size) |
| 78 | { | 81 | { |
| @@ -82,16 +85,17 @@ void CDString::Parse(const Byte *p, unsigned size) | |||
| 82 | static UString ParseDString(const Byte *data, unsigned size) | 85 | static UString ParseDString(const Byte *data, unsigned size) |
| 83 | { | 86 | { |
| 84 | UString res; | 87 | UString res; |
| 85 | if (size > 0) | 88 | if (size != 0) |
| 86 | { | 89 | { |
| 87 | wchar_t *p; | 90 | wchar_t *p; |
| 88 | Byte type = data[0]; | 91 | const Byte type = *data++; |
| 92 | size--; | ||
| 89 | if (type == 8) | 93 | if (type == 8) |
| 90 | { | 94 | { |
| 91 | p = res.GetBuf(size); | 95 | p = res.GetBuf(size); |
| 92 | for (unsigned i = 1; i < size; i++) | 96 | for (unsigned i = 0; i < size; i++) |
| 93 | { | 97 | { |
| 94 | wchar_t c = data[i]; | 98 | const wchar_t c = data[i]; |
| 95 | if (c == 0) | 99 | if (c == 0) |
| 96 | break; | 100 | break; |
| 97 | *p++ = c; | 101 | *p++ = c; |
| @@ -99,10 +103,11 @@ static UString ParseDString(const Byte *data, unsigned size) | |||
| 99 | } | 103 | } |
| 100 | else if (type == 16) | 104 | else if (type == 16) |
| 101 | { | 105 | { |
| 106 | size &= ~(unsigned)1; | ||
| 102 | p = res.GetBuf(size / 2); | 107 | p = res.GetBuf(size / 2); |
| 103 | for (unsigned i = 1; i + 2 <= size; i += 2) | 108 | for (unsigned i = 0; i < size; i += 2) |
| 104 | { | 109 | { |
| 105 | wchar_t c = GetBe16(data + i); | 110 | const wchar_t c = GetBe16(data + i); |
| 106 | if (c == 0) | 111 | if (c == 0) |
| 107 | break; | 112 | break; |
| 108 | *p++ = c; | 113 | *p++ = c; |
| @@ -116,75 +121,117 @@ static UString ParseDString(const Byte *data, unsigned size) | |||
| 116 | return res; | 121 | return res; |
| 117 | } | 122 | } |
| 118 | 123 | ||
| 124 | UString CDString32::GetString() const | ||
| 125 | { | ||
| 126 | const unsigned size = Data[sizeof(Data) - 1]; | ||
| 127 | return ParseDString(Data, MyMin(size, (unsigned)(sizeof(Data) - 1))); | ||
| 128 | } | ||
| 129 | |||
| 119 | UString CDString128::GetString() const | 130 | UString CDString128::GetString() const |
| 120 | { | 131 | { |
| 121 | unsigned size = Data[sizeof(Data) - 1]; | 132 | const unsigned size = Data[sizeof(Data) - 1]; |
| 122 | return ParseDString(Data, MyMin(size, (unsigned)(sizeof(Data) - 1))); | 133 | return ParseDString(Data, MyMin(size, (unsigned)(sizeof(Data) - 1))); |
| 123 | } | 134 | } |
| 124 | 135 | ||
| 125 | UString CDString::GetString() const { return ParseDString(Data, (unsigned)Data.Size()); } | 136 | UString CDString::GetString() const { return ParseDString(Data, (unsigned)Data.Size()); } |
| 126 | 137 | ||
| 127 | void CTime::Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); } | 138 | void CTime::Parse(const Byte *p) { memcpy(Data, p, sizeof(Data)); } |
| 128 | 139 | ||
| 129 | /* | 140 | |
| 130 | void CRegId::Parse(const Byte *buf) | 141 | static void AddCommentChars(UString &dest, const char *s, size_t size) |
| 131 | { | 142 | { |
| 132 | Flags = buf[0]; | 143 | for (size_t i = 0; i < size; i++) |
| 133 | memcpy(Id, buf + 1, sizeof(Id)); | 144 | { |
| 134 | memcpy(Suffix, buf + 24, sizeof(Suffix)); | 145 | char c = s[i]; |
| 146 | if (c == 0) | ||
| 147 | break; | ||
| 148 | if (c < 0x20) | ||
| 149 | c = '_'; | ||
| 150 | dest += (wchar_t)c; | ||
| 151 | } | ||
| 135 | } | 152 | } |
| 136 | */ | ||
| 137 | 153 | ||
| 138 | // ECMA 3/7.1 | ||
| 139 | 154 | ||
| 140 | struct CExtent | 155 | void CRegId::Parse(const Byte *p) |
| 141 | { | 156 | { |
| 142 | UInt32 Len; | 157 | Flags = p[0]; |
| 143 | UInt32 Pos; | 158 | memcpy(Id, p + 1, sizeof(Id)); |
| 159 | memcpy(Suffix, p + 24, sizeof(Suffix)); | ||
| 160 | } | ||
| 144 | 161 | ||
| 145 | void Parse(const Byte *buf); | 162 | void CRegId::AddCommentTo(UString &s) const |
| 146 | }; | 163 | { |
| 164 | AddCommentChars(s, Id, sizeof(Id)); | ||
| 165 | } | ||
| 147 | 166 | ||
| 148 | void CExtent::Parse(const Byte *buf) | 167 | void CRegId::AddUdfVersionTo(UString &s) const |
| 149 | { | 168 | { |
| 150 | Len = Get32(buf); | 169 | // use it only for "Domain Identifier Suffix" and "UDF Identifier Suffix" |
| 151 | Pos = Get32(buf + 4); | 170 | // UDF 2.1.5.3 |
| 171 | // Revision in hex (3 digits) | ||
| 172 | const Byte minor = Suffix[0]; | ||
| 173 | const Byte major = Suffix[1]; | ||
| 174 | if (major != 0 || minor != 0) | ||
| 175 | { | ||
| 176 | char temp[16]; | ||
| 177 | ConvertUInt32ToHex(major, temp); | ||
| 178 | s += temp; | ||
| 179 | s += '.'; | ||
| 180 | ConvertUInt32ToHex8Digits(minor, temp); | ||
| 181 | s += &temp[8 - 2]; | ||
| 182 | } | ||
| 152 | } | 183 | } |
| 153 | 184 | ||
| 185 | |||
| 186 | // ---------- ECMA Part 3: Volume Structure ---------- | ||
| 187 | |||
| 188 | void CExtent::Parse(const Byte *p) | ||
| 189 | { | ||
| 190 | /* Len shall be less than < 2^30. | ||
| 191 | Unless otherwise specified, the length shall be an integral multiple of the logical sector size. | ||
| 192 | If (Len == 0), no extent is specified and (Pos) shall contain 0 */ | ||
| 193 | G32 (0, Len); | ||
| 194 | G32 (4, Pos); | ||
| 195 | } | ||
| 196 | |||
| 197 | |||
| 154 | // ECMA 3/7.2 | 198 | // ECMA 3/7.2 |
| 155 | 199 | ||
| 156 | struct CTag | 200 | struct CTag |
| 157 | { | 201 | { |
| 158 | UInt16 Id; | 202 | UInt16 Id; |
| 159 | UInt16 Version; | 203 | // UInt16 Version; |
| 160 | // Byte Checksum; | 204 | // Byte Checksum; |
| 161 | // UInt16 SerialNumber; | 205 | // UInt16 SerialNumber; |
| 162 | // UInt16 Crc; | 206 | // UInt16 Crc; |
| 163 | // UInt16 CrcLen; | 207 | UInt16 CrcLen; |
| 164 | // UInt32 TagLocation; | 208 | // UInt32 TagLocation; // the number of the logical sector |
| 165 | 209 | ||
| 166 | HRESULT Parse(const Byte *buf, size_t size); | 210 | HRESULT Parse(const Byte *p, size_t size); |
| 167 | }; | 211 | }; |
| 168 | 212 | ||
| 169 | HRESULT CTag::Parse(const Byte *buf, size_t size) | 213 | HRESULT CTag::Parse(const Byte *p, size_t size) |
| 170 | { | 214 | { |
| 171 | if (size < 16) | 215 | if (size < 16) |
| 172 | return S_FALSE; | 216 | return S_FALSE; |
| 173 | Byte sum = 0; | 217 | { |
| 174 | int i; | 218 | unsigned sum = 0; |
| 175 | for (i = 0; i < 4; i++) sum = (Byte)(sum + buf[i]); | 219 | for (unsigned i = 0; i < 16; i++) |
| 176 | for (i = 5; i < 16; i++) sum = (Byte)(sum + buf[i]); | 220 | sum = sum + p[i]; |
| 177 | if (sum != buf[4] || buf[5] != 0) return S_FALSE; | 221 | if ((Byte)(sum - p[4]) != p[4] || p[5] != 0) |
| 178 | 222 | return S_FALSE; | |
| 179 | Id = Get16(buf); | 223 | } |
| 180 | Version = Get16(buf + 2); | 224 | Id = Get16(p); |
| 181 | // SerialNumber = Get16(buf + 6); | 225 | const UInt16 Version = Get16(p + 2); |
| 182 | UInt32 crc = Get16(buf + 8); | 226 | if (Version != 2 && Version != 3) |
| 183 | UInt32 crcLen = Get16(buf + 10); | 227 | return S_FALSE; |
| 184 | // TagLocation = Get32(buf + 12); | 228 | // SerialNumber = Get16(p + 6); |
| 185 | 229 | const UInt32 crc = Get16(p + 8); | |
| 186 | if (size >= 16 + crcLen) | 230 | CrcLen = Get16(p + 10); |
| 187 | if (crc == Crc16Calc(buf + 16, (size_t)crcLen)) | 231 | // TagLocation = Get32(p + 12); |
| 232 | |||
| 233 | if (size >= 16 + (size_t)CrcLen) | ||
| 234 | if (crc == Crc16Calc(p + 16, (size_t)CrcLen)) | ||
| 188 | return S_OK; | 235 | return S_OK; |
| 189 | return S_FALSE; | 236 | return S_FALSE; |
| 190 | } | 237 | } |
| @@ -210,52 +257,78 @@ enum EDescriptorType | |||
| 210 | DESC_TYPE_Terminal = 260, | 257 | DESC_TYPE_Terminal = 260, |
| 211 | DESC_TYPE_File = 261, | 258 | DESC_TYPE_File = 261, |
| 212 | DESC_TYPE_ExtendedAttrHeader = 262, | 259 | DESC_TYPE_ExtendedAttrHeader = 262, |
| 213 | DESC_TYPE_UnallocatedSpace = 263, | 260 | DESC_TYPE_UnallocatedSpaceEntry = 263, |
| 214 | DESC_TYPE_SpaceBitmap = 264, | 261 | DESC_TYPE_SpaceBitmap = 264, |
| 215 | DESC_TYPE_PartitionIntegrity = 265, | 262 | DESC_TYPE_PartitionIntegrity = 265, |
| 216 | DESC_TYPE_ExtendedFile = 266 | 263 | DESC_TYPE_ExtendedFile = 266 |
| 217 | }; | 264 | }; |
| 218 | 265 | ||
| 219 | 266 | ||
| 220 | void CLogBlockAddr::Parse(const Byte *buf) | 267 | void CLogBlockAddr::Parse(const Byte *p) |
| 221 | { | 268 | { |
| 222 | Pos = Get32(buf); | 269 | G32 (0, Pos); |
| 223 | PartitionRef = Get16(buf + 4); | 270 | G16 (4, PartitionRef); |
| 224 | } | 271 | } |
| 225 | 272 | ||
| 226 | void CShortAllocDesc::Parse(const Byte *buf) | 273 | void CShortAllocDesc::Parse(const Byte *p) |
| 227 | { | 274 | { |
| 228 | Len = Get32(buf); | 275 | G32 (0, Len); |
| 229 | Pos = Get32(buf + 4); | 276 | G32 (4, Pos); |
| 230 | } | 277 | } |
| 231 | 278 | ||
| 232 | /* | 279 | /* |
| 233 | void CADImpUse::Parse(const Byte *buf) | 280 | void CADImpUse::Parse(const Byte *p) |
| 234 | { | 281 | { |
| 235 | Flags = Get16(buf); | 282 | G16 (0, Flags); |
| 236 | UdfUniqueId = Get32(buf + 2); | 283 | G32 (2, UdfUniqueId); |
| 237 | } | 284 | } |
| 238 | */ | 285 | */ |
| 239 | 286 | ||
| 240 | void CLongAllocDesc::Parse(const Byte *buf) | 287 | void CLongAllocDesc::Parse(const Byte *p) |
| 241 | { | 288 | { |
| 242 | Len = Get32(buf); | 289 | G32 (0, Len); |
| 243 | Location.Parse(buf + 4); | 290 | Location.Parse(p + 4); |
| 244 | // memcpy(ImplUse, buf + 10, sizeof(ImplUse)); | 291 | // memcpy(ImplUse, p + 10, sizeof(ImplUse)); |
| 245 | // adImpUse.Parse(ImplUse); | 292 | // adImpUse.Parse(ImplUse); |
| 246 | } | 293 | } |
| 247 | 294 | ||
| 248 | bool CInArchive::CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const | 295 | |
| 296 | void CPrimeVol::Parse(const Byte *p) | ||
| 297 | { | ||
| 298 | // G32 (16, VolumeDescriptorSequenceNumber); | ||
| 299 | G32 (20, PrimaryVolumeDescriptorNumber); | ||
| 300 | VolumeId.Parse(p + 24); | ||
| 301 | G16 (56, VolumeSequenceNumber); | ||
| 302 | G16 (58, MaximumVolumeSequenceNumber); | ||
| 303 | // G16 (60, InterchangeLevel); | ||
| 304 | // G16 (62, MaximumInterchangeLevel); | ||
| 305 | // G32 (64, CharacterSetList) | ||
| 306 | // G32 (68, MaximumCharacterSetList) | ||
| 307 | VolumeSetId.Parse(p + 72); | ||
| 308 | // 200 64 Descriptor Character Set charspec (1/7.2.1) | ||
| 309 | // 264 64 Explanatory Character Set charspec (1/7.2.1) | ||
| 310 | // VolumeAbstract.Parse(p + 328); | ||
| 311 | // VolumeCopyrightNotice.Parse(p + 336); | ||
| 312 | ApplicationId.Parse(p + 344); | ||
| 313 | RecordingTime.Parse(p + 376); | ||
| 314 | ImplId.Parse(p + 388); | ||
| 315 | // 420 64 Implementation Use bytes | ||
| 316 | // G32 (484, PredecessorVolumeDescriptorSequenceLocation); | ||
| 317 | // G16 (488, Flags); | ||
| 318 | } | ||
| 319 | |||
| 320 | |||
| 321 | |||
| 322 | bool CInArchive::CheckExtent(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len) const | ||
| 249 | { | 323 | { |
| 250 | const CLogVol &vol = LogVols[volIndex]; | 324 | const CLogVol &vol = LogVols[volIndex]; |
| 251 | if (partitionRef >= (int)vol.PartitionMaps.Size()) | 325 | if (partitionRef >= vol.PartitionMaps.Size()) |
| 252 | return false; | 326 | return false; |
| 253 | const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; | 327 | const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; |
| 254 | UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize; | 328 | return ((UInt64)blockPos * vol.BlockSize + len) <= ((UInt64)partition.Len << SecLogSize); |
| 255 | return (offset + len) <= (((UInt64)partition.Pos + partition.Len) << SecLogSize); | ||
| 256 | } | 329 | } |
| 257 | 330 | ||
| 258 | bool CInArchive::CheckItemExtents(int volIndex, const CItem &item) const | 331 | bool CInArchive::CheckItemExtents(unsigned volIndex, const CItem &item) const |
| 259 | { | 332 | { |
| 260 | FOR_VECTOR (i, item.Extents) | 333 | FOR_VECTOR (i, item.Extents) |
| 261 | { | 334 | { |
| @@ -266,7 +339,7 @@ bool CInArchive::CheckItemExtents(int volIndex, const CItem &item) const | |||
| 266 | return true; | 339 | return true; |
| 267 | } | 340 | } |
| 268 | 341 | ||
| 269 | HRESULT CInArchive::Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf) | 342 | HRESULT CInArchive::Read(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len, Byte *buf) |
| 270 | { | 343 | { |
| 271 | if (!CheckExtent(volIndex, partitionRef, blockPos, len)) | 344 | if (!CheckExtent(volIndex, partitionRef, blockPos, len)) |
| 272 | return S_FALSE; | 345 | return S_FALSE; |
| @@ -274,20 +347,20 @@ HRESULT CInArchive::Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 | |||
| 274 | const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; | 347 | const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; |
| 275 | UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize; | 348 | UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize; |
| 276 | RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); | 349 | RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); |
| 277 | HRESULT res = ReadStream_FALSE(_stream, buf, len); | 350 | offset += len; |
| 278 | if (res == S_FALSE && offset + len > FileSize) | 351 | UpdatePhySize(offset); |
| 352 | const HRESULT res = ReadStream_FALSE(_stream, buf, len); | ||
| 353 | if (res == S_FALSE && offset > FileSize) | ||
| 279 | UnexpectedEnd = true; | 354 | UnexpectedEnd = true; |
| 280 | RINOK(res); | 355 | return res; |
| 281 | UpdatePhySize(offset + len); | ||
| 282 | return S_OK; | ||
| 283 | } | 356 | } |
| 284 | 357 | ||
| 285 | HRESULT CInArchive::Read(int volIndex, const CLongAllocDesc &lad, Byte *buf) | 358 | HRESULT CInArchive::ReadLad(unsigned volIndex, const CLongAllocDesc &lad, Byte *buf) |
| 286 | { | 359 | { |
| 287 | return Read(volIndex, lad.Location.PartitionRef, lad.Location.Pos, lad.GetLen(), (Byte *)buf); | 360 | return Read(volIndex, lad.Location.PartitionRef, lad.Location.Pos, lad.GetLen(), (Byte *)buf); |
| 288 | } | 361 | } |
| 289 | 362 | ||
| 290 | HRESULT CInArchive::ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf) | 363 | HRESULT CInArchive::ReadFromFile(unsigned volIndex, const CItem &item, CByteBuffer &buf) |
| 291 | { | 364 | { |
| 292 | if (item.Size >= (UInt32)1 << 30) | 365 | if (item.Size >= (UInt32)1 << 30) |
| 293 | return S_FALSE; | 366 | return S_FALSE; |
| @@ -301,7 +374,7 @@ HRESULT CInArchive::ReadFromFile(int volIndex, const CItem &item, CByteBuffer &b | |||
| 301 | FOR_VECTOR (i, item.Extents) | 374 | FOR_VECTOR (i, item.Extents) |
| 302 | { | 375 | { |
| 303 | const CMyExtent &e = item.Extents[i]; | 376 | const CMyExtent &e = item.Extents[i]; |
| 304 | UInt32 len = e.GetLen(); | 377 | const UInt32 len = e.GetLen(); |
| 305 | RINOK(Read(volIndex, e.PartitionRef, e.Pos, len, (Byte *)buf + pos)); | 378 | RINOK(Read(volIndex, e.PartitionRef, e.Pos, len, (Byte *)buf + pos)); |
| 306 | pos += len; | 379 | pos += len; |
| 307 | } | 380 | } |
| @@ -311,36 +384,70 @@ HRESULT CInArchive::ReadFromFile(int volIndex, const CItem &item, CByteBuffer &b | |||
| 311 | 384 | ||
| 312 | void CIcbTag::Parse(const Byte *p) | 385 | void CIcbTag::Parse(const Byte *p) |
| 313 | { | 386 | { |
| 314 | // PriorDirectNum = Get32(p); | 387 | // G32 (0, PriorDirectNum); |
| 315 | // StrategyType = Get16(p + 4); | 388 | // G16 (4, StrategyType); |
| 316 | // StrategyParam = Get16(p + 6); | 389 | // G16 (6, StrategyParam); |
| 317 | // MaxNumOfEntries = Get16(p + 8); | 390 | // G16 (8, MaxNumOfEntries); |
| 318 | FileType = p[11]; | 391 | FileType = p[11]; |
| 319 | // ParentIcb.Parse(p + 12); | 392 | // ParentIcb.Parse(p + 12); |
| 320 | Flags = Get16(p + 18); | 393 | G16 (18, Flags); |
| 321 | } | 394 | } |
| 322 | 395 | ||
| 396 | |||
| 397 | // ECMA 4/14.9 File Entry | ||
| 398 | // UDF FileEntry 2.3.6 | ||
| 399 | |||
| 400 | // ECMA 4/14.17 Extended File Entry | ||
| 401 | |||
| 323 | void CItem::Parse(const Byte *p) | 402 | void CItem::Parse(const Byte *p) |
| 324 | { | 403 | { |
| 325 | // Uid = Get32(p + 36); | 404 | // (-1) can be stored in Uid/Gid. |
| 326 | // Gid = Get32(p + 40); | 405 | // G32 (36, Uid); |
| 327 | // Permissions = Get32(p + 44); | 406 | // G32 (40, Gid); |
| 328 | // FileLinkCount = Get16(p + 48); | 407 | // G32 (44, Permissions); |
| 408 | G16 (48, FileLinkCount); | ||
| 329 | // RecordFormat = p[50]; | 409 | // RecordFormat = p[50]; |
| 330 | // RecordDisplayAttr = p[51]; | 410 | // RecordDisplayAttr = p[51]; |
| 331 | // RecordLen = Get32(p + 52); | 411 | // G32 (52, RecordLen); |
| 332 | Size = Get64(p + 56); | 412 | G64 (56, Size); |
| 333 | NumLogBlockRecorded = Get64(p + 64); | 413 | if (IsExtended) |
| 414 | { | ||
| 415 | // The sum of all Information Length fields for all streams of a file (including the default stream). If this file has no | ||
| 416 | // streams, the Object Size shall be equal to the Information Length. | ||
| 417 | // G64 (64, ObjectSize); | ||
| 418 | p += 8; | ||
| 419 | } | ||
| 420 | G64 (64, NumLogBlockRecorded); | ||
| 334 | ATime.Parse(p + 72); | 421 | ATime.Parse(p + 72); |
| 335 | MTime.Parse(p + 84); | 422 | MTime.Parse(p + 84); |
| 423 | if (IsExtended) | ||
| 424 | { | ||
| 425 | CreateTime.Parse(p + 96); | ||
| 426 | p += 12; | ||
| 427 | } | ||
| 336 | AttribTime.Parse(p + 96); | 428 | AttribTime.Parse(p + 96); |
| 337 | // CheckPoint = Get32(p + 108); | 429 | // G32 (108, CheckPoint); |
| 430 | /* | ||
| 431 | if (IsExtended) | ||
| 432 | { | ||
| 433 | // Get32(p + 112); // reserved | ||
| 434 | p += 4; | ||
| 435 | } | ||
| 338 | // ExtendedAttrIcb.Parse(p + 112); | 436 | // ExtendedAttrIcb.Parse(p + 112); |
| 437 | if (IsExtended) | ||
| 438 | { | ||
| 439 | StreamDirectoryIcb.Parse(p + 128); | ||
| 440 | p += 16; | ||
| 441 | } | ||
| 442 | */ | ||
| 443 | |||
| 339 | // ImplId.Parse(p + 128); | 444 | // ImplId.Parse(p + 128); |
| 340 | // UniqueId = Get64(p + 160); | 445 | // G64 (160, UniqueId); |
| 341 | } | 446 | } |
| 342 | 447 | ||
| 343 | // 4/14.4 | 448 | |
| 449 | // ECMA 4/14.4 | ||
| 450 | |||
| 344 | struct CFileId | 451 | struct CFileId |
| 345 | { | 452 | { |
| 346 | // UInt16 FileVersion; | 453 | // UInt16 FileVersion; |
| @@ -350,38 +457,40 @@ struct CFileId | |||
| 350 | CLongAllocDesc Icb; | 457 | CLongAllocDesc Icb; |
| 351 | 458 | ||
| 352 | bool IsItLinkParent() const { return (FileCharacteristics & FILEID_CHARACS_Parent) != 0; } | 459 | bool IsItLinkParent() const { return (FileCharacteristics & FILEID_CHARACS_Parent) != 0; } |
| 353 | HRESULT Parse(const Byte *p, size_t size, size_t &processed); | 460 | size_t Parse(const Byte *p, size_t size); |
| 354 | }; | 461 | }; |
| 355 | 462 | ||
| 356 | HRESULT CFileId::Parse(const Byte *p, size_t size, size_t &processed) | 463 | size_t CFileId::Parse(const Byte *p, size_t size) |
| 357 | { | 464 | { |
| 358 | processed = 0; | 465 | size_t processed = 0; |
| 359 | if (size < 38) | 466 | if (size < 38) |
| 360 | return S_FALSE; | 467 | return 0; |
| 361 | CTag tag; | 468 | CTag tag; |
| 362 | RINOK(tag.Parse(p, size)); | 469 | RINOK(tag.Parse(p, size)); |
| 363 | if (tag.Id != DESC_TYPE_FileId) | 470 | if (tag.Id != DESC_TYPE_FileId) |
| 364 | return S_FALSE; | 471 | return 0; |
| 365 | // FileVersion = Get16(p + 16); | 472 | // FileVersion = Get16(p + 16); |
| 366 | FileCharacteristics = p[18]; | 473 | FileCharacteristics = p[18]; |
| 367 | unsigned idLen = p[19]; | 474 | const unsigned idLen = p[19]; |
| 368 | Icb.Parse(p + 20); | 475 | Icb.Parse(p + 20); |
| 369 | unsigned impLen = Get16(p + 36); | 476 | const unsigned impLen = Get16(p + 36); |
| 370 | if (size < 38 + idLen + impLen) | 477 | if (size < 38 + idLen + impLen) |
| 371 | return S_FALSE; | 478 | return 0; |
| 372 | // ImplUse.SetCapacity(impLen); | ||
| 373 | processed = 38; | 479 | processed = 38; |
| 374 | // memcpy(ImplUse, p + processed, impLen); | 480 | // ImplUse.CopyFrom(p + processed, impLen); |
| 375 | processed += impLen; | 481 | processed += impLen; |
| 376 | Id.Parse(p + processed, idLen); | 482 | Id.Parse(p + processed, idLen); |
| 377 | processed += idLen; | 483 | processed += idLen; |
| 378 | for (;(processed & 3) != 0; processed++) | 484 | for (;(processed & 3) != 0; processed++) |
| 379 | if (p[processed] != 0) | 485 | if (p[processed] != 0) |
| 380 | return S_FALSE; | 486 | return 0; |
| 381 | return (processed <= size) ? S_OK : S_FALSE; | 487 | if ((size_t)tag.CrcLen + 16 != processed) return 0; |
| 488 | return (processed <= size) ? processed : 0; | ||
| 382 | } | 489 | } |
| 383 | 490 | ||
| 384 | HRESULT CInArchive::ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed) | 491 | |
| 492 | |||
| 493 | HRESULT CInArchive::ReadFileItem(unsigned volIndex, unsigned fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed) | ||
| 385 | { | 494 | { |
| 386 | if (Files.Size() % 100 == 0) | 495 | if (Files.Size() % 100 == 0) |
| 387 | RINOK(_progress->SetCompleted(Files.Size(), _processedProgressBytes)); | 496 | RINOK(_progress->SetCompleted(Files.Size(), _processedProgressBytes)); |
| @@ -389,12 +498,12 @@ HRESULT CInArchive::ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc | |||
| 389 | return S_FALSE; | 498 | return S_FALSE; |
| 390 | CFile &file = Files.Back(); | 499 | CFile &file = Files.Back(); |
| 391 | const CLogVol &vol = LogVols[volIndex]; | 500 | const CLogVol &vol = LogVols[volIndex]; |
| 392 | unsigned partitionRef = lad.Location.PartitionRef; | 501 | const unsigned partitionRef = lad.Location.PartitionRef; |
| 393 | if (partitionRef >= vol.PartitionMaps.Size()) | 502 | if (partitionRef >= vol.PartitionMaps.Size()) |
| 394 | return S_FALSE; | 503 | return S_FALSE; |
| 395 | CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; | 504 | CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex]; |
| 396 | 505 | ||
| 397 | UInt32 key = lad.Location.Pos; | 506 | const UInt32 key = lad.Location.Pos; |
| 398 | UInt32 value; | 507 | UInt32 value; |
| 399 | const UInt32 kRecursedErrorValue = (UInt32)(Int32)-1; | 508 | const UInt32 kRecursedErrorValue = (UInt32)(Int32)-1; |
| 400 | if (partition.Map.Find(key, value)) | 509 | if (partition.Map.Find(key, value)) |
| @@ -416,32 +525,47 @@ HRESULT CInArchive::ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc | |||
| 416 | return S_OK; | 525 | return S_OK; |
| 417 | } | 526 | } |
| 418 | 527 | ||
| 419 | HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed) | 528 | |
| 529 | // (fsIndex = -1) means that it's metadata file | ||
| 530 | |||
| 531 | HRESULT CInArchive::ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed) | ||
| 420 | { | 532 | { |
| 421 | if (Items.Size() > kNumItemsMax) | 533 | if (Items.Size() >= kNumItemsMax) |
| 422 | return S_FALSE; | 534 | return S_FALSE; |
| 423 | Items.Add(CItem()); | 535 | CItem &item = Items.AddNew(); |
| 424 | CItem &item = Items.Back(); | ||
| 425 | 536 | ||
| 426 | const CLogVol &vol = LogVols[volIndex]; | 537 | const CLogVol &vol = LogVols[volIndex]; |
| 427 | 538 | ||
| 428 | if (lad.GetLen() != vol.BlockSize) | 539 | const size_t size = lad.GetLen(); |
| 540 | if (size != vol.BlockSize) | ||
| 429 | return S_FALSE; | 541 | return S_FALSE; |
| 430 | 542 | ||
| 431 | const size_t size = lad.GetLen(); | ||
| 432 | CByteBuffer buf(size); | 543 | CByteBuffer buf(size); |
| 433 | RINOK(Read(volIndex, lad, buf)); | 544 | RINOK(ReadLad(volIndex, lad, buf)); |
| 434 | 545 | ||
| 435 | CTag tag; | 546 | CTag tag; |
| 436 | const Byte *p = buf; | 547 | const Byte *p = buf; |
| 437 | RINOK(tag.Parse(p, size)); | 548 | RINOK(tag.Parse(p, size)); |
| 438 | if (size < 176) | 549 | |
| 550 | item.IsExtended = (tag.Id == DESC_TYPE_ExtendedFile); | ||
| 551 | const size_t kExtendOffset = item.IsExtended ? 40 : 0; | ||
| 552 | |||
| 553 | if (size < kExtendOffset + 176) | ||
| 439 | return S_FALSE; | 554 | return S_FALSE; |
| 440 | if (tag.Id != DESC_TYPE_File) | 555 | if (tag.Id != DESC_TYPE_File && |
| 556 | tag.Id != DESC_TYPE_ExtendedFile) | ||
| 441 | return S_FALSE; | 557 | return S_FALSE; |
| 442 | 558 | ||
| 443 | item.IcbTag.Parse(p + 16); | 559 | item.IcbTag.Parse(p + 16); |
| 444 | if (item.IcbTag.FileType != ICB_FILE_TYPE_DIR && | 560 | |
| 561 | if (fsIndex < 0) | ||
| 562 | { | ||
| 563 | if (item.IcbTag.FileType != ICB_FILE_TYPE_METADATA && | ||
| 564 | item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR) | ||
| 565 | return S_FALSE; | ||
| 566 | } | ||
| 567 | else if ( | ||
| 568 | item.IcbTag.FileType != ICB_FILE_TYPE_DIR && | ||
| 445 | item.IcbTag.FileType != ICB_FILE_TYPE_FILE) | 569 | item.IcbTag.FileType != ICB_FILE_TYPE_FILE) |
| 446 | return S_FALSE; | 570 | return S_FALSE; |
| 447 | 571 | ||
| @@ -449,12 +573,12 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la | |||
| 449 | 573 | ||
| 450 | _processedProgressBytes += (UInt64)item.NumLogBlockRecorded * vol.BlockSize + size; | 574 | _processedProgressBytes += (UInt64)item.NumLogBlockRecorded * vol.BlockSize + size; |
| 451 | 575 | ||
| 452 | UInt32 extendedAttrLen = Get32(p + 168); | 576 | const UInt32 extendedAttrLen = Get32(p + 168 + kExtendOffset); |
| 453 | UInt32 allocDescriptorsLen = Get32(p + 172); | 577 | const UInt32 allocDescriptorsLen = Get32(p + 172 + kExtendOffset); |
| 454 | 578 | ||
| 455 | if ((extendedAttrLen & 3) != 0) | 579 | if ((extendedAttrLen & 3) != 0) |
| 456 | return S_FALSE; | 580 | return S_FALSE; |
| 457 | size_t pos = 176; | 581 | size_t pos = 176 + kExtendOffset; |
| 458 | if (extendedAttrLen > size - pos) | 582 | if (extendedAttrLen > size - pos) |
| 459 | return S_FALSE; | 583 | return S_FALSE; |
| 460 | /* | 584 | /* |
| @@ -472,10 +596,10 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la | |||
| 472 | */ | 596 | */ |
| 473 | pos += extendedAttrLen; | 597 | pos += extendedAttrLen; |
| 474 | 598 | ||
| 475 | int desctType = item.IcbTag.GetDescriptorType(); | 599 | const int descType = item.IcbTag.GetDescriptorType(); |
| 476 | if (allocDescriptorsLen > size - pos) | 600 | if (allocDescriptorsLen > size - pos) |
| 477 | return S_FALSE; | 601 | return S_FALSE; |
| 478 | if (desctType == ICB_DESC_TYPE_INLINE) | 602 | if (descType == ICB_DESC_TYPE_INLINE) |
| 479 | { | 603 | { |
| 480 | item.IsInline = true; | 604 | item.IsInline = true; |
| 481 | item.InlineData.CopyFrom(p + pos, allocDescriptorsLen); | 605 | item.InlineData.CopyFrom(p + pos, allocDescriptorsLen); |
| @@ -483,12 +607,12 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la | |||
| 483 | else | 607 | else |
| 484 | { | 608 | { |
| 485 | item.IsInline = false; | 609 | item.IsInline = false; |
| 486 | if (desctType != ICB_DESC_TYPE_SHORT && desctType != ICB_DESC_TYPE_LONG) | 610 | if (descType != ICB_DESC_TYPE_SHORT && descType != ICB_DESC_TYPE_LONG) |
| 487 | return S_FALSE; | 611 | return S_FALSE; |
| 488 | for (UInt32 i = 0; i < allocDescriptorsLen;) | 612 | for (UInt32 i = 0; i < allocDescriptorsLen;) |
| 489 | { | 613 | { |
| 490 | CMyExtent e; | 614 | CMyExtent e; |
| 491 | if (desctType == ICB_DESC_TYPE_SHORT) | 615 | if (descType == ICB_DESC_TYPE_SHORT) |
| 492 | { | 616 | { |
| 493 | if (i + 8 > allocDescriptorsLen) | 617 | if (i + 8 > allocDescriptorsLen) |
| 494 | return S_FALSE; | 618 | return S_FALSE; |
| @@ -516,6 +640,9 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la | |||
| 516 | 640 | ||
| 517 | if (item.IcbTag.IsDir()) | 641 | if (item.IcbTag.IsDir()) |
| 518 | { | 642 | { |
| 643 | if (fsIndex < 0) | ||
| 644 | return S_FALSE; | ||
| 645 | |||
| 519 | if (!item.CheckChunkSizes() || !CheckItemExtents(volIndex, item)) | 646 | if (!item.CheckChunkSizes() || !CheckItemExtents(volIndex, item)) |
| 520 | return S_FALSE; | 647 | return S_FALSE; |
| 521 | CByteBuffer buf2; | 648 | CByteBuffer buf2; |
| @@ -525,13 +652,17 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la | |||
| 525 | item.InlineData.Free(); | 652 | item.InlineData.Free(); |
| 526 | 653 | ||
| 527 | const Byte *p2 = buf2; | 654 | const Byte *p2 = buf2; |
| 528 | const size_t size2 = buf2.Size(); | 655 | size_t size2 = buf2.Size(); |
| 529 | size_t processedTotal = 0; | 656 | while (size2 != 0) |
| 530 | for (; processedTotal < size2;) | ||
| 531 | { | 657 | { |
| 532 | size_t processedCur; | ||
| 533 | CFileId fileId; | 658 | CFileId fileId; |
| 534 | RINOK(fileId.Parse(p2 + processedTotal, size2 - processedTotal, processedCur)); | 659 | { |
| 660 | const size_t cur = fileId.Parse(p2, size2); | ||
| 661 | if (cur == 0) | ||
| 662 | return S_FALSE; | ||
| 663 | p2 += cur; | ||
| 664 | size2 -= cur; | ||
| 665 | } | ||
| 535 | if (!fileId.IsItLinkParent()) | 666 | if (!fileId.IsItLinkParent()) |
| 536 | { | 667 | { |
| 537 | CFile file; | 668 | CFile file; |
| @@ -545,12 +676,11 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la | |||
| 545 | return S_FALSE; | 676 | return S_FALSE; |
| 546 | 677 | ||
| 547 | item.SubFiles.Add(Files.Size()); | 678 | item.SubFiles.Add(Files.Size()); |
| 548 | if (Files.Size() > kNumFilesMax) | 679 | if (Files.Size() >= kNumFilesMax) |
| 549 | return S_FALSE; | 680 | return S_FALSE; |
| 550 | Files.Add(file); | 681 | Files.Add(file); |
| 551 | RINOK(ReadFileItem(volIndex, fsIndex, fileId.Icb, numRecurseAllowed)); | 682 | RINOK(ReadFileItem(volIndex, fsIndex, fileId.Icb, numRecurseAllowed)); |
| 552 | } | 683 | } |
| 553 | processedTotal += processedCur; | ||
| 554 | } | 684 | } |
| 555 | } | 685 | } |
| 556 | else | 686 | else |
| @@ -567,6 +697,7 @@ HRESULT CInArchive::ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &la | |||
| 567 | return S_OK; | 697 | return S_OK; |
| 568 | } | 698 | } |
| 569 | 699 | ||
| 700 | |||
| 570 | HRESULT CInArchive::FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed) | 701 | HRESULT CInArchive::FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed) |
| 571 | { | 702 | { |
| 572 | if ((_numRefs & 0xFFF) == 0) | 703 | if ((_numRefs & 0xFFF) == 0) |
| @@ -591,6 +722,7 @@ HRESULT CInArchive::FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int n | |||
| 591 | return S_OK; | 722 | return S_OK; |
| 592 | } | 723 | } |
| 593 | 724 | ||
| 725 | |||
| 594 | API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size) | 726 | API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size) |
| 595 | { | 727 | { |
| 596 | UInt32 res = k_IsArc_Res_NO; | 728 | UInt32 res = k_IsArc_Res_NO; |
| @@ -608,7 +740,11 @@ API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size) | |||
| 608 | CTag tag; | 740 | CTag tag; |
| 609 | if (tag.Parse(p + offset, bufSize) == S_OK) | 741 | if (tag.Parse(p + offset, bufSize) == S_OK) |
| 610 | if (tag.Id == DESC_TYPE_AnchorVolPtr) | 742 | if (tag.Id == DESC_TYPE_AnchorVolPtr) |
| 611 | return k_IsArc_Res_YES; | 743 | { |
| 744 | if (Get32(p + offset + 12) == 256 && // TagLocation | ||
| 745 | tag.CrcLen >= 16) | ||
| 746 | return k_IsArc_Res_YES; | ||
| 747 | } | ||
| 612 | } | 748 | } |
| 613 | } | 749 | } |
| 614 | } | 750 | } |
| @@ -656,7 +792,7 @@ HRESULT CInArchive::Open2() | |||
| 656 | { | 792 | { |
| 657 | if (SecLogSize < 8) | 793 | if (SecLogSize < 8) |
| 658 | return S_FALSE; | 794 | return S_FALSE; |
| 659 | UInt32 offset = (UInt32)256 << SecLogSize; | 795 | const UInt32 offset = (UInt32)256 << SecLogSize; |
| 660 | if (offset >= fileSize) | 796 | if (offset >= fileSize) |
| 661 | continue; | 797 | continue; |
| 662 | RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); | 798 | RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL)); |
| @@ -668,71 +804,86 @@ HRESULT CInArchive::Open2() | |||
| 668 | CTag tag; | 804 | CTag tag; |
| 669 | if (tag.Parse(buf, readSize) == S_OK) | 805 | if (tag.Parse(buf, readSize) == S_OK) |
| 670 | if (tag.Id == DESC_TYPE_AnchorVolPtr) | 806 | if (tag.Id == DESC_TYPE_AnchorVolPtr) |
| 671 | break; | 807 | { |
| 808 | if (Get32(buf + 12) == 256 && | ||
| 809 | tag.CrcLen >= 16) // TagLocation | ||
| 810 | break; | ||
| 811 | } | ||
| 672 | } | 812 | } |
| 673 | } | 813 | } |
| 674 | 814 | ||
| 675 | PhySize = (UInt32)(256 + 1) << SecLogSize; | 815 | PhySize = (UInt32)(256 + 1) << SecLogSize; |
| 676 | IsArc = true; | 816 | IsArc = true; |
| 677 | 817 | ||
| 818 | // UDF 2.2.3 AnchorVolumeDescriptorPointer | ||
| 819 | |||
| 678 | CExtent extentVDS; | 820 | CExtent extentVDS; |
| 679 | extentVDS.Parse(buf + 16); | 821 | extentVDS.Parse(buf + 16); |
| 680 | { | 822 | { |
| 681 | CExtent extentVDS2; | 823 | CExtent extentVDS2; |
| 682 | extentVDS2.Parse(buf + 24); | 824 | extentVDS2.Parse(buf + 24); |
| 683 | UpdatePhySize(((UInt64)extentVDS.Pos << SecLogSize) + extentVDS.Len); | 825 | UpdatePhySize(extentVDS); |
| 684 | UpdatePhySize(((UInt64)extentVDS2.Pos << SecLogSize) + extentVDS2.Len); | 826 | UpdatePhySize(extentVDS2); |
| 685 | } | 827 | } |
| 686 | 828 | ||
| 687 | for (UInt32 location = 0; ; location++) | 829 | for (UInt32 location = 0; ; location++) |
| 688 | { | 830 | { |
| 689 | const size_t bufSize = (size_t)1 << SecLogSize; | 831 | if (location >= (extentVDS.Len >> SecLogSize)) |
| 690 | if (((UInt64)(location + 1) << SecLogSize) > extentVDS.Len) | ||
| 691 | return S_FALSE; | 832 | return S_FALSE; |
| 692 | 833 | ||
| 693 | UInt64 offs = (UInt64)(extentVDS.Pos + location) << SecLogSize; | 834 | const size_t bufSize = (size_t)1 << SecLogSize; |
| 694 | RINOK(_stream->Seek(offs, STREAM_SEEK_SET, NULL)); | ||
| 695 | HRESULT res = ReadStream_FALSE(_stream, buf, bufSize); | ||
| 696 | if (res == S_FALSE && offs + bufSize > FileSize) | ||
| 697 | UnexpectedEnd = true; | ||
| 698 | RINOK(res); | ||
| 699 | |||
| 700 | |||
| 701 | CTag tag; | ||
| 702 | { | 835 | { |
| 703 | const size_t pos = 0; | 836 | const UInt64 offs = ((UInt64)extentVDS.Pos + location) << SecLogSize; |
| 704 | RINOK(tag.Parse(buf + pos, bufSize - pos)); | 837 | RINOK(_stream->Seek(offs, STREAM_SEEK_SET, NULL)); |
| 838 | const HRESULT res = ReadStream_FALSE(_stream, buf, bufSize); | ||
| 839 | if (res == S_FALSE && offs + bufSize > FileSize) | ||
| 840 | UnexpectedEnd = true; | ||
| 841 | RINOK(res); | ||
| 705 | } | 842 | } |
| 843 | |||
| 844 | CTag tag; | ||
| 845 | RINOK(tag.Parse(buf, bufSize)); | ||
| 846 | |||
| 706 | if (tag.Id == DESC_TYPE_Terminating) | 847 | if (tag.Id == DESC_TYPE_Terminating) |
| 707 | break; | 848 | break; |
| 708 | 849 | ||
| 850 | if (tag.Id == DESC_TYPE_PrimVol) | ||
| 851 | { | ||
| 852 | CPrimeVol &pm = PrimeVols.AddNew(); | ||
| 853 | pm.Parse(buf); | ||
| 854 | continue; | ||
| 855 | } | ||
| 856 | |||
| 709 | if (tag.Id == DESC_TYPE_Partition) | 857 | if (tag.Id == DESC_TYPE_Partition) |
| 710 | { | 858 | { |
| 711 | // Partition Descriptor | 859 | // Partition Descriptor |
| 712 | // ECMA 167 3/10.5 | 860 | // ECMA 3/10.5 |
| 713 | // UDF / 2.2.14 | 861 | // UDF 2.2.14 |
| 714 | |||
| 715 | if (Partitions.Size() >= kNumPartitionsMax) | 862 | if (Partitions.Size() >= kNumPartitionsMax) |
| 716 | return S_FALSE; | 863 | return S_FALSE; |
| 717 | CPartition partition; | 864 | CPartition partition; |
| 718 | // UInt32 volDescSeqNumer = Get32(buf + 16); | 865 | // const UInt32 volDescSeqNumer = Get32(buf + 16); |
| 719 | // partition.Flags = Get16(buf + 20); | 866 | partition.Flags = Get16(buf + 20); |
| 720 | partition.Number = Get16(buf + 22); | 867 | partition.Number = Get16(buf + 22); |
| 721 | // partition.ContentsId.Parse(buf + 24); | 868 | partition.ContentsId.Parse(buf + 24); |
| 722 | 869 | ||
| 723 | // memcpy(partition.ContentsUse, buf + 56, sizeof(partition.ContentsUse)); | 870 | // memcpy(partition.ContentsUse, buf + 56, sizeof(partition.ContentsUse)); |
| 724 | // ContentsUse is Partition Header Description. | 871 | // ContentsUse contains Partition Header Description. |
| 872 | // ECMA 4/14.3 | ||
| 873 | // UDF PartitionHeaderDescriptor 2.3.3 | ||
| 725 | 874 | ||
| 726 | // partition.AccessType = Get32(buf + 184); | 875 | partition.AccessType = Get32(buf + 184); |
| 727 | partition.Pos = Get32(buf + 188); | 876 | partition.Pos = Get32(buf + 188); |
| 728 | partition.Len = Get32(buf + 192); | 877 | partition.Len = Get32(buf + 192); |
| 729 | // partition.ImplId.Parse(buf + 196); | 878 | partition.ImplId.Parse(buf + 196); |
| 730 | // memcpy(partition.ImplUse, buf + 228, sizeof(partition.ImplUse)); | 879 | // memcpy(partition.ImplUse, buf + 228, sizeof(partition.ImplUse)); |
| 731 | 880 | ||
| 732 | PRF(printf("\nPartition number = %2d pos = %d len = %d", partition.Number, partition.Pos, partition.Len)); | 881 | PRF(printf("\nPartition number = %2d pos = %d len = %d", partition.Number, partition.Pos, partition.Len)); |
| 733 | Partitions.Add(partition); | 882 | Partitions.Add(partition); |
| 883 | continue; | ||
| 734 | } | 884 | } |
| 735 | else if (tag.Id == DESC_TYPE_LogicalVol) | 885 | |
| 886 | if (tag.Id == DESC_TYPE_LogicalVol) | ||
| 736 | { | 887 | { |
| 737 | /* Logical Volume Descriptor | 888 | /* Logical Volume Descriptor |
| 738 | ECMA 3/10.6 | 889 | ECMA 3/10.6 |
| @@ -740,46 +891,65 @@ HRESULT CInArchive::Open2() | |||
| 740 | 891 | ||
| 741 | if (LogVols.Size() >= kNumLogVolumesMax) | 892 | if (LogVols.Size() >= kNumLogVolumesMax) |
| 742 | return S_FALSE; | 893 | return S_FALSE; |
| 743 | CLogVol vol; | 894 | CLogVol &vol = LogVols.AddNew(); |
| 895 | |||
| 744 | vol.Id.Parse(buf + 84); | 896 | vol.Id.Parse(buf + 84); |
| 745 | vol.BlockSize = Get32(buf + 212); | 897 | vol.BlockSize = Get32(buf + 212); |
| 746 | // vol.DomainId.Parse(buf + 216); | 898 | if (vol.BlockSize != ((UInt32)1 << SecLogSize)) |
| 747 | 899 | { | |
| 900 | // UDF 2.2.4.2 LogicalBlockSize | ||
| 901 | // UDF probably doesn't allow different sizes | ||
| 902 | return S_FALSE; | ||
| 903 | } | ||
| 904 | /* | ||
| 748 | if (vol.BlockSize < 512 || vol.BlockSize > ((UInt32)1 << 30)) | 905 | if (vol.BlockSize < 512 || vol.BlockSize > ((UInt32)1 << 30)) |
| 749 | return S_FALSE; | 906 | return S_FALSE; |
| 750 | 907 | */ | |
| 751 | // memcpy(vol.ContentsUse, buf + 248, sizeof(vol.ContentsUse)); | 908 | |
| 752 | vol.FileSetLocation.Parse(buf + 248); | 909 | vol.DomainId.Parse(buf + 216); |
| 910 | |||
| 911 | // ECMA 4/3.1 | ||
| 912 | // UDF 2.2.4.4 LogicalVolumeContentsUse | ||
| 753 | /* the extent in which the first File Set Descriptor Sequence | 913 | /* the extent in which the first File Set Descriptor Sequence |
| 754 | of the logical volume is recorded */ | 914 | of the logical volume is recorded */ |
| 915 | vol.FileSetLocation.Parse(buf + 248); | ||
| 916 | // memcpy(vol.ContentsUse, buf + 248, sizeof(vol.ContentsUse)); | ||
| 755 | 917 | ||
| 756 | // UInt32 mapTableLength = Get32(buf + 264); | 918 | vol.ImplId.Parse(buf + 272); |
| 757 | UInt32 numPartitionMaps = Get32(buf + 268); | 919 | // memcpy(vol.ImplUse, buf + 304, sizeof(vol.ImplUse)); |
| 920 | // vol.IntegritySequenceExtent.Parse(buf + 432); | ||
| 921 | |||
| 922 | const UInt32 mapTableLen = Get32(buf + 264); | ||
| 923 | const UInt32 numPartitionMaps = Get32(buf + 268); | ||
| 758 | if (numPartitionMaps > kNumPartitionsMax) | 924 | if (numPartitionMaps > kNumPartitionsMax) |
| 759 | return S_FALSE; | 925 | return S_FALSE; |
| 760 | // vol.ImplId.Parse(buf + 272); | ||
| 761 | // memcpy(vol.ImplUse, buf + 128, sizeof(vol.ImplUse)); | ||
| 762 | 926 | ||
| 763 | PRF(printf("\nLogicalVol numPartitionMaps = %2d", numPartitionMaps)); | 927 | PRF(printf("\nLogicalVol numPartitionMaps = %2d", numPartitionMaps)); |
| 928 | |||
| 764 | size_t pos = 440; | 929 | size_t pos = 440; |
| 930 | if (mapTableLen > bufSize - pos) | ||
| 931 | return S_FALSE; | ||
| 932 | const size_t posLimit = pos + mapTableLen; | ||
| 933 | |||
| 765 | for (UInt32 i = 0; i < numPartitionMaps; i++) | 934 | for (UInt32 i = 0; i < numPartitionMaps; i++) |
| 766 | { | 935 | { |
| 767 | if (pos + 2 > bufSize) | 936 | // ECMA 3/10.7 Partition maps |
| 937 | if (pos + 2 > posLimit) | ||
| 768 | return S_FALSE; | 938 | return S_FALSE; |
| 769 | CPartitionMap pm; | 939 | CPartitionMap pm; |
| 770 | pm.Type = buf[pos]; | 940 | pm.Type = buf[pos + 0]; |
| 771 | // pm.Length = buf[pos + 1]; | 941 | // pm.Length = buf[pos + 1]; |
| 772 | Byte len = buf[pos + 1]; | 942 | const Byte len = buf[pos + 1]; |
| 773 | 943 | if (pos + len > posLimit) | |
| 774 | if (pos + len > bufSize) | ||
| 775 | return S_FALSE; | 944 | return S_FALSE; |
| 776 | 945 | ||
| 777 | // memcpy(pm.Data, buf + pos + 2, pm.Length - 2); | 946 | // memcpy(pm.Data, buf + pos + 2, pm.Length - 2); |
| 778 | if (pm.Type == 1) | 947 | if (pm.Type == 1) |
| 779 | { | 948 | { |
| 780 | if (len != 6) // < 6 | 949 | // ECMA 3/10.7.2 |
| 950 | if (len != 6) | ||
| 781 | return S_FALSE; | 951 | return S_FALSE; |
| 782 | // pm.VolSeqNumber = Get16(buf + pos + 2); | 952 | pm.VolumeSequenceNumber = Get16(buf + pos + 2); |
| 783 | pm.PartitionNumber = Get16(buf + pos + 4); | 953 | pm.PartitionNumber = Get16(buf + pos + 4); |
| 784 | PRF(printf("\nPartitionMap type 1 PartitionNumber = %2d", pm.PartitionNumber)); | 954 | PRF(printf("\nPartitionMap type 1 PartitionNumber = %2d", pm.PartitionNumber)); |
| 785 | } | 955 | } |
| @@ -790,28 +960,60 @@ HRESULT CInArchive::Open2() | |||
| 790 | /* ECMA 10.7.3 / Type 2 Partition Map | 960 | /* ECMA 10.7.3 / Type 2 Partition Map |
| 791 | 62 bytes: Partition Identifier. */ | 961 | 62 bytes: Partition Identifier. */ |
| 792 | 962 | ||
| 793 | /* UDF 2.6 | 963 | /* UDF |
| 794 | 2.2.8 Virtual Partition Map | 964 | 2.2.8 "*UDF Virtual Partition" |
| 795 | This is an extension of ECMA 167 to expand its scope to include | 965 | 2.2.9 "*UDF Sparable Partition" |
| 796 | sequentially written media (eg. CD-R). This extension is for a | 966 | 2.2.10 "*UDF Metadata Partition" |
| 797 | Partition Map entry to describe a virtual space. */ | 967 | */ |
| 798 | 968 | ||
| 799 | // It's not implemented still. | 969 | if (Get16(buf + pos + 2) != 0) // reserved |
| 800 | if (Get16(buf + pos + 2) != 0) | ||
| 801 | return S_FALSE; | 970 | return S_FALSE; |
| 802 | // pm.VolSeqNumber = Get16(buf + pos + 36); | 971 | |
| 972 | pm.PartitionTypeId.Parse(buf + pos + 4); | ||
| 973 | pm.VolumeSequenceNumber = Get16(buf + pos + 36); | ||
| 803 | pm.PartitionNumber = Get16(buf + pos + 38); | 974 | pm.PartitionNumber = Get16(buf + pos + 38); |
| 975 | |||
| 976 | if (memcmp(pm.PartitionTypeId.Id, "*UDF Metadata Partition", 23) != 0) | ||
| 977 | return S_FALSE; | ||
| 978 | |||
| 979 | // UDF 2.2.10 Metadata Partition Map | ||
| 980 | pm.MetadataFileLocation = Get32(buf + pos + 40); | ||
| 981 | // pm.MetadataMirrorFileLocation = Get32(buf + pos + 44); | ||
| 982 | // pm.MetadataBitmapFileLocation = Get32(buf + pos + 48); | ||
| 983 | // pm.AllocationUnitSize = Get32(buf + pos + 52); | ||
| 984 | // pm.AlignmentUnitSize = Get16(buf + pos + 56); | ||
| 985 | // pm.Flags = buf[pos + 58]; | ||
| 986 | |||
| 804 | PRF(printf("\nPartitionMap type 2 PartitionNumber = %2d", pm.PartitionNumber)); | 987 | PRF(printf("\nPartitionMap type 2 PartitionNumber = %2d", pm.PartitionNumber)); |
| 805 | // Unsupported = true; | 988 | // Unsupported = true; |
| 806 | return S_FALSE; | 989 | // return S_FALSE; |
| 807 | } | 990 | } |
| 808 | else | 991 | else |
| 809 | return S_FALSE; | 992 | return S_FALSE; |
| 810 | pos += len; | 993 | pos += len; |
| 811 | vol.PartitionMaps.Add(pm); | 994 | vol.PartitionMaps.Add(pm); |
| 812 | } | 995 | } |
| 813 | LogVols.Add(vol); | 996 | continue; |
| 997 | } | ||
| 998 | |||
| 999 | /* | ||
| 1000 | if (tag.Id == DESC_TYPE_UnallocSpace) | ||
| 1001 | { | ||
| 1002 | // UInt32 volDescSeqNumer = Get32(buf + 16); | ||
| 1003 | const UInt32 numAlocDescs = Get32(buf + 20); | ||
| 1004 | // we need examples for (numAlocDescs != 0) case | ||
| 1005 | if (numAlocDescs > (bufSize - 24) / 8) | ||
| 1006 | return S_FALSE; | ||
| 1007 | for (UInt32 i = 0; i < numAlocDescs; i++) | ||
| 1008 | { | ||
| 1009 | CExtent e; | ||
| 1010 | e.Parse(buf + 24 + i * 8); | ||
| 1011 | } | ||
| 1012 | continue; | ||
| 814 | } | 1013 | } |
| 1014 | else | ||
| 1015 | continue; | ||
| 1016 | */ | ||
| 815 | } | 1017 | } |
| 816 | 1018 | ||
| 817 | UInt64 totalSize = 0; | 1019 | UInt64 totalSize = 0; |
| @@ -823,12 +1025,18 @@ HRESULT CInArchive::Open2() | |||
| 823 | FOR_VECTOR (pmIndex, vol.PartitionMaps) | 1025 | FOR_VECTOR (pmIndex, vol.PartitionMaps) |
| 824 | { | 1026 | { |
| 825 | CPartitionMap &pm = vol.PartitionMaps[pmIndex]; | 1027 | CPartitionMap &pm = vol.PartitionMaps[pmIndex]; |
| 826 | unsigned i; | 1028 | for (unsigned i = 0;; i++) |
| 827 | for (i = 0; i < Partitions.Size(); i++) | ||
| 828 | { | 1029 | { |
| 1030 | if (i == Partitions.Size()) | ||
| 1031 | return S_FALSE; | ||
| 829 | CPartition &part = Partitions[i]; | 1032 | CPartition &part = Partitions[i]; |
| 830 | if (part.Number == pm.PartitionNumber) | 1033 | if (part.Number == pm.PartitionNumber) |
| 831 | { | 1034 | { |
| 1035 | pm.PartitionIndex = i; | ||
| 1036 | if (pm.Type == 2) | ||
| 1037 | break; | ||
| 1038 | |||
| 1039 | /* | ||
| 832 | if (part.VolIndex >= 0) | 1040 | if (part.VolIndex >= 0) |
| 833 | { | 1041 | { |
| 834 | // it's for 2.60. Fix it | 1042 | // it's for 2.60. Fix it |
| @@ -836,15 +1044,85 @@ HRESULT CInArchive::Open2() | |||
| 836 | return S_FALSE; | 1044 | return S_FALSE; |
| 837 | // return S_FALSE; | 1045 | // return S_FALSE; |
| 838 | } | 1046 | } |
| 839 | pm.PartitionIndex = i; | ||
| 840 | part.VolIndex = volIndex; | 1047 | part.VolIndex = volIndex; |
| 1048 | */ | ||
| 841 | 1049 | ||
| 842 | totalSize += (UInt64)part.Len << SecLogSize; | 1050 | totalSize += (UInt64)part.Len << SecLogSize; |
| 843 | break; | 1051 | break; |
| 844 | } | 1052 | } |
| 845 | } | 1053 | } |
| 846 | if (i == Partitions.Size()) | 1054 | } |
| 1055 | } | ||
| 1056 | |||
| 1057 | for (volIndex = 0; volIndex < LogVols.Size(); volIndex++) | ||
| 1058 | { | ||
| 1059 | CLogVol &vol = LogVols[volIndex]; | ||
| 1060 | FOR_VECTOR (pmIndex, vol.PartitionMaps) | ||
| 1061 | { | ||
| 1062 | CPartitionMap &pm = vol.PartitionMaps[pmIndex]; | ||
| 1063 | if (pm.Type != 2) | ||
| 1064 | continue; | ||
| 1065 | |||
| 1066 | { | ||
| 1067 | CLongAllocDesc lad; | ||
| 1068 | lad.Len = vol.BlockSize; | ||
| 1069 | lad.Location.Pos = pm.MetadataFileLocation; | ||
| 1070 | // lad.Location.Pos = pm.MetadataMirrorFileLocation; | ||
| 1071 | |||
| 1072 | lad.Location.PartitionRef = (UInt16)pmIndex; | ||
| 1073 | |||
| 1074 | /* we need correct PartitionMaps[lad.Location.PartitionRef].PartitionIndex. | ||
| 1075 | so we can use pmIndex or find (Type==1) PartitionMap */ | ||
| 1076 | FOR_VECTOR (pmIndex2, vol.PartitionMaps) | ||
| 1077 | { | ||
| 1078 | const CPartitionMap &pm2 = vol.PartitionMaps[pmIndex2]; | ||
| 1079 | if (pm2.PartitionNumber == pm.PartitionNumber && pm2.Type == 1) | ||
| 1080 | { | ||
| 1081 | lad.Location.PartitionRef = (UInt16)pmIndex2; | ||
| 1082 | break; | ||
| 1083 | } | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | RINOK(ReadItem(volIndex, | ||
| 1087 | -1, // (fsIndex = -1) means that it's metadata | ||
| 1088 | lad, | ||
| 1089 | 1)); // numRecurseAllowed | ||
| 1090 | } | ||
| 1091 | { | ||
| 1092 | const CItem &item = Items.Back(); | ||
| 1093 | if (!CheckItemExtents(volIndex, item)) | ||
| 1094 | return S_FALSE; | ||
| 1095 | if (item.Extents.Size() != 1) | ||
| 1096 | return S_FALSE; | ||
| 1097 | |||
| 1098 | const CMyExtent &e = item.Extents[0]; | ||
| 1099 | const CPartition &part = Partitions[pm.PartitionIndex]; | ||
| 1100 | CPartition mp = part; | ||
| 1101 | mp.IsMetadata = true; | ||
| 1102 | // mp.Number = part.Number; | ||
| 1103 | mp.Pos = part.Pos + e.Pos; | ||
| 1104 | mp.Len = e.Len >> SecLogSize; | ||
| 1105 | pm.PartitionIndex = Partitions.Add(mp); | ||
| 1106 | } | ||
| 1107 | // Items.DeleteBack(); // we can delete that metadata item | ||
| 1108 | |||
| 1109 | /* | ||
| 1110 | // short version of code to read metadata file. | ||
| 1111 | RINOK(CInArchive::Read(volIndex, pmIndex, pm.MetadataFileLocation, 224, buf)); | ||
| 1112 | CTag tag; | ||
| 1113 | RINOK(tag.Parse(buf, 224)); | ||
| 1114 | if (tag.Id != DESC_TYPE_ExtendedFile) | ||
| 847 | return S_FALSE; | 1115 | return S_FALSE; |
| 1116 | CShortAllocDesc sad; | ||
| 1117 | sad.Parse(buf + 216); | ||
| 1118 | const CPartition &part = Partitions[pm.PartitionIndex]; | ||
| 1119 | CPartition mp = part; | ||
| 1120 | mp.IsMetadata = true; | ||
| 1121 | // mp.Number = part.Number; | ||
| 1122 | mp.Pos = part.Pos + sad.Pos; | ||
| 1123 | mp.Len = sad.Len >> SecLogSize; | ||
| 1124 | pm.PartitionIndex = Partitions.Add(mp); | ||
| 1125 | */ | ||
| 848 | } | 1126 | } |
| 849 | } | 1127 | } |
| 850 | 1128 | ||
| @@ -865,37 +1143,41 @@ HRESULT CInArchive::Open2() | |||
| 865 | if (nextExtent.GetLen() < 512) | 1143 | if (nextExtent.GetLen() < 512) |
| 866 | return S_FALSE; | 1144 | return S_FALSE; |
| 867 | CByteBuffer buf2(nextExtent.GetLen()); | 1145 | CByteBuffer buf2(nextExtent.GetLen()); |
| 868 | RINOK(Read(volIndex, nextExtent, buf2)); | 1146 | RINOK(ReadLad(volIndex, nextExtent, buf2)); |
| 869 | const Byte *p = buf2; | 1147 | const Byte *p = buf2; |
| 870 | size_t size = nextExtent.GetLen(); | 1148 | const size_t size = nextExtent.GetLen(); |
| 871 | 1149 | ||
| 872 | CTag tag; | 1150 | CTag tag; |
| 873 | RINOK(tag.Parse(p, size)); | 1151 | RINOK(tag.Parse(p, size)); |
| 874 | 1152 | ||
| 1153 | /* | ||
| 1154 | // commented in 22.01 | ||
| 875 | if (tag.Id == DESC_TYPE_ExtendedFile) | 1155 | if (tag.Id == DESC_TYPE_ExtendedFile) |
| 876 | { | 1156 | { |
| 877 | // ECMA 4 / 14.17 | 1157 | // ECMA 4 / 14.17 |
| 878 | // 2.60 ?? | 1158 | // 2.60 ?? |
| 879 | return S_FALSE; | 1159 | return S_FALSE; |
| 880 | } | 1160 | } |
| 1161 | */ | ||
| 881 | 1162 | ||
| 882 | if (tag.Id != DESC_TYPE_FileSet) | 1163 | if (tag.Id != DESC_TYPE_FileSet) |
| 883 | return S_FALSE; | 1164 | return S_FALSE; |
| 884 | 1165 | ||
| 885 | PRF(printf("\n FileSet", volIndex)); | 1166 | PRF(printf("\n FileSet", volIndex)); |
| 886 | CFileSet fs; | 1167 | CFileSet fs; |
| 887 | fs.RecodringTime.Parse(p + 16); | 1168 | fs.RecordingTime.Parse(p + 16); |
| 888 | // fs.InterchangeLevel = Get16(p + 18); | 1169 | // fs.InterchangeLevel = Get16(p + 18); |
| 889 | // fs.MaxInterchangeLevel = Get16(p + 20); | 1170 | // fs.MaxInterchangeLevel = Get16(p + 20); |
| 890 | // fs.FileSetNumber = Get32(p + 40); | 1171 | fs.FileSetNumber = Get32(p + 40); |
| 891 | // fs.FileSetDescNumber = Get32(p + 44); | 1172 | fs.FileSetDescNumber = Get32(p + 44); |
| 892 | 1173 | ||
| 893 | // fs.Id.Parse(p + 304); | 1174 | fs.LogicalVolumeId.Parse(p + 112); |
| 894 | // fs.CopyrightId.Parse(p + 336); | 1175 | fs.Id.Parse(p + 304); |
| 895 | // fs.AbstractId.Parse(p + 368); | 1176 | fs.CopyrightId.Parse(p + 336); |
| 1177 | fs.AbstractId.Parse(p + 368); | ||
| 896 | 1178 | ||
| 897 | fs.RootDirICB.Parse(p + 400); | 1179 | fs.RootDirICB.Parse(p + 400); |
| 898 | // fs.DomainId.Parse(p + 416); | 1180 | fs.DomainId.Parse(p + 416); |
| 899 | 1181 | ||
| 900 | // fs.SystemStreamDirICB.Parse(p + 464); | 1182 | // fs.SystemStreamDirICB.Parse(p + 464); |
| 901 | 1183 | ||
| @@ -907,7 +1189,7 @@ HRESULT CInArchive::Open2() | |||
| 907 | FOR_VECTOR (fsIndex, vol.FileSets) | 1189 | FOR_VECTOR (fsIndex, vol.FileSets) |
| 908 | { | 1190 | { |
| 909 | CFileSet &fs = vol.FileSets[fsIndex]; | 1191 | CFileSet &fs = vol.FileSets[fsIndex]; |
| 910 | unsigned fileIndex = Files.Size(); | 1192 | const unsigned fileIndex = Files.Size(); |
| 911 | Files.AddNew(); | 1193 | Files.AddNew(); |
| 912 | RINOK(ReadFileItem(volIndex, fsIndex, fs.RootDirICB, kNumRecursionLevelsMax)); | 1194 | RINOK(ReadFileItem(volIndex, fsIndex, fs.RootDirICB, kNumRecursionLevelsMax)); |
| 913 | RINOK(FillRefs(fs, fileIndex, -1, kNumRecursionLevelsMax)); | 1195 | RINOK(FillRefs(fs, fileIndex, -1, kNumRecursionLevelsMax)); |
| @@ -937,16 +1219,16 @@ HRESULT CInArchive::Open2() | |||
| 937 | FOR_VECTOR (extentIndex, item.Extents) | 1219 | FOR_VECTOR (extentIndex, item.Extents) |
| 938 | { | 1220 | { |
| 939 | const CMyExtent &extent = item.Extents[extentIndex]; | 1221 | const CMyExtent &extent = item.Extents[extentIndex]; |
| 940 | UInt32 len = extent.GetLen(); | 1222 | const UInt32 len = extent.GetLen(); |
| 941 | if (len == 0) | 1223 | if (len == 0) |
| 942 | continue; | 1224 | continue; |
| 943 | if (size < len) | 1225 | if (size < len) |
| 944 | break; | 1226 | break; |
| 945 | 1227 | ||
| 946 | int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; | 1228 | const unsigned partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex; |
| 947 | UInt32 logBlockNumber = extent.Pos; | 1229 | const UInt32 logBlockNumber = extent.Pos; |
| 948 | const CPartition &partition = Partitions[partitionIndex]; | 1230 | const CPartition &partition = Partitions[partitionIndex]; |
| 949 | UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + | 1231 | const UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + |
| 950 | (UInt64)logBlockNumber * vol.BlockSize; | 1232 | (UInt64)logBlockNumber * vol.BlockSize; |
| 951 | UpdatePhySize(offset + len); | 1233 | UpdatePhySize(offset + len); |
| 952 | } | 1234 | } |
| @@ -984,7 +1266,8 @@ HRESULT CInArchive::Open2() | |||
| 984 | if (readSize == 0) | 1266 | if (readSize == 0) |
| 985 | break; | 1267 | break; |
| 986 | 1268 | ||
| 987 | if (readSize == secSize && NoEndAnchor) | 1269 | // some udf contain many EndAnchors |
| 1270 | if (readSize == secSize /* && NoEndAnchor */) | ||
| 988 | { | 1271 | { |
| 989 | CTag tag; | 1272 | CTag tag; |
| 990 | if (tag.Parse(buf, readSize) == S_OK && | 1273 | if (tag.Parse(buf, readSize) == S_OK && |
| @@ -1051,6 +1334,7 @@ void CInArchive::Clear() | |||
| 1051 | 1334 | ||
| 1052 | Partitions.Clear(); | 1335 | Partitions.Clear(); |
| 1053 | LogVols.Clear(); | 1336 | LogVols.Clear(); |
| 1337 | PrimeVols.Clear(); | ||
| 1054 | Items.Clear(); | 1338 | Items.Clear(); |
| 1055 | Files.Clear(); | 1339 | Files.Clear(); |
| 1056 | _fileNameLengthTotal = 0; | 1340 | _fileNameLengthTotal = 0; |
| @@ -1060,16 +1344,291 @@ void CInArchive::Clear() | |||
| 1060 | _processedProgressBytes = 0; | 1344 | _processedProgressBytes = 0; |
| 1061 | } | 1345 | } |
| 1062 | 1346 | ||
| 1347 | |||
| 1348 | static const char * const g_PartitionTypes[] = | ||
| 1349 | { | ||
| 1350 | "Pseudo-Overwritable" // UDF | ||
| 1351 | , "Read-Only" | ||
| 1352 | , "Write-Once" | ||
| 1353 | , "Rewritable" | ||
| 1354 | , "Overwritable" | ||
| 1355 | }; | ||
| 1356 | |||
| 1357 | |||
| 1358 | static void AddComment_Align(UString &s) | ||
| 1359 | { | ||
| 1360 | s += " "; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | static void AddComment_PropName(UString &s, const char *name) | ||
| 1364 | { | ||
| 1365 | AddComment_Align(s); | ||
| 1366 | s += name; | ||
| 1367 | s += ": "; | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | static void AddComment_UInt32(UString &s, const char *name, UInt32 val) | ||
| 1371 | { | ||
| 1372 | AddComment_PropName(s, name); | ||
| 1373 | s.Add_UInt32(val); | ||
| 1374 | s.Add_LF(); | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | static void AddComment_UInt32_2(UString &s, const char *name, UInt32 val) | ||
| 1378 | { | ||
| 1379 | AddComment_Align(s); | ||
| 1380 | AddComment_UInt32(s, name, val); | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | |||
| 1384 | static void AddComment_UInt64(UString &s, const char *name, UInt64 val) | ||
| 1385 | { | ||
| 1386 | AddComment_PropName(s, name); | ||
| 1387 | s.Add_UInt64(val); | ||
| 1388 | s.Add_LF(); | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | static void AddComment_RegId(UString &s, const char *name, const CRegId &ri) | ||
| 1392 | { | ||
| 1393 | AddComment_PropName(s, name); | ||
| 1394 | ri.AddCommentTo(s); | ||
| 1395 | s.Add_LF(); | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | static void AddComment_RegId_Domain(UString &s, const char *name, const CRegId &ri) | ||
| 1399 | { | ||
| 1400 | AddComment_PropName(s, name); | ||
| 1401 | ri.AddCommentTo(s); | ||
| 1402 | { | ||
| 1403 | UString s2; | ||
| 1404 | ri.AddUdfVersionTo(s2); | ||
| 1405 | if (!s2.IsEmpty()) | ||
| 1406 | { | ||
| 1407 | s += "::"; | ||
| 1408 | s += s2; | ||
| 1409 | } | ||
| 1410 | } | ||
| 1411 | s.Add_LF(); | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | |||
| 1415 | // UDF 6.3.1 OS Class | ||
| 1416 | |||
| 1417 | static const char * const g_OsClasses[] = | ||
| 1418 | { | ||
| 1419 | NULL | ||
| 1420 | , "DOS" | ||
| 1421 | , "OS/2" | ||
| 1422 | , "Macintosh OS" | ||
| 1423 | , "UNIX" | ||
| 1424 | , "Windows 9x" | ||
| 1425 | , "Windows NT" | ||
| 1426 | , "OS/400" | ||
| 1427 | , "BeOS" | ||
| 1428 | , "Windows CE" | ||
| 1429 | }; | ||
| 1430 | |||
| 1431 | // UDF 6.3.2 OS Identifier | ||
| 1432 | |||
| 1433 | static const char * const g_OsIds_Unix[] = | ||
| 1434 | { | ||
| 1435 | NULL // "Generic" | ||
| 1436 | , "AIX" | ||
| 1437 | , "SUN OS / Solaris" | ||
| 1438 | , "HP/UX" | ||
| 1439 | , "Silicon Graphics Irix" | ||
| 1440 | , "Linux" | ||
| 1441 | , "MKLinux" | ||
| 1442 | , "FreeBSD" | ||
| 1443 | , "NetBSD" | ||
| 1444 | }; | ||
| 1445 | |||
| 1446 | static void AddOs_Class_Id(UString &s, const char *p) | ||
| 1447 | { | ||
| 1448 | // UDF 2.1.5.3 Implementation Identifier Suffix | ||
| 1449 | // Appendix 6.3 Operating System Identifiers. | ||
| 1450 | const Byte osClass = p[0]; | ||
| 1451 | if (osClass != 0) | ||
| 1452 | { | ||
| 1453 | s += "::"; | ||
| 1454 | s += TypeToString(g_OsClasses, ARRAY_SIZE(g_OsClasses), osClass); | ||
| 1455 | } | ||
| 1456 | const Byte osId = p[1]; | ||
| 1457 | if (osId != 0) | ||
| 1458 | { | ||
| 1459 | s += "::"; | ||
| 1460 | if (osClass == 4) // unix | ||
| 1461 | { | ||
| 1462 | s += TypeToString(g_OsIds_Unix, ARRAY_SIZE(g_OsIds_Unix), osId); | ||
| 1463 | } | ||
| 1464 | else | ||
| 1465 | s.Add_UInt32(osId); | ||
| 1466 | } | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | |||
| 1470 | static void AddComment_RegId_Impl(UString &s, const char *name, const CRegId &ri) | ||
| 1471 | { | ||
| 1472 | AddComment_PropName(s, name); | ||
| 1473 | ri.AddCommentTo(s); | ||
| 1474 | { | ||
| 1475 | AddOs_Class_Id(s, ri.Suffix); | ||
| 1476 | } | ||
| 1477 | s.Add_LF(); | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | |||
| 1481 | static void AddComment_RegId_UdfId(UString &s, const char *name, const CRegId &ri) | ||
| 1482 | { | ||
| 1483 | AddComment_PropName(s, name); | ||
| 1484 | ri.AddCommentTo(s); | ||
| 1485 | { | ||
| 1486 | // UDF 2.1.5.3 | ||
| 1487 | // UDF Identifier Suffix format | ||
| 1488 | UString s2; | ||
| 1489 | ri.AddUdfVersionTo(s2); | ||
| 1490 | if (!s2.IsEmpty()) | ||
| 1491 | { | ||
| 1492 | s += "::"; | ||
| 1493 | s += s2; | ||
| 1494 | } | ||
| 1495 | AddOs_Class_Id(s, &ri.Suffix[2]); | ||
| 1496 | } | ||
| 1497 | s.Add_LF(); | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | static void AddComment_DString32(UString &s, const char *name, const CDString32 &d) | ||
| 1501 | { | ||
| 1502 | AddComment_Align(s); | ||
| 1503 | AddComment_PropName(s, name); | ||
| 1504 | s += d.GetString(); | ||
| 1505 | s.Add_LF(); | ||
| 1506 | } | ||
| 1507 | |||
| 1063 | UString CInArchive::GetComment() const | 1508 | UString CInArchive::GetComment() const |
| 1064 | { | 1509 | { |
| 1065 | UString res; | 1510 | UString s; |
| 1066 | FOR_VECTOR (i, LogVols) | ||
| 1067 | { | 1511 | { |
| 1068 | if (i != 0) | 1512 | s += "Primary Volumes:"; |
| 1069 | res.Add_Space(); | 1513 | s.Add_LF(); |
| 1070 | res += LogVols[i].GetName(); | 1514 | FOR_VECTOR (i, PrimeVols) |
| 1515 | { | ||
| 1516 | if (i != 0) | ||
| 1517 | s.Add_LF(); | ||
| 1518 | const CPrimeVol &pv = PrimeVols[i]; | ||
| 1519 | // AddComment_UInt32(s, "VolumeDescriptorSequenceNumber", pv.VolumeDescriptorSequenceNumber); | ||
| 1520 | // if (PrimeVols.Size() != 1 || pv.PrimaryVolumeDescriptorNumber != 0) | ||
| 1521 | AddComment_UInt32(s, "PrimaryVolumeDescriptorNumber", pv.PrimaryVolumeDescriptorNumber); | ||
| 1522 | // if (pv.MaximumVolumeSequenceNumber != 1 || pv.VolumeSequenceNumber != 1) | ||
| 1523 | AddComment_UInt32(s, "VolumeSequenceNumber", pv.VolumeSequenceNumber); | ||
| 1524 | if (pv.MaximumVolumeSequenceNumber != 1) | ||
| 1525 | AddComment_UInt32(s, "MaximumVolumeSequenceNumber", pv.MaximumVolumeSequenceNumber); | ||
| 1526 | AddComment_PropName(s, "VolumeId"); | ||
| 1527 | s += pv.VolumeId.GetString(); | ||
| 1528 | s.Add_LF(); | ||
| 1529 | AddComment_PropName(s, "VolumeSetId"); | ||
| 1530 | s += pv.VolumeSetId.GetString(); | ||
| 1531 | s.Add_LF(); | ||
| 1532 | // AddComment_UInt32(s, "InterchangeLevel", pv.InterchangeLevel); | ||
| 1533 | // AddComment_UInt32(s, "MaximumInterchangeLevel", pv.MaximumInterchangeLevel); | ||
| 1534 | AddComment_RegId(s, "ApplicationId", pv.ApplicationId); | ||
| 1535 | AddComment_RegId_Impl(s, "ImplementationId", pv.ImplId); | ||
| 1536 | } | ||
| 1071 | } | 1537 | } |
| 1072 | return res; | 1538 | { |
| 1539 | s += "Partitions:"; | ||
| 1540 | s.Add_LF(); | ||
| 1541 | FOR_VECTOR (i, Partitions) | ||
| 1542 | { | ||
| 1543 | if (i != 0) | ||
| 1544 | s.Add_LF(); | ||
| 1545 | const CPartition &part = Partitions[i]; | ||
| 1546 | AddComment_UInt32(s, "PartitionIndex", i); | ||
| 1547 | AddComment_UInt32(s, "PartitionNumber", part.Number); | ||
| 1548 | if (part.IsMetadata) | ||
| 1549 | AddComment_UInt32(s, "IsMetadata", 1); | ||
| 1550 | else | ||
| 1551 | { | ||
| 1552 | AddComment_RegId(s, "ContentsId", part.ContentsId); | ||
| 1553 | AddComment_RegId_Impl(s, "ImplementationId", part.ImplId); | ||
| 1554 | AddComment_PropName(s, "AccessType"); | ||
| 1555 | s += TypeToString(g_PartitionTypes, ARRAY_SIZE(g_PartitionTypes), part.AccessType); | ||
| 1556 | s.Add_LF(); | ||
| 1557 | } | ||
| 1558 | AddComment_UInt64(s, "Size", (UInt64)part.Len << SecLogSize); | ||
| 1559 | AddComment_UInt64(s, "Pos", (UInt64)part.Pos << SecLogSize); | ||
| 1560 | } | ||
| 1561 | } | ||
| 1562 | s += "Logical Volumes:"; | ||
| 1563 | s.Add_LF(); | ||
| 1564 | { | ||
| 1565 | FOR_VECTOR (i, LogVols) | ||
| 1566 | { | ||
| 1567 | if (i != 0) | ||
| 1568 | s.Add_LF(); | ||
| 1569 | const CLogVol &vol = LogVols[i]; | ||
| 1570 | if (LogVols.Size() != 1) | ||
| 1571 | AddComment_UInt32(s, "Number", i); | ||
| 1572 | AddComment_PropName(s, "Id"); | ||
| 1573 | s += vol.Id.GetString(); | ||
| 1574 | s.Add_LF(); | ||
| 1575 | AddComment_UInt32(s, "BlockSize", vol.BlockSize); | ||
| 1576 | AddComment_RegId_Domain(s, "DomainId", vol.DomainId); | ||
| 1577 | AddComment_RegId_Impl(s, "ImplementationId", vol.ImplId); | ||
| 1578 | // AddComment_UInt64(s, "IntegritySequenceExtent_Len", vol.IntegritySequenceExtent.Len); | ||
| 1579 | // AddComment_UInt64(s, "IntegritySequenceExtent_Pos", (UInt64)vol.IntegritySequenceExtent.Pos << SecLogSize); | ||
| 1580 | |||
| 1581 | s += " Partition Maps:"; | ||
| 1582 | s.Add_LF(); | ||
| 1583 | { | ||
| 1584 | FOR_VECTOR (j, vol.PartitionMaps) | ||
| 1585 | { | ||
| 1586 | if (j != 0) | ||
| 1587 | s.Add_LF(); | ||
| 1588 | const CPartitionMap &pm = vol.PartitionMaps[j]; | ||
| 1589 | AddComment_UInt32_2(s, "PartitionMap", j); | ||
| 1590 | AddComment_UInt32_2(s, "Type", pm.Type); | ||
| 1591 | AddComment_UInt32_2(s, "VolumeSequenceNumber", pm.VolumeSequenceNumber); | ||
| 1592 | AddComment_UInt32_2(s, "PartitionNumber", pm.PartitionNumber); | ||
| 1593 | if (pm.Type == 2) | ||
| 1594 | { | ||
| 1595 | AddComment_UInt32_2(s, "MetadataFileLocation", pm.MetadataFileLocation); | ||
| 1596 | // AddComment_UInt32_2(s, "MetadataMirrorFileLocation", pm.MetadataMirrorFileLocation); | ||
| 1597 | // AddComment_UInt32_2(s, "MetadataBitmapFileLocation", pm.MetadataBitmapFileLocation); | ||
| 1598 | // AddComment_UInt32_2(s, "AllocationUnitSize", pm.AllocationUnitSize); | ||
| 1599 | // AddComment_UInt32_2(s, "AlignmentUnitSize", pm.AlignmentUnitSize); | ||
| 1600 | // AddComment_UInt32_2(s, "Flags", pm.Flags); | ||
| 1601 | AddComment_Align(s); AddComment_RegId_UdfId(s, "PartitionTypeId", pm.PartitionTypeId); | ||
| 1602 | } | ||
| 1603 | } | ||
| 1604 | } | ||
| 1605 | s += " File Sets:"; | ||
| 1606 | s.Add_LF(); | ||
| 1607 | { | ||
| 1608 | FOR_VECTOR (j, vol.FileSets) | ||
| 1609 | { | ||
| 1610 | if (j != 0) | ||
| 1611 | s.Add_LF(); | ||
| 1612 | const CFileSet &fs = vol.FileSets[j]; | ||
| 1613 | AddComment_Align(s); AddComment_UInt32(s, "FileSetNumber", fs.FileSetNumber); | ||
| 1614 | AddComment_Align(s); AddComment_UInt32(s, "FileSetDescNumber", fs.FileSetDescNumber); | ||
| 1615 | |||
| 1616 | AddComment_Align(s); | ||
| 1617 | AddComment_PropName(s, "LogicalVolumeId"); | ||
| 1618 | s += fs.LogicalVolumeId.GetString(); | ||
| 1619 | s.Add_LF(); | ||
| 1620 | |||
| 1621 | AddComment_DString32(s, "Id", fs.Id); | ||
| 1622 | AddComment_DString32(s, "CopyrightId", fs.CopyrightId); | ||
| 1623 | AddComment_DString32(s, "AbstractId", fs.AbstractId); | ||
| 1624 | |||
| 1625 | AddComment_Align(s); | ||
| 1626 | AddComment_RegId_Domain(s, "DomainId", fs.DomainId); | ||
| 1627 | } | ||
| 1628 | } | ||
| 1629 | } | ||
| 1630 | } | ||
| 1631 | return s; | ||
| 1073 | } | 1632 | } |
| 1074 | 1633 | ||
| 1075 | static UString GetSpecName(const UString &name) | 1634 | static UString GetSpecName(const UString &name) |
| @@ -1089,7 +1648,7 @@ static void UpdateWithName(UString &res, const UString &addString) | |||
| 1089 | res.Insert(0, addString + WCHAR_PATH_SEPARATOR); | 1648 | res.Insert(0, addString + WCHAR_PATH_SEPARATOR); |
| 1090 | } | 1649 | } |
| 1091 | 1650 | ||
| 1092 | UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex, | 1651 | UString CInArchive::GetItemPath(unsigned volIndex, unsigned fsIndex, unsigned refIndex, |
| 1093 | bool showVolName, bool showFsName) const | 1652 | bool showVolName, bool showFsName) const |
| 1094 | { | 1653 | { |
| 1095 | // showVolName = true; | 1654 | // showVolName = true; |
| @@ -1101,9 +1660,10 @@ UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex, | |||
| 1101 | for (;;) | 1660 | for (;;) |
| 1102 | { | 1661 | { |
| 1103 | const CRef &ref = fs.Refs[refIndex]; | 1662 | const CRef &ref = fs.Refs[refIndex]; |
| 1104 | refIndex = ref.Parent; | 1663 | // we break on root file (that probably has empty name) |
| 1105 | if (refIndex < 0) | 1664 | if (ref.Parent < 0) |
| 1106 | break; | 1665 | break; |
| 1666 | refIndex = ref.Parent; | ||
| 1107 | UpdateWithName(name, GetSpecName(Files[ref.FileIndex].GetName())); | 1667 | UpdateWithName(name, GetSpecName(Files[ref.FileIndex].GetName())); |
| 1108 | } | 1668 | } |
| 1109 | 1669 | ||
diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h index 4e7dfa1..d962e7d 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h | |||
| @@ -17,16 +17,15 @@ namespace NUdf { | |||
| 17 | // ---------- ECMA Part 1 ---------- | 17 | // ---------- ECMA Part 1 ---------- |
| 18 | 18 | ||
| 19 | // ECMA 1/7.2.12 | 19 | // ECMA 1/7.2.12 |
| 20 | // UDF 2.1.3 | ||
| 20 | 21 | ||
| 21 | /* | ||
| 22 | struct CDString32 | 22 | struct CDString32 |
| 23 | { | 23 | { |
| 24 | Byte Data[32]; | 24 | Byte Data[32]; |
| 25 | 25 | ||
| 26 | void Parse(const Byte *buf); | 26 | void Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); } |
| 27 | // UString GetString() const; | 27 | UString GetString() const; |
| 28 | }; | 28 | }; |
| 29 | */ | ||
| 30 | 29 | ||
| 31 | struct CDString128 | 30 | struct CDString128 |
| 32 | { | 31 | { |
| @@ -46,6 +45,7 @@ struct CDString | |||
| 46 | 45 | ||
| 47 | 46 | ||
| 48 | // ECMA 1/7.3 | 47 | // ECMA 1/7.3 |
| 48 | // UDF 2.1.4 timestamp | ||
| 49 | 49 | ||
| 50 | struct CTime | 50 | struct CTime |
| 51 | { | 51 | { |
| @@ -65,9 +65,9 @@ struct CTime | |||
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | 67 | ||
| 68 | // ECMA 1/7.4 | 68 | // ECMA 1/7.4 regid |
| 69 | // UDF 2.1.5 EntityID | ||
| 69 | 70 | ||
| 70 | /* | ||
| 71 | struct CRegId | 71 | struct CRegId |
| 72 | { | 72 | { |
| 73 | Byte Flags; | 73 | Byte Flags; |
| @@ -75,44 +75,97 @@ struct CRegId | |||
| 75 | char Suffix[8]; | 75 | char Suffix[8]; |
| 76 | 76 | ||
| 77 | void Parse(const Byte *buf); | 77 | void Parse(const Byte *buf); |
| 78 | void AddCommentTo(UString &s) const; | ||
| 79 | void AddUdfVersionTo(UString &s) const; | ||
| 78 | }; | 80 | }; |
| 79 | */ | 81 | |
| 82 | |||
| 80 | 83 | ||
| 81 | // ---------- ECMA Part 3: Volume Structure ---------- | 84 | // ---------- ECMA Part 3: Volume Structure ---------- |
| 82 | 85 | ||
| 83 | // ECMA 3/10.5 | 86 | // ECMA 3/7.1 |
| 84 | 87 | ||
| 85 | struct CPartition | 88 | struct CExtent |
| 89 | { | ||
| 90 | UInt32 Len; | ||
| 91 | UInt32 Pos; // logical sector number | ||
| 92 | |||
| 93 | void Parse(const Byte *p); | ||
| 94 | }; | ||
| 95 | |||
| 96 | |||
| 97 | // ECMA 3/10.1 | ||
| 98 | // UDF 2.2.2 PrimaryVolumeDescriptor | ||
| 99 | |||
| 100 | struct CPrimeVol | ||
| 86 | { | 101 | { |
| 102 | // UInt32 VolumeDescriptorSequenceNumber; | ||
| 103 | UInt32 PrimaryVolumeDescriptorNumber; | ||
| 104 | CDString32 VolumeId; | ||
| 105 | UInt16 VolumeSequenceNumber; | ||
| 106 | UInt16 MaximumVolumeSequenceNumber; | ||
| 107 | // UInt16 InterchangeLevel; | ||
| 108 | // UInt16 MaximumInterchangeLevel; | ||
| 109 | // UInt32 CharacterSetList; | ||
| 110 | // UInt32 MaximumCharacterSetList; | ||
| 111 | CDString128 VolumeSetId; | ||
| 112 | // charspec DescriptorCharacterSet; // (1/7.2.1) | ||
| 113 | // charspec ExplanatoryCharacterSet; // (1/7.2.1) | ||
| 114 | // CExtent VolumeAbstract; | ||
| 115 | // CExtent VolumeCopyrightNotice; | ||
| 116 | CRegId ApplicationId; | ||
| 117 | CTime RecordingTime; | ||
| 118 | CRegId ImplId; | ||
| 119 | // bytes ImplementationUse | ||
| 120 | // UInt32 PredecessorVolumeDescriptorSequenceLocation; | ||
| 87 | // UInt16 Flags; | 121 | // UInt16 Flags; |
| 88 | UInt16 Number; | ||
| 89 | // CRegId ContentsId; | ||
| 90 | // Byte ContentsUse[128]; | ||
| 91 | // UInt32 AccessType; | ||
| 92 | 122 | ||
| 123 | void Parse(const Byte *p); | ||
| 124 | }; | ||
| 125 | |||
| 126 | |||
| 127 | // ECMA 3/10.5 | ||
| 128 | // UDF 2.2.14 PartitionDescriptor | ||
| 129 | |||
| 130 | struct CPartition | ||
| 131 | { | ||
| 93 | UInt32 Pos; | 132 | UInt32 Pos; |
| 94 | UInt32 Len; | 133 | UInt32 Len; |
| 95 | 134 | ||
| 96 | // CRegId ImplId; | 135 | UInt16 Flags; |
| 136 | UInt16 Number; | ||
| 137 | CRegId ContentsId; | ||
| 138 | // Byte ContentsUse[128]; | ||
| 139 | UInt32 AccessType; | ||
| 140 | |||
| 141 | CRegId ImplId; | ||
| 97 | // Byte ImplUse[128]; | 142 | // Byte ImplUse[128]; |
| 98 | 143 | ||
| 99 | int VolIndex; | 144 | // int VolIndex; |
| 100 | CMap32 Map; | 145 | CMap32 Map; |
| 101 | 146 | ||
| 102 | CPartition(): VolIndex(-1) {} | 147 | bool IsMetadata; |
| 148 | |||
| 149 | CPartition(): | ||
| 150 | // VolIndex(-1), | ||
| 151 | IsMetadata(false) {} | ||
| 103 | 152 | ||
| 104 | // bool IsNsr() const { return (strncmp(ContentsId.Id, "+NSR0", 5) == 0); } | 153 | // bool IsNsr() const { return (strncmp(ContentsId.Id, "+NSR0", 5) == 0); } |
| 105 | // bool IsAllocated() const { return ((Flags & 1) != 0); } | 154 | // bool IsAllocated() const { return ((Flags & 1) != 0); } |
| 106 | }; | 155 | }; |
| 107 | 156 | ||
| 157 | |||
| 158 | // ECMA 4/7.1 lb_addr | ||
| 159 | |||
| 108 | struct CLogBlockAddr | 160 | struct CLogBlockAddr |
| 109 | { | 161 | { |
| 110 | UInt32 Pos; | 162 | UInt32 Pos; |
| 111 | UInt16 PartitionRef; | 163 | UInt16 PartitionRef; |
| 112 | 164 | ||
| 113 | void Parse(const Byte *buf); | 165 | void Parse(const Byte *p); |
| 114 | }; | 166 | }; |
| 115 | 167 | ||
| 168 | |||
| 116 | enum EShortAllocDescType | 169 | enum EShortAllocDescType |
| 117 | { | 170 | { |
| 118 | SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated = 0, | 171 | SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated = 0, |
| @@ -121,16 +174,18 @@ enum EShortAllocDescType | |||
| 121 | SHORT_ALLOC_DESC_TYPE_NextExtent = 3 | 174 | SHORT_ALLOC_DESC_TYPE_NextExtent = 3 |
| 122 | }; | 175 | }; |
| 123 | 176 | ||
| 177 | |||
| 178 | // ECMA 4/14.14.1 short_ad | ||
| 179 | |||
| 124 | struct CShortAllocDesc | 180 | struct CShortAllocDesc |
| 125 | { | 181 | { |
| 126 | UInt32 Len; | 182 | UInt32 Len; |
| 127 | UInt32 Pos; | 183 | UInt32 Pos; |
| 128 | 184 | ||
| 129 | // 4/14.14.1 | ||
| 130 | // UInt32 GetLen() const { return Len & 0x3FFFFFFF; } | 185 | // UInt32 GetLen() const { return Len & 0x3FFFFFFF; } |
| 131 | // UInt32 GetType() const { return Len >> 30; } | 186 | // UInt32 GetType() const { return Len >> 30; } |
| 132 | // bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } | 187 | // bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } |
| 133 | void Parse(const Byte *buf); | 188 | void Parse(const Byte *p); |
| 134 | }; | 189 | }; |
| 135 | 190 | ||
| 136 | /* | 191 | /* |
| @@ -138,10 +193,13 @@ struct CADImpUse | |||
| 138 | { | 193 | { |
| 139 | UInt16 Flags; | 194 | UInt16 Flags; |
| 140 | UInt32 UdfUniqueId; | 195 | UInt32 UdfUniqueId; |
| 141 | void Parse(const Byte *buf); | 196 | void Parse(const Byte *p); |
| 142 | }; | 197 | }; |
| 143 | */ | 198 | */ |
| 144 | 199 | ||
| 200 | // ECMA 4/14.14.2 long_ad | ||
| 201 | // UDF 2.3.10.1 | ||
| 202 | |||
| 145 | struct CLongAllocDesc | 203 | struct CLongAllocDesc |
| 146 | { | 204 | { |
| 147 | UInt32 Len; | 205 | UInt32 Len; |
| @@ -153,29 +211,48 @@ struct CLongAllocDesc | |||
| 153 | UInt32 GetLen() const { return Len & 0x3FFFFFFF; } | 211 | UInt32 GetLen() const { return Len & 0x3FFFFFFF; } |
| 154 | UInt32 GetType() const { return Len >> 30; } | 212 | UInt32 GetType() const { return Len >> 30; } |
| 155 | bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } | 213 | bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } |
| 156 | void Parse(const Byte *buf); | 214 | void Parse(const Byte *p); |
| 157 | }; | 215 | }; |
| 158 | 216 | ||
| 217 | |||
| 218 | // ECMA 3/10.7 Partition maps | ||
| 219 | // UDF 2.2.8-2.2.10 Partition Maps | ||
| 220 | |||
| 159 | struct CPartitionMap | 221 | struct CPartitionMap |
| 160 | { | 222 | { |
| 223 | unsigned PartitionIndex; | ||
| 224 | |||
| 161 | Byte Type; | 225 | Byte Type; |
| 162 | // Byte Len; | 226 | // Byte Len; |
| 163 | 227 | ||
| 164 | // Type - 1 | 228 | // ECMA 10.7.2 |
| 165 | // UInt16 VolSeqNumber; | 229 | UInt16 VolumeSequenceNumber; |
| 166 | UInt16 PartitionNumber; | 230 | UInt16 PartitionNumber; |
| 231 | |||
| 232 | CRegId PartitionTypeId; | ||
| 167 | 233 | ||
| 168 | // Byte Data[256]; | 234 | // UDF 2.2.10 Metadata Partition Map |
| 235 | UInt32 MetadataFileLocation; | ||
| 236 | // UInt32 MetadataMirrorFileLocation; | ||
| 237 | // UInt32 MetadataBitmapFileLocation; | ||
| 238 | // UInt32 AllocationUnitSize; // (Blocks) | ||
| 239 | // UInt16 AlignmentUnitSize; // (Blocks) | ||
| 240 | // Byte Flags; | ||
| 169 | 241 | ||
| 170 | int PartitionIndex; | 242 | // Byte Data[256]; |
| 243 | // CPartitionMap(): PartitionIndex(-1) {} | ||
| 171 | }; | 244 | }; |
| 172 | 245 | ||
| 173 | // ECMA 4/14.6 | 246 | |
| 247 | // ECMA 4/14.6.6 | ||
| 174 | 248 | ||
| 175 | enum EIcbFileType | 249 | enum EIcbFileType |
| 176 | { | 250 | { |
| 177 | ICB_FILE_TYPE_DIR = 4, | 251 | ICB_FILE_TYPE_DIR = 4, |
| 178 | ICB_FILE_TYPE_FILE = 5 | 252 | ICB_FILE_TYPE_FILE = 5, |
| 253 | |||
| 254 | ICB_FILE_TYPE_METADATA = 250, // 2.2.13.1 Metadata File | ||
| 255 | ICB_FILE_TYPE_METADATA_MIRROR = 251 | ||
| 179 | }; | 256 | }; |
| 180 | 257 | ||
| 181 | enum EIcbDescriptorType | 258 | enum EIcbDescriptorType |
| @@ -186,6 +263,9 @@ enum EIcbDescriptorType | |||
| 186 | ICB_DESC_TYPE_INLINE = 3 | 263 | ICB_DESC_TYPE_INLINE = 3 |
| 187 | }; | 264 | }; |
| 188 | 265 | ||
| 266 | // ECMA 4/14.6 | ||
| 267 | // UDF 3.3.2 | ||
| 268 | |||
| 189 | struct CIcbTag | 269 | struct CIcbTag |
| 190 | { | 270 | { |
| 191 | // UInt32 PriorDirectNum; | 271 | // UInt32 PriorDirectNum; |
| @@ -201,33 +281,35 @@ struct CIcbTag | |||
| 201 | void Parse(const Byte *p); | 281 | void Parse(const Byte *p); |
| 202 | }; | 282 | }; |
| 203 | 283 | ||
| 284 | // ECMA 4/14.4.3 | ||
| 204 | // const Byte FILEID_CHARACS_Existance = (1 << 0); | 285 | // const Byte FILEID_CHARACS_Existance = (1 << 0); |
| 205 | const Byte FILEID_CHARACS_Parent = (1 << 3); | 286 | const Byte FILEID_CHARACS_Parent = (1 << 3); |
| 206 | 287 | ||
| 207 | struct CFile | 288 | struct CFile |
| 208 | { | 289 | { |
| 290 | int ItemIndex; | ||
| 209 | // UInt16 FileVersion; | 291 | // UInt16 FileVersion; |
| 210 | // Byte FileCharacteristics; | 292 | // Byte FileCharacteristics; |
| 211 | // CByteBuffer ImplUse; | 293 | // CByteBuffer ImplUse; |
| 212 | CDString Id; | 294 | CDString Id; |
| 213 | 295 | ||
| 214 | int ItemIndex; | ||
| 215 | |||
| 216 | CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {} | 296 | CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {} |
| 217 | UString GetName() const { return Id.GetString(); } | 297 | UString GetName() const { return Id.GetString(); } |
| 218 | }; | 298 | }; |
| 219 | 299 | ||
| 300 | |||
| 220 | struct CMyExtent | 301 | struct CMyExtent |
| 221 | { | 302 | { |
| 222 | UInt32 Pos; | 303 | UInt32 Pos; |
| 223 | UInt32 Len; | 304 | UInt32 Len; |
| 224 | unsigned PartitionRef; | 305 | unsigned PartitionRef; // index in CLogVol::PartitionMaps |
| 225 | 306 | ||
| 226 | UInt32 GetLen() const { return Len & 0x3FFFFFFF; } | 307 | UInt32 GetLen() const { return Len & 0x3FFFFFFF; } |
| 227 | UInt32 GetType() const { return Len >> 30; } | 308 | UInt32 GetType() const { return Len >> 30; } |
| 228 | bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } | 309 | bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; } |
| 229 | }; | 310 | }; |
| 230 | 311 | ||
| 312 | |||
| 231 | struct CItem | 313 | struct CItem |
| 232 | { | 314 | { |
| 233 | CIcbTag IcbTag; | 315 | CIcbTag IcbTag; |
| @@ -235,26 +317,30 @@ struct CItem | |||
| 235 | // UInt32 Uid; | 317 | // UInt32 Uid; |
| 236 | // UInt32 Gid; | 318 | // UInt32 Gid; |
| 237 | // UInt32 Permissions; | 319 | // UInt32 Permissions; |
| 238 | // UInt16 FileLinkCount; | 320 | UInt16 FileLinkCount; |
| 239 | // Byte RecordFormat; | 321 | // Byte RecordFormat; |
| 240 | // Byte RecordDisplayAttr; | 322 | // Byte RecordDisplayAttr; |
| 241 | // UInt32 RecordLen; | 323 | // UInt32 RecordLen; |
| 242 | UInt64 Size; | 324 | UInt64 Size; |
| 243 | UInt64 NumLogBlockRecorded; | 325 | UInt64 NumLogBlockRecorded; |
| 326 | // UInt64 ObjectSize; | ||
| 327 | |||
| 244 | CTime ATime; | 328 | CTime ATime; |
| 245 | CTime MTime; | 329 | CTime MTime; |
| 246 | CTime AttribTime; // Attribute time : most recent date and time of the day of file creation or modification of the attributes of. | 330 | CTime AttribTime; // Attribute time : most recent date and time of the day of file creation or modification of the attributes of. |
| 331 | CTime CreateTime; | ||
| 247 | // UInt32 CheckPoint; | 332 | // UInt32 CheckPoint; |
| 248 | // CLongAllocDesc ExtendedAttrIcb; | 333 | // CLongAllocDesc ExtendedAttrIcb; |
| 249 | // CRegId ImplId; | 334 | // CRegId ImplId; |
| 250 | // UInt64 UniqueId; | 335 | // UInt64 UniqueId; |
| 251 | 336 | ||
| 337 | bool IsExtended; | ||
| 252 | bool IsInline; | 338 | bool IsInline; |
| 253 | CByteBuffer InlineData; | 339 | CByteBuffer InlineData; |
| 254 | CRecordVector<CMyExtent> Extents; | 340 | CRecordVector<CMyExtent> Extents; |
| 255 | CUIntVector SubFiles; | 341 | CUIntVector SubFiles; |
| 256 | 342 | ||
| 257 | void Parse(const Byte *buf); | 343 | void Parse(const Byte *p); |
| 258 | 344 | ||
| 259 | bool IsRecAndAlloc() const | 345 | bool IsRecAndAlloc() const |
| 260 | { | 346 | { |
| @@ -279,53 +365,65 @@ struct CItem | |||
| 279 | bool IsDir() const { return IcbTag.IsDir(); } | 365 | bool IsDir() const { return IcbTag.IsDir(); } |
| 280 | }; | 366 | }; |
| 281 | 367 | ||
| 368 | |||
| 282 | struct CRef | 369 | struct CRef |
| 283 | { | 370 | { |
| 284 | int Parent; | ||
| 285 | unsigned FileIndex; | 371 | unsigned FileIndex; |
| 372 | int Parent; | ||
| 286 | }; | 373 | }; |
| 287 | 374 | ||
| 288 | 375 | ||
| 289 | // ECMA 4 / 14.1 | 376 | // ECMA 4 / 14.1 |
| 290 | struct CFileSet | 377 | struct CFileSet |
| 291 | { | 378 | { |
| 292 | CTime RecodringTime; | 379 | CRecordVector<CRef> Refs; |
| 380 | |||
| 381 | CTime RecordingTime; | ||
| 293 | // UInt16 InterchangeLevel; | 382 | // UInt16 InterchangeLevel; |
| 294 | // UInt16 MaxInterchangeLevel; | 383 | // UInt16 MaxInterchangeLevel; |
| 295 | // UInt32 FileSetNumber; | 384 | UInt32 FileSetNumber; |
| 296 | // UInt32 FileSetDescNumber; | 385 | UInt32 FileSetDescNumber; |
| 297 | // CDString32 Id; | 386 | CDString128 LogicalVolumeId; |
| 298 | // CDString32 CopyrightId; | 387 | CDString32 Id; |
| 299 | // CDString32 AbstractId; | 388 | CDString32 CopyrightId; |
| 389 | CDString32 AbstractId; | ||
| 300 | 390 | ||
| 301 | CLongAllocDesc RootDirICB; | 391 | CLongAllocDesc RootDirICB; |
| 302 | // CRegId DomainId; | 392 | CRegId DomainId; |
| 303 | // CLongAllocDesc SystemStreamDirICB; | 393 | // CLongAllocDesc SystemStreamDirICB; |
| 304 | |||
| 305 | CRecordVector<CRef> Refs; | ||
| 306 | }; | 394 | }; |
| 307 | 395 | ||
| 308 | 396 | ||
| 397 | /* 8.3 Volume descriptors | ||
| 398 | 8.4 | ||
| 399 | A Volume Descriptor Sequence: | ||
| 400 | shall contain one or more Primary Volume Descriptors. | ||
| 401 | */ | ||
| 402 | |||
| 309 | // ECMA 3/10.6 | 403 | // ECMA 3/10.6 |
| 404 | // UDF 2.2.4 LogicalVolumeDescriptor | ||
| 310 | 405 | ||
| 311 | struct CLogVol | 406 | struct CLogVol |
| 312 | { | 407 | { |
| 313 | CDString128 Id; | 408 | CObjectVector<CPartitionMap> PartitionMaps; |
| 409 | CObjectVector<CFileSet> FileSets; | ||
| 410 | |||
| 314 | UInt32 BlockSize; | 411 | UInt32 BlockSize; |
| 315 | // CRegId DomainId; | 412 | CDString128 Id; |
| 413 | CRegId DomainId; | ||
| 316 | 414 | ||
| 317 | // Byte ContentsUse[16]; | 415 | // Byte ContentsUse[16]; |
| 318 | CLongAllocDesc FileSetLocation; // UDF | 416 | CLongAllocDesc FileSetLocation; // UDF |
| 319 | 417 | ||
| 320 | // CRegId ImplId; | 418 | CRegId ImplId; |
| 321 | // Byte ImplUse[128]; | 419 | // Byte ImplUse[128]; |
| 322 | 420 | // CExtent IntegritySequenceExtent; | |
| 323 | CObjectVector<CPartitionMap> PartitionMaps; | ||
| 324 | CObjectVector<CFileSet> FileSets; | ||
| 325 | 421 | ||
| 326 | UString GetName() const { return Id.GetString(); } | 422 | UString GetName() const { return Id.GetString(); } |
| 327 | }; | 423 | }; |
| 328 | 424 | ||
| 425 | |||
| 426 | |||
| 329 | struct CProgressVirt | 427 | struct CProgressVirt |
| 330 | { | 428 | { |
| 331 | virtual HRESULT SetTotal(UInt64 numBytes) PURE; | 429 | virtual HRESULT SetTotal(UInt64 numBytes) PURE; |
| @@ -335,15 +433,42 @@ struct CProgressVirt | |||
| 335 | 433 | ||
| 336 | class CInArchive | 434 | class CInArchive |
| 337 | { | 435 | { |
| 436 | public: | ||
| 437 | CObjectVector<CLogVol> LogVols; | ||
| 438 | CObjectVector<CItem> Items; | ||
| 439 | CObjectVector<CFile> Files; | ||
| 440 | CObjectVector<CPartition> Partitions; | ||
| 441 | |||
| 442 | unsigned SecLogSize; | ||
| 443 | UInt64 PhySize; | ||
| 444 | UInt64 FileSize; | ||
| 445 | |||
| 446 | bool IsArc; | ||
| 447 | bool Unsupported; | ||
| 448 | bool UnexpectedEnd; | ||
| 449 | bool NoEndAnchor; | ||
| 450 | |||
| 451 | CObjectVector<CPrimeVol> PrimeVols; | ||
| 452 | |||
| 453 | HRESULT Open(IInStream *inStream, CProgressVirt *progress); | ||
| 454 | void Clear(); | ||
| 455 | |||
| 456 | UString GetComment() const; | ||
| 457 | UString GetItemPath(unsigned volIndex, unsigned fsIndex, unsigned refIndex, | ||
| 458 | bool showVolName, bool showFsName) const; | ||
| 459 | |||
| 460 | bool CheckItemExtents(unsigned volIndex, const CItem &item) const; | ||
| 461 | |||
| 462 | private: | ||
| 338 | IInStream *_stream; | 463 | IInStream *_stream; |
| 339 | CProgressVirt *_progress; | 464 | CProgressVirt *_progress; |
| 340 | 465 | ||
| 341 | HRESULT Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf); | 466 | HRESULT Read(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len, Byte *buf); |
| 342 | HRESULT Read(int volIndex, const CLongAllocDesc &lad, Byte *buf); | 467 | HRESULT ReadLad(unsigned volIndex, const CLongAllocDesc &lad, Byte *buf); |
| 343 | HRESULT ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf); | 468 | HRESULT ReadFromFile(unsigned volIndex, const CItem &item, CByteBuffer &buf); |
| 344 | 469 | ||
| 345 | HRESULT ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed); | 470 | HRESULT ReadFileItem(unsigned volIndex, unsigned fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed); |
| 346 | HRESULT ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed); | 471 | HRESULT ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed); |
| 347 | 472 | ||
| 348 | HRESULT Open2(); | 473 | HRESULT Open2(); |
| 349 | HRESULT FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed); | 474 | HRESULT FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed); |
| @@ -354,37 +479,18 @@ class CInArchive | |||
| 354 | unsigned _numRefs; | 479 | unsigned _numRefs; |
| 355 | UInt32 _numExtents; | 480 | UInt32 _numExtents; |
| 356 | UInt64 _inlineExtentsSize; | 481 | UInt64 _inlineExtentsSize; |
| 357 | bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const; | 482 | bool CheckExtent(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len) const; |
| 358 | |||
| 359 | public: | ||
| 360 | CObjectVector<CPartition> Partitions; | ||
| 361 | CObjectVector<CLogVol> LogVols; | ||
| 362 | |||
| 363 | CObjectVector<CItem> Items; | ||
| 364 | CObjectVector<CFile> Files; | ||
| 365 | |||
| 366 | unsigned SecLogSize; | ||
| 367 | UInt64 PhySize; | ||
| 368 | UInt64 FileSize; | ||
| 369 | |||
| 370 | bool IsArc; | ||
| 371 | bool Unsupported; | ||
| 372 | bool UnexpectedEnd; | ||
| 373 | bool NoEndAnchor; | ||
| 374 | 483 | ||
| 375 | void UpdatePhySize(UInt64 val) | 484 | void UpdatePhySize(UInt64 val) |
| 376 | { | 485 | { |
| 377 | if (PhySize < val) | 486 | if (PhySize < val) |
| 378 | PhySize = val; | 487 | PhySize = val; |
| 379 | } | 488 | } |
| 380 | HRESULT Open(IInStream *inStream, CProgressVirt *progress); | ||
| 381 | void Clear(); | ||
| 382 | |||
| 383 | UString GetComment() const; | ||
| 384 | UString GetItemPath(int volIndex, int fsIndex, int refIndex, | ||
| 385 | bool showVolName, bool showFsName) const; | ||
| 386 | 489 | ||
| 387 | bool CheckItemExtents(int volIndex, const CItem &item) const; | 490 | void UpdatePhySize(const CExtent &e) |
| 491 | { | ||
| 492 | UpdatePhySize(((UInt64)e.Pos << SecLogSize) + e.Len); | ||
| 493 | } | ||
| 388 | }; | 494 | }; |
| 389 | 495 | ||
| 390 | API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size); | 496 | API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size); |
diff --git a/CPP/7zip/Bundles/Alone/makefile.gcc b/CPP/7zip/Bundles/Alone/makefile.gcc index 38f8d59..20d6a86 100644 --- a/CPP/7zip/Bundles/Alone/makefile.gcc +++ b/CPP/7zip/Bundles/Alone/makefile.gcc | |||
| @@ -13,11 +13,20 @@ LOCAL_FLAGS_ST = | |||
| 13 | MT_OBJS = | 13 | MT_OBJS = |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | ifdef SystemDrive | ||
| 17 | IS_MINGW = 1 | ||
| 18 | else | ||
| 19 | ifdef SYSTEMDRIVE | ||
| 20 | # ifdef OS | ||
| 21 | IS_MINGW = 1 | ||
| 22 | endif | ||
| 23 | endif | ||
| 24 | |||
| 16 | ifdef ST_MODE | 25 | ifdef ST_MODE |
| 17 | 26 | ||
| 18 | LOCAL_FLAGS_ST = -D_7ZIP_ST | 27 | LOCAL_FLAGS_ST = -D_7ZIP_ST |
| 19 | 28 | ||
| 20 | ifdef SystemDrive | 29 | ifdef IS_MINGW |
| 21 | MT_OBJS = \ | 30 | MT_OBJS = \ |
| 22 | $O/Threads.o \ | 31 | $O/Threads.o \ |
| 23 | 32 | ||
| @@ -41,7 +50,7 @@ endif | |||
| 41 | 50 | ||
| 42 | LOCAL_FLAGS_SYS = | 51 | LOCAL_FLAGS_SYS = |
| 43 | 52 | ||
| 44 | ifdef SystemDrive | 53 | ifdef IS_MINGW |
| 45 | 54 | ||
| 46 | LOCAL_FLAGS_SYS = \ | 55 | LOCAL_FLAGS_SYS = \ |
| 47 | -D_7ZIP_LARGE_PAGES \ | 56 | -D_7ZIP_LARGE_PAGES \ |
diff --git a/CPP/7zip/Bundles/Alone2/makefile.gcc b/CPP/7zip/Bundles/Alone2/makefile.gcc index f8d31db..49f9fd0 100644 --- a/CPP/7zip/Bundles/Alone2/makefile.gcc +++ b/CPP/7zip/Bundles/Alone2/makefile.gcc | |||
| @@ -9,6 +9,15 @@ CONSOLE_VARIANT_FLAGS=-DPROG_VARIANT_Z | |||
| 9 | include ../Format7zF/Arc_gcc.mak | 9 | include ../Format7zF/Arc_gcc.mak |
| 10 | 10 | ||
| 11 | ifdef SystemDrive | 11 | ifdef SystemDrive |
| 12 | IS_MINGW = 1 | ||
| 13 | else | ||
| 14 | ifdef SYSTEMDRIVE | ||
| 15 | # ifdef OS | ||
| 16 | IS_MINGW = 1 | ||
| 17 | endif | ||
| 18 | endif | ||
| 19 | |||
| 20 | ifdef IS_MINGW | ||
| 12 | 21 | ||
| 13 | LOCAL_FLAGS_SYS = \ | 22 | LOCAL_FLAGS_SYS = \ |
| 14 | -D_7ZIP_LARGE_PAGES \ | 23 | -D_7ZIP_LARGE_PAGES \ |
diff --git a/CPP/7zip/Bundles/Alone7z/makefile.gcc b/CPP/7zip/Bundles/Alone7z/makefile.gcc index 8565452..f11fcde 100644 --- a/CPP/7zip/Bundles/Alone7z/makefile.gcc +++ b/CPP/7zip/Bundles/Alone7z/makefile.gcc | |||
| @@ -6,6 +6,15 @@ CONSOLE_VARIANT_FLAGS=-DPROG_VARIANT_R | |||
| 6 | # USE_ASM = 1 | 6 | # USE_ASM = 1 |
| 7 | # ST_MODE = 1 | 7 | # ST_MODE = 1 |
| 8 | 8 | ||
| 9 | ifdef SystemDrive | ||
| 10 | IS_MINGW = 1 | ||
| 11 | else | ||
| 12 | ifdef SYSTEMDRIVE | ||
| 13 | # ifdef OS | ||
| 14 | IS_MINGW = 1 | ||
| 15 | endif | ||
| 16 | endif | ||
| 17 | |||
| 9 | include ../../LzmaDec_gcc.mak | 18 | include ../../LzmaDec_gcc.mak |
| 10 | 19 | ||
| 11 | 20 | ||
| @@ -17,7 +26,7 @@ ifdef ST_MODE | |||
| 17 | 26 | ||
| 18 | LOCAL_FLAGS_ST = -D_7ZIP_ST | 27 | LOCAL_FLAGS_ST = -D_7ZIP_ST |
| 19 | 28 | ||
| 20 | ifdef SystemDrive | 29 | ifdef IS_MINGW |
| 21 | MT_OBJS = \ | 30 | MT_OBJS = \ |
| 22 | $O/Threads.o \ | 31 | $O/Threads.o \ |
| 23 | 32 | ||
| @@ -41,7 +50,7 @@ endif | |||
| 41 | 50 | ||
| 42 | LOCAL_FLAGS_SYS = | 51 | LOCAL_FLAGS_SYS = |
| 43 | 52 | ||
| 44 | ifdef SystemDrive | 53 | ifdef IS_MINGW |
| 45 | 54 | ||
| 46 | LOCAL_FLAGS_SYS = \ | 55 | LOCAL_FLAGS_SYS = \ |
| 47 | -D_7ZIP_LARGE_PAGES \ | 56 | -D_7ZIP_LARGE_PAGES \ |
diff --git a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak index e5e1e21..1292dd8 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak | |||
| @@ -3,12 +3,20 @@ include ../../LzmaDec_gcc.mak | |||
| 3 | LOCAL_FLAGS_ST = | 3 | LOCAL_FLAGS_ST = |
| 4 | MT_OBJS = | 4 | MT_OBJS = |
| 5 | 5 | ||
| 6 | ifdef SystemDrive | ||
| 7 | IS_MINGW = 1 | ||
| 8 | else | ||
| 9 | ifdef SYSTEMDRIVE | ||
| 10 | # ifdef OS | ||
| 11 | IS_MINGW = 1 | ||
| 12 | endif | ||
| 13 | endif | ||
| 6 | 14 | ||
| 7 | ifdef ST_MODE | 15 | ifdef ST_MODE |
| 8 | 16 | ||
| 9 | LOCAL_FLAGS_ST = -D_7ZIP_ST | 17 | LOCAL_FLAGS_ST = -D_7ZIP_ST |
| 10 | 18 | ||
| 11 | ifdef SystemDrive | 19 | ifdef IS_MINGW |
| 12 | MT_OBJS = \ | 20 | MT_OBJS = \ |
| 13 | $O/Threads.o \ | 21 | $O/Threads.o \ |
| 14 | 22 | ||
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index cf2d9e8..bd2ed44 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp | |||
| @@ -2847,6 +2847,10 @@ SOURCE=..\..\Archive\HfsHandler.cpp | |||
| 2847 | # End Source File | 2847 | # End Source File |
| 2848 | # Begin Source File | 2848 | # Begin Source File |
| 2849 | 2849 | ||
| 2850 | SOURCE=..\..\Archive\HfsHandler.h | ||
| 2851 | # End Source File | ||
| 2852 | # Begin Source File | ||
| 2853 | |||
| 2850 | SOURCE=..\..\Archive\IArchive.h | 2854 | SOURCE=..\..\Archive\IArchive.h |
| 2851 | # End Source File | 2855 | # End Source File |
| 2852 | # Begin Source File | 2856 | # Begin Source File |
diff --git a/CPP/7zip/Bundles/Format7zF/makefile.gcc b/CPP/7zip/Bundles/Format7zF/makefile.gcc index 1953dd5..e468d7c 100644 --- a/CPP/7zip/Bundles/Format7zF/makefile.gcc +++ b/CPP/7zip/Bundles/Format7zF/makefile.gcc | |||
| @@ -8,6 +8,16 @@ DEF_FILE = ../../Archive/Archive2.def | |||
| 8 | include Arc_gcc.mak | 8 | include Arc_gcc.mak |
| 9 | 9 | ||
| 10 | ifdef SystemDrive | 10 | ifdef SystemDrive |
| 11 | IS_MINGW = 1 | ||
| 12 | else | ||
| 13 | ifdef SYSTEMDRIVE | ||
| 14 | # ifdef OS | ||
| 15 | IS_MINGW = 1 | ||
| 16 | endif | ||
| 17 | endif | ||
| 18 | |||
| 19 | |||
| 20 | ifdef IS_MINGW | ||
| 11 | 21 | ||
| 12 | LOCAL_FLAGS_WIN = \ | 22 | LOCAL_FLAGS_WIN = \ |
| 13 | -D_7ZIP_LARGE_PAGES \ | 23 | -D_7ZIP_LARGE_PAGES \ |
diff --git a/CPP/7zip/Bundles/LzmaCon/makefile.gcc b/CPP/7zip/Bundles/LzmaCon/makefile.gcc index 58c204a..e45ebb6 100644 --- a/CPP/7zip/Bundles/LzmaCon/makefile.gcc +++ b/CPP/7zip/Bundles/LzmaCon/makefile.gcc | |||
| @@ -10,6 +10,15 @@ LOCAL_FLAGS_ST = | |||
| 10 | MT_OBJS = | 10 | MT_OBJS = |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | ifdef SystemDrive | ||
| 14 | IS_MINGW = 1 | ||
| 15 | else | ||
| 16 | ifdef SYSTEMDRIVE | ||
| 17 | # ifdef OS | ||
| 18 | IS_MINGW = 1 | ||
| 19 | endif | ||
| 20 | endif | ||
| 21 | |||
| 13 | ifdef ST_MODE | 22 | ifdef ST_MODE |
| 14 | 23 | ||
| 15 | LOCAL_FLAGS_ST = -D_7ZIP_ST | 24 | LOCAL_FLAGS_ST = -D_7ZIP_ST |
| @@ -30,7 +39,7 @@ endif | |||
| 30 | 39 | ||
| 31 | LOCAL_FLAGS_SYS = | 40 | LOCAL_FLAGS_SYS = |
| 32 | 41 | ||
| 33 | ifdef SystemDrive | 42 | ifdef IS_MINGW |
| 34 | 43 | ||
| 35 | SYS_OBJS = \ | 44 | SYS_OBJS = \ |
| 36 | $O/Registry.o \ | 45 | $O/Registry.o \ |
diff --git a/CPP/7zip/Bundles/SFXCon/makefile.gcc b/CPP/7zip/Bundles/SFXCon/makefile.gcc index 889ec1f..551b3e1 100644 --- a/CPP/7zip/Bundles/SFXCon/makefile.gcc +++ b/CPP/7zip/Bundles/SFXCon/makefile.gcc | |||
| @@ -11,11 +11,20 @@ LOCAL_FLAGS_ST = | |||
| 11 | MT_OBJS = | 11 | MT_OBJS = |
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | ifdef SystemDrive | ||
| 15 | IS_MINGW = 1 | ||
| 16 | else | ||
| 17 | ifdef SYSTEMDRIVE | ||
| 18 | # ifdef OS | ||
| 19 | IS_MINGW = 1 | ||
| 20 | endif | ||
| 21 | endif | ||
| 22 | |||
| 14 | ifdef ST_MODE | 23 | ifdef ST_MODE |
| 15 | 24 | ||
| 16 | LOCAL_FLAGS_ST = -D_7ZIP_ST | 25 | LOCAL_FLAGS_ST = -D_7ZIP_ST |
| 17 | 26 | ||
| 18 | ifdef SystemDrive | 27 | ifdef IS_MINGW |
| 19 | MT_OBJS = \ | 28 | MT_OBJS = \ |
| 20 | $O/Threads.o \ | 29 | $O/Threads.o \ |
| 21 | 30 | ||
| @@ -35,7 +44,7 @@ endif | |||
| 35 | 44 | ||
| 36 | LOCAL_FLAGS_SYS = | 45 | LOCAL_FLAGS_SYS = |
| 37 | 46 | ||
| 38 | ifdef SystemDrive | 47 | ifdef IS_MINGW |
| 39 | 48 | ||
| 40 | LOCAL_FLAGS_SYS = \ | 49 | LOCAL_FLAGS_SYS = \ |
| 41 | 50 | ||
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index 6862a9b..0349e90 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp | |||
| @@ -11,9 +11,12 @@ | |||
| 11 | #include <grp.h> | 11 | #include <grp.h> |
| 12 | #include <pwd.h> | 12 | #include <pwd.h> |
| 13 | 13 | ||
| 14 | // for major minor | 14 | // for major()/minor(): |
| 15 | // BSD: <sys/types.h> | 15 | #if defined(__FreeBSD__) || defined(BSD) |
| 16 | #include <sys/types.h> | ||
| 17 | #else | ||
| 16 | #include <sys/sysmacros.h> | 18 | #include <sys/sysmacros.h> |
| 19 | #endif | ||
| 17 | 20 | ||
| 18 | #endif | 21 | #endif |
| 19 | 22 | ||
diff --git a/CPP/7zip/Compress/LzfseDecoder.cpp b/CPP/7zip/Compress/LzfseDecoder.cpp index 41c7445..0eb10af 100644 --- a/CPP/7zip/Compress/LzfseDecoder.cpp +++ b/CPP/7zip/Compress/LzfseDecoder.cpp | |||
| @@ -89,11 +89,8 @@ HRESULT CDecoder::DecodeUncompressed(UInt32 unpackSize) | |||
| 89 | 89 | ||
| 90 | 90 | ||
| 91 | 91 | ||
| 92 | HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize) | 92 | HRESULT CDecoder::DecodeLzvn(UInt32 unpackSize, UInt32 packSize) |
| 93 | { | 93 | { |
| 94 | UInt32 packSize; | ||
| 95 | RINOK(GetUInt32(packSize)); | ||
| 96 | |||
| 97 | PRF(printf("\nLZVN %7u %7u", unpackSize, packSize)); | 94 | PRF(printf("\nLZVN %7u %7u", unpackSize, packSize)); |
| 98 | 95 | ||
| 99 | UInt32 D = 0; | 96 | UInt32 D = 0; |
| @@ -854,6 +851,16 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStr | |||
| 854 | UInt64 prevOut = 0; | 851 | UInt64 prevOut = 0; |
| 855 | UInt64 prevIn = 0; | 852 | UInt64 prevIn = 0; |
| 856 | 853 | ||
| 854 | if (LzvnMode) | ||
| 855 | { | ||
| 856 | const UInt64 unpackSize = *outSize; | ||
| 857 | const UInt64 packSize = *inSize; | ||
| 858 | if (unpackSize > (UInt32)(Int32)-1 | ||
| 859 | || packSize > (UInt32)(Int32)-1) | ||
| 860 | return S_FALSE; | ||
| 861 | RINOK(DecodeLzvn((UInt32)unpackSize, (UInt32)packSize)); | ||
| 862 | } | ||
| 863 | else | ||
| 857 | for (;;) | 864 | for (;;) |
| 858 | { | 865 | { |
| 859 | const UInt64 pos = m_OutWindowStream.GetProcessedSize(); | 866 | const UInt64 pos = m_OutWindowStream.GetProcessedSize(); |
| @@ -889,7 +896,12 @@ STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStr | |||
| 889 | if (v == kSignature_LZFSE_V1 || v == kSignature_LZFSE_V2) | 896 | if (v == kSignature_LZFSE_V1 || v == kSignature_LZFSE_V2) |
| 890 | res = DecodeLzfse(cur, (Byte)v); | 897 | res = DecodeLzfse(cur, (Byte)v); |
| 891 | else if (v == 0x6E) // 'n' | 898 | else if (v == 0x6E) // 'n' |
| 892 | res = DecodeLzvn(cur); | 899 | { |
| 900 | UInt32 packSize; | ||
| 901 | res = GetUInt32(packSize); | ||
| 902 | if (res == S_OK) | ||
| 903 | res = DecodeLzvn(cur, packSize); | ||
| 904 | } | ||
| 893 | else if (v == 0x2D) // '-' | 905 | else if (v == 0x2D) // '-' |
| 894 | res = DecodeUncompressed(cur); | 906 | res = DecodeUncompressed(cur); |
| 895 | else | 907 | else |
diff --git a/CPP/7zip/Compress/LzfseDecoder.h b/CPP/7zip/Compress/LzfseDecoder.h index 0156a08..401e0ba 100644 --- a/CPP/7zip/Compress/LzfseDecoder.h +++ b/CPP/7zip/Compress/LzfseDecoder.h | |||
| @@ -41,14 +41,23 @@ class CDecoder: | |||
| 41 | HRESULT GetUInt32(UInt32 &val); | 41 | HRESULT GetUInt32(UInt32 &val); |
| 42 | 42 | ||
| 43 | HRESULT DecodeUncompressed(UInt32 unpackSize); | 43 | HRESULT DecodeUncompressed(UInt32 unpackSize); |
| 44 | HRESULT DecodeLzvn(UInt32 unpackSize); | 44 | HRESULT DecodeLzvn(UInt32 unpackSize, UInt32 packSize); |
| 45 | HRESULT DecodeLzfse(UInt32 unpackSize, Byte version); | 45 | HRESULT DecodeLzfse(UInt32 unpackSize, Byte version); |
| 46 | 46 | ||
| 47 | STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, | 47 | STDMETHOD(CodeReal)(ISequentialInStream *inStream, ISequentialOutStream *outStream, |
| 48 | const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); | 48 | const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); |
| 49 | public: | 49 | public: |
| 50 | bool LzvnMode; | ||
| 50 | MY_UNKNOWN_IMP | 51 | MY_UNKNOWN_IMP |
| 51 | 52 | ||
| 53 | CDecoder(): | ||
| 54 | LzvnMode(false) | ||
| 55 | {} | ||
| 56 | |||
| 57 | // sizes are checked in Code() | ||
| 58 | // UInt64 GetInputProcessedSize() const { return m_InStream.GetProcessedSize(); } | ||
| 59 | // UInt64 GetOutputProcessedSize() const { return m_OutWindowStream.GetProcessedSize(); } | ||
| 60 | |||
| 52 | STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, | 61 | STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, |
| 53 | const UInt64 *outSize, ICompressProgressInfo *progress); | 62 | const UInt64 *outSize, ICompressProgressInfo *progress); |
| 54 | }; | 63 | }; |
diff --git a/CPP/7zip/UI/Client7z/makefile.gcc b/CPP/7zip/UI/Client7z/makefile.gcc index b65095b..3f97205 100644 --- a/CPP/7zip/UI/Client7z/makefile.gcc +++ b/CPP/7zip/UI/Client7z/makefile.gcc | |||
| @@ -6,6 +6,16 @@ IS_NOT_STANDALONE = 1 | |||
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | ifdef SystemDrive | 8 | ifdef SystemDrive |
| 9 | IS_MINGW = 1 | ||
| 10 | else | ||
| 11 | ifdef SYSTEMDRIVE | ||
| 12 | # ifdef OS | ||
| 13 | IS_MINGW = 1 | ||
| 14 | endif | ||
| 15 | endif | ||
| 16 | |||
| 17 | |||
| 18 | ifdef IS_MINGW | ||
| 9 | 19 | ||
| 10 | SYS_OBJS = \ | 20 | SYS_OBJS = \ |
| 11 | $O/resource.o \ | 21 | $O/resource.o \ |
diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index a4ac413..dab3725 100644 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp | |||
| @@ -187,7 +187,7 @@ CDirItems::CDirItems(): | |||
| 187 | , ReadSecure(false) | 187 | , ReadSecure(false) |
| 188 | #endif | 188 | #endif |
| 189 | #ifndef _WIN32 | 189 | #ifndef _WIN32 |
| 190 | , StoreOwnerName(true) | 190 | , StoreOwnerName(false) |
| 191 | #endif | 191 | #endif |
| 192 | , Callback(NULL) | 192 | , Callback(NULL) |
| 193 | { | 193 | { |
| @@ -1361,6 +1361,7 @@ HRESULT CDirItems::FillDeviceSizes() | |||
| 1361 | // 200K/sec speed | 1361 | // 200K/sec speed |
| 1362 | u.Empty(); | 1362 | u.Empty(); |
| 1363 | const passwd *pw = getpwuid(OwnerNameMap.Numbers[i]); | 1363 | const passwd *pw = getpwuid(OwnerNameMap.Numbers[i]); |
| 1364 | // printf("\ngetpwuid=%s\n", pw->pw_name); | ||
| 1364 | if (pw) | 1365 | if (pw) |
| 1365 | { | 1366 | { |
| 1366 | a = pw->pw_name; | 1367 | a = pw->pw_name; |
diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index 926a275..c93bfc7 100644 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp | |||
| @@ -8,11 +8,15 @@ | |||
| 8 | // #include <grp.h> | 8 | // #include <grp.h> |
| 9 | // #include <pwd.h> | 9 | // #include <pwd.h> |
| 10 | 10 | ||
| 11 | // for major minor: | 11 | // for major()/minor(): |
| 12 | // BSD: <sys/types.h> | 12 | #if defined(__FreeBSD__) || defined(BSD) |
| 13 | #include <sys/types.h> | ||
| 14 | #else | ||
| 13 | #include <sys/sysmacros.h> | 15 | #include <sys/sysmacros.h> |
| 14 | #endif | 16 | #endif |
| 15 | 17 | ||
| 18 | #endif | ||
| 19 | |||
| 16 | #ifndef _7ZIP_ST | 20 | #ifndef _7ZIP_ST |
| 17 | #include "../../../Windows/Synchronization.h" | 21 | #include "../../../Windows/Synchronization.h" |
| 18 | #endif | 22 | #endif |
diff --git a/CPP/7zip/UI/Console/Console.dsp b/CPP/7zip/UI/Console/Console.dsp index f6a3254..ea336cf 100644 --- a/CPP/7zip/UI/Console/Console.dsp +++ b/CPP/7zip/UI/Console/Console.dsp | |||
| @@ -345,6 +345,10 @@ SOURCE=..\..\..\Windows\Registry.h | |||
| 345 | # End Source File | 345 | # End Source File |
| 346 | # Begin Source File | 346 | # Begin Source File |
| 347 | 347 | ||
| 348 | SOURCE=..\..\..\Windows\SecurityUtils.h | ||
| 349 | # End Source File | ||
| 350 | # Begin Source File | ||
| 351 | |||
| 348 | SOURCE=..\..\..\Windows\Synchronization.h | 352 | SOURCE=..\..\..\Windows\Synchronization.h |
| 349 | # End Source File | 353 | # End Source File |
| 350 | # Begin Source File | 354 | # Begin Source File |
diff --git a/CPP/7zip/UI/Console/makefile.gcc b/CPP/7zip/UI/Console/makefile.gcc index ed05a14..d7e4447 100644 --- a/CPP/7zip/UI/Console/makefile.gcc +++ b/CPP/7zip/UI/Console/makefile.gcc | |||
| @@ -9,11 +9,20 @@ IS_NOT_STANDALONE = 1 | |||
| 9 | LOCAL_FLAGS_ST = | 9 | LOCAL_FLAGS_ST = |
| 10 | MT_OBJS = | 10 | MT_OBJS = |
| 11 | 11 | ||
| 12 | ifdef SystemDrive | ||
| 13 | IS_MINGW = 1 | ||
| 14 | else | ||
| 15 | ifdef SYSTEMDRIVE | ||
| 16 | # ifdef OS | ||
| 17 | IS_MINGW = 1 | ||
| 18 | endif | ||
| 19 | endif | ||
| 20 | |||
| 12 | ifdef ST_MODE | 21 | ifdef ST_MODE |
| 13 | 22 | ||
| 14 | LOCAL_FLAGS_ST = -D_7ZIP_ST | 23 | LOCAL_FLAGS_ST = -D_7ZIP_ST |
| 15 | 24 | ||
| 16 | ifdef SystemDrive | 25 | ifdef IS_MINGW |
| 17 | MT_OBJS = \ | 26 | MT_OBJS = \ |
| 18 | $O/Threads.o \ | 27 | $O/Threads.o \ |
| 19 | 28 | ||
| @@ -31,7 +40,7 @@ endif | |||
| 31 | 40 | ||
| 32 | LOCAL_FLAGS_WIN= | 41 | LOCAL_FLAGS_WIN= |
| 33 | 42 | ||
| 34 | ifdef SystemDrive | 43 | ifdef IS_MINGW |
| 35 | 44 | ||
| 36 | LOCAL_FLAGS_WIN = \ | 45 | LOCAL_FLAGS_WIN = \ |
| 37 | -D_7ZIP_LARGE_PAGES \ | 46 | -D_7ZIP_LARGE_PAGES \ |
diff --git a/CPP/7zip/UI/Explorer/resource.rc b/CPP/7zip/UI/Explorer/resource.rc index 6659290..acfa6e5 100644 --- a/CPP/7zip/UI/Explorer/resource.rc +++ b/CPP/7zip/UI/Explorer/resource.rc | |||
| @@ -7,4 +7,4 @@ MY_VERSION_INFO_DLL("7-Zip Shell Extension", "7-zip") | |||
| 7 | 1 24 MOVEABLE PURE "7-zip.dll.manifest" | 7 | 1 24 MOVEABLE PURE "7-zip.dll.manifest" |
| 8 | #endif | 8 | #endif |
| 9 | 9 | ||
| 10 | IDI_ICON ICON "..\FileManager\FM.ico" | 10 | IDI_ICON ICON "../FileManager/FM.ico" |
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index 72cb0ce..f603061 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp | |||
| @@ -5,8 +5,13 @@ | |||
| 5 | #if defined(_MSC_VER) | 5 | #if defined(_MSC_VER) |
| 6 | #include <winternl.h> | 6 | #include <winternl.h> |
| 7 | #else | 7 | #else |
| 8 | // mingw | 8 | #if defined(__GNUC__) && (__GNUC__ >= 10) |
| 9 | #include <ddk/winddk.h> | 9 | // new mingw: |
| 10 | #include <winternl.h> | ||
| 11 | #else | ||
| 12 | // old mingw: | ||
| 13 | #include <ddk/winddk.h> | ||
| 14 | #endif | ||
| 10 | #endif | 15 | #endif |
| 11 | 16 | ||
| 12 | #include "../../../Common/ComTry.h" | 17 | #include "../../../Common/ComTry.h" |
diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index ff444b3..4ca931b 100644 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp | |||
| @@ -29,6 +29,9 @@ using namespace NFind; | |||
| 29 | extern bool g_IsNT; | 29 | extern bool g_IsNT; |
| 30 | #endif | 30 | #endif |
| 31 | 31 | ||
| 32 | #define MY_CAST_FUNC (void(*)()) | ||
| 33 | // #define MY_CAST_FUNC | ||
| 34 | |||
| 32 | namespace NFsFolder { | 35 | namespace NFsFolder { |
| 33 | 36 | ||
| 34 | HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib) | 37 | HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib) |
| @@ -245,7 +248,9 @@ void CCopyState::Prepare() | |||
| 245 | my_CopyFileExA = NULL; | 248 | my_CopyFileExA = NULL; |
| 246 | if (!g_IsNT) | 249 | if (!g_IsNT) |
| 247 | { | 250 | { |
| 248 | my_CopyFileExA = (Func_CopyFileExA)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "CopyFileExA"); | 251 | my_CopyFileExA = (Func_CopyFileExA) |
| 252 | MY_CAST_FUNC | ||
| 253 | ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "CopyFileExA"); | ||
| 249 | } | 254 | } |
| 250 | else | 255 | else |
| 251 | #endif | 256 | #endif |
diff --git a/CPP/7zip/UI/FileManager/MyCom2.h b/CPP/7zip/UI/FileManager/MyCom2.h index c45c215..5fe1ef7 100644 --- a/CPP/7zip/UI/FileManager/MyCom2.h +++ b/CPP/7zip/UI/FileManager/MyCom2.h | |||
| @@ -7,8 +7,9 @@ | |||
| 7 | 7 | ||
| 8 | #define MY_ADDREF_RELEASE_MT \ | 8 | #define MY_ADDREF_RELEASE_MT \ |
| 9 | STDMETHOD_(ULONG, AddRef)() { InterlockedIncrement((LONG *)&__m_RefCount); return __m_RefCount; } \ | 9 | STDMETHOD_(ULONG, AddRef)() { InterlockedIncrement((LONG *)&__m_RefCount); return __m_RefCount; } \ |
| 10 | STDMETHOD_(ULONG, Release)() { InterlockedDecrement((LONG *)&__m_RefCount); if (__m_RefCount != 0) \ | 10 | STDMETHOD_(ULONG, Release)() { InterlockedDecrement((LONG *)&__m_RefCount); \ |
| 11 | return __m_RefCount; delete this; return 0; } | 11 | if (__m_RefCount != 0) return __m_RefCount; \ |
| 12 | delete this; return 0; } | ||
| 12 | 13 | ||
| 13 | #define MY_UNKNOWN_IMP_SPEC_MT2(i1, i) \ | 14 | #define MY_UNKNOWN_IMP_SPEC_MT2(i1, i) \ |
| 14 | MY_QUERYINTERFACE_BEGIN \ | 15 | MY_QUERYINTERFACE_BEGIN \ |
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp index e34e74f..a683b5e 100644 --- a/CPP/7zip/UI/FileManager/PanelOperations.cpp +++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp | |||
| @@ -24,6 +24,9 @@ using namespace NWindows; | |||
| 24 | using namespace NFile; | 24 | using namespace NFile; |
| 25 | using namespace NName; | 25 | using namespace NName; |
| 26 | 26 | ||
| 27 | #define MY_CAST_FUNC (void(*)()) | ||
| 28 | // #define MY_CAST_FUNC | ||
| 29 | |||
| 27 | #ifndef _UNICODE | 30 | #ifndef _UNICODE |
| 28 | extern bool g_IsNT; | 31 | extern bool g_IsNT; |
| 29 | #endif | 32 | #endif |
| @@ -96,7 +99,7 @@ HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progr | |||
| 96 | } | 99 | } |
| 97 | 100 | ||
| 98 | #ifndef _UNICODE | 101 | #ifndef _UNICODE |
| 99 | typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp); | 102 | typedef int (WINAPI * Func_SHFileOperationW)(LPSHFILEOPSTRUCTW lpFileOp); |
| 100 | #endif | 103 | #endif |
| 101 | 104 | ||
| 102 | /* | 105 | /* |
| @@ -192,9 +195,10 @@ void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin)) | |||
| 192 | #ifdef _UNICODE | 195 | #ifdef _UNICODE |
| 193 | /* res = */ ::SHFileOperationW(&fo); | 196 | /* res = */ ::SHFileOperationW(&fo); |
| 194 | #else | 197 | #else |
| 195 | SHFileOperationWP shFileOperationW = (SHFileOperationWP) | 198 | Func_SHFileOperationW shFileOperationW = (Func_SHFileOperationW) |
| 199 | MY_CAST_FUNC | ||
| 196 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHFileOperationW"); | 200 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHFileOperationW"); |
| 197 | if (shFileOperationW == 0) | 201 | if (!shFileOperationW) |
| 198 | return; | 202 | return; |
| 199 | /* res = */ shFileOperationW(&fo); | 203 | /* res = */ shFileOperationW(&fo); |
| 200 | #endif | 204 | #endif |
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp index b756dfc..d8e0f8b 100644 --- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp +++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp | |||
| @@ -12,6 +12,9 @@ | |||
| 12 | 12 | ||
| 13 | #include <ShlObj.h> | 13 | #include <ShlObj.h> |
| 14 | 14 | ||
| 15 | #define MY_CAST_FUNC (void(*)()) | ||
| 16 | // #define MY_CAST_FUNC | ||
| 17 | |||
| 15 | #ifndef _UNICODE | 18 | #ifndef _UNICODE |
| 16 | extern bool g_IsNT; | 19 | extern bool g_IsNT; |
| 17 | #endif | 20 | #endif |
| @@ -39,15 +42,16 @@ int GetIconIndexForCSIDL(int csidl) | |||
| 39 | } | 42 | } |
| 40 | 43 | ||
| 41 | #ifndef _UNICODE | 44 | #ifndef _UNICODE |
| 42 | typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); | 45 | typedef int (WINAPI * Func_SHGetFileInfoW)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags); |
| 43 | 46 | ||
| 44 | static struct CSHGetFileInfoInit | 47 | static struct CSHGetFileInfoInit |
| 45 | { | 48 | { |
| 46 | SHGetFileInfoWP shGetFileInfoW; | 49 | Func_SHGetFileInfoW shGetFileInfoW; |
| 47 | CSHGetFileInfoInit() | 50 | CSHGetFileInfoInit() |
| 48 | { | 51 | { |
| 49 | shGetFileInfoW = (SHGetFileInfoWP) | 52 | shGetFileInfoW = (Func_SHGetFileInfoW) |
| 50 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW"); | 53 | MY_CAST_FUNC |
| 54 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW"); | ||
| 51 | } | 55 | } |
| 52 | } g_SHGetFileInfoInit; | 56 | } g_SHGetFileInfoInit; |
| 53 | #endif | 57 | #endif |
diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp index 6a989fc..4edf025 100644 --- a/CPP/7zip/UI/FileManager/TextPairs.cpp +++ b/CPP/7zip/UI/FileManager/TextPairs.cpp | |||
| @@ -104,13 +104,16 @@ void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, 0); } | |||
| 104 | 104 | ||
| 105 | int CPairsStorage::FindID(const UString &id, int &insertPos) const | 105 | int CPairsStorage::FindID(const UString &id, int &insertPos) const |
| 106 | { | 106 | { |
| 107 | int left = 0, right = Pairs.Size(); | 107 | unsigned left = 0, right = Pairs.Size(); |
| 108 | while (left != right) | 108 | while (left != right) |
| 109 | { | 109 | { |
| 110 | int mid = (left + right) / 2; | 110 | const unsigned mid = (left + right) / 2; |
| 111 | int compResult = ComparePairIDs(id, Pairs[mid].ID); | 111 | const int compResult = ComparePairIDs(id, Pairs[mid].ID); |
| 112 | if (compResult == 0) | 112 | if (compResult == 0) |
| 113 | { | ||
| 114 | insertPos = mid; // to disable GCC warning | ||
| 113 | return mid; | 115 | return mid; |
| 116 | } | ||
| 114 | if (compResult < 0) | 117 | if (compResult < 0) |
| 115 | right = mid; | 118 | right = mid; |
| 116 | else | 119 | else |
| @@ -129,7 +132,7 @@ int CPairsStorage::FindID(const UString &id) const | |||
| 129 | void CPairsStorage::AddPair(const CTextPair &pair) | 132 | void CPairsStorage::AddPair(const CTextPair &pair) |
| 130 | { | 133 | { |
| 131 | int insertPos; | 134 | int insertPos; |
| 132 | int pos = FindID(pair.ID, insertPos); | 135 | const int pos = FindID(pair.ID, insertPos); |
| 133 | if (pos >= 0) | 136 | if (pos >= 0) |
| 134 | Pairs[pos] = pair; | 137 | Pairs[pos] = pair; |
| 135 | else | 138 | else |
| @@ -138,7 +141,7 @@ void CPairsStorage::AddPair(const CTextPair &pair) | |||
| 138 | 141 | ||
| 139 | void CPairsStorage::DeletePair(const UString &id) | 142 | void CPairsStorage::DeletePair(const UString &id) |
| 140 | { | 143 | { |
| 141 | int pos = FindID(id); | 144 | const int pos = FindID(id); |
| 142 | if (pos >= 0) | 145 | if (pos >= 0) |
| 143 | Pairs.Delete(pos); | 146 | Pairs.Delete(pos); |
| 144 | } | 147 | } |
| @@ -146,7 +149,7 @@ void CPairsStorage::DeletePair(const UString &id) | |||
| 146 | bool CPairsStorage::GetValue(const UString &id, UString &value) const | 149 | bool CPairsStorage::GetValue(const UString &id, UString &value) const |
| 147 | { | 150 | { |
| 148 | value.Empty(); | 151 | value.Empty(); |
| 149 | int pos = FindID(id); | 152 | const int pos = FindID(id); |
| 150 | if (pos < 0) | 153 | if (pos < 0) |
| 151 | return false; | 154 | return false; |
| 152 | value = Pairs[pos].Value; | 155 | value = Pairs[pos].Value; |
| @@ -155,7 +158,7 @@ bool CPairsStorage::GetValue(const UString &id, UString &value) const | |||
| 155 | 158 | ||
| 156 | UString CPairsStorage::GetValue(const UString &id) const | 159 | UString CPairsStorage::GetValue(const UString &id) const |
| 157 | { | 160 | { |
| 158 | int pos = FindID(id); | 161 | const int pos = FindID(id); |
| 159 | if (pos < 0) | 162 | if (pos < 0) |
| 160 | return UString(); | 163 | return UString(); |
| 161 | return Pairs[pos].Value; | 164 | return Pairs[pos].Value; |
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 25b9219..b85ae1e 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp | |||
| @@ -292,6 +292,7 @@ static const CFormatInfo g_Formats[] = | |||
| 292 | "Tar", | 292 | "Tar", |
| 293 | (1 << 0), | 293 | (1 << 0), |
| 294 | METHODS_PAIR(g_TarMethods), | 294 | METHODS_PAIR(g_TarMethods), |
| 295 | 0 | ||
| 295 | // kFF_Time_Unix | kFF_Time_Win // | kFF_Time_1ns | 296 | // kFF_Time_Unix | kFF_Time_Win // | kFF_Time_1ns |
| 296 | }, | 297 | }, |
| 297 | { | 298 | { |
| @@ -596,7 +597,6 @@ void CCompressDialog::EnableMultiCombo(unsigned id) | |||
| 596 | } | 597 | } |
| 597 | 598 | ||
| 598 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s); | 599 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s); |
| 599 | static void FormatOptions_To_String(const NCompression::CFormatOptions &fo, AString &s); | ||
| 600 | 600 | ||
| 601 | static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res) | 601 | static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res) |
| 602 | { | 602 | { |
| @@ -607,7 +607,7 @@ static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBoo | |||
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | #define SET_GUI_BOOL(name) \ | 609 | #define SET_GUI_BOOL(name) \ |
| 610 | Combine_Two_BoolPairs(Info. ## name, m_RegistryInfo. ## name, name) | 610 | Combine_Two_BoolPairs(Info. name, m_RegistryInfo. name, name) |
| 611 | 611 | ||
| 612 | 612 | ||
| 613 | static void Set_Final_BoolPairs( | 613 | static void Set_Final_BoolPairs( |
| @@ -630,7 +630,7 @@ static void Set_Final_BoolPairs( | |||
| 630 | } | 630 | } |
| 631 | 631 | ||
| 632 | #define SET_FINAL_BOOL_PAIRS(name) \ | 632 | #define SET_FINAL_BOOL_PAIRS(name) \ |
| 633 | Set_Final_BoolPairs(name, Info. ## name, m_RegistryInfo. ## name) | 633 | Set_Final_BoolPairs(name, Info. name, m_RegistryInfo. name) |
| 634 | 634 | ||
| 635 | void CCompressDialog::FormatChanged(bool isChanged) | 635 | void CCompressDialog::FormatChanged(bool isChanged) |
| 636 | { | 636 | { |
| @@ -2711,7 +2711,7 @@ void CCompressDialog::ShowOptionsString() | |||
| 2711 | NCompression::CFormatOptions &fo = Get_FormatOptions(); | 2711 | NCompression::CFormatOptions &fo = Get_FormatOptions(); |
| 2712 | 2712 | ||
| 2713 | AString s; | 2713 | AString s; |
| 2714 | if (fo.TimePrec != -1) | 2714 | if (fo.IsSet_TimePrec()) |
| 2715 | { | 2715 | { |
| 2716 | s.Add_OptSpaced("tp"); | 2716 | s.Add_OptSpaced("tp"); |
| 2717 | s.Add_UInt32(fo.TimePrec); | 2717 | s.Add_UInt32(fo.TimePrec); |
diff --git a/CPP/Windows/MemoryLock.cpp b/CPP/Windows/MemoryLock.cpp index fdfbeb9..24866b1 100644 --- a/CPP/Windows/MemoryLock.cpp +++ b/CPP/Windows/MemoryLock.cpp | |||
| @@ -21,7 +21,7 @@ typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR | |||
| 21 | typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges, | 21 | typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges, |
| 22 | PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength); | 22 | PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength); |
| 23 | } | 23 | } |
| 24 | #define GET_PROC_ADDR(fff, name) Func_ ## fff my_ ## fff = (Func_ ## fff)GetProcAddress(hModule, name) | 24 | #define GET_PROC_ADDR(fff, name) Func_ ## fff my_ ## fff = (Func_ ## fff) (void(*)()) GetProcAddress(hModule, name) |
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| 27 | bool EnablePrivilege(LPCTSTR privilegeName, bool enable) | 27 | bool EnablePrivilege(LPCTSTR privilegeName, bool enable) |
diff --git a/CPP/Windows/SecurityUtils.cpp b/CPP/Windows/SecurityUtils.cpp index 8a7f45c..ede83fa 100644 --- a/CPP/Windows/SecurityUtils.cpp +++ b/CPP/Windows/SecurityUtils.cpp | |||
| @@ -4,6 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include "SecurityUtils.h" | 5 | #include "SecurityUtils.h" |
| 6 | 6 | ||
| 7 | #define MY_CAST_FUNC (void(*)()) | ||
| 8 | // #define MY_CAST_FUNC | ||
| 9 | |||
| 7 | namespace NWindows { | 10 | namespace NWindows { |
| 8 | namespace NSecurity { | 11 | namespace NSecurity { |
| 9 | 12 | ||
| @@ -50,8 +53,10 @@ static void MyLookupSids(CPolicy &policy, PSID ps) | |||
| 50 | } | 53 | } |
| 51 | */ | 54 | */ |
| 52 | 55 | ||
| 56 | extern "C" { | ||
| 57 | |||
| 53 | #ifndef _UNICODE | 58 | #ifndef _UNICODE |
| 54 | typedef BOOL (WINAPI * LookupAccountNameWP)( | 59 | typedef BOOL (WINAPI * Func_LookupAccountNameW)( |
| 55 | LPCWSTR lpSystemName, | 60 | LPCWSTR lpSystemName, |
| 56 | LPCWSTR lpAccountName, | 61 | LPCWSTR lpAccountName, |
| 57 | PSID Sid, | 62 | PSID Sid, |
| @@ -62,13 +67,17 @@ typedef BOOL (WINAPI * LookupAccountNameWP)( | |||
| 62 | ); | 67 | ); |
| 63 | #endif | 68 | #endif |
| 64 | 69 | ||
| 70 | } | ||
| 71 | |||
| 65 | static PSID GetSid(LPWSTR accountName) | 72 | static PSID GetSid(LPWSTR accountName) |
| 66 | { | 73 | { |
| 67 | #ifndef _UNICODE | 74 | #ifndef _UNICODE |
| 68 | HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll")); | 75 | HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll")); |
| 69 | if (hModule == NULL) | 76 | if (hModule == NULL) |
| 70 | return NULL; | 77 | return NULL; |
| 71 | LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW"); | 78 | Func_LookupAccountNameW lookupAccountNameW = (Func_LookupAccountNameW) |
| 79 | MY_CAST_FUNC | ||
| 80 | GetProcAddress(hModule, "LookupAccountNameW"); | ||
| 72 | if (lookupAccountNameW == NULL) | 81 | if (lookupAccountNameW == NULL) |
| 73 | return NULL; | 82 | return NULL; |
| 74 | #endif | 83 | #endif |
diff --git a/CPP/Windows/SecurityUtils.h b/CPP/Windows/SecurityUtils.h index 8966dfd..c0d7b12 100644 --- a/CPP/Windows/SecurityUtils.h +++ b/CPP/Windows/SecurityUtils.h | |||
| @@ -7,6 +7,31 @@ | |||
| 7 | 7 | ||
| 8 | #include "Defs.h" | 8 | #include "Defs.h" |
| 9 | 9 | ||
| 10 | #ifndef _UNICODE | ||
| 11 | |||
| 12 | extern "C" { | ||
| 13 | typedef NTSTATUS (NTAPI *Func_LsaOpenPolicy)(PLSA_UNICODE_STRING SystemName, | ||
| 14 | PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle); | ||
| 15 | typedef NTSTATUS (NTAPI *Func_LsaClose)(LSA_HANDLE ObjectHandle); | ||
| 16 | typedef NTSTATUS (NTAPI *Func_LsaAddAccountRights)(LSA_HANDLE PolicyHandle, | ||
| 17 | PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights ); | ||
| 18 | #define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) | ||
| 19 | } | ||
| 20 | |||
| 21 | #define POLICY_FUNC_CALL(fff, str) \ | ||
| 22 | if (hModule == NULL) return MY_STATUS_NOT_IMPLEMENTED; \ | ||
| 23 | Func_ ## fff v = (Func_ ## fff) (void(*)()) GetProcAddress(hModule, str); \ | ||
| 24 | if (!v) return MY_STATUS_NOT_IMPLEMENTED; \ | ||
| 25 | const NTSTATUS res = v | ||
| 26 | |||
| 27 | #else | ||
| 28 | |||
| 29 | #define POLICY_FUNC_CALL(fff, str) \ | ||
| 30 | const NTSTATUS res = ::fff | ||
| 31 | |||
| 32 | #endif | ||
| 33 | |||
| 34 | |||
| 10 | namespace NWindows { | 35 | namespace NWindows { |
| 11 | namespace NSecurity { | 36 | namespace NSecurity { |
| 12 | 37 | ||
| @@ -53,15 +78,9 @@ public: | |||
| 53 | 78 | ||
| 54 | }; | 79 | }; |
| 55 | 80 | ||
| 56 | #ifndef _UNICODE | ||
| 57 | typedef NTSTATUS (NTAPI *LsaOpenPolicyP)(PLSA_UNICODE_STRING SystemName, | ||
| 58 | PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle); | ||
| 59 | typedef NTSTATUS (NTAPI *LsaCloseP)(LSA_HANDLE ObjectHandle); | ||
| 60 | typedef NTSTATUS (NTAPI *LsaAddAccountRightsP)(LSA_HANDLE PolicyHandle, | ||
| 61 | PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights ); | ||
| 62 | #define MY_STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L) | ||
| 63 | #endif | ||
| 64 | 81 | ||
| 82 | |||
| 83 | |||
| 65 | struct CPolicy | 84 | struct CPolicy |
| 66 | { | 85 | { |
| 67 | protected: | 86 | protected: |
| @@ -82,43 +101,17 @@ public: | |||
| 82 | NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes, | 101 | NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes, |
| 83 | ACCESS_MASK desiredAccess) | 102 | ACCESS_MASK desiredAccess) |
| 84 | { | 103 | { |
| 85 | #ifndef _UNICODE | ||
| 86 | if (hModule == NULL) | ||
| 87 | return MY_STATUS_NOT_IMPLEMENTED; | ||
| 88 | LsaOpenPolicyP lsaOpenPolicy = (LsaOpenPolicyP)GetProcAddress(hModule, "LsaOpenPolicy"); | ||
| 89 | if (lsaOpenPolicy == NULL) | ||
| 90 | return MY_STATUS_NOT_IMPLEMENTED; | ||
| 91 | #endif | ||
| 92 | |||
| 93 | Close(); | 104 | Close(); |
| 94 | return | 105 | POLICY_FUNC_CALL (LsaOpenPolicy, "LsaOpenPolicy") |
| 95 | #ifdef _UNICODE | ||
| 96 | ::LsaOpenPolicy | ||
| 97 | #else | ||
| 98 | lsaOpenPolicy | ||
| 99 | #endif | ||
| 100 | (systemName, objectAttributes, desiredAccess, &_handle); | 106 | (systemName, objectAttributes, desiredAccess, &_handle); |
| 107 | return res; | ||
| 101 | } | 108 | } |
| 102 | 109 | ||
| 103 | NTSTATUS Close() | 110 | NTSTATUS Close() |
| 104 | { | 111 | { |
| 105 | if (_handle == NULL) | 112 | if (_handle == NULL) |
| 106 | return 0; | 113 | return 0; |
| 107 | 114 | POLICY_FUNC_CALL (LsaClose, "LsaClose") | |
| 108 | #ifndef _UNICODE | ||
| 109 | if (hModule == NULL) | ||
| 110 | return MY_STATUS_NOT_IMPLEMENTED; | ||
| 111 | LsaCloseP lsaClose = (LsaCloseP)GetProcAddress(hModule, "LsaClose"); | ||
| 112 | if (lsaClose == NULL) | ||
| 113 | return MY_STATUS_NOT_IMPLEMENTED; | ||
| 114 | #endif | ||
| 115 | |||
| 116 | NTSTATUS res = | ||
| 117 | #ifdef _UNICODE | ||
| 118 | ::LsaClose | ||
| 119 | #else | ||
| 120 | lsaClose | ||
| 121 | #endif | ||
| 122 | (_handle); | 115 | (_handle); |
| 123 | _handle = NULL; | 116 | _handle = NULL; |
| 124 | return res; | 117 | return res; |
| @@ -137,21 +130,9 @@ public: | |||
| 137 | 130 | ||
| 138 | NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights) | 131 | NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights) |
| 139 | { | 132 | { |
| 140 | #ifndef _UNICODE | 133 | POLICY_FUNC_CALL (LsaAddAccountRights, "LsaAddAccountRights") |
| 141 | if (hModule == NULL) | ||
| 142 | return MY_STATUS_NOT_IMPLEMENTED; | ||
| 143 | LsaAddAccountRightsP lsaAddAccountRights = (LsaAddAccountRightsP)GetProcAddress(hModule, "LsaAddAccountRights"); | ||
| 144 | if (lsaAddAccountRights == NULL) | ||
| 145 | return MY_STATUS_NOT_IMPLEMENTED; | ||
| 146 | #endif | ||
| 147 | |||
| 148 | return | ||
| 149 | #ifdef _UNICODE | ||
| 150 | ::LsaAddAccountRights | ||
| 151 | #else | ||
| 152 | lsaAddAccountRights | ||
| 153 | #endif | ||
| 154 | (_handle, accountSid, userRights, countOfRights); | 134 | (_handle, accountSid, userRights, countOfRights); |
| 135 | return res; | ||
| 155 | } | 136 | } |
| 156 | NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights) | 137 | NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights) |
| 157 | { return AddAccountRights(accountSid, userRights, 1); } | 138 | { return AddAccountRights(accountSid, userRights, 1); } |
diff --git a/CPP/Windows/Shell.cpp b/CPP/Windows/Shell.cpp index d0f9032..071833c 100644 --- a/CPP/Windows/Shell.cpp +++ b/CPP/Windows/Shell.cpp | |||
| @@ -258,14 +258,21 @@ bool BrowseForFolder(HWND owner, LPCTSTR title, | |||
| 258 | 258 | ||
| 259 | #ifndef _UNICODE | 259 | #ifndef _UNICODE |
| 260 | 260 | ||
| 261 | typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath); | 261 | extern "C" { |
| 262 | typedef BOOL (WINAPI * Func_SHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath); | ||
| 263 | typedef LPITEMIDLIST (WINAPI * Func_SHBrowseForFolderW)(LPBROWSEINFOW lpbi); | ||
| 264 | } | ||
| 265 | |||
| 266 | #define MY_CAST_FUNC (void(*)()) | ||
| 267 | // #define MY_CAST_FUNC | ||
| 262 | 268 | ||
| 263 | bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) | 269 | bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) |
| 264 | { | 270 | { |
| 265 | path.Empty(); | 271 | path.Empty(); |
| 266 | SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP) | 272 | Func_SHGetPathFromIDListW shGetPathFromIDListW = (Func_SHGetPathFromIDListW) |
| 273 | MY_CAST_FUNC | ||
| 267 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW"); | 274 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW"); |
| 268 | if (shGetPathFromIDListW == 0) | 275 | if (!shGetPathFromIDListW) |
| 269 | return false; | 276 | return false; |
| 270 | const unsigned len = MAX_PATH * 2; | 277 | const unsigned len = MAX_PATH * 2; |
| 271 | bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len))); | 278 | bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len))); |
| @@ -273,14 +280,14 @@ bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) | |||
| 273 | return result; | 280 | return result; |
| 274 | } | 281 | } |
| 275 | 282 | ||
| 276 | typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi); | ||
| 277 | 283 | ||
| 278 | static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) | 284 | static bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) |
| 279 | { | 285 | { |
| 280 | NWindows::NCOM::CComInitializer comInitializer; | 286 | NWindows::NCOM::CComInitializer comInitializer; |
| 281 | SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP) | 287 | Func_SHBrowseForFolderW shBrowseForFolderW = (Func_SHBrowseForFolderW) |
| 288 | MY_CAST_FUNC | ||
| 282 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW"); | 289 | ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW"); |
| 283 | if (shBrowseForFolderW == 0) | 290 | if (!shBrowseForFolderW) |
| 284 | return false; | 291 | return false; |
| 285 | LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo); | 292 | LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo); |
| 286 | if (itemIDList == NULL) | 293 | if (itemIDList == NULL) |
diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index c7a61b4..123182e 100644 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | <?xml version="1.0"?> | 1 | <?xml version="1.0"?> |
| 2 | 2 | ||
| 3 | <?define VerMajor = "22" ?> | 3 | <?define VerMajor = "22" ?> |
| 4 | <?define VerMinor = "00" ?> | 4 | <?define VerMinor = "01" ?> |
| 5 | <?define VerBuild = "00" ?> | 5 | <?define VerBuild = "00" ?> |
| 6 | <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> | 6 | <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> |
| 7 | <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> | 7 | <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> |
diff --git a/DOC/readme.txt b/DOC/readme.txt index 0f6c77b..faec8dc 100644 --- a/DOC/readme.txt +++ b/DOC/readme.txt | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | 7-Zip 21.07 Sources | 1 | 7-Zip 22.01 Sources |
| 2 | ------------------- | 2 | ------------------- |
| 3 | 3 | ||
| 4 | 7-Zip is a file archiver for Windows. | 4 | 7-Zip is a file archiver for Windows. |
| 5 | 5 | ||
| 6 | 7-Zip Copyright (C) 1999-2021 Igor Pavlov. | 6 | 7-Zip Copyright (C) 1999-2022 Igor Pavlov. |
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | License Info | 9 | License Info |
