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
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 |