Updated packages from Carthage
This commit is contained in:
parent
d46c9ee32a
commit
bc011c0cbf
|
@ -1,3 +1,3 @@
|
||||||
github "abbeycode/UnrarKit" "2.9"
|
github "abbeycode/UnrarKit" "2.10"
|
||||||
github "abbeycode/UnzipKit" "1.9"
|
github "abbeycode/UnzipKit" "1.9"
|
||||||
github "sindresorhus/DockProgress" "v3.2.0"
|
github "sindresorhus/DockProgress" "v3.2.0"
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
"commitish" : "v3.2.0",
|
"commitish" : "v3.2.0",
|
||||||
"Mac" : [
|
"Mac" : [
|
||||||
{
|
{
|
||||||
"hash" : "13e7fe07ca491fe900ae7c858e66797a66d0a2e1dffde3a2c0b64188b211012e",
|
"hash" : "19676367de93b3ec3bc61b60e454d565ca1c47fe32c4116ef78955c7ecdfcd1e",
|
||||||
"name" : "DockProgress",
|
"name" : "DockProgress",
|
||||||
"linking" : "dynamic",
|
"linking" : "dynamic",
|
||||||
"swiftToolchainVersion" : "5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)"
|
"swiftToolchainVersion" : "5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8)"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
"Mac" : [
|
"Mac" : [
|
||||||
{
|
{
|
||||||
"name" : "UnrarKit",
|
"name" : "UnrarKit",
|
||||||
"hash" : "0ee8db439c431777277ec76976faa8a1d19ba93d3f6977094746350e942215d3",
|
"hash" : "e18e69a1e9f0344776a442bf542e0a45be0427977b765897399058bb766e83db",
|
||||||
"linking" : "dynamic"
|
"linking" : "dynamic"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -12,11 +12,11 @@
|
||||||
"tvOS" : [
|
"tvOS" : [
|
||||||
|
|
||||||
],
|
],
|
||||||
"commitish" : "2.9",
|
"commitish" : "2.10",
|
||||||
"iOS" : [
|
"iOS" : [
|
||||||
{
|
{
|
||||||
"name" : "UnrarKit",
|
"name" : "UnrarKit",
|
||||||
"hash" : "2c752a88c360be277b938f55190d07bc6688ce0452932b4fbf52a12e9bfcf5d0",
|
"hash" : "308b414f23c29d8599f7b214fb8ef39ea574ac8117b21b6946a7c969b9cf38b4",
|
||||||
"linking" : "dynamic"
|
"linking" : "dynamic"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
BIN
Carthage/Build/Mac/DockProgress.framework.dSYM/Contents/Resources/DWARF/DockProgress
generated
vendored
BIN
Carthage/Build/Mac/DockProgress.framework.dSYM/Contents/Resources/DWARF/DockProgress
generated
vendored
Binary file not shown.
Binary file not shown.
18
Carthage/Build/Mac/DockProgress.framework/Versions/A/Headers/DockProgress-Swift.h
generated
vendored
18
Carthage/Build/Mac/DockProgress.framework/Versions/A/Headers/DockProgress-Swift.h
generated
vendored
|
@ -1,6 +1,6 @@
|
||||||
#if 0
|
#if 0
|
||||||
#elif defined(__arm64__) && __arm64__
|
#elif defined(__arm64__) && __arm64__
|
||||||
// Generated by Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
|
// Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8)
|
||||||
#ifndef DOCKPROGRESS_SWIFT_H
|
#ifndef DOCKPROGRESS_SWIFT_H
|
||||||
#define DOCKPROGRESS_SWIFT_H
|
#define DOCKPROGRESS_SWIFT_H
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
|
@ -186,6 +186,13 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
|
||||||
#if !defined(IBSegueAction)
|
#if !defined(IBSegueAction)
|
||||||
# define IBSegueAction
|
# define IBSegueAction
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(SWIFT_EXTERN)
|
||||||
|
# if defined(__cplusplus)
|
||||||
|
# define SWIFT_EXTERN extern "C"
|
||||||
|
# else
|
||||||
|
# define SWIFT_EXTERN extern
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
#if __has_feature(modules)
|
#if __has_feature(modules)
|
||||||
#if __has_warning("-Watimport-in-framework-header")
|
#if __has_warning("-Watimport-in-framework-header")
|
||||||
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
||||||
|
@ -221,7 +228,7 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(__x86_64__) && __x86_64__
|
#elif defined(__x86_64__) && __x86_64__
|
||||||
// Generated by Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
|
// Generated by Apple Swift version 5.6 (swiftlang-5.6.0.323.62 clang-1316.0.20.8)
|
||||||
#ifndef DOCKPROGRESS_SWIFT_H
|
#ifndef DOCKPROGRESS_SWIFT_H
|
||||||
#define DOCKPROGRESS_SWIFT_H
|
#define DOCKPROGRESS_SWIFT_H
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
|
@ -407,6 +414,13 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
|
||||||
#if !defined(IBSegueAction)
|
#if !defined(IBSegueAction)
|
||||||
# define IBSegueAction
|
# define IBSegueAction
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(SWIFT_EXTERN)
|
||||||
|
# if defined(__cplusplus)
|
||||||
|
# define SWIFT_EXTERN extern "C"
|
||||||
|
# else
|
||||||
|
# define SWIFT_EXTERN extern
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
#if __has_feature(modules)
|
#if __has_feature(modules)
|
||||||
#if __has_warning("-Watimport-in-framework-header")
|
#if __has_warning("-Watimport-in-framework-header")
|
||||||
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3,7 +3,7 @@
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>BuildMachineOSBuild</key>
|
<key>BuildMachineOSBuild</key>
|
||||||
<string>20E241</string>
|
<string>21F5048e</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>DockProgress</string>
|
<string>DockProgress</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
@ -23,19 +23,19 @@
|
||||||
<key>DTCompiler</key>
|
<key>DTCompiler</key>
|
||||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||||
<key>DTPlatformBuild</key>
|
<key>DTPlatformBuild</key>
|
||||||
<string>12E262</string>
|
<string>13E500a</string>
|
||||||
<key>DTPlatformName</key>
|
<key>DTPlatformName</key>
|
||||||
<string>macosx</string>
|
<string>macosx</string>
|
||||||
<key>DTPlatformVersion</key>
|
<key>DTPlatformVersion</key>
|
||||||
<string>11.3</string>
|
<string>12.3</string>
|
||||||
<key>DTSDKBuild</key>
|
<key>DTSDKBuild</key>
|
||||||
<string>20E214</string>
|
<string>21E226</string>
|
||||||
<key>DTSDKName</key>
|
<key>DTSDKName</key>
|
||||||
<string>macosx11.3</string>
|
<string>macosx12.3</string>
|
||||||
<key>DTXcode</key>
|
<key>DTXcode</key>
|
||||||
<string>1250</string>
|
<string>1331</string>
|
||||||
<key>DTXcodeBuild</key>
|
<key>DTXcodeBuild</key>
|
||||||
<string>12E262</string>
|
<string>13E500a</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>10.12</string>
|
<string>10.12</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>2.9</string>
|
<string>2.10-beta8</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>2.9</string>
|
<string>2.10-beta8</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
Binary file not shown.
|
@ -6,14 +6,14 @@
|
||||||
|
|
||||||
#import <CoreGraphics/CoreGraphics.h>
|
#import <CoreGraphics/CoreGraphics.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "UnrarKitMacros.h"
|
#import <UnrarKit/UnrarKitMacros.h>
|
||||||
|
|
||||||
RarosHppIgnore
|
RarosHppIgnore
|
||||||
#import "raros.hpp"
|
#import <UnrarKit/raros.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
DllHppIgnore
|
DllHppIgnore
|
||||||
#import "dll.hpp"
|
#import <UnrarKit/dll.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
@class URKFileInfo;
|
@class URKFileInfo;
|
||||||
|
@ -25,7 +25,7 @@ DllHppIgnore
|
||||||
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The archive's header is empty
|
* The last file of the archive has been read
|
||||||
*/
|
*/
|
||||||
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||||
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The header is broken
|
* The header's CRC doesn't match the decompressed data's CRC
|
||||||
*/
|
*/
|
||||||
URKErrorCodeBadData = ERAR_BAD_DATA,
|
URKErrorCodeBadData = ERAR_BAD_DATA,
|
||||||
|
|
||||||
|
@ -173,6 +173,17 @@ extern NSString *URKErrorDomain;
|
||||||
*/
|
*/
|
||||||
@property(nullable, strong) NSProgress *progress;
|
@property(nullable, strong) NSProgress *progress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When performing operations on a RAR archive, the contents of compressed files are checked
|
||||||
|
* against the record of what they were when the archive was created. If there's a mismatch,
|
||||||
|
* either the metadata (header) or archive contents have become corrupted. You can defeat this check by
|
||||||
|
* setting this property to YES, though there may be security implications to turning the
|
||||||
|
* warnings off, as it may indicate a maliciously crafted archive intended to exploit a vulnerability.
|
||||||
|
*
|
||||||
|
* It's recommended to leave the decision of how to treat archives with mismatched CRCs to the user
|
||||||
|
*/
|
||||||
|
@property (assign) BOOL ignoreCRCMismatches;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **DEPRECATED:** Creates and returns an archive at the given path
|
* **DEPRECATED:** Creates and returns an archive at the given path
|
||||||
|
@ -475,15 +486,34 @@ extern NSString *URKErrorDomain;
|
||||||
- (BOOL)validatePassword;
|
- (BOOL)validatePassword;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Extract each file in the archive, checking whether the data matches the CRC checksum
|
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||||
stored at the time it was written
|
the archived file and its header
|
||||||
|
|
||||||
@return YES if the data is all correct, false if any check failed
|
@return YES if the data is all correct, false if any check failed (_even if ignoreCRCMismatches is YES_)
|
||||||
*/
|
*/
|
||||||
- (BOOL)checkDataIntegrity;
|
- (BOOL)checkDataIntegrity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Extract a particular file, to determine if its data matches the CRC
|
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||||
|
the archived file and its header. If any file's CRC doesn't match, run the given block
|
||||||
|
to allow the API consumer to decide whether to ignore mismatches. NOTE: This may be a
|
||||||
|
security risk. The block is intended to prompt the user, which is why it's forced onto
|
||||||
|
the main thread, rather than making a design-time decision
|
||||||
|
|
||||||
|
@param ignoreCRCMismatches This block, called on the main thread, allows a consuming API to
|
||||||
|
prompt the user whether or not he'd like to ignore CRC mismatches.
|
||||||
|
This block is called the first time a CRC mismatch is detected, if
|
||||||
|
at all. It won't be called if all CRCs match. If this returns YES,
|
||||||
|
then all further CRC mismatches will be ignored for the
|
||||||
|
archive instance
|
||||||
|
|
||||||
|
@return YES if the data is all correct and/or the block returns YES; returns false if
|
||||||
|
any check failed and the given block also returns NO
|
||||||
|
*/
|
||||||
|
- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)(void))ignoreCRCMismatches;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check a particular file, to determine if its data matches the CRC
|
||||||
checksum stored at the time it written
|
checksum stored at the time it written
|
||||||
|
|
||||||
@param filePath The file in the archive to check
|
@param filePath The file in the archive to check
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "UnrarKitMacros.h"
|
#import <UnrarKit/UnrarKitMacros.h>
|
||||||
|
|
||||||
RarosHppIgnore
|
RarosHppIgnore
|
||||||
#import "raros.hpp"
|
#import <UnrarKit/raros.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
DllHppIgnore
|
DllHppIgnore
|
||||||
#import "dll.hpp"
|
#import <UnrarKit/dll.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
/* See http://www.forensicswiki.org/wiki/RAR and
|
/* See http://www.forensicswiki.org/wiki/RAR and
|
||||||
|
|
|
@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber;
|
||||||
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
||||||
|
|
||||||
|
|
||||||
#import "URKArchive.h"
|
#import <UnrarKit/URKArchive.h>
|
||||||
#import "URKFileInfo.h"
|
#import <UnrarKit/URKFileInfo.h>
|
||||||
|
|
|
@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \
|
||||||
#import <os/activity.h>
|
#import <os/activity.h>
|
||||||
|
|
||||||
// Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp]
|
// Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp]
|
||||||
extern os_log_t unrarkit_log; // Declared in URKArchive.m
|
extern os_log_t unrarkit_log; // Declared in URKArchive.mm
|
||||||
extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m
|
extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m
|
||||||
#define URKLogInit() \
|
#define URKLogInit() \
|
||||||
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef _UNRAR_DLL_
|
#ifndef _UNRAR_DLL_
|
||||||
#define _UNRAR_DLL_
|
#define _UNRAR_DLL_
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
#define ERAR_SUCCESS 0
|
#define ERAR_SUCCESS 0
|
||||||
#define ERAR_END_ARCHIVE 10
|
#define ERAR_END_ARCHIVE 10
|
||||||
|
@ -135,6 +135,8 @@ typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM
|
||||||
#define ROADF_ENCHEADERS 0x0080
|
#define ROADF_ENCHEADERS 0x0080
|
||||||
#define ROADF_FIRSTVOLUME 0x0100
|
#define ROADF_FIRSTVOLUME 0x0100
|
||||||
|
|
||||||
|
#define ROADOF_KEEPBROKEN 0x0001
|
||||||
|
|
||||||
struct RAROpenArchiveDataEx
|
struct RAROpenArchiveDataEx
|
||||||
{
|
{
|
||||||
char *ArcName;
|
char *ArcName;
|
||||||
|
@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx
|
||||||
unsigned int Flags;
|
unsigned int Flags;
|
||||||
UNRARCALLBACK Callback;
|
UNRARCALLBACK Callback;
|
||||||
LPARAM UserData;
|
LPARAM UserData;
|
||||||
unsigned int Reserved[28];
|
unsigned int OpFlags;
|
||||||
|
wchar_t *CmtBufW;
|
||||||
|
unsigned int Reserved[25];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UNRARCALLBACK_MESSAGES {
|
enum UNRARCALLBACK_MESSAGES {
|
||||||
|
@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>BuildMachineOSBuild</key>
|
<key>BuildMachineOSBuild</key>
|
||||||
<string>17D47</string>
|
<string>19H2</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>English</string>
|
<string>English</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>FMWK</string>
|
<string>FMWK</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>2.9</string>
|
<string>2.10-beta8</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleSupportedPlatforms</key>
|
<key>CFBundleSupportedPlatforms</key>
|
||||||
|
@ -25,20 +25,24 @@
|
||||||
<string>MacOSX</string>
|
<string>MacOSX</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>2.9</string>
|
<string>2.10-beta8</string>
|
||||||
<key>DTCompiler</key>
|
<key>DTCompiler</key>
|
||||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||||
<key>DTPlatformBuild</key>
|
<key>DTPlatformBuild</key>
|
||||||
<string>9E145</string>
|
<string>12A7300</string>
|
||||||
|
<key>DTPlatformName</key>
|
||||||
|
<string>macosx</string>
|
||||||
<key>DTPlatformVersion</key>
|
<key>DTPlatformVersion</key>
|
||||||
<string>GM</string>
|
<string>10.15.6</string>
|
||||||
<key>DTSDKBuild</key>
|
<key>DTSDKBuild</key>
|
||||||
<string>17E189</string>
|
<string>19G68</string>
|
||||||
<key>DTSDKName</key>
|
<key>DTSDKName</key>
|
||||||
<string>macosx10.13</string>
|
<string>macosx10.15</string>
|
||||||
<key>DTXcode</key>
|
<key>DTXcode</key>
|
||||||
<string>0930</string>
|
<string>1201</string>
|
||||||
<key>DTXcodeBuild</key>
|
<key>DTXcodeBuild</key>
|
||||||
<string>9E145</string>
|
<string>12A7300</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.15</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>BuildMachineOSBuild</key>
|
<key>BuildMachineOSBuild</key>
|
||||||
<string>17D47</string>
|
<string>19H2</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>English</string>
|
<string>English</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>BNDL</string>
|
<string>BNDL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>2.9</string>
|
<string>2.10-beta8</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleSupportedPlatforms</key>
|
<key>CFBundleSupportedPlatforms</key>
|
||||||
|
@ -23,21 +23,25 @@
|
||||||
<string>MacOSX</string>
|
<string>MacOSX</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>2.9</string>
|
<string>2.10-beta8</string>
|
||||||
<key>DTCompiler</key>
|
<key>DTCompiler</key>
|
||||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||||
<key>DTPlatformBuild</key>
|
<key>DTPlatformBuild</key>
|
||||||
<string>9E145</string>
|
<string>12A7300</string>
|
||||||
|
<key>DTPlatformName</key>
|
||||||
|
<string>macosx</string>
|
||||||
<key>DTPlatformVersion</key>
|
<key>DTPlatformVersion</key>
|
||||||
<string>GM</string>
|
<string>10.15.6</string>
|
||||||
<key>DTSDKBuild</key>
|
<key>DTSDKBuild</key>
|
||||||
<string>17E189</string>
|
<string>19G68</string>
|
||||||
<key>DTSDKName</key>
|
<key>DTSDKName</key>
|
||||||
<string>macosx10.13</string>
|
<string>macosx10.15</string>
|
||||||
<key>DTXcode</key>
|
<key>DTXcode</key>
|
||||||
<string>0930</string>
|
<string>1201</string>
|
||||||
<key>DTXcodeBuild</key>
|
<key>DTXcodeBuild</key>
|
||||||
<string>9E145</string>
|
<string>12A7300</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.15</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2017 Abbey Code. All rights reserved.</string>
|
<string>Copyright © 2017 Abbey Code. All rights reserved.</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
Binary file not shown.
|
@ -13,8 +13,8 @@
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>2.9</string>
|
<string>2.10-beta8</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>2.9</string>
|
<string>2.10-beta8</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
Binary file not shown.
|
@ -6,14 +6,14 @@
|
||||||
|
|
||||||
#import <CoreGraphics/CoreGraphics.h>
|
#import <CoreGraphics/CoreGraphics.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "UnrarKitMacros.h"
|
#import <UnrarKit/UnrarKitMacros.h>
|
||||||
|
|
||||||
RarosHppIgnore
|
RarosHppIgnore
|
||||||
#import "raros.hpp"
|
#import <UnrarKit/raros.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
DllHppIgnore
|
DllHppIgnore
|
||||||
#import "dll.hpp"
|
#import <UnrarKit/dll.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
@class URKFileInfo;
|
@class URKFileInfo;
|
||||||
|
@ -25,7 +25,7 @@ DllHppIgnore
|
||||||
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The archive's header is empty
|
* The last file of the archive has been read
|
||||||
*/
|
*/
|
||||||
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||||
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The header is broken
|
* The header's CRC doesn't match the decompressed data's CRC
|
||||||
*/
|
*/
|
||||||
URKErrorCodeBadData = ERAR_BAD_DATA,
|
URKErrorCodeBadData = ERAR_BAD_DATA,
|
||||||
|
|
||||||
|
@ -173,6 +173,17 @@ extern NSString *URKErrorDomain;
|
||||||
*/
|
*/
|
||||||
@property(nullable, strong) NSProgress *progress;
|
@property(nullable, strong) NSProgress *progress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When performing operations on a RAR archive, the contents of compressed files are checked
|
||||||
|
* against the record of what they were when the archive was created. If there's a mismatch,
|
||||||
|
* either the metadata (header) or archive contents have become corrupted. You can defeat this check by
|
||||||
|
* setting this property to YES, though there may be security implications to turning the
|
||||||
|
* warnings off, as it may indicate a maliciously crafted archive intended to exploit a vulnerability.
|
||||||
|
*
|
||||||
|
* It's recommended to leave the decision of how to treat archives with mismatched CRCs to the user
|
||||||
|
*/
|
||||||
|
@property (assign) BOOL ignoreCRCMismatches;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **DEPRECATED:** Creates and returns an archive at the given path
|
* **DEPRECATED:** Creates and returns an archive at the given path
|
||||||
|
@ -475,15 +486,34 @@ extern NSString *URKErrorDomain;
|
||||||
- (BOOL)validatePassword;
|
- (BOOL)validatePassword;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Extract each file in the archive, checking whether the data matches the CRC checksum
|
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||||
stored at the time it was written
|
the archived file and its header
|
||||||
|
|
||||||
@return YES if the data is all correct, false if any check failed
|
@return YES if the data is all correct, false if any check failed (_even if ignoreCRCMismatches is YES_)
|
||||||
*/
|
*/
|
||||||
- (BOOL)checkDataIntegrity;
|
- (BOOL)checkDataIntegrity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Extract a particular file, to determine if its data matches the CRC
|
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||||
|
the archived file and its header. If any file's CRC doesn't match, run the given block
|
||||||
|
to allow the API consumer to decide whether to ignore mismatches. NOTE: This may be a
|
||||||
|
security risk. The block is intended to prompt the user, which is why it's forced onto
|
||||||
|
the main thread, rather than making a design-time decision
|
||||||
|
|
||||||
|
@param ignoreCRCMismatches This block, called on the main thread, allows a consuming API to
|
||||||
|
prompt the user whether or not he'd like to ignore CRC mismatches.
|
||||||
|
This block is called the first time a CRC mismatch is detected, if
|
||||||
|
at all. It won't be called if all CRCs match. If this returns YES,
|
||||||
|
then all further CRC mismatches will be ignored for the
|
||||||
|
archive instance
|
||||||
|
|
||||||
|
@return YES if the data is all correct and/or the block returns YES; returns false if
|
||||||
|
any check failed and the given block also returns NO
|
||||||
|
*/
|
||||||
|
- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)(void))ignoreCRCMismatches;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check a particular file, to determine if its data matches the CRC
|
||||||
checksum stored at the time it written
|
checksum stored at the time it written
|
||||||
|
|
||||||
@param filePath The file in the archive to check
|
@param filePath The file in the archive to check
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "UnrarKitMacros.h"
|
#import <UnrarKit/UnrarKitMacros.h>
|
||||||
|
|
||||||
RarosHppIgnore
|
RarosHppIgnore
|
||||||
#import "raros.hpp"
|
#import <UnrarKit/raros.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
DllHppIgnore
|
DllHppIgnore
|
||||||
#import "dll.hpp"
|
#import <UnrarKit/dll.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
/* See http://www.forensicswiki.org/wiki/RAR and
|
/* See http://www.forensicswiki.org/wiki/RAR and
|
||||||
|
|
|
@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber;
|
||||||
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
||||||
|
|
||||||
|
|
||||||
#import "URKArchive.h"
|
#import <UnrarKit/URKArchive.h>
|
||||||
#import "URKFileInfo.h"
|
#import <UnrarKit/URKFileInfo.h>
|
||||||
|
|
|
@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \
|
||||||
#import <os/activity.h>
|
#import <os/activity.h>
|
||||||
|
|
||||||
// Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp]
|
// Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp]
|
||||||
extern os_log_t unrarkit_log; // Declared in URKArchive.m
|
extern os_log_t unrarkit_log; // Declared in URKArchive.mm
|
||||||
extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m
|
extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m
|
||||||
#define URKLogInit() \
|
#define URKLogInit() \
|
||||||
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef _UNRAR_DLL_
|
#ifndef _UNRAR_DLL_
|
||||||
#define _UNRAR_DLL_
|
#define _UNRAR_DLL_
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
#define ERAR_SUCCESS 0
|
#define ERAR_SUCCESS 0
|
||||||
#define ERAR_END_ARCHIVE 10
|
#define ERAR_END_ARCHIVE 10
|
||||||
|
@ -135,6 +135,8 @@ typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM
|
||||||
#define ROADF_ENCHEADERS 0x0080
|
#define ROADF_ENCHEADERS 0x0080
|
||||||
#define ROADF_FIRSTVOLUME 0x0100
|
#define ROADF_FIRSTVOLUME 0x0100
|
||||||
|
|
||||||
|
#define ROADOF_KEEPBROKEN 0x0001
|
||||||
|
|
||||||
struct RAROpenArchiveDataEx
|
struct RAROpenArchiveDataEx
|
||||||
{
|
{
|
||||||
char *ArcName;
|
char *ArcName;
|
||||||
|
@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx
|
||||||
unsigned int Flags;
|
unsigned int Flags;
|
||||||
UNRARCALLBACK Callback;
|
UNRARCALLBACK Callback;
|
||||||
LPARAM UserData;
|
LPARAM UserData;
|
||||||
unsigned int Reserved[28];
|
unsigned int OpFlags;
|
||||||
|
wchar_t *CmtBufW;
|
||||||
|
unsigned int Reserved[25];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UNRARCALLBACK_MESSAGES {
|
enum UNRARCALLBACK_MESSAGES {
|
||||||
|
@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,7 +1,12 @@
|
||||||
language: objective-c
|
language: objective-c
|
||||||
osx_image: xcode9.3
|
osx_image: xcode12
|
||||||
|
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- circle-ci
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
- pod --version
|
||||||
# Make log level less verbose. Temporarily undo if more info is needed
|
# Make log level less verbose. Temporarily undo if more info is needed
|
||||||
- sudo log config --mode "level:default"
|
- sudo log config --mode "level:default"
|
||||||
|
|
||||||
|
@ -15,7 +20,7 @@ matrix:
|
||||||
- stage: Test
|
- stage: Test
|
||||||
env: Name=iOS
|
env: Name=iOS
|
||||||
# The CLANG arguments and find command fail the build on analyzer errors
|
# The CLANG arguments and find command fail the build on analyzer errors
|
||||||
script: xcodebuild -workspace UnrarKit.xcworkspace -scheme UnrarKit -destination 'platform=iOS Simulator,name=iPhone 7,OS=latest' -configuration Release analyze test CLANG_ANALYZER_OUTPUT=html CLANG_ANALYZER_OUTPUT_DIR=analyzer-output && [[ -z `find analyzer-output -name "*.html"` ]]
|
script: xcodebuild -workspace UnrarKit.xcworkspace -scheme UnrarKit -destination 'platform=iOS Simulator,name=iPhone 11,OS=latest' -configuration Release analyze test CLANG_ANALYZER_OUTPUT=html CLANG_ANALYZER_OUTPUT_DIR=analyzer-output && [[ -z `find analyzer-output -name "*.html"` ]]
|
||||||
|
|
||||||
- stage: Test
|
- stage: Test
|
||||||
env: Name=ExampleAppBuild
|
env: Name=ExampleAppBuild
|
||||||
|
@ -32,5 +37,4 @@ matrix:
|
||||||
|
|
||||||
- stage: Release
|
- stage: Release
|
||||||
if: tag IS present
|
if: tag IS present
|
||||||
before_install: brew upgrade python # Needs Python 3
|
|
||||||
script: ./Scripts/push-output.sh
|
script: ./Scripts/push-output.sh
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
# UnrarKit CHANGELOG
|
# UnrarKit CHANGELOG
|
||||||
|
|
||||||
|
## 2.10
|
||||||
|
|
||||||
|
* Added method (`checkDataIntegrityIgnoringCRCMismatches:`) to prompt user for a decision on whether or not to ignore CRC mismatches (Issue #82)
|
||||||
|
* Fixed crash in `+pathIsARAR:` when a file is unreadable (Issue #85)
|
||||||
|
* Fixed crash in `-_unrarOpenFile:inMode:withPassword:error:` (PR #97)
|
||||||
|
* Updated to v5.9.4 of UnRAR library
|
||||||
|
* Xcode 12 compatibility in Carthage
|
||||||
|
|
||||||
|
|
||||||
## 2.9
|
## 2.9
|
||||||
|
|
||||||
* Added support for `NSProgress` and `NSProgressReporting` in all extraction and iteration methods (Issue #34)
|
* Added support for `NSProgress` and `NSProgressReporting` in all extraction and iteration methods (Issue #34)
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
|
|
||||||
#import <CoreGraphics/CoreGraphics.h>
|
#import <CoreGraphics/CoreGraphics.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "UnrarKitMacros.h"
|
#import <UnrarKit/UnrarKitMacros.h>
|
||||||
|
|
||||||
RarosHppIgnore
|
RarosHppIgnore
|
||||||
#import "raros.hpp"
|
#import <UnrarKit/raros.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
DllHppIgnore
|
DllHppIgnore
|
||||||
#import "dll.hpp"
|
#import <UnrarKit/dll.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
@class URKFileInfo;
|
@class URKFileInfo;
|
||||||
|
@ -25,7 +25,7 @@ DllHppIgnore
|
||||||
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The archive's header is empty
|
* The last file of the archive has been read
|
||||||
*/
|
*/
|
||||||
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||||
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The header is broken
|
* The header's CRC doesn't match the decompressed data's CRC
|
||||||
*/
|
*/
|
||||||
URKErrorCodeBadData = ERAR_BAD_DATA,
|
URKErrorCodeBadData = ERAR_BAD_DATA,
|
||||||
|
|
||||||
|
@ -173,6 +173,17 @@ extern NSString *URKErrorDomain;
|
||||||
*/
|
*/
|
||||||
@property(nullable, strong) NSProgress *progress;
|
@property(nullable, strong) NSProgress *progress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When performing operations on a RAR archive, the contents of compressed files are checked
|
||||||
|
* against the record of what they were when the archive was created. If there's a mismatch,
|
||||||
|
* either the metadata (header) or archive contents have become corrupted. You can defeat this check by
|
||||||
|
* setting this property to YES, though there may be security implications to turning the
|
||||||
|
* warnings off, as it may indicate a maliciously crafted archive intended to exploit a vulnerability.
|
||||||
|
*
|
||||||
|
* It's recommended to leave the decision of how to treat archives with mismatched CRCs to the user
|
||||||
|
*/
|
||||||
|
@property (assign) BOOL ignoreCRCMismatches;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **DEPRECATED:** Creates and returns an archive at the given path
|
* **DEPRECATED:** Creates and returns an archive at the given path
|
||||||
|
@ -475,15 +486,34 @@ extern NSString *URKErrorDomain;
|
||||||
- (BOOL)validatePassword;
|
- (BOOL)validatePassword;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Extract each file in the archive, checking whether the data matches the CRC checksum
|
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||||
stored at the time it was written
|
the archived file and its header
|
||||||
|
|
||||||
@return YES if the data is all correct, false if any check failed
|
@return YES if the data is all correct, false if any check failed (_even if ignoreCRCMismatches is YES_)
|
||||||
*/
|
*/
|
||||||
- (BOOL)checkDataIntegrity;
|
- (BOOL)checkDataIntegrity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Extract a particular file, to determine if its data matches the CRC
|
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||||
|
the archived file and its header. If any file's CRC doesn't match, run the given block
|
||||||
|
to allow the API consumer to decide whether to ignore mismatches. NOTE: This may be a
|
||||||
|
security risk. The block is intended to prompt the user, which is why it's forced onto
|
||||||
|
the main thread, rather than making a design-time decision
|
||||||
|
|
||||||
|
@param ignoreCRCMismatches This block, called on the main thread, allows a consuming API to
|
||||||
|
prompt the user whether or not he'd like to ignore CRC mismatches.
|
||||||
|
This block is called the first time a CRC mismatch is detected, if
|
||||||
|
at all. It won't be called if all CRCs match. If this returns YES,
|
||||||
|
then all further CRC mismatches will be ignored for the
|
||||||
|
archive instance
|
||||||
|
|
||||||
|
@return YES if the data is all correct and/or the block returns YES; returns false if
|
||||||
|
any check failed and the given block also returns NO
|
||||||
|
*/
|
||||||
|
- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)(void))ignoreCRCMismatches;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check a particular file, to determine if its data matches the CRC
|
||||||
checksum stored at the time it written
|
checksum stored at the time it written
|
||||||
|
|
||||||
@param filePath The file in the archive to check
|
@param filePath The file in the archive to check
|
||||||
|
|
|
@ -28,6 +28,11 @@ BOOL unrarkitIsAtLeast10_13SDK;
|
||||||
|
|
||||||
static NSBundle *_resources = nil;
|
static NSBundle *_resources = nil;
|
||||||
|
|
||||||
|
typedef enum : NSUInteger {
|
||||||
|
URKReadHeaderLoopActionStopReading,
|
||||||
|
URKReadHeaderLoopActionContinueReading,
|
||||||
|
} URKReadHeaderLoopAction;
|
||||||
|
|
||||||
|
|
||||||
@interface URKArchive ()
|
@interface URKArchive ()
|
||||||
|
|
||||||
|
@ -46,6 +51,9 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
@property (strong) NSObject *threadLock;
|
@property (strong) NSObject *threadLock;
|
||||||
|
|
||||||
|
@property (copy) NSString *lastArchivePath;
|
||||||
|
@property (copy) NSString *lastFilepath;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,6 +168,10 @@ NS_DESIGNATED_INITIALIZER
|
||||||
error:&bookmarkError];
|
error:&bookmarkError];
|
||||||
_password = password;
|
_password = password;
|
||||||
_threadLock = [[NSObject alloc] init];
|
_threadLock = [[NSObject alloc] init];
|
||||||
|
|
||||||
|
_lastArchivePath = nil;
|
||||||
|
_lastFilepath = nil;
|
||||||
|
_ignoreCRCMismatches = NO;
|
||||||
|
|
||||||
if (bookmarkError) {
|
if (bookmarkError) {
|
||||||
URKLogFault("Error creating bookmark to RAR archive: %{public}@", bookmarkError);
|
URKLogFault("Error creating bookmark to RAR archive: %{public}@", bookmarkError);
|
||||||
|
@ -336,6 +348,9 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
URKLogDebug("File is not a RAR. Unknown contents in 7th and 8th bytes (%02X %02X)", dataBytes[6], dataBytes[7]);
|
URKLogDebug("File is not a RAR. Unknown contents in 7th and 8th bytes (%02X %02X)", dataBytes[6], dataBytes[7]);
|
||||||
}
|
}
|
||||||
|
@catch (NSException *e) {
|
||||||
|
URKLogError("Error checking if %{public}@ is a RAR archive: %{public}@", filePath, e);
|
||||||
|
}
|
||||||
@finally {
|
@finally {
|
||||||
[handle closeFile];
|
[handle closeFile];
|
||||||
}
|
}
|
||||||
|
@ -508,8 +523,7 @@ NS_DESIGNATED_INITIALIZER
|
||||||
URKLogInfo("Extracting to %{public}@", filePath);
|
URKLogInfo("Extracting to %{public}@", filePath);
|
||||||
|
|
||||||
URKLogDebug("Reading through RAR header looking for files...");
|
URKLogDebug("Reading through RAR header looking for files...");
|
||||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) {
|
while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) {
|
||||||
fileInfo = [URKFileInfo fileInfo:welf.header];
|
|
||||||
URKLogDebug("Extracting %{public}@ (%{iec-bytes}lld)", fileInfo.filename, fileInfo.uncompressedSize);
|
URKLogDebug("Extracting %{public}@ (%{iec-bytes}lld)", fileInfo.filename, fileInfo.uncompressedSize);
|
||||||
NSURL *extractedURL = [[NSURL fileURLWithPath:filePath] URLByAppendingPathComponent:fileInfo.filename];
|
NSURL *extractedURL = [[NSURL fileURLWithPath:filePath] URLByAppendingPathComponent:fileInfo.filename];
|
||||||
[progress setUserInfoObject:extractedURL
|
[progress setUserInfoObject:extractedURL
|
||||||
|
@ -517,7 +531,7 @@ NS_DESIGNATED_INITIALIZER
|
||||||
[progress setUserInfoObject:fileInfo
|
[progress setUserInfoObject:fileInfo
|
||||||
forKey:URKProgressInfoKeyFileInfoExtracting];
|
forKey:URKProgressInfoKeyFileInfoExtracting];
|
||||||
|
|
||||||
if ([self headerContainsErrors:innerError]) {
|
if ([welf headerContainsErrors:innerError]) {
|
||||||
URKLogError("Header contains an error")
|
URKLogError("Header contains an error")
|
||||||
result = NO;
|
result = NO;
|
||||||
return;
|
return;
|
||||||
|
@ -525,7 +539,7 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
if (progress.isCancelled) {
|
if (progress.isCancelled) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName];
|
[welf assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName];
|
||||||
URKLogInfo("Halted file extraction due to user cancellation: %{public}@", errorName);
|
URKLogInfo("Halted file extraction due to user cancellation: %{public}@", errorName);
|
||||||
result = NO;
|
result = NO;
|
||||||
return;
|
return;
|
||||||
|
@ -537,7 +551,7 @@ NS_DESIGNATED_INITIALIZER
|
||||||
encoding:NSUTF8StringEncoding];
|
encoding:NSUTF8StringEncoding];
|
||||||
if (!utf8ConversionSucceeded) {
|
if (!utf8ConversionSucceeded) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:URKErrorCodeStringConversion errorName:&errorName];
|
[welf assignError:innerError code:URKErrorCodeStringConversion errorName:&errorName];
|
||||||
URKLogError("Error converting file to UTF-8 (buffer too short?)");
|
URKLogError("Error converting file to UTF-8 (buffer too short?)");
|
||||||
result = NO;
|
result = NO;
|
||||||
return;
|
return;
|
||||||
|
@ -550,12 +564,13 @@ NS_DESIGNATED_INITIALIZER
|
||||||
};
|
};
|
||||||
RARSetCallback(welf.rarFile, AllowCancellationCallbackProc, (long)shouldCancelBlock);
|
RARSetCallback(welf.rarFile, AllowCancellationCallbackProc, (long)shouldCancelBlock);
|
||||||
|
|
||||||
if ((PFCode = RARProcessFile(welf.rarFile, RAR_EXTRACT, cFilePath, NULL)) != 0) {
|
PFCode = RARProcessFile(welf.rarFile, RAR_EXTRACT, cFilePath, NULL);
|
||||||
|
if (![welf didReturnSuccessfully:PFCode]) {
|
||||||
RARSetCallback(welf.rarFile, NULL, NULL);
|
RARSetCallback(welf.rarFile, NULL, NULL);
|
||||||
|
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
NSInteger errorCode = progress.isCancelled ? URKErrorCodeUserCancelled : PFCode;
|
NSInteger errorCode = progress.isCancelled ? URKErrorCodeUserCancelled : PFCode;
|
||||||
[self assignError:innerError code:errorCode errorName:&errorName];
|
[welf assignError:innerError code:errorCode errorName:&errorName];
|
||||||
URKLogError("Error extracting file: %{public}@ (%ld)", errorName, (long)errorCode);
|
URKLogError("Error extracting file: %{public}@ (%ld)", errorName, (long)errorCode);
|
||||||
result = NO;
|
result = NO;
|
||||||
return;
|
return;
|
||||||
|
@ -582,14 +597,14 @@ NS_DESIGNATED_INITIALIZER
|
||||||
}
|
}
|
||||||
|
|
||||||
RARSetCallback(welf.rarFile, NULL, NULL);
|
RARSetCallback(welf.rarFile, NULL, NULL);
|
||||||
|
|
||||||
if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) {
|
if (![welf didReturnSuccessfully:RHCode]) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:RHCode errorName:&errorName];
|
[welf assignError:innerError code:RHCode errorName:&errorName];
|
||||||
URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode);
|
URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode);
|
||||||
result = NO;
|
result = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progressBlock) {
|
if (progressBlock) {
|
||||||
progressBlock(fileInfo, 1.0);
|
progressBlock(fileInfo, 1.0);
|
||||||
}
|
}
|
||||||
|
@ -642,14 +657,12 @@ NS_DESIGNATED_INITIALIZER
|
||||||
URKFileInfo *fileInfo;
|
URKFileInfo *fileInfo;
|
||||||
|
|
||||||
URKLogDebug("Reading through RAR header looking for files...");
|
URKLogDebug("Reading through RAR header looking for files...");
|
||||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) {
|
while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) {
|
||||||
if ([self headerContainsErrors:innerError]) {
|
if ([welf headerContainsErrors:innerError]) {
|
||||||
URKLogError("Header contains an error")
|
URKLogError("Header contains an error")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileInfo = [URKFileInfo fileInfo:welf.header];
|
|
||||||
|
|
||||||
if ([fileInfo.filename isEqualToString:filePath]) {
|
if ([fileInfo.filename isEqualToString:filePath]) {
|
||||||
URKLogDebug("Extracting %{public}@", fileInfo.filename);
|
URKLogDebug("Extracting %{public}@", fileInfo.filename);
|
||||||
break;
|
break;
|
||||||
|
@ -658,7 +671,7 @@ NS_DESIGNATED_INITIALIZER
|
||||||
URKLogDebug("Skipping %{public}@", fileInfo.filename);
|
URKLogDebug("Skipping %{public}@", fileInfo.filename);
|
||||||
if ((PFCode = RARProcessFileW(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) {
|
if ((PFCode = RARProcessFileW(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
[welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
||||||
URKLogError("Error skipping file: %{public}@ (%d)", errorName, PFCode);
|
URKLogError("Error skipping file: %{public}@ (%d)", errorName, PFCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -667,7 +680,7 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
if (RHCode != ERAR_SUCCESS) {
|
if (RHCode != ERAR_SUCCESS) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:RHCode errorName:&errorName];
|
[welf assignError:innerError code:RHCode errorName:&errorName];
|
||||||
URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode);
|
URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -715,14 +728,14 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
if (progress.isCancelled) {
|
if (progress.isCancelled) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName];
|
[welf assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName];
|
||||||
URKLogInfo("Returning nil data from extraction due to user cancellation: %{public}@", errorName);
|
URKLogInfo("Returning nil data from extraction due to user cancellation: %{public}@", errorName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PFCode != 0) {
|
if (![welf didReturnSuccessfully:PFCode]) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
[welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
||||||
URKLogError("Error extracting file data: %{public}@ (%d)", errorName, PFCode);
|
URKLogError("Error extracting file data: %{public}@ (%d)", errorName, PFCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -813,27 +826,36 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
BOOL stop = NO;
|
BOOL stop = NO;
|
||||||
|
|
||||||
NSProgress *progress = [self beginProgressOperation:totalSize.longLongValue];
|
NSProgress *progress = [welf beginProgressOperation:totalSize.longLongValue];
|
||||||
|
|
||||||
URKLogDebug("Reading through RAR header looking for files...");
|
URKLogDebug("Reading through RAR header looking for files...");
|
||||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == 0) {
|
|
||||||
|
URKFileInfo *info = nil;
|
||||||
|
while ([welf readHeader:&RHCode info:&info] == URKReadHeaderLoopActionContinueReading) {
|
||||||
if (stop || progress.isCancelled) {
|
if (stop || progress.isCancelled) {
|
||||||
URKLogDebug("Action dictated an early stop");
|
URKLogDebug("Action dictated an early stop");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([self headerContainsErrors:innerError]) {
|
if ([welf headerContainsErrors:innerError]) {
|
||||||
URKLogError("Header contains an error")
|
URKLogError("Header contains an error")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
URKFileInfo *info = [URKFileInfo fileInfo:welf.header];
|
|
||||||
URKLogDebug("Performing action on %{public}@", info.filename);
|
URKLogDebug("Performing action on %{public}@", info.filename);
|
||||||
|
|
||||||
// Empty file, or a directory
|
// Empty file, or a directory
|
||||||
if (info.uncompressedSize == 0) {
|
if (info.isDirectory || info.uncompressedSize == 0) {
|
||||||
URKLogDebug("%{public}@ is an empty file, or a directory", info.filename);
|
URKLogDebug("%{public}@ is an empty file, or a directory", info.filename);
|
||||||
action(info, [NSData data], &stop);
|
action(info, [NSData data], &stop);
|
||||||
|
PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL);
|
||||||
|
if (PFCode != 0) {
|
||||||
|
NSString *errorName = nil;
|
||||||
|
[welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
||||||
|
URKLogError("Error skipping directory: %{public}@ (%d)", errorName, PFCode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,9 +867,9 @@ NS_DESIGNATED_INITIALIZER
|
||||||
URKLogInfo("Processing file...");
|
URKLogInfo("Processing file...");
|
||||||
PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL);
|
PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL);
|
||||||
|
|
||||||
if (PFCode != 0) {
|
if (![welf didReturnSuccessfully:PFCode]) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
[welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
||||||
URKLogError("Error processing file: %{public}@ (%d)", errorName, PFCode);
|
URKLogError("Error processing file: %{public}@ (%d)", errorName, PFCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -861,14 +883,14 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
if (progress.isCancelled) {
|
if (progress.isCancelled) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName];
|
[welf assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName];
|
||||||
URKLogInfo("Returning NO from performOnData:error: due to user cancellation: %{public}@", errorName);
|
URKLogInfo("Returning NO from performOnData:error: due to user cancellation: %{public}@", errorName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) {
|
if (![welf didReturnSuccessfully:RHCode]) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:RHCode errorName:&errorName];
|
[welf assignError:innerError code:RHCode errorName:&errorName];
|
||||||
URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode);
|
URKLogError("Error reading file header: %{public}@ (%d)", errorName, RHCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -897,24 +919,22 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
URKLogInfo("Looping through files, looking for %{public}@...", filePath);
|
URKLogInfo("Looping through files, looking for %{public}@...", filePath);
|
||||||
|
|
||||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) {
|
while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) {
|
||||||
if ([self headerContainsErrors:innerError]) {
|
if ([welf headerContainsErrors:innerError]) {
|
||||||
URKLogDebug("Header contains error")
|
URKLogDebug("Header contains error")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
URKLogDebug("Getting file info from header");
|
|
||||||
fileInfo = [URKFileInfo fileInfo:welf.header];
|
|
||||||
|
|
||||||
if ([fileInfo.filename isEqualToString:filePath]) {
|
if ([fileInfo.filename isEqualToString:filePath]) {
|
||||||
URKLogDebug("Found desired file");
|
URKLogDebug("Found desired file");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
URKLogDebug("Skipping file...");
|
URKLogDebug("Skipping file...");
|
||||||
if ((PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) {
|
PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL);
|
||||||
|
if (![welf didReturnSuccessfully:PFCode]) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
[welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
||||||
URKLogError("Failed to skip file: %{public}@ (%d)", errorName, PFCode);
|
URKLogError("Failed to skip file: %{public}@ (%d)", errorName, PFCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -924,9 +944,9 @@ NS_DESIGNATED_INITIALIZER
|
||||||
long long totalBytes = fileInfo.uncompressedSize;
|
long long totalBytes = fileInfo.uncompressedSize;
|
||||||
progress.totalUnitCount = totalBytes;
|
progress.totalUnitCount = totalBytes;
|
||||||
|
|
||||||
if (RHCode != ERAR_SUCCESS) {
|
if (![welf didReturnSuccessfully:RHCode]) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:RHCode errorName:&errorName];
|
[welf assignError:innerError code:RHCode errorName:&errorName];
|
||||||
URKLogError("Header read yielded error: %{public}@ (%d)", errorName, RHCode);
|
URKLogError("Header read yielded error: %{public}@ (%d)", errorName, RHCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -965,14 +985,14 @@ NS_DESIGNATED_INITIALIZER
|
||||||
|
|
||||||
if (progress.isCancelled) {
|
if (progress.isCancelled) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName];
|
[welf assignError:innerError code:URKErrorCodeUserCancelled errorName:&errorName];
|
||||||
URKLogError("Buffered data extraction has been cancelled: %{public}@", errorName);
|
URKLogError("Buffered data extraction has been cancelled: %{public}@", errorName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PFCode != 0) {
|
if (![welf didReturnSuccessfully:PFCode]) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
[welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
||||||
URKLogError("Error processing file: %{public}@ (%d)", errorName, PFCode);
|
URKLogError("Error processing file: %{public}@ (%d)", errorName, PFCode);
|
||||||
}
|
}
|
||||||
} inMode:RAR_OM_EXTRACT error:&actionError];
|
} inMode:RAR_OM_EXTRACT error:&actionError];
|
||||||
|
@ -1049,7 +1069,7 @@ NS_DESIGNATED_INITIALIZER
|
||||||
int RHCode = RARReadHeaderEx(welf.rarFile, welf.header);
|
int RHCode = RARReadHeaderEx(welf.rarFile, welf.header);
|
||||||
int PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL);
|
int PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL);
|
||||||
|
|
||||||
if ([self headerContainsErrors:innerError]) {
|
if ([welf headerContainsErrors:innerError]) {
|
||||||
if (error.code == ERAR_MISSING_PASSWORD) {
|
if (error.code == ERAR_MISSING_PASSWORD) {
|
||||||
URKLogDebug("Password invalidated by header");
|
URKLogDebug("Password invalidated by header");
|
||||||
passwordIsGood = NO;
|
passwordIsGood = NO;
|
||||||
|
@ -1062,13 +1082,18 @@ NS_DESIGNATED_INITIALIZER
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RHCode == ERAR_MISSING_PASSWORD || PFCode == ERAR_MISSING_PASSWORD
|
if (RHCode == ERAR_MISSING_PASSWORD || PFCode == ERAR_MISSING_PASSWORD
|
||||||
|| RHCode == ERAR_BAD_DATA || PFCode == ERAR_BAD_DATA
|
|
||||||
|| RHCode == ERAR_BAD_PASSWORD || PFCode == ERAR_BAD_PASSWORD)
|
|| RHCode == ERAR_BAD_PASSWORD || PFCode == ERAR_BAD_PASSWORD)
|
||||||
{
|
{
|
||||||
URKLogDebug("Missing/bad password indicated by RHCode (%d) or PFCode (%d)", RHCode, PFCode);
|
URKLogDebug("Missing/bad password indicated by RHCode (%d) or PFCode (%d)", RHCode, PFCode);
|
||||||
passwordIsGood = NO;
|
passwordIsGood = NO;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ([welf hasBadCRC:RHCode] || [welf hasBadCRC:PFCode]) {
|
||||||
|
URKLogDebug("Missing/bad password indicated via CRC mismatch by RHCode (%d) or PFCode (%d)", RHCode, PFCode);
|
||||||
|
passwordIsGood = NO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
} inMode:RAR_OM_EXTRACT error:&error];
|
} inMode:RAR_OM_EXTRACT error:&error];
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
@ -1084,47 +1109,96 @@ NS_DESIGNATED_INITIALIZER
|
||||||
return [self checkDataIntegrityOfFile:(NSString *_Nonnull)nil];
|
return [self checkDataIntegrityOfFile:(NSString *_Nonnull)nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)checkDataIntegrityOfFile:(NSString *)filePath
|
- (BOOL)checkDataIntegrityIgnoringCRCMismatches:(BOOL(^)())ignoreCRCMismatches
|
||||||
|
{
|
||||||
|
int rhCode = [self dataIntegrityCodeOfFile:nil];
|
||||||
|
if (rhCode == ERAR_SUCCESS) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rhCode == ERAR_BAD_DATA) {
|
||||||
|
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
|
||||||
|
|
||||||
|
__block BOOL blockResult;
|
||||||
|
|
||||||
|
if ([NSOperationQueue currentQueue] == mainQueue) {
|
||||||
|
blockResult = ignoreCRCMismatches();
|
||||||
|
} else {
|
||||||
|
[mainQueue addOperations:@[[NSBlockOperation blockOperationWithBlock:^{
|
||||||
|
blockResult = ignoreCRCMismatches();
|
||||||
|
}]]
|
||||||
|
waitUntilFinished:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ignoreCRCMismatches = blockResult;
|
||||||
|
return self.ignoreCRCMismatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)checkDataIntegrityOfFile:(NSString *)filePath {
|
||||||
|
return [self dataIntegrityCodeOfFile:filePath] == ERAR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int)dataIntegrityCodeOfFile:(NSString *)filePath
|
||||||
{
|
{
|
||||||
URKCreateActivity("Checking Data Integrity");
|
URKCreateActivity("Checking Data Integrity");
|
||||||
|
|
||||||
URKLogInfo("Checking integrity of %{public}@", filePath ? filePath : @"whole archive");
|
URKLogInfo("Checking integrity of %{public}@", filePath ? filePath : @"whole archive");
|
||||||
|
|
||||||
__block BOOL corruptDataFound = YES;
|
__block int RHCode = 0;
|
||||||
|
__block int PFCode = 0;
|
||||||
|
|
||||||
|
__weak URKArchive *welf = self;
|
||||||
|
|
||||||
NSError *performOnFilesError = nil;
|
NSError *performOnFilesError = nil;
|
||||||
[self performOnFilesInArchive:^(URKFileInfo *fileInfo, BOOL *stop) {
|
BOOL wasSuccessful = [self performActionWithArchiveOpen:^(NSError **innerError) {
|
||||||
URKCreateActivity("Iterating through each file");
|
URKCreateActivity("Iterating through each file");
|
||||||
corruptDataFound = NO; // Set inside here so invalid archives are marked as corrupt
|
while (true) {
|
||||||
if (filePath && ![fileInfo.filename isEqualToString:filePath]) return;
|
URKFileInfo *fileInfo = nil;
|
||||||
|
[welf readHeader:&RHCode info:&fileInfo];
|
||||||
URKLogDebug("Extracting '%{public}@ to check its CRC...", fileInfo.filename);
|
welf.lastFilepath = nil;
|
||||||
NSError *extractError = nil;
|
welf.lastArchivePath = nil;
|
||||||
NSData *fileData = [self extractData:fileInfo error:&extractError];
|
|
||||||
if (!fileData) {
|
if (RHCode == ERAR_END_ARCHIVE) {
|
||||||
URKLogError("Error extracting %{public}@: %{public}@", fileInfo.filename, extractError);
|
RHCode = ERAR_SUCCESS;
|
||||||
*stop = YES;
|
break;
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
if (filePath && ![fileInfo.filename isEqualToString:filePath]) continue;
|
||||||
|
|
||||||
|
if (RHCode != ERAR_SUCCESS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL)) != ERAR_SUCCESS) {
|
||||||
|
RHCode = PFCode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePath) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} inMode:RAR_OM_EXTRACT error:&performOnFilesError];
|
||||||
uLong expectedCRC = fileInfo.CRC;
|
|
||||||
uLong actualCRC = crc32((uLong)0, (const Bytef*)fileData.bytes, (uint)fileData.length);
|
if (RHCode == ERAR_END_ARCHIVE) {
|
||||||
URKLogDebug("Checking integrity of %{public}@. Expected CRC: %010lu vs. Actual: %010lu",
|
RHCode = ERAR_SUCCESS;
|
||||||
fileInfo.filename, expectedCRC, actualCRC);
|
}
|
||||||
if (expectedCRC != actualCRC) {
|
|
||||||
corruptDataFound = YES;
|
|
||||||
URKLogError("Corrupt data found (filename: %{public}@, expected CRC: %010lu, actual CRC: %010lu",
|
|
||||||
fileInfo.filename, expectedCRC, actualCRC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filePath) *stop = YES;
|
|
||||||
} error:&performOnFilesError];
|
|
||||||
|
|
||||||
if (performOnFilesError) {
|
if (performOnFilesError) {
|
||||||
URKLogError("Error checking data integrity: %{public}@", performOnFilesError);
|
URKLogError("Error checking data integrity: %{public}@", performOnFilesError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !corruptDataFound;
|
if (!wasSuccessful) {
|
||||||
|
URKLogError("Error checking data integrity");
|
||||||
|
if (RHCode == ERAR_SUCCESS) {
|
||||||
|
RHCode = ERAR_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RHCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1269,22 +1343,24 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon
|
||||||
|
|
||||||
URKLogDebug("Setting archive name...");
|
URKLogDebug("Setting archive name...");
|
||||||
|
|
||||||
const char *filenameData = (const char *) [rarFile UTF8String];
|
self.flags->ArcName = strdup(rarFile.UTF8String);
|
||||||
self.flags->ArcName = new char[strlen(filenameData) + 1];
|
self.flags->OpenMode = (uint)mode;
|
||||||
strcpy(self.flags->ArcName, filenameData);
|
self.flags->OpFlags = self.ignoreCRCMismatches ? ROADOF_KEEPBROKEN : 0;
|
||||||
self.flags->OpenMode = (uint)mode;
|
|
||||||
|
|
||||||
URKLogDebug("Opening archive %{public}@...", rarFile);
|
URKLogDebug("Opening archive %{public}@...", rarFile);
|
||||||
|
|
||||||
self.rarFile = RAROpenArchiveEx(self.flags);
|
self.rarFile = RAROpenArchiveEx(self.flags);
|
||||||
if (self.rarFile == 0 || self.flags->OpenResult != 0) {
|
if (self.rarFile == 0 || self.flags->OpenResult != 0) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:error code:(NSInteger)self.flags->OpenResult errorName:&errorName];
|
[self assignError:error code:(NSInteger)self.flags->OpenResult errorName:&errorName];
|
||||||
URKLogError("Error opening archive: %{public}@ (%d)", errorName, self.flags->OpenResult);
|
URKLogError("Error opening archive: %{public}@ (%d)", errorName, self.flags->OpenResult);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(aPassword != nil) {
|
self.lastFilepath = nil;
|
||||||
|
self.lastArchivePath = nil;
|
||||||
|
|
||||||
|
if (aPassword != nil) {
|
||||||
URKLogDebug("Setting password...");
|
URKLogDebug("Setting password...");
|
||||||
|
|
||||||
char cPassword[2048];
|
char cPassword[2048];
|
||||||
|
@ -1339,10 +1415,10 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon
|
||||||
|
|
||||||
URKLogDebug("Reading through RAR header looking for files...");
|
URKLogDebug("Reading through RAR header looking for files...");
|
||||||
|
|
||||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == 0) {
|
URKFileInfo *info = nil;
|
||||||
|
while ([welf readHeader:&RHCode info:&info] == URKReadHeaderLoopActionContinueReading) {
|
||||||
URKLogDebug("Calling iterateAllFileInfo handler");
|
URKLogDebug("Calling iterateAllFileInfo handler");
|
||||||
BOOL shouldStop = NO;
|
BOOL shouldStop = NO;
|
||||||
URKFileInfo *info = [URKFileInfo fileInfo:welf.header];
|
|
||||||
action(info, &shouldStop);
|
action(info, &shouldStop);
|
||||||
|
|
||||||
if (shouldStop) {
|
if (shouldStop) {
|
||||||
|
@ -1353,15 +1429,15 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon
|
||||||
URKLogDebug("Skipping to next file...");
|
URKLogDebug("Skipping to next file...");
|
||||||
if ((PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) {
|
if ((PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
[welf assignError:innerError code:(NSInteger)PFCode errorName:&errorName];
|
||||||
URKLogError("Error skipping to next header file: %{public}@ (%d)", errorName, PFCode);
|
URKLogError("Error skipping to next header file: %{public}@ (%d)", errorName, PFCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) {
|
if (![welf didReturnSuccessfully:RHCode]) {
|
||||||
NSString *errorName = nil;
|
NSString *errorName = nil;
|
||||||
[self assignError:innerError code:RHCode errorName:&errorName];
|
[welf assignError:innerError code:RHCode errorName:&errorName];
|
||||||
URKLogError("Error reading RAR header: %{public}@ (%d)", errorName, RHCode);
|
URKLogError("Error reading RAR header: %{public}@ (%d)", errorName, RHCode);
|
||||||
}
|
}
|
||||||
} inMode:RAR_OM_LIST_INCSPLIT error:error];
|
} inMode:RAR_OM_LIST_INCSPLIT error:error];
|
||||||
|
@ -1485,7 +1561,7 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errorName = [NSString stringWithFormat:@"Unknown (%ld)", (long)errorCode];
|
errorName = [NSString stringWithFormat:@"Unknown (%ld)", (long)errorCode];
|
||||||
detail = [NSString localizedStringWithFormat:NSLocalizedStringFromTableInBundle(@"Unknown error encountered (code %ld)", @"UnrarKit", _resources, @"Error detail string"), errorCode];
|
detail = [NSString localizedStringWithFormat:NSLocalizedStringFromTableInBundle(@"Unknown error encountered (code %ld)", @"UnrarKit", _resources, @"Error detail string"), (long)errorCode];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1641,4 +1717,71 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon
|
||||||
return volumeURL;
|
return volumeURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (URKReadHeaderLoopAction) readHeader:(int *)returnCode
|
||||||
|
info:(URKFileInfo *__autoreleasing *)info
|
||||||
|
{
|
||||||
|
NSAssert(returnCode != NULL, @"otherReturnCode argument is required");
|
||||||
|
NSAssert(info != NULL, @"info argument is required");
|
||||||
|
|
||||||
|
URKLogDebug("Reading RAR header");
|
||||||
|
*returnCode = RARReadHeaderEx(self.rarFile, self.header);
|
||||||
|
URKLogDebug("Reading file info from RAR header");
|
||||||
|
*info = [URKFileInfo fileInfo:self.header];
|
||||||
|
URKLogDebug("RARReadHeaderEx returned %d", *returnCode);
|
||||||
|
|
||||||
|
URKReadHeaderLoopAction result;
|
||||||
|
|
||||||
|
switch (*returnCode) {
|
||||||
|
case ERAR_SUCCESS:
|
||||||
|
result = URKReadHeaderLoopActionContinueReading;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ERAR_END_ARCHIVE:
|
||||||
|
URKLogDebug("Successful return code from RARReadHeaderEx");
|
||||||
|
result = URKReadHeaderLoopActionStopReading;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ERAR_BAD_DATA:
|
||||||
|
if (self.ignoreCRCMismatches) {
|
||||||
|
URKLogError("Ignoring CRC mismatch in %{public}@", (*info).filename);
|
||||||
|
result = URKReadHeaderLoopActionContinueReading;
|
||||||
|
} else {
|
||||||
|
URKLogError("CRC mismatch when reading %{public}@. To read the archive and ignore CRC mismatches, use -checkDataIntegrityIgnoringCRCMismatches:", (*info).filename);
|
||||||
|
result = URKReadHeaderLoopActionStopReading;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
result = URKReadHeaderLoopActionStopReading;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == URKReadHeaderLoopActionContinueReading
|
||||||
|
&& [self.lastFilepath isEqualToString:(*info).filename]
|
||||||
|
&& [self.lastArchivePath isEqualToString:(*info).archiveName])
|
||||||
|
{
|
||||||
|
URKLogInfo("Same header returned twice. Presuming archive done being read. Probably a bad CRC")
|
||||||
|
result = URKReadHeaderLoopActionStopReading;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.lastFilepath = (result == URKReadHeaderLoopActionStopReading
|
||||||
|
? nil
|
||||||
|
: (*info).filename);
|
||||||
|
self.lastArchivePath = (result == URKReadHeaderLoopActionStopReading
|
||||||
|
? nil
|
||||||
|
: (*info).archiveName);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)didReturnSuccessfully:(int)returnCode {
|
||||||
|
return (returnCode == ERAR_SUCCESS
|
||||||
|
|| returnCode == ERAR_END_ARCHIVE
|
||||||
|
|| (returnCode == ERAR_BAD_DATA && self.ignoreCRCMismatches));
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasBadCRC:(int)returnCode {
|
||||||
|
return returnCode == ERAR_BAD_DATA && !self.ignoreCRCMismatches;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "UnrarKitMacros.h"
|
#import <UnrarKit/UnrarKitMacros.h>
|
||||||
|
|
||||||
RarosHppIgnore
|
RarosHppIgnore
|
||||||
#import "raros.hpp"
|
#import <UnrarKit/raros.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
DllHppIgnore
|
DllHppIgnore
|
||||||
#import "dll.hpp"
|
#import <UnrarKit/dll.hpp>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
/* See http://www.forensicswiki.org/wiki/RAR and
|
/* See http://www.forensicswiki.org/wiki/RAR and
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
_isEncryptedWithPassword = fileHeader->Flags & (1 << 2);
|
_isEncryptedWithPassword = fileHeader->Flags & (1 << 2);
|
||||||
//_fileHasComment = fileHeader->Flags & (1 << 3)
|
//_fileHasComment = fileHeader->Flags & (1 << 3)
|
||||||
|
|
||||||
_isDirectory = fileHeader->Flags & RHDF_DIRECTORY;
|
_isDirectory = (fileHeader->Flags & RHDF_DIRECTORY) ? YES : NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|
|
@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber;
|
||||||
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
||||||
|
|
||||||
|
|
||||||
#import "URKArchive.h"
|
#import <UnrarKit/URKArchive.h>
|
||||||
#import "URKFileInfo.h"
|
#import <UnrarKit/URKFileInfo.h>
|
||||||
|
|
|
@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \
|
||||||
#import <os/activity.h>
|
#import <os/activity.h>
|
||||||
|
|
||||||
// Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp]
|
// Called from +[UnrarKit initialize] and +[URKArchiveTestCase setUp]
|
||||||
extern os_log_t unrarkit_log; // Declared in URKArchive.m
|
extern os_log_t unrarkit_log; // Declared in URKArchive.mm
|
||||||
extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m
|
extern BOOL unrarkitIsAtLeast10_13SDK; // Declared in URKArchive.m
|
||||||
#define URKLogInit() \
|
#define URKLogInit() \
|
||||||
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
||||||
|
|
|
@ -143,17 +143,15 @@
|
||||||
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0930;
|
LastUpgradeCheck = 1200;
|
||||||
};
|
};
|
||||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "UnrarExample" */;
|
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "UnrarExample" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
developmentRegion = English;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 1;
|
hasScannedForEncodings = 1;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
English,
|
en,
|
||||||
Japanese,
|
Base,
|
||||||
French,
|
|
||||||
German,
|
|
||||||
);
|
);
|
||||||
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
|
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
|
@ -257,6 +255,7 @@
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
@ -272,14 +271,13 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
|
OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-lc++",
|
"-lc++",
|
||||||
"-all_load",
|
"-all_load",
|
||||||
);
|
);
|
||||||
PREBINDING = NO;
|
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
@ -301,6 +299,7 @@
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
@ -316,13 +315,12 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||||
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
|
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-lc++",
|
"-lc++",
|
||||||
"-all_load",
|
"-all_load",
|
||||||
);
|
);
|
||||||
PREBINDING = NO;
|
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
WARNING_CFLAGS = "-Wno-error=unused-command-line-argument";
|
WARNING_CFLAGS = "-Wno-error=unused-command-line-argument";
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0930"
|
LastUpgradeVersion = "1200"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
@ -27,8 +27,6 @@
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
|
||||||
</Testables>
|
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
|
@ -38,8 +36,8 @@
|
||||||
ReferencedContainer = "container:UnrarExample.xcodeproj">
|
ReferencedContainer = "container:UnrarExample.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
<AdditionalOptions>
|
<Testables>
|
||||||
</AdditionalOptions>
|
</Testables>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
|
@ -61,8 +59,6 @@
|
||||||
ReferencedContainer = "container:UnrarExample.xcodeproj">
|
ReferencedContainer = "container:UnrarExample.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
|
|
@ -4,8 +4,15 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||||
{
|
{
|
||||||
if (!MainComment)
|
if (!MainComment)
|
||||||
return false;
|
return false;
|
||||||
SaveFilePos SavePos(*this);
|
int64 SavePos=Tell();
|
||||||
|
bool Success=DoGetComment(CmtData);
|
||||||
|
Seek(SavePos,SEEK_SET);
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Archive::DoGetComment(Array<wchar> *CmtData)
|
||||||
|
{
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
uint CmtLength;
|
uint CmtLength;
|
||||||
if (Format==RARFMT14)
|
if (Format==RARFMT14)
|
||||||
|
@ -34,7 +41,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
// Old style (RAR 2.9) comment header embedded into the main
|
// Old style (RAR 2.9) comment header embedded into the main
|
||||||
// archive header.
|
// archive header.
|
||||||
if (BrokenHeader)
|
if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
|
||||||
{
|
{
|
||||||
uiMsg(UIERROR_CMTBROKEN,FileName);
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||||
return false;
|
return false;
|
||||||
|
@ -57,6 +64,8 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||||
#else
|
#else
|
||||||
UnpCmtLength=GetByte();
|
UnpCmtLength=GetByte();
|
||||||
UnpCmtLength+=(GetByte()<<8);
|
UnpCmtLength+=(GetByte()<<8);
|
||||||
|
if (CmtLength<2)
|
||||||
|
return false;
|
||||||
CmtLength-=2;
|
CmtLength-=2;
|
||||||
DataIO.SetCmt13Encryption();
|
DataIO.SetCmt13Encryption();
|
||||||
CommHead.UnpVer=15;
|
CommHead.UnpVer=15;
|
||||||
|
@ -85,15 +94,18 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||||
byte *UnpData;
|
byte *UnpData;
|
||||||
size_t UnpDataSize;
|
size_t UnpDataSize;
|
||||||
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
|
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
|
||||||
|
if (UnpDataSize>0)
|
||||||
|
{
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
// If we ever decide to extend it to Android, we'll need to alloc
|
// If we ever decide to extend it to Android, we'll need to alloc
|
||||||
// 4x memory for OEM to UTF-8 output here.
|
// 4x memory for OEM to UTF-8 output here.
|
||||||
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
|
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
|
||||||
#endif
|
#endif
|
||||||
CmtData->Alloc(UnpDataSize+1);
|
CmtData->Alloc(UnpDataSize+1);
|
||||||
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
|
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
|
||||||
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
|
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
|
||||||
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -131,7 +143,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
||||||
bool Archive::ReadCommentData(Array<wchar> *CmtData)
|
bool Archive::ReadCommentData(Array<wchar> *CmtData)
|
||||||
{
|
{
|
||||||
Array<byte> CmtRaw;
|
Array<byte> CmtRaw;
|
||||||
if (!ReadSubData(&CmtRaw,NULL))
|
if (!ReadSubData(&CmtRaw,NULL,false))
|
||||||
return false;
|
return false;
|
||||||
size_t CmtSize=CmtRaw.Size();
|
size_t CmtSize=CmtRaw.Size();
|
||||||
CmtRaw.Push(0);
|
CmtRaw.Push(0);
|
||||||
|
|
|
@ -208,15 +208,16 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This check allows to make RS based recovery even if password is incorrect.
|
|
||||||
// But we should not do it for EnableBroken or we'll get 'not RAR archive'
|
// We should not do it for EnableBroken or we'll get 'not RAR archive'
|
||||||
// messages when extracting encrypted archives with wrong password.
|
// messages when extracting encrypted archives with wrong password.
|
||||||
if (FailedHeaderDecryption && !EnableBroken)
|
if (FailedHeaderDecryption && !EnableBroken)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing.
|
if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing.
|
||||||
{
|
{
|
||||||
uiMsg(UIERROR_MHEADERBROKEN,FileName);
|
if (!FailedHeaderDecryption) // If not reported a wrong password already.
|
||||||
|
uiMsg(UIERROR_MHEADERBROKEN,FileName);
|
||||||
if (!EnableBroken)
|
if (!EnableBroken)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -232,7 +233,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||||
// immediately after IsArchive call.
|
// immediately after IsArchive call.
|
||||||
if (HeadersLeft && (!SilentOpen || !Encrypted))
|
if (HeadersLeft && (!SilentOpen || !Encrypted))
|
||||||
{
|
{
|
||||||
SaveFilePos SavePos(*this);
|
int64 SavePos=Tell();
|
||||||
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||||
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
||||||
|
|
||||||
|
@ -261,6 +262,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||||
CurBlockPos=SaveCurBlockPos;
|
CurBlockPos=SaveCurBlockPos;
|
||||||
NextBlockPos=SaveNextBlockPos;
|
NextBlockPos=SaveNextBlockPos;
|
||||||
CurHeaderType=SaveCurHeaderType;
|
CurHeaderType=SaveCurHeaderType;
|
||||||
|
Seek(SavePos,SEEK_SET);
|
||||||
}
|
}
|
||||||
if (!Volume || FirstVolume)
|
if (!Volume || FirstVolume)
|
||||||
wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName));
|
wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName));
|
||||||
|
|
|
@ -20,13 +20,15 @@ enum ADDSUBDATA_FLAGS
|
||||||
ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode.
|
ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// RAR5 headers must not exceed 2 MB.
|
||||||
|
#define MAX_HEADER_SIZE_RAR5 0x200000
|
||||||
|
|
||||||
class Archive:public File
|
class Archive:public File
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
void UpdateLatestTime(FileHeader *CurBlock);
|
void UpdateLatestTime(FileHeader *CurBlock);
|
||||||
void ConvertNameCase(wchar *Name);
|
void ConvertNameCase(wchar *Name);
|
||||||
void ConvertFileHeader(FileHeader *hd);
|
void ConvertFileHeader(FileHeader *hd);
|
||||||
void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite);
|
|
||||||
size_t ReadHeader14();
|
size_t ReadHeader14();
|
||||||
size_t ReadHeader15();
|
size_t ReadHeader15();
|
||||||
size_t ReadHeader50();
|
size_t ReadHeader50();
|
||||||
|
@ -34,8 +36,8 @@ class Archive:public File
|
||||||
void RequestArcPassword();
|
void RequestArcPassword();
|
||||||
void UnexpEndArcMsg();
|
void UnexpEndArcMsg();
|
||||||
void BrokenHeaderMsg();
|
void BrokenHeaderMsg();
|
||||||
void UnkEncVerMsg(const wchar *Name);
|
void UnkEncVerMsg(const wchar *Name,const wchar *Info);
|
||||||
void UnkEncVerMsg();
|
bool DoGetComment(Array<wchar> *CmtData);
|
||||||
bool ReadCommentData(Array<wchar> *CmtData);
|
bool ReadCommentData(Array<wchar> *CmtData);
|
||||||
|
|
||||||
#if !defined(RAR_NOCRYPT)
|
#if !defined(RAR_NOCRYPT)
|
||||||
|
@ -63,8 +65,6 @@ class Archive:public File
|
||||||
size_t SearchBlock(HEADER_TYPE HeaderType);
|
size_t SearchBlock(HEADER_TYPE HeaderType);
|
||||||
size_t SearchSubBlock(const wchar *Type);
|
size_t SearchSubBlock(const wchar *Type);
|
||||||
size_t SearchRR();
|
size_t SearchRR();
|
||||||
void WriteBlock(HEADER_TYPE HeaderType,BaseBlock *wb=NULL,bool OnlySetSize=false,bool NonFinalWrite=false);
|
|
||||||
void SetBlockSize(HEADER_TYPE HeaderType,BaseBlock *wb=NULL) {WriteBlock(HeaderType,wb,true);}
|
|
||||||
size_t ReadHeader();
|
size_t ReadHeader();
|
||||||
void CheckArc(bool EnableBroken);
|
void CheckArc(bool EnableBroken);
|
||||||
void CheckOpen(const wchar *Name);
|
void CheckOpen(const wchar *Name);
|
||||||
|
@ -81,8 +81,8 @@ class Archive:public File
|
||||||
int64 GetStartPos();
|
int64 GetStartPos();
|
||||||
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
|
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
|
||||||
const wchar *Name,uint Flags);
|
const wchar *Name,uint Flags);
|
||||||
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
|
bool ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode);
|
||||||
HEADER_TYPE GetHeaderType() {return CurHeaderType;};
|
HEADER_TYPE GetHeaderType() {return CurHeaderType;}
|
||||||
RAROptions* GetRAROptions() {return Cmd;}
|
RAROptions* GetRAROptions() {return Cmd;}
|
||||||
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
|
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -10,7 +10,10 @@ size_t Archive::ReadHeader()
|
||||||
|
|
||||||
CurBlockPos=Tell();
|
CurBlockPos=Tell();
|
||||||
|
|
||||||
size_t ReadSize;
|
// Other developers asked us to initialize it to suppress "may be used
|
||||||
|
// uninitialized" warning in code below in some compilers.
|
||||||
|
size_t ReadSize=0;
|
||||||
|
|
||||||
switch(Format)
|
switch(Format)
|
||||||
{
|
{
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
|
@ -113,9 +116,9 @@ void Archive::BrokenHeaderMsg()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Archive::UnkEncVerMsg(const wchar *Name)
|
void Archive::UnkEncVerMsg(const wchar *Name,const wchar *Info)
|
||||||
{
|
{
|
||||||
uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name);
|
uiMsg(UIERROR_UNKNOWNENCMETHOD,FileName,Name,Info);
|
||||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +204,7 @@ size_t Archive::ReadHeader15()
|
||||||
if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0)
|
if (ShortBlock.HeaderType==HEAD_MAIN && (ShortBlock.Flags & MHD_COMMENT)!=0)
|
||||||
{
|
{
|
||||||
// Old style (up to RAR 2.9) main archive comment embedded into
|
// Old style (up to RAR 2.9) main archive comment embedded into
|
||||||
// the main archive header found. While we can read the entire
|
// the main archive header found. While we can read the entire
|
||||||
// ShortBlock.HeadSize here and remove this part of "if", it would be
|
// ShortBlock.HeadSize here and remove this part of "if", it would be
|
||||||
// waste of memory, because we'll read and process this comment data
|
// waste of memory, because we'll read and process this comment data
|
||||||
// in other function anyway and we do not need them here now.
|
// in other function anyway and we do not need them here now.
|
||||||
|
@ -227,7 +230,7 @@ size_t Archive::ReadHeader15()
|
||||||
Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0;
|
Encrypted=(MainHead.Flags & MHD_PASSWORD)!=0;
|
||||||
Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0;
|
Signed=MainHead.PosAV!=0 || MainHead.HighPosAV!=0;
|
||||||
MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0;
|
MainHead.CommentInHeader=(MainHead.Flags & MHD_COMMENT)!=0;
|
||||||
|
|
||||||
// Only for encrypted 3.0+ archives. 2.x archives did not have this
|
// Only for encrypted 3.0+ archives. 2.x archives did not have this
|
||||||
// flag, so for non-encrypted archives, we'll set it later based on
|
// flag, so for non-encrypted archives, we'll set it later based on
|
||||||
// file attributes.
|
// file attributes.
|
||||||
|
@ -254,7 +257,7 @@ size_t Archive::ReadHeader15()
|
||||||
hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
|
hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
|
||||||
hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
|
hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
|
||||||
hd->Version=(hd->Flags & LHD_VERSION)!=0;
|
hd->Version=(hd->Flags & LHD_VERSION)!=0;
|
||||||
|
|
||||||
hd->DataSize=Raw.Get4();
|
hd->DataSize=Raw.Get4();
|
||||||
uint LowUnpSize=Raw.Get4();
|
uint LowUnpSize=Raw.Get4();
|
||||||
hd->HostOS=Raw.Get1();
|
hd->HostOS=Raw.Get1();
|
||||||
|
@ -265,21 +268,21 @@ size_t Archive::ReadHeader15()
|
||||||
uint FileTime=Raw.Get4();
|
uint FileTime=Raw.Get4();
|
||||||
hd->UnpVer=Raw.Get1();
|
hd->UnpVer=Raw.Get1();
|
||||||
|
|
||||||
// RAR15 did not use the special dictionary size to mark dirs.
|
|
||||||
if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0)
|
|
||||||
hd->Dir=true;
|
|
||||||
|
|
||||||
hd->Method=Raw.Get1()-0x30;
|
hd->Method=Raw.Get1()-0x30;
|
||||||
size_t NameSize=Raw.Get2();
|
size_t NameSize=Raw.Get2();
|
||||||
hd->FileAttr=Raw.Get4();
|
hd->FileAttr=Raw.Get4();
|
||||||
|
|
||||||
|
// RAR15 did not use the special dictionary size to mark dirs.
|
||||||
|
if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0)
|
||||||
|
hd->Dir=true;
|
||||||
|
|
||||||
hd->CryptMethod=CRYPT_NONE;
|
hd->CryptMethod=CRYPT_NONE;
|
||||||
if (hd->Encrypted)
|
if (hd->Encrypted)
|
||||||
switch(hd->UnpVer)
|
switch(hd->UnpVer)
|
||||||
{
|
{
|
||||||
case 13: hd->CryptMethod=CRYPT_RAR13; break;
|
case 13: hd->CryptMethod=CRYPT_RAR13; break;
|
||||||
case 15: hd->CryptMethod=CRYPT_RAR15; break;
|
case 15: hd->CryptMethod=CRYPT_RAR15; break;
|
||||||
case 20:
|
case 20:
|
||||||
case 26: hd->CryptMethod=CRYPT_RAR20; break;
|
case 26: hd->CryptMethod=CRYPT_RAR20; break;
|
||||||
default: hd->CryptMethod=CRYPT_RAR30; break;
|
default: hd->CryptMethod=CRYPT_RAR30; break;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +304,7 @@ size_t Archive::ReadHeader15()
|
||||||
}
|
}
|
||||||
|
|
||||||
hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
|
hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
|
||||||
|
|
||||||
hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;
|
hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;
|
||||||
|
|
||||||
uint HighPackSize,HighUnpSize;
|
uint HighPackSize,HighUnpSize;
|
||||||
|
@ -311,7 +314,7 @@ size_t Archive::ReadHeader15()
|
||||||
HighUnpSize=Raw.Get4();
|
HighUnpSize=Raw.Get4();
|
||||||
hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
|
hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HighPackSize=HighUnpSize=0;
|
HighPackSize=HighUnpSize=0;
|
||||||
// UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
|
// UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
|
||||||
|
@ -399,8 +402,8 @@ size_t Archive::ReadHeader15()
|
||||||
if (rmode & 4)
|
if (rmode & 4)
|
||||||
rlt.Second++;
|
rlt.Second++;
|
||||||
rlt.Reminder=0;
|
rlt.Reminder=0;
|
||||||
int count=rmode&3;
|
uint count=rmode&3;
|
||||||
for (int J=0;J<count;J++)
|
for (uint J=0;J<count;J++)
|
||||||
{
|
{
|
||||||
byte CurByte=Raw.Get1();
|
byte CurByte=Raw.Get1();
|
||||||
rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
|
rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
|
||||||
|
@ -506,7 +509,7 @@ size_t Archive::ReadHeader15()
|
||||||
NextBlockPos+=Raw.Get4();
|
NextBlockPos+=Raw.Get4();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ushort HeaderCRC=Raw.GetCRC15(false);
|
ushort HeaderCRC=Raw.GetCRC15(false);
|
||||||
|
|
||||||
// Old AV header does not have header CRC properly set.
|
// Old AV header does not have header CRC properly set.
|
||||||
|
@ -518,7 +521,6 @@ size_t Archive::ReadHeader15()
|
||||||
{
|
{
|
||||||
// Last 7 bytes of recovered volume can contain zeroes, because
|
// Last 7 bytes of recovered volume can contain zeroes, because
|
||||||
// REV files store its own information (volume number, etc.) here.
|
// REV files store its own information (volume number, etc.) here.
|
||||||
SaveFilePos SavePos(*this);
|
|
||||||
int64 Length=Tell();
|
int64 Length=Tell();
|
||||||
Seek(Length-7,SEEK_SET);
|
Seek(Length-7,SEEK_SET);
|
||||||
Recovered=true;
|
Recovered=true;
|
||||||
|
@ -563,6 +565,11 @@ size_t Archive::ReadHeader50()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We repeat the password request only for manually entered passwords
|
||||||
|
// and not for -p<pwd>. Wrong password can be intentionally provided
|
||||||
|
// in -p<pwd> to not stop batch processing for encrypted archives.
|
||||||
|
bool GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet();
|
||||||
|
|
||||||
while (true) // Repeat the password prompt for wrong passwords.
|
while (true) // Repeat the password prompt for wrong passwords.
|
||||||
{
|
{
|
||||||
RequestArcPassword();
|
RequestArcPassword();
|
||||||
|
@ -572,11 +579,23 @@ size_t Archive::ReadHeader50()
|
||||||
// Verify password validity.
|
// Verify password validity.
|
||||||
if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0)
|
if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0)
|
||||||
{
|
{
|
||||||
// This message is used by Android GUI and Windows GUI and SFX to
|
if (GlobalPassword) // For -p<pwd> or Ctrl+P.
|
||||||
// reset cached passwords. Update appropriate code if changed.
|
{
|
||||||
uiMsg(UIWAIT_BADPSW,FileName);
|
// This message is used by Android GUI to reset cached passwords.
|
||||||
|
// Update appropriate code if changed.
|
||||||
|
uiMsg(UIERROR_BADPSW,FileName,FileName);
|
||||||
|
FailedHeaderDecryption=true;
|
||||||
|
ErrHandler.SetErrorCode(RARX_BADPWD);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else // For passwords entered manually.
|
||||||
|
{
|
||||||
|
// This message is used by Android GUI and Windows GUI and SFX to
|
||||||
|
// reset cached passwords. Update appropriate code if changed.
|
||||||
|
uiMsg(UIWAIT_BADPSW,FileName,FileName);
|
||||||
|
Cmd->Password.Clean();
|
||||||
|
}
|
||||||
|
|
||||||
Cmd->Password.Clean();
|
|
||||||
#ifdef RARDLL
|
#ifdef RARDLL
|
||||||
// Avoid new requests for unrar.dll to prevent the infinite loop
|
// Avoid new requests for unrar.dll to prevent the infinite loop
|
||||||
// if app always returns the same password.
|
// if app always returns the same password.
|
||||||
|
@ -595,8 +614,8 @@ size_t Archive::ReadHeader50()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header size must not occupy more than 3 variable length integer bytes
|
// Header size must not occupy more than 3 variable length integer bytes
|
||||||
// resulting in 2 MB maximum header size, so here we read 4 byte CRC32
|
// resulting in 2 MB maximum header size (MAX_HEADER_SIZE_RAR5),
|
||||||
// followed by 3 bytes or less of header size.
|
// so here we read 4 byte CRC32 followed by 3 bytes or less of header size.
|
||||||
const size_t FirstReadSize=7; // Smallest possible block size.
|
const size_t FirstReadSize=7; // Smallest possible block size.
|
||||||
if (Raw.Read(FirstReadSize)<FirstReadSize)
|
if (Raw.Read(FirstReadSize)<FirstReadSize)
|
||||||
{
|
{
|
||||||
|
@ -624,7 +643,7 @@ size_t Archive::ReadHeader50()
|
||||||
BrokenHeaderMsg();
|
BrokenHeaderMsg();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Raw.Read(SizeToRead);
|
Raw.Read(SizeToRead);
|
||||||
|
|
||||||
if (Raw.Size()<HeaderSize)
|
if (Raw.Size()<HeaderSize)
|
||||||
|
@ -657,7 +676,7 @@ size_t Archive::ReadHeader50()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 ExtraSize=0;
|
uint64 ExtraSize=0;
|
||||||
if ((ShortBlock.Flags & HFL_EXTRA)!=0)
|
if ((ShortBlock.Flags & HFL_EXTRA)!=0)
|
||||||
{
|
{
|
||||||
|
@ -685,7 +704,9 @@ size_t Archive::ReadHeader50()
|
||||||
uint CryptVersion=(uint)Raw.GetV();
|
uint CryptVersion=(uint)Raw.GetV();
|
||||||
if (CryptVersion>CRYPT_VERSION)
|
if (CryptVersion>CRYPT_VERSION)
|
||||||
{
|
{
|
||||||
UnkEncVerMsg(FileName);
|
wchar Info[20];
|
||||||
|
swprintf(Info,ASIZE(Info),L"h%u",CryptVersion);
|
||||||
|
UnkEncVerMsg(FileName,Info);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint EncFlags=(uint)Raw.GetV();
|
uint EncFlags=(uint)Raw.GetV();
|
||||||
|
@ -693,9 +714,12 @@ size_t Archive::ReadHeader50()
|
||||||
CryptHead.Lg2Count=Raw.Get1();
|
CryptHead.Lg2Count=Raw.Get1();
|
||||||
if (CryptHead.Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX)
|
if (CryptHead.Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX)
|
||||||
{
|
{
|
||||||
UnkEncVerMsg(FileName);
|
wchar Info[20];
|
||||||
|
swprintf(Info,ASIZE(Info),L"hc%u",CryptHead.Lg2Count);
|
||||||
|
UnkEncVerMsg(FileName,Info);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Raw.GetB(CryptHead.Salt,SIZE_SALT50);
|
Raw.GetB(CryptHead.Salt,SIZE_SALT50);
|
||||||
if (CryptHead.UsePswCheck)
|
if (CryptHead.UsePswCheck)
|
||||||
{
|
{
|
||||||
|
@ -746,7 +770,7 @@ size_t Archive::ReadHeader50()
|
||||||
// to not break normal archive processing by calling function.
|
// to not break normal archive processing by calling function.
|
||||||
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||||
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
||||||
|
|
||||||
QOpen.Init(this,false);
|
QOpen.Init(this,false);
|
||||||
QOpen.Load(MainHead.QOpenOffset);
|
QOpen.Load(MainHead.QOpenOffset);
|
||||||
|
|
||||||
|
@ -771,7 +795,7 @@ size_t Archive::ReadHeader50()
|
||||||
hd->PackSize=DataSize;
|
hd->PackSize=DataSize;
|
||||||
hd->FileFlags=(uint)Raw.GetV();
|
hd->FileFlags=(uint)Raw.GetV();
|
||||||
hd->UnpSize=Raw.GetV();
|
hd->UnpSize=Raw.GetV();
|
||||||
|
|
||||||
hd->UnknownUnpSize=(hd->FileFlags & FHFL_UNPUNKNOWN)!=0;
|
hd->UnknownUnpSize=(hd->FileFlags & FHFL_UNPUNKNOWN)!=0;
|
||||||
if (hd->UnknownUnpSize)
|
if (hd->UnknownUnpSize)
|
||||||
hd->UnpSize=INT64NDF;
|
hd->UnpSize=INT64NDF;
|
||||||
|
@ -798,6 +822,8 @@ size_t Archive::ReadHeader50()
|
||||||
// but it was already used in RAR 1.5 and Unpack needs to distinguish
|
// but it was already used in RAR 1.5 and Unpack needs to distinguish
|
||||||
// them.
|
// them.
|
||||||
hd->UnpVer=(CompInfo & 0x3f) + 50;
|
hd->UnpVer=(CompInfo & 0x3f) + 50;
|
||||||
|
if (hd->UnpVer!=50) // Only 5.0 compression is known now.
|
||||||
|
hd->UnpVer=VER_UNKNOWN;
|
||||||
|
|
||||||
hd->HostOS=(byte)Raw.GetV();
|
hd->HostOS=(byte)Raw.GetV();
|
||||||
size_t NameSize=(size_t)Raw.GetV();
|
size_t NameSize=(size_t)Raw.GetV();
|
||||||
|
@ -856,7 +882,7 @@ size_t Archive::ReadHeader50()
|
||||||
RecoverySize=Header.RecSectionSize*Header.RecCount;
|
RecoverySize=Header.RecSectionSize*Header.RecCount;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (BadCRC) // Add the file name to broken header message displayed above.
|
if (BadCRC) // Add the file name to broken header message displayed above.
|
||||||
uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName);
|
uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName);
|
||||||
}
|
}
|
||||||
|
@ -972,8 +998,12 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||||
{
|
{
|
||||||
FileHeader *hd=(FileHeader *)bb;
|
FileHeader *hd=(FileHeader *)bb;
|
||||||
uint EncVersion=(uint)Raw->GetV();
|
uint EncVersion=(uint)Raw->GetV();
|
||||||
if (EncVersion > CRYPT_VERSION)
|
if (EncVersion>CRYPT_VERSION)
|
||||||
UnkEncVerMsg(hd->FileName);
|
{
|
||||||
|
wchar Info[20];
|
||||||
|
swprintf(Info,ASIZE(Info),L"x%u",EncVersion);
|
||||||
|
UnkEncVerMsg(hd->FileName,Info);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint Flags=(uint)Raw->GetV();
|
uint Flags=(uint)Raw->GetV();
|
||||||
|
@ -981,7 +1011,11 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||||
hd->UseHashKey=(Flags & FHEXTRA_CRYPT_HASHMAC)!=0;
|
hd->UseHashKey=(Flags & FHEXTRA_CRYPT_HASHMAC)!=0;
|
||||||
hd->Lg2Count=Raw->Get1();
|
hd->Lg2Count=Raw->Get1();
|
||||||
if (hd->Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX)
|
if (hd->Lg2Count>CRYPT5_KDF_LG2_COUNT_MAX)
|
||||||
UnkEncVerMsg(hd->FileName);
|
{
|
||||||
|
wchar Info[20];
|
||||||
|
swprintf(Info,ASIZE(Info),L"xc%u",hd->Lg2Count);
|
||||||
|
UnkEncVerMsg(hd->FileName,Info);
|
||||||
|
}
|
||||||
Raw->GetB(hd->Salt,SIZE_SALT50);
|
Raw->GetB(hd->Salt,SIZE_SALT50);
|
||||||
Raw->GetB(hd->InitV,SIZE_INITV);
|
Raw->GetB(hd->InitV,SIZE_INITV);
|
||||||
if (hd->UsePswCheck)
|
if (hd->UsePswCheck)
|
||||||
|
@ -1222,11 +1256,13 @@ size_t Archive::ReadHeader14()
|
||||||
Raw.Read(NameSize);
|
Raw.Read(NameSize);
|
||||||
|
|
||||||
char FileName[NM];
|
char FileName[NM];
|
||||||
Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName)));
|
size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
|
||||||
FileName[NameSize]=0;
|
Raw.GetB((byte *)FileName,ReadNameSize);
|
||||||
|
FileName[ReadNameSize]=0;
|
||||||
IntToExt(FileName,FileName,ASIZE(FileName));
|
IntToExt(FileName,FileName,ASIZE(FileName));
|
||||||
CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName));
|
CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName));
|
||||||
ConvertNameCase(FileHead.FileName);
|
ConvertNameCase(FileHead.FileName);
|
||||||
|
ConvertFileHeader(&FileHead);
|
||||||
|
|
||||||
if (Raw.Size()!=0)
|
if (Raw.Size()!=0)
|
||||||
NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize;
|
NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize;
|
||||||
|
@ -1273,7 +1309,7 @@ void Archive::ConvertAttributes()
|
||||||
|
|
||||||
if (mask == (mode_t) -1)
|
if (mask == (mode_t) -1)
|
||||||
{
|
{
|
||||||
// umask call returns the current umask value. Argument (022) is not
|
// umask call returns the current umask value. Argument (022) is not
|
||||||
// really important here.
|
// really important here.
|
||||||
mask = umask(022);
|
mask = umask(022);
|
||||||
|
|
||||||
|
@ -1350,8 +1386,8 @@ void Archive::ConvertFileHeader(FileHeader *hd)
|
||||||
|
|
||||||
// ':' in file names is allowed in Unix, but not in Windows.
|
// ':' in file names is allowed in Unix, but not in Windows.
|
||||||
// Even worse, file data will be written to NTFS stream on NTFS,
|
// Even worse, file data will be written to NTFS stream on NTFS,
|
||||||
// so automatic name correction on file create error in extraction
|
// so automatic name correction on file create error in extraction
|
||||||
// routine does not work. In Windows and DOS versions we better
|
// routine does not work. In Windows and DOS versions we better
|
||||||
// replace ':' now.
|
// replace ':' now.
|
||||||
if (*s==':')
|
if (*s==':')
|
||||||
*s='_';
|
*s='_';
|
||||||
|
@ -1380,7 +1416,7 @@ int64 Archive::GetStartPos()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode)
|
||||||
{
|
{
|
||||||
if (BrokenHeader)
|
if (BrokenHeader)
|
||||||
{
|
{
|
||||||
|
@ -1428,6 +1464,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
||||||
SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
|
SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
|
||||||
SubDataIO.EnableShowProgress(false);
|
SubDataIO.EnableShowProgress(false);
|
||||||
SubDataIO.SetFiles(this,DestFile);
|
SubDataIO.SetFiles(this,DestFile);
|
||||||
|
SubDataIO.SetTestMode(TestMode);
|
||||||
SubDataIO.UnpVolume=SubHead.SplitAfter;
|
SubDataIO.UnpVolume=SubHead.SplitAfter;
|
||||||
SubDataIO.SetSubHeader(&SubHead,NULL);
|
SubDataIO.SetSubHeader(&SubHead,NULL);
|
||||||
Unpack.SetDestSize(SubHead.UnpSize);
|
Unpack.SetDestSize(SubHead.UnpSize);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#define _RAR_BLAKE2_
|
#define _RAR_BLAKE2_
|
||||||
|
|
||||||
#define BLAKE2_DIGEST_SIZE 32
|
#define BLAKE2_DIGEST_SIZE 32
|
||||||
|
#define BLAKE2_THREADS_NUMBER 8
|
||||||
|
|
||||||
enum blake2s_constant
|
enum blake2s_constant
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "rar.hpp"
|
#include "rar.hpp"
|
||||||
|
|
||||||
|
#include "cmdfilter.cpp"
|
||||||
|
#include "cmdmix.cpp"
|
||||||
|
|
||||||
CommandData::CommandData()
|
CommandData::CommandData()
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
|
@ -120,6 +123,7 @@ void CommandData::ParseArg(wchar *Arg)
|
||||||
wchar CmdChar=toupperw(*Command);
|
wchar CmdChar=toupperw(*Command);
|
||||||
bool Add=wcschr(L"AFUM",CmdChar)!=NULL;
|
bool Add=wcschr(L"AFUM",CmdChar)!=NULL;
|
||||||
bool Extract=CmdChar=='X' || CmdChar=='E';
|
bool Extract=CmdChar=='X' || CmdChar=='E';
|
||||||
|
bool Repair=CmdChar=='R' && Command[1]==0;
|
||||||
if (EndSeparator && !Add)
|
if (EndSeparator && !Add)
|
||||||
wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
||||||
else
|
else
|
||||||
|
@ -130,15 +134,15 @@ void CommandData::ParseArg(wchar *Arg)
|
||||||
FindData FileData;
|
FindData FileData;
|
||||||
bool Found=FindFile::FastFind(Arg,&FileData);
|
bool Found=FindFile::FastFind(Arg,&FileData);
|
||||||
if ((!Found || ListMode==RCLM_ACCEPT_LISTS) &&
|
if ((!Found || ListMode==RCLM_ACCEPT_LISTS) &&
|
||||||
ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg))
|
ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg+1))
|
||||||
{
|
{
|
||||||
FileLists=true;
|
FileLists=true;
|
||||||
|
|
||||||
ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true);
|
ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else // We use 'destpath\' when extracting and reparing.
|
||||||
if (Found && FileData.IsDir && Extract && *ExtrPath==0)
|
if (Found && FileData.IsDir && (Extract || Repair) && *ExtrPath==0)
|
||||||
{
|
{
|
||||||
wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
||||||
AddEndSlash(ExtrPath,ASIZE(ExtrPath));
|
AddEndSlash(ExtrPath,ASIZE(ExtrPath));
|
||||||
|
@ -280,17 +284,24 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||||
ClearArc=true;
|
ClearArc=true;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
AppendArcNameToPath=true;
|
if (Switch[2]==0)
|
||||||
|
AppendArcNameToPath=APPENDARCNAME_DESTPATH;
|
||||||
|
else
|
||||||
|
if (Switch[2]=='1')
|
||||||
|
AppendArcNameToPath=APPENDARCNAME_OWNDIR;
|
||||||
break;
|
break;
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
case 'G':
|
case 'G':
|
||||||
if (Switch[2]=='-' && Switch[3]==0)
|
if (Switch[2]=='-' && Switch[3]==0)
|
||||||
GenerateArcName=0;
|
GenerateArcName=0;
|
||||||
else
|
else
|
||||||
{
|
if (toupperw(Switch[2])=='F')
|
||||||
GenerateArcName=true;
|
wcsncpyz(DefGenerateMask,Switch+3,ASIZE(DefGenerateMask));
|
||||||
wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
|
else
|
||||||
}
|
{
|
||||||
|
GenerateArcName=true;
|
||||||
|
wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'I':
|
case 'I':
|
||||||
|
@ -302,7 +313,7 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||||
AddArcOnly=true;
|
AddArcOnly=true;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
wcscpy(ArcPath,Switch+2);
|
wcsncpyz(ArcPath,Switch+2,ASIZE(ArcPath));
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
SyncFiles=true;
|
SyncFiles=true;
|
||||||
|
@ -365,11 +376,11 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||||
default:
|
default:
|
||||||
if (Switch[1]=='+')
|
if (Switch[1]=='+')
|
||||||
{
|
{
|
||||||
InclFileAttr|=GetExclAttr(Switch+2);
|
InclFileAttr|=GetExclAttr(Switch+2,InclDir);
|
||||||
InclAttrSet=true;
|
InclAttrSet=true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ExclFileAttr|=GetExclAttr(Switch+1);
|
ExclFileAttr|=GetExclAttr(Switch+1,ExclDir);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -407,9 +418,9 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||||
wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName));
|
wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (wcsicomp(Switch+1,L"SND")==0)
|
if (wcsnicomp(Switch+1,L"SND",3)==0)
|
||||||
{
|
{
|
||||||
Sound=true;
|
Sound=Switch[4]=='-' ? SOUND_NOTIFY_OFF : SOUND_NOTIFY_ON;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (wcsicomp(Switch+1,L"ERR")==0)
|
if (wcsicomp(Switch+1,L"ERR")==0)
|
||||||
|
@ -805,51 +816,19 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||||
ArcTime=ARCTIME_LATEST;
|
ArcTime=ARCTIME_LATEST;
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
FileTimeBefore.SetAgeText(Switch+2);
|
SetTimeFilters(Switch+2,true,true);
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
FileTimeAfter.SetAgeText(Switch+2);
|
SetTimeFilters(Switch+2,false,true);
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
FileTimeBefore.SetIsoText(Switch+2);
|
SetTimeFilters(Switch+2,true,false);
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
FileTimeAfter.SetIsoText(Switch+2);
|
SetTimeFilters(Switch+2,false,false);
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
{
|
SetStoreTimeMode(Switch+2);
|
||||||
EXTTIME_MODE Mode=EXTTIME_HIGH3;
|
|
||||||
bool CommonMode=Switch[2]>='0' && Switch[2]<='4';
|
|
||||||
if (CommonMode)
|
|
||||||
Mode=(EXTTIME_MODE)(Switch[2]-'0');
|
|
||||||
if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore.
|
|
||||||
Mode=EXTTIME_HIGH3;
|
|
||||||
if (Switch[2]=='-')
|
|
||||||
Mode=EXTTIME_NONE;
|
|
||||||
if (CommonMode || Switch[2]=='-' || Switch[2]=='+' || Switch[2]==0)
|
|
||||||
xmtime=xctime=xatime=Mode;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Switch[3]>='0' && Switch[3]<='4')
|
|
||||||
Mode=(EXTTIME_MODE)(Switch[3]-'0');
|
|
||||||
if (Mode==EXTTIME_HIGH1 || Mode==EXTTIME_HIGH2) // '2' and '3' not supported anymore.
|
|
||||||
Mode=EXTTIME_HIGH3;
|
|
||||||
if (Switch[3]=='-')
|
|
||||||
Mode=EXTTIME_NONE;
|
|
||||||
switch(toupperw(Switch[2]))
|
|
||||||
{
|
|
||||||
case 'M':
|
|
||||||
xmtime=Mode;
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
xctime=Mode;
|
|
||||||
break;
|
|
||||||
case 'A':
|
|
||||||
xatime=Mode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
Test=false;
|
Test=false;
|
||||||
|
@ -897,7 +876,7 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||||
if (Switch[1]==0)
|
if (Switch[1]==0)
|
||||||
{
|
{
|
||||||
// If comment file is not specified, we read data from stdin.
|
// If comment file is not specified, we read data from stdin.
|
||||||
wcscpy(CommentFile,L"stdin");
|
wcsncpyz(CommentFile,L"stdin",ASIZE(CommentFile));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wcsncpyz(CommentFile,Switch+1,ASIZE(CommentFile));
|
wcsncpyz(CommentFile,Switch+1,ASIZE(CommentFile));
|
||||||
|
@ -922,309 +901,6 @@ void CommandData::BadSwitch(const wchar *Switch)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void CommandData::OutTitle()
|
|
||||||
{
|
|
||||||
if (BareOutput || DisableCopyright)
|
|
||||||
return;
|
|
||||||
#if defined(__GNUC__) && defined(SFX_MODULE)
|
|
||||||
mprintf(St(MCopyrightS));
|
|
||||||
#else
|
|
||||||
#ifndef SILENT
|
|
||||||
static bool TitleShown=false;
|
|
||||||
if (TitleShown)
|
|
||||||
return;
|
|
||||||
TitleShown=true;
|
|
||||||
|
|
||||||
wchar Version[80];
|
|
||||||
if (RARVER_BETA!=0)
|
|
||||||
swprintf(Version,ASIZE(Version),L"%d.%02d %ls %d",RARVER_MAJOR,RARVER_MINOR,St(MBeta),RARVER_BETA);
|
|
||||||
else
|
|
||||||
swprintf(Version,ASIZE(Version),L"%d.%02d",RARVER_MAJOR,RARVER_MINOR);
|
|
||||||
#if defined(_WIN_32) || defined(_WIN_64)
|
|
||||||
wcsncatz(Version,L" ",ASIZE(Version));
|
|
||||||
#endif
|
|
||||||
#ifdef _WIN_32
|
|
||||||
wcsncatz(Version,St(Mx86),ASIZE(Version));
|
|
||||||
#endif
|
|
||||||
#ifdef _WIN_64
|
|
||||||
wcsncatz(Version,St(Mx64),ASIZE(Version));
|
|
||||||
#endif
|
|
||||||
if (PrintVersion)
|
|
||||||
{
|
|
||||||
mprintf(L"%s",Version);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
mprintf(St(MUCopyright),Version,RARVER_YEAR);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline bool CmpMSGID(MSGID i1,MSGID i2)
|
|
||||||
{
|
|
||||||
#ifdef MSGID_INT
|
|
||||||
return i1==i2;
|
|
||||||
#else
|
|
||||||
// If MSGID is const char*, we cannot compare pointers only.
|
|
||||||
// Pointers to different instances of same string can differ,
|
|
||||||
// so we need to compare complete strings.
|
|
||||||
return wcscmp(i1,i2)==0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void CommandData::OutHelp(RAR_EXIT ExitCode)
|
|
||||||
{
|
|
||||||
#if !defined(SILENT)
|
|
||||||
OutTitle();
|
|
||||||
static MSGID Help[]={
|
|
||||||
#ifdef SFX_MODULE
|
|
||||||
// Console SFX switches definition.
|
|
||||||
MCHelpCmd,MSHelpCmdE,MSHelpCmdT,MSHelpCmdV
|
|
||||||
#else
|
|
||||||
// UnRAR switches definition.
|
|
||||||
MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,
|
|
||||||
MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,
|
|
||||||
MCHelpSwAT,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,MCHelpSwAI,MCHelpSwAP,
|
|
||||||
MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,
|
|
||||||
MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,
|
|
||||||
MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,
|
|
||||||
MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOW,MCHelpSwP,
|
|
||||||
MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSL,MCHelpSwSM,
|
|
||||||
MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,
|
|
||||||
MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal,
|
|
||||||
MCHelpSwY
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
for (uint I=0;I<ASIZE(Help);I++)
|
|
||||||
{
|
|
||||||
#ifndef SFX_MODULE
|
|
||||||
if (CmpMSGID(Help[I],MCHelpSwV))
|
|
||||||
continue;
|
|
||||||
#ifndef _WIN_ALL
|
|
||||||
static MSGID Win32Only[]={
|
|
||||||
MCHelpSwIEML,MCHelpSwVD,MCHelpSwAO,MCHelpSwOS,MCHelpSwIOFF,
|
|
||||||
MCHelpSwEP2,MCHelpSwOC,MCHelpSwONI,MCHelpSwDR,MCHelpSwRI
|
|
||||||
};
|
|
||||||
bool Found=false;
|
|
||||||
for (int J=0;J<sizeof(Win32Only)/sizeof(Win32Only[0]);J++)
|
|
||||||
if (CmpMSGID(Help[I],Win32Only[J]))
|
|
||||||
{
|
|
||||||
Found=true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (Found)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
#if !defined(_UNIX) && !defined(_WIN_ALL)
|
|
||||||
if (CmpMSGID(Help[I],MCHelpSwOW))
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
#if !defined(_WIN_ALL) && !defined(_EMX)
|
|
||||||
if (CmpMSGID(Help[I],MCHelpSwAC))
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
#ifndef SAVE_LINKS
|
|
||||||
if (CmpMSGID(Help[I],MCHelpSwOL))
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
#ifndef RAR_SMP
|
|
||||||
if (CmpMSGID(Help[I],MCHelpSwMT))
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
mprintf(St(Help[I]));
|
|
||||||
}
|
|
||||||
mprintf(L"\n");
|
|
||||||
ErrHandler.Exit(ExitCode);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Return 'true' if we need to exclude the file from processing as result
|
|
||||||
// of -x switch. If CheckInclList is true, we also check the file against
|
|
||||||
// the include list created with -n switch.
|
|
||||||
bool CommandData::ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList)
|
|
||||||
{
|
|
||||||
if (CheckArgs(&ExclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
|
|
||||||
return true;
|
|
||||||
if (!CheckInclList || InclArgs.ItemsCount()==0)
|
|
||||||
return false;
|
|
||||||
if (CheckArgs(&InclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CommandData::CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode)
|
|
||||||
{
|
|
||||||
wchar *Name=ConvertPath(CheckName,NULL);
|
|
||||||
wchar FullName[NM];
|
|
||||||
wchar CurMask[NM];
|
|
||||||
*FullName=0;
|
|
||||||
Args->Rewind();
|
|
||||||
while (Args->GetString(CurMask,ASIZE(CurMask)))
|
|
||||||
{
|
|
||||||
wchar *LastMaskChar=PointToLastChar(CurMask);
|
|
||||||
bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only.
|
|
||||||
|
|
||||||
if (Dir)
|
|
||||||
{
|
|
||||||
// CheckName is a directory.
|
|
||||||
if (DirMask)
|
|
||||||
{
|
|
||||||
// We process the directory and have the directory exclusion mask.
|
|
||||||
// So let's convert "mask\" to "mask" and process it normally.
|
|
||||||
|
|
||||||
*LastMaskChar=0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// REMOVED, we want -npath\* to match empty folders too.
|
|
||||||
// If mask has wildcards in name part and does not have the trailing
|
|
||||||
// '\' character, we cannot use it for directories.
|
|
||||||
|
|
||||||
// if (IsWildcard(PointToName(CurMask)))
|
|
||||||
// continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we process a file inside of directory excluded by "dirmask\".
|
|
||||||
// we want to exclude such file too. So we convert "dirmask\" to
|
|
||||||
// "dirmask\*". It is important for operations other than archiving
|
|
||||||
// with -x. When archiving with -x, directory matched by "dirmask\"
|
|
||||||
// is excluded from further scanning.
|
|
||||||
|
|
||||||
if (DirMask)
|
|
||||||
wcsncatz(CurMask,L"*",ASIZE(CurMask));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SFX_MODULE
|
|
||||||
if (CheckFullPath && IsFullPath(CurMask))
|
|
||||||
{
|
|
||||||
// We do not need to do the special "*\" processing here, because
|
|
||||||
// unlike the "else" part of this "if", now we convert names to full
|
|
||||||
// format, so they all include the path, which is matched by "*\"
|
|
||||||
// correctly. Moreover, removing "*\" from mask would break
|
|
||||||
// the comparison, because now all names have the path.
|
|
||||||
|
|
||||||
if (*FullName==0)
|
|
||||||
ConvertNameToFull(CheckName,FullName,ASIZE(FullName));
|
|
||||||
if (CmpName(CurMask,FullName,MatchMode))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
wchar NewName[NM+2],*CurName=Name;
|
|
||||||
|
|
||||||
// Important to convert before "*\" check below, so masks like
|
|
||||||
// d:*\something are processed properly.
|
|
||||||
wchar *CmpMask=ConvertPath(CurMask,NULL);
|
|
||||||
|
|
||||||
if (CmpMask[0]=='*' && IsPathDiv(CmpMask[1]))
|
|
||||||
{
|
|
||||||
// We want "*\name" to match 'name' not only in subdirectories,
|
|
||||||
// but also in the current directory. We convert the name
|
|
||||||
// from 'name' to '.\name' to be matched by "*\" part even if it is
|
|
||||||
// in current directory.
|
|
||||||
NewName[0]='.';
|
|
||||||
NewName[1]=CPATHDIVIDER;
|
|
||||||
wcsncpyz(NewName+2,Name,ASIZE(NewName)-2);
|
|
||||||
CurName=NewName;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CmpName(CmpMask,CurName,MatchMode))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SFX_MODULE
|
|
||||||
// Now this function performs only one task and only in Windows version:
|
|
||||||
// it skips symlinks to directories if -e1024 switch is specified.
|
|
||||||
// Symlinks are skipped in ScanTree class, so their entire contents
|
|
||||||
// is skipped too. Without this function we would check the attribute
|
|
||||||
// only directly before archiving, so we would skip the symlink record,
|
|
||||||
// but not the contents of symlinked directory.
|
|
||||||
bool CommandData::ExclDirByAttr(uint FileAttr)
|
|
||||||
{
|
|
||||||
#ifdef _WIN_ALL
|
|
||||||
if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0 &&
|
|
||||||
(ExclFileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SFX_MODULE
|
|
||||||
// Return 'true' if we need to exclude the file from processing.
|
|
||||||
bool CommandData::TimeCheck(RarTime &ft)
|
|
||||||
{
|
|
||||||
if (FileTimeBefore.IsSet() && ft>=FileTimeBefore)
|
|
||||||
return true;
|
|
||||||
if (FileTimeAfter.IsSet() && ft<=FileTimeAfter)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SFX_MODULE
|
|
||||||
// Return 'true' if we need to exclude the file from processing.
|
|
||||||
bool CommandData::SizeCheck(int64 Size)
|
|
||||||
{
|
|
||||||
if (FileSizeLess!=INT64NDF && Size>=FileSizeLess)
|
|
||||||
return(true);
|
|
||||||
if (FileSizeMore!=INT64NDF && Size<=FileSizeMore)
|
|
||||||
return(true);
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
|
|
||||||
wchar *MatchedArg,uint MatchedArgSize)
|
|
||||||
{
|
|
||||||
if (MatchedArg!=NULL && MatchedArgSize>0)
|
|
||||||
*MatchedArg=0;
|
|
||||||
// if (wcslen(FileHead.FileName)>=NM)
|
|
||||||
// return 0;
|
|
||||||
bool Dir=FileHead.Dir;
|
|
||||||
if (ExclCheck(FileHead.FileName,Dir,false,true))
|
|
||||||
return 0;
|
|
||||||
#ifndef SFX_MODULE
|
|
||||||
if (TimeCheck(FileHead.mtime))
|
|
||||||
return 0;
|
|
||||||
if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0)
|
|
||||||
return 0;
|
|
||||||
if (!Dir && SizeCheck(FileHead.UnpSize))
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
wchar *ArgName;
|
|
||||||
FileArgs.Rewind();
|
|
||||||
for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++)
|
|
||||||
if (CmpName(ArgName,FileHead.FileName,MatchType))
|
|
||||||
{
|
|
||||||
if (ExactMatch!=NULL)
|
|
||||||
*ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0;
|
|
||||||
if (MatchedArg!=NULL)
|
|
||||||
wcsncpyz(MatchedArg,ArgName,MatchedArgSize);
|
|
||||||
return StringCount;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CommandData::ProcessCommand()
|
void CommandData::ProcessCommand()
|
||||||
{
|
{
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
|
@ -1255,7 +931,10 @@ void CommandData::ProcessCommand()
|
||||||
if (wcschr(L"AFUMD",*Command)==NULL)
|
if (wcschr(L"AFUMD",*Command)==NULL)
|
||||||
{
|
{
|
||||||
if (GenerateArcName)
|
if (GenerateArcName)
|
||||||
GenerateArchiveName(ArcName,ASIZE(ArcName),GenerateMask,false);
|
{
|
||||||
|
const wchar *Mask=*GenerateMask!=0 ? GenerateMask:DefGenerateMask;
|
||||||
|
GenerateArchiveName(ArcName,ASIZE(ArcName),Mask,false);
|
||||||
|
}
|
||||||
|
|
||||||
StringList ArcMasks;
|
StringList ArcMasks;
|
||||||
ArcMasks.AddString(ArcName);
|
ArcMasks.AddString(ArcName);
|
||||||
|
@ -1274,7 +953,6 @@ void CommandData::ProcessCommand()
|
||||||
case 'X':
|
case 'X':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'T':
|
case 'T':
|
||||||
case 'I':
|
|
||||||
{
|
{
|
||||||
CmdExtract Extract(this);
|
CmdExtract Extract(this);
|
||||||
Extract.DoExtract();
|
Extract.DoExtract();
|
||||||
|
@ -1317,7 +995,7 @@ bool CommandData::IsSwitch(int Ch)
|
||||||
|
|
||||||
|
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
uint CommandData::GetExclAttr(const wchar *Str)
|
uint CommandData::GetExclAttr(const wchar *Str,bool &Dir)
|
||||||
{
|
{
|
||||||
if (IsDigit(*Str))
|
if (IsDigit(*Str))
|
||||||
return wcstol(Str,NULL,0);
|
return wcstol(Str,NULL,0);
|
||||||
|
@ -1327,10 +1005,10 @@ uint CommandData::GetExclAttr(const wchar *Str)
|
||||||
{
|
{
|
||||||
switch(toupperw(*Str))
|
switch(toupperw(*Str))
|
||||||
{
|
{
|
||||||
#ifdef _UNIX
|
|
||||||
case 'D':
|
case 'D':
|
||||||
Attr|=S_IFDIR;
|
Dir=true;
|
||||||
break;
|
break;
|
||||||
|
#ifdef _UNIX
|
||||||
case 'V':
|
case 'V':
|
||||||
Attr|=S_IFCHR;
|
Attr|=S_IFCHR;
|
||||||
break;
|
break;
|
||||||
|
@ -1344,9 +1022,6 @@ uint CommandData::GetExclAttr(const wchar *Str)
|
||||||
case 'S':
|
case 'S':
|
||||||
Attr|=0x4;
|
Attr|=0x4;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
|
||||||
Attr|=0x10;
|
|
||||||
break;
|
|
||||||
case 'A':
|
case 'A':
|
||||||
Attr|=0x20;
|
Attr|=0x20;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -6,13 +6,19 @@
|
||||||
|
|
||||||
enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS};
|
enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS};
|
||||||
|
|
||||||
|
enum IS_PROCESS_FILE_FLAGS {IPFF_EXCLUDE_PARENT=1};
|
||||||
|
|
||||||
class CommandData:public RAROptions
|
class CommandData:public RAROptions
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
void ProcessSwitchesString(const wchar *Str);
|
void ProcessSwitchesString(const wchar *Str);
|
||||||
void ProcessSwitch(const wchar *Switch);
|
void ProcessSwitch(const wchar *Switch);
|
||||||
void BadSwitch(const wchar *Switch);
|
void BadSwitch(const wchar *Switch);
|
||||||
uint GetExclAttr(const wchar *Str);
|
uint GetExclAttr(const wchar *Str,bool &Dir);
|
||||||
|
#if !defined(SFX_MODULE)
|
||||||
|
void SetTimeFilters(const wchar *Mod,bool Before,bool Age);
|
||||||
|
void SetStoreTimeMode(const wchar *S);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool FileLists;
|
bool FileLists;
|
||||||
bool NoMoreSwitches;
|
bool NoMoreSwitches;
|
||||||
|
@ -34,11 +40,11 @@ class CommandData:public RAROptions
|
||||||
bool ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
|
bool ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,bool CheckInclList);
|
||||||
static bool CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode);
|
static bool CheckArgs(StringList *Args,bool Dir,const wchar *CheckName,bool CheckFullPath,int MatchMode);
|
||||||
bool ExclDirByAttr(uint FileAttr);
|
bool ExclDirByAttr(uint FileAttr);
|
||||||
bool TimeCheck(RarTime &ft);
|
bool TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta);
|
||||||
bool SizeCheck(int64 Size);
|
bool SizeCheck(int64 Size);
|
||||||
bool AnyFiltersActive();
|
bool AnyFiltersActive();
|
||||||
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH,
|
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
|
||||||
wchar *MatchedArg=NULL,uint MatchedArgSize=0);
|
bool Flags,wchar *MatchedArg,uint MatchedArgSize);
|
||||||
void ProcessCommand();
|
void ProcessCommand();
|
||||||
void AddArcName(const wchar *Name);
|
void AddArcName(const wchar *Name);
|
||||||
bool GetArcName(wchar *Name,int MaxSize);
|
bool GetArcName(wchar *Name,int MaxSize);
|
||||||
|
|
|
@ -73,7 +73,7 @@ uint CRC32(uint StartCRC,const void *Addr,size_t Size)
|
||||||
crc_tables[5][(byte)(StartCRC >> 16)] ^
|
crc_tables[5][(byte)(StartCRC >> 16)] ^
|
||||||
crc_tables[4][(byte)(StartCRC >> 24)] ^
|
crc_tables[4][(byte)(StartCRC >> 24)] ^
|
||||||
crc_tables[3][(byte) NextData ] ^
|
crc_tables[3][(byte) NextData ] ^
|
||||||
crc_tables[2][(byte)(NextData >>8 ) ] ^
|
crc_tables[2][(byte)(NextData >> 8) ] ^
|
||||||
crc_tables[1][(byte)(NextData >> 16)] ^
|
crc_tables[1][(byte)(NextData >> 16)] ^
|
||||||
crc_tables[0][(byte)(NextData >> 24)];
|
crc_tables[0][(byte)(NextData >> 24)];
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co
|
||||||
sha1_context c;
|
sha1_context c;
|
||||||
sha1_init(&c);
|
sha1_init(&c);
|
||||||
|
|
||||||
const int HashRounds=0x40000;
|
const uint HashRounds=0x40000;
|
||||||
for (int I=0;I<HashRounds;I++)
|
for (uint I=0;I<HashRounds;I++)
|
||||||
{
|
{
|
||||||
sha1_process_rar29( &c, RawPsw, RawLength );
|
sha1_process_rar29( &c, RawPsw, RawLength );
|
||||||
byte PswNum[3];
|
byte PswNum[3];
|
||||||
|
@ -47,8 +47,8 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co
|
||||||
}
|
}
|
||||||
uint32 digest[5];
|
uint32 digest[5];
|
||||||
sha1_done( &c, digest );
|
sha1_done( &c, digest );
|
||||||
for (int I=0;I<4;I++)
|
for (uint I=0;I<4;I++)
|
||||||
for (int J=0;J<4;J++)
|
for (uint J=0;J<4;J++)
|
||||||
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
|
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
|
||||||
|
|
||||||
KDF3Cache[KDF3CachePos].Pwd=*Password;
|
KDF3Cache[KDF3CachePos].Pwd=*Password;
|
||||||
|
|
|
@ -42,6 +42,7 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||||
Data->Cmd.DllError=0;
|
Data->Cmd.DllError=0;
|
||||||
Data->OpenMode=r->OpenMode;
|
Data->OpenMode=r->OpenMode;
|
||||||
Data->Cmd.FileArgs.AddString(L"*");
|
Data->Cmd.FileArgs.AddString(L"*");
|
||||||
|
Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0;
|
||||||
|
|
||||||
char AnsiArcName[NM];
|
char AnsiArcName[NM];
|
||||||
*AnsiArcName=0;
|
*AnsiArcName=0;
|
||||||
|
@ -94,36 +95,50 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
||||||
r->Flags=0;
|
r->Flags=0;
|
||||||
|
|
||||||
if (Data->Arc.Volume)
|
if (Data->Arc.Volume)
|
||||||
r->Flags|=0x01;
|
r->Flags|=ROADF_VOLUME;
|
||||||
|
if (Data->Arc.MainComment)
|
||||||
|
r->Flags|=ROADF_COMMENT;
|
||||||
if (Data->Arc.Locked)
|
if (Data->Arc.Locked)
|
||||||
r->Flags|=0x04;
|
r->Flags|=ROADF_LOCK;
|
||||||
if (Data->Arc.Solid)
|
if (Data->Arc.Solid)
|
||||||
r->Flags|=0x08;
|
r->Flags|=ROADF_SOLID;
|
||||||
if (Data->Arc.NewNumbering)
|
if (Data->Arc.NewNumbering)
|
||||||
r->Flags|=0x10;
|
r->Flags|=ROADF_NEWNUMBERING;
|
||||||
if (Data->Arc.Signed)
|
if (Data->Arc.Signed)
|
||||||
r->Flags|=0x20;
|
r->Flags|=ROADF_SIGNED;
|
||||||
if (Data->Arc.Protected)
|
if (Data->Arc.Protected)
|
||||||
r->Flags|=0x40;
|
r->Flags|=ROADF_RECOVERY;
|
||||||
if (Data->Arc.Encrypted)
|
if (Data->Arc.Encrypted)
|
||||||
r->Flags|=0x80;
|
r->Flags|=ROADF_ENCHEADERS;
|
||||||
if (Data->Arc.FirstVolume)
|
if (Data->Arc.FirstVolume)
|
||||||
r->Flags|=0x100;
|
r->Flags|=ROADF_FIRSTVOLUME;
|
||||||
|
|
||||||
Array<wchar> CmtDataW;
|
Array<wchar> CmtDataW;
|
||||||
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
|
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
|
||||||
{
|
{
|
||||||
Array<char> CmtData(CmtDataW.Size()*4+1);
|
if (r->CmtBufW!=NULL)
|
||||||
memset(&CmtData[0],0,CmtData.Size());
|
{
|
||||||
WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1);
|
CmtDataW.Push(0);
|
||||||
size_t Size=strlen(&CmtData[0])+1;
|
size_t Size=wcslen(&CmtDataW[0])+1;
|
||||||
|
|
||||||
r->Flags|=2;
|
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||||
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||||
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW));
|
||||||
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
|
r->CmtBufW[r->CmtSize-1]=0;
|
||||||
if (Size<=r->CmtBufSize)
|
}
|
||||||
r->CmtBuf[r->CmtSize-1]=0;
|
else
|
||||||
|
if (r->CmtBuf!=NULL)
|
||||||
|
{
|
||||||
|
Array<char> CmtData(CmtDataW.Size()*4+1);
|
||||||
|
memset(&CmtData[0],0,CmtData.Size());
|
||||||
|
WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1);
|
||||||
|
size_t Size=strlen(&CmtData[0])+1;
|
||||||
|
|
||||||
|
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||||
|
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||||
|
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
|
||||||
|
r->CmtBuf[r->CmtSize-1]=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
r->CmtState=r->CmtSize=0;
|
r->CmtState=r->CmtSize=0;
|
||||||
|
@ -253,10 +268,7 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
||||||
D->UnpSize=uint(hd->UnpSize & 0xffffffff);
|
D->UnpSize=uint(hd->UnpSize & 0xffffffff);
|
||||||
D->UnpSizeHigh=uint(hd->UnpSize>>32);
|
D->UnpSizeHigh=uint(hd->UnpSize>>32);
|
||||||
D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
|
D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
|
||||||
if (Data->Arc.Format==RARFMT50)
|
D->UnpVer=Data->Arc.FileHead.UnpVer;
|
||||||
D->UnpVer=Data->Arc.FileHead.UnpVer==0 ? 50 : 200; // If it is not 0, just set it to something big.
|
|
||||||
else
|
|
||||||
D->UnpVer=Data->Arc.FileHead.UnpVer;
|
|
||||||
D->FileCRC=hd->FileHash.CRC32;
|
D->FileCRC=hd->FileHash.CRC32;
|
||||||
D->FileTime=hd->mtime.GetDos();
|
D->FileTime=hd->mtime.GetDos();
|
||||||
|
|
||||||
|
@ -372,7 +384,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
||||||
if (DestNameW!=NULL)
|
if (DestNameW!=NULL)
|
||||||
wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
|
wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
|
||||||
|
|
||||||
wcscpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T");
|
wcsncpyz(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T",ASIZE(Data->Cmd.Command));
|
||||||
Data->Cmd.Test=Operation!=RAR_EXTRACT;
|
Data->Cmd.Test=Operation!=RAR_EXTRACT;
|
||||||
bool Repeat=false;
|
bool Repeat=false;
|
||||||
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
|
Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
|
||||||
|
@ -439,16 +451,16 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef RAR_NOCRYPT
|
|
||||||
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
|
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
|
||||||
{
|
{
|
||||||
|
#ifndef RAR_NOCRYPT
|
||||||
DataSet *Data=(DataSet *)hArcData;
|
DataSet *Data=(DataSet *)hArcData;
|
||||||
wchar PasswordW[MAXPASSWORD];
|
wchar PasswordW[MAXPASSWORD];
|
||||||
GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
|
GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
|
||||||
Data->Cmd.Password.Set(PasswordW);
|
Data->Cmd.Password.Set(PasswordW);
|
||||||
cleandata(PasswordW,sizeof(PasswordW));
|
cleandata(PasswordW,sizeof(PasswordW));
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int PASCAL RARGetDllVersion()
|
int PASCAL RARGetDllVersion()
|
||||||
|
|
|
@ -5,6 +5,7 @@ EXPORTS
|
||||||
RARReadHeader
|
RARReadHeader
|
||||||
RARReadHeaderEx
|
RARReadHeaderEx
|
||||||
RARProcessFile
|
RARProcessFile
|
||||||
|
RARProcessFileW
|
||||||
RARSetCallback
|
RARSetCallback
|
||||||
RARSetChangeVolProc
|
RARSetChangeVolProc
|
||||||
RARSetProcessDataProc
|
RARSetProcessDataProc
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef _UNRAR_DLL_
|
#ifndef _UNRAR_DLL_
|
||||||
#define _UNRAR_DLL_
|
#define _UNRAR_DLL_
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
#define ERAR_SUCCESS 0
|
#define ERAR_SUCCESS 0
|
||||||
#define ERAR_END_ARCHIVE 10
|
#define ERAR_END_ARCHIVE 10
|
||||||
|
@ -135,6 +135,8 @@ typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LPARAM UserData,LPARAM P1,LPARAM
|
||||||
#define ROADF_ENCHEADERS 0x0080
|
#define ROADF_ENCHEADERS 0x0080
|
||||||
#define ROADF_FIRSTVOLUME 0x0100
|
#define ROADF_FIRSTVOLUME 0x0100
|
||||||
|
|
||||||
|
#define ROADOF_KEEPBROKEN 0x0001
|
||||||
|
|
||||||
struct RAROpenArchiveDataEx
|
struct RAROpenArchiveDataEx
|
||||||
{
|
{
|
||||||
char *ArcName;
|
char *ArcName;
|
||||||
|
@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx
|
||||||
unsigned int Flags;
|
unsigned int Flags;
|
||||||
UNRARCALLBACK Callback;
|
UNRARCALLBACK Callback;
|
||||||
LPARAM UserData;
|
LPARAM UserData;
|
||||||
unsigned int Reserved[28];
|
unsigned int OpFlags;
|
||||||
|
wchar_t *CmtBufW;
|
||||||
|
unsigned int Reserved[25];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UNRARCALLBACK_MESSAGES {
|
enum UNRARCALLBACK_MESSAGES {
|
||||||
|
@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 5, 60, 3, 2672
|
FILEVERSION 5, 91, 100, 3470
|
||||||
PRODUCTVERSION 5, 60, 3, 2672
|
PRODUCTVERSION 5, 91, 100, 3470
|
||||||
FILEOS VOS__WINDOWS32
|
FILEOS VOS__WINDOWS32
|
||||||
FILETYPE VFT_APP
|
FILETYPE VFT_APP
|
||||||
{
|
{
|
||||||
|
@ -14,9 +14,9 @@ FILETYPE VFT_APP
|
||||||
VALUE "CompanyName", "Alexander Roshal\0"
|
VALUE "CompanyName", "Alexander Roshal\0"
|
||||||
VALUE "ProductName", "RAR decompression library\0"
|
VALUE "ProductName", "RAR decompression library\0"
|
||||||
VALUE "FileDescription", "RAR decompression library\0"
|
VALUE "FileDescription", "RAR decompression library\0"
|
||||||
VALUE "FileVersion", "5.60.3\0"
|
VALUE "FileVersion", "5.91.0\0"
|
||||||
VALUE "ProductVersion", "5.60.3\0"
|
VALUE "ProductVersion", "5.91.0\0"
|
||||||
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2018\0"
|
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2020\0"
|
||||||
VALUE "OriginalFilename", "Unrar.dll\0"
|
VALUE "OriginalFilename", "Unrar.dll\0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,7 @@ void ErrorHandler::OpenErrorMsg(const wchar *FileName)
|
||||||
|
|
||||||
void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName)
|
void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||||
{
|
{
|
||||||
|
Wait(); // Keep GUI responsive if many files cannot be opened when archiving.
|
||||||
uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
|
uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
|
||||||
SysErrMsg();
|
SysErrMsg();
|
||||||
SetErrorCode(RARX_OPEN);
|
SetErrorCode(RARX_OPEN);
|
||||||
|
@ -270,6 +271,7 @@ void _stdfunction ProcessSignal(int SigType)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ErrHandler.UserBreak=true;
|
ErrHandler.UserBreak=true;
|
||||||
|
ErrHandler.SetDisableShutdown();
|
||||||
mprintf(St(MBreak));
|
mprintf(St(MBreak));
|
||||||
|
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
|
@ -293,7 +295,7 @@ void _stdfunction ProcessSignal(int SigType)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN_ALL) && !defined(_MSC_VER)
|
#if defined(_WIN_ALL) && !defined(_MSC_VER)
|
||||||
// never reached, just to avoid a compiler warning
|
// Never reached, just to avoid a compiler warning
|
||||||
return TRUE;
|
return TRUE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -327,7 +329,7 @@ void ErrorHandler::Throw(RAR_EXIT Code)
|
||||||
|
|
||||||
bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size)
|
bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size)
|
||||||
{
|
{
|
||||||
#if !defined(SFX_MODULE) && !defined(SILENT)
|
#ifndef SILENT
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
int ErrType=GetLastError();
|
int ErrType=GetLastError();
|
||||||
if (ErrType!=0)
|
if (ErrType!=0)
|
||||||
|
@ -360,7 +362,7 @@ void ErrorHandler::SysErrMsg()
|
||||||
return;
|
return;
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
wchar *CurMsg=Msg;
|
wchar *CurMsg=Msg;
|
||||||
while (CurMsg!=NULL)
|
while (CurMsg!=NULL) // Print string with \r\n as several strings to multiple lines.
|
||||||
{
|
{
|
||||||
while (*CurMsg=='\r' || *CurMsg=='\n')
|
while (*CurMsg=='\r' || *CurMsg=='\n')
|
||||||
CurMsg++;
|
CurMsg++;
|
||||||
|
|
|
@ -56,11 +56,12 @@ class ErrorHandler
|
||||||
uint GetErrorCount() {return ErrCount;}
|
uint GetErrorCount() {return ErrCount;}
|
||||||
void SetSignalHandlers(bool Enable);
|
void SetSignalHandlers(bool Enable);
|
||||||
void Throw(RAR_EXIT Code);
|
void Throw(RAR_EXIT Code);
|
||||||
void SetSilent(bool Mode) {Silent=Mode;};
|
void SetSilent(bool Mode) {Silent=Mode;}
|
||||||
bool GetSysErrMsg(wchar *Msg,size_t Size);
|
bool GetSysErrMsg(wchar *Msg,size_t Size);
|
||||||
void SysErrMsg();
|
void SysErrMsg();
|
||||||
int GetSystemErrorCode();
|
int GetSystemErrorCode();
|
||||||
void SetSystemErrorCode(int Code);
|
void SetSystemErrorCode(int Code);
|
||||||
|
void SetDisableShutdown() {DisableShutdown=true;}
|
||||||
bool IsShutdownEnabled() {return !DisableShutdown;}
|
bool IsShutdownEnabled() {return !DisableShutdown;}
|
||||||
|
|
||||||
bool UserBreak; // Ctrl+Break is pressed.
|
bool UserBreak; // Ctrl+Break is pressed.
|
||||||
|
|
|
@ -40,6 +40,8 @@ void CmdExtract::DoExtract()
|
||||||
{
|
{
|
||||||
if (Cmd->ManualPassword)
|
if (Cmd->ManualPassword)
|
||||||
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
|
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
|
||||||
|
|
||||||
|
ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit().
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
EXTRACT_ARC_CODE Code=ExtractArchive();
|
EXTRACT_ARC_CODE Code=ExtractArchive();
|
||||||
|
@ -59,7 +61,11 @@ void CmdExtract::DoExtract()
|
||||||
{
|
{
|
||||||
if (!PasswordCancelled)
|
if (!PasswordCancelled)
|
||||||
uiMsg(UIERROR_NOFILESTOEXTRACT,ArcName);
|
uiMsg(UIERROR_NOFILESTOEXTRACT,ArcName);
|
||||||
ErrHandler.SetErrorCode(RARX_NOFILES);
|
|
||||||
|
// Other error codes may explain a reason of "no files extracted" clearer,
|
||||||
|
// so set it only if no other errors found (wrong mask set by user).
|
||||||
|
if (ErrHandler.GetErrorCode()==RARX_SUCCESS)
|
||||||
|
ErrHandler.SetErrorCode(RARX_NOFILES);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (!Cmd->DisableDone)
|
if (!Cmd->DisableDone)
|
||||||
|
@ -83,13 +89,12 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc)
|
||||||
FirstFile=true;
|
FirstFile=true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PasswordAll=(Cmd->Password.IsSet());
|
GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet();
|
||||||
|
|
||||||
DataIO.UnpVolume=false;
|
DataIO.UnpVolume=false;
|
||||||
|
|
||||||
PrevProcessed=false;
|
PrevProcessed=false;
|
||||||
AllMatchesExact=true;
|
AllMatchesExact=true;
|
||||||
ReconstructDone=false;
|
|
||||||
AnySolidDataUnpackedWell=false;
|
AnySolidDataUnpackedWell=false;
|
||||||
|
|
||||||
StartTime.SetCurrentTime();
|
StartTime.SetCurrentTime();
|
||||||
|
@ -157,7 +162,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
||||||
// This size is necessary to display the correct total progress indicator.
|
// This size is necessary to display the correct total progress indicator.
|
||||||
|
|
||||||
wchar NextName[NM];
|
wchar NextName[NM];
|
||||||
wcscpy(NextName,Arc.FileName);
|
wcsncpyz(NextName,Arc.FileName,ASIZE(NextName));
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -257,15 +262,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||||
if (HeaderType==HEAD_ENDARC)
|
if (HeaderType==HEAD_ENDARC)
|
||||||
if (Arc.EndArcHead.NextVolume)
|
if (Arc.EndArcHead.NextVolume)
|
||||||
{
|
{
|
||||||
#ifndef NOVOLUME
|
#ifdef NOVOLUME
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||||
{
|
{
|
||||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
Arc.Seek(Arc.CurBlockPos,SEEK_SET);
|
Arc.Seek(Arc.CurBlockPos,SEEK_SET);
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
@ -294,7 +301,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||||
|
|
||||||
bool EqualNames=false;
|
bool EqualNames=false;
|
||||||
wchar MatchedArg[NM];
|
wchar MatchedArg[NM];
|
||||||
int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,MatchedArg,ASIZE(MatchedArg));
|
int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,0,MatchedArg,ASIZE(MatchedArg));
|
||||||
bool MatchFound=MatchNumber!=0;
|
bool MatchFound=MatchNumber!=0;
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
if (Cmd->ExclPath==EXCL_BASEPATH)
|
if (Cmd->ExclPath==EXCL_BASEPATH)
|
||||||
|
@ -319,6 +326,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||||
|
|
||||||
if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
|
if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName))
|
||||||
{
|
{
|
||||||
|
wcsncpyz(Cmd->ArcName,ArcName,ASIZE(ArcName)); // For GUI "Delete archive after extraction".
|
||||||
// If first volume name does not match the current name and if such
|
// If first volume name does not match the current name and if such
|
||||||
// volume name really exists, let's unpack from this first volume.
|
// volume name really exists, let's unpack from this first volume.
|
||||||
Repeat=true;
|
Repeat=true;
|
||||||
|
@ -340,7 +348,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wchar ArcFileName[NM];
|
wchar ArcFileName[NM];
|
||||||
ConvertPath(Arc.FileHead.FileName,ArcFileName);
|
ConvertPath(Arc.FileHead.FileName,ArcFileName,ASIZE(ArcFileName));
|
||||||
|
|
||||||
if (Arc.FileHead.Version)
|
if (Arc.FileHead.Version)
|
||||||
{
|
{
|
||||||
|
@ -468,17 +476,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||||
memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 &&
|
memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 &&
|
||||||
!Arc.BrokenHeader)
|
!Arc.BrokenHeader)
|
||||||
{
|
{
|
||||||
if (PasswordAll) // For -p<pwd> or Ctrl+P.
|
if (GlobalPassword) // For -p<pwd> or Ctrl+P to avoid the infinite loop.
|
||||||
{
|
{
|
||||||
// This message is used by Android GUI to reset cached passwords.
|
// This message is used by Android GUI to reset cached passwords.
|
||||||
// Update appropriate code if changed.
|
// Update appropriate code if changed.
|
||||||
uiMsg(UIERROR_BADPSW,ArcFileName);
|
uiMsg(UIERROR_BADPSW,Arc.FileName,ArcFileName);
|
||||||
}
|
}
|
||||||
else // For passwords entered manually.
|
else // For passwords entered manually.
|
||||||
{
|
{
|
||||||
// This message is used by Android GUI and Windows GUI and SFX to
|
// This message is used by Android GUI and Windows GUI and SFX to
|
||||||
// reset cached passwords. Update appropriate code if changed.
|
// reset cached passwords. Update appropriate code if changed.
|
||||||
uiMsg(UIWAIT_BADPSW,ArcFileName);
|
uiMsg(UIWAIT_BADPSW,Arc.FileName,ArcFileName);
|
||||||
Cmd->Password.Clean();
|
Cmd->Password.Clean();
|
||||||
|
|
||||||
// Avoid new requests for unrar.dll to prevent the infinite loop
|
// Avoid new requests for unrar.dll to prevent the infinite loop
|
||||||
|
@ -609,11 +617,14 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!TestMode && !Arc.BrokenHeader &&
|
uint64 Preallocated=0;
|
||||||
(Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize &&
|
if (!TestMode && !Arc.BrokenHeader && Arc.FileHead.UnpSize>1000000 &&
|
||||||
|
Arc.FileHead.PackSize*1024>Arc.FileHead.UnpSize &&
|
||||||
(Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
|
(Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
|
||||||
|
{
|
||||||
CurFile.Prealloc(Arc.FileHead.UnpSize);
|
CurFile.Prealloc(Arc.FileHead.UnpSize);
|
||||||
|
Preallocated=Arc.FileHead.UnpSize;
|
||||||
|
}
|
||||||
CurFile.SetAllowDelete(!Cmd->KeepBroken);
|
CurFile.SetAllowDelete(!Cmd->KeepBroken);
|
||||||
|
|
||||||
bool FileCreateMode=!TestMode && !SkipSolid && Command!='P';
|
bool FileCreateMode=!TestMode && !SkipSolid && Command!='P';
|
||||||
|
@ -725,37 +736,52 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||||
else
|
else
|
||||||
mprintf(L"\b\b\b\b\b ");
|
mprintf(L"\b\b\b\b\b ");
|
||||||
|
|
||||||
|
// If we successfully unpacked a hard link, we wish to set its file
|
||||||
|
// attributes. Hard link shares file metadata with link target,
|
||||||
|
// so we do not need to set link time or owner. But when we overwrite
|
||||||
|
// an existing link, we can call PrepareToDelete(), which affects
|
||||||
|
// link target attributes as well. So we set link attributes to restore
|
||||||
|
// both target and link attributes if PrepareToDelete() changed them.
|
||||||
|
bool SetAttrOnly=LinkEntry && Arc.FileHead.RedirType==FSREDIR_HARDLINK && LinkSuccess;
|
||||||
|
|
||||||
if (!TestMode && (Command=='X' || Command=='E') &&
|
if (!TestMode && (Command=='X' || Command=='E') &&
|
||||||
(!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) &&
|
(!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) &&
|
||||||
(!BrokenFile || Cmd->KeepBroken))
|
(!BrokenFile || Cmd->KeepBroken))
|
||||||
{
|
{
|
||||||
// We could preallocate more space that really written to broken file.
|
// Below we use DestFileName instead of CurFile.FileName,
|
||||||
if (BrokenFile)
|
// so we can set file attributes also for hard links, which do not
|
||||||
CurFile.Truncate();
|
// have the open CurFile. These strings are the same for other items.
|
||||||
|
|
||||||
#if defined(_WIN_ALL) || defined(_EMX)
|
if (!SetAttrOnly)
|
||||||
if (Cmd->ClearArc)
|
{
|
||||||
Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
|
// We could preallocate more space that really written to broken file
|
||||||
#endif
|
// or file with crafted header.
|
||||||
|
if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated))
|
||||||
|
CurFile.Truncate();
|
||||||
|
|
||||||
|
|
||||||
CurFile.SetOpenFileTime(
|
CurFile.SetOpenFileTime(
|
||||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||||
Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
|
Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
|
||||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||||
CurFile.Close();
|
CurFile.Close();
|
||||||
|
|
||||||
|
SetFileHeaderExtra(Cmd,Arc,DestFileName);
|
||||||
|
|
||||||
|
CurFile.SetCloseFileTime(
|
||||||
|
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||||
|
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
if (Cmd->SetCompressedAttr &&
|
if (Cmd->SetCompressedAttr &&
|
||||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0)
|
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0)
|
||||||
SetFileCompression(CurFile.FileName,true);
|
SetFileCompression(DestFileName,true);
|
||||||
|
if (Cmd->ClearArc)
|
||||||
|
Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
|
||||||
#endif
|
#endif
|
||||||
SetFileHeaderExtra(Cmd,Arc,CurFile.FileName);
|
if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr))
|
||||||
|
uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName);
|
||||||
CurFile.SetCloseFileTime(
|
|
||||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
|
||||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
|
||||||
if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(CurFile.FileName,Arc.FileHead.FileAttr))
|
|
||||||
uiMsg(UIERROR_FILEATTR,Arc.FileName,CurFile.FileName);
|
|
||||||
|
|
||||||
PrevProcessed=true;
|
PrevProcessed=true;
|
||||||
}
|
}
|
||||||
|
@ -846,9 +872,12 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
if (Cmd->AppendArcNameToPath)
|
if (Cmd->AppendArcNameToPath!=APPENDARCNAME_NONE)
|
||||||
{
|
{
|
||||||
wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
|
if (Cmd->AppendArcNameToPath==APPENDARCNAME_DESTPATH)
|
||||||
|
wcsncatz(DestName,PointToName(Arc.FirstVolumeName),DestSize);
|
||||||
|
else
|
||||||
|
wcsncpyz(DestName,Arc.FirstVolumeName,DestSize); // To archive own dir.
|
||||||
SetExt(DestName,NULL,DestSize);
|
SetExt(DestName,NULL,DestSize);
|
||||||
AddEndSlash(DestName,DestSize);
|
AddEndSlash(DestName,DestSize);
|
||||||
}
|
}
|
||||||
|
@ -961,14 +990,18 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
|
||||||
if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password)/* || !Cmd->Password.IsSet()*/)
|
if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password)/* || !Cmd->Password.IsSet()*/)
|
||||||
{
|
{
|
||||||
// Suppress "test is ok" message if user cancelled the password prompt.
|
// Suppress "test is ok" message if user cancelled the password prompt.
|
||||||
uiMsg(UIERROR_INCERRCOUNT);
|
// 2019.03.23: If some archives are tested ok and prompt is cancelled for others,
|
||||||
|
// do we really need to suppress "test is ok"? Also if we set an empty password
|
||||||
|
// and "Use for all archives" in WinRAR Ctrl+P and skip some encrypted archives.
|
||||||
|
// We commented out this UIERROR_INCERRCOUNT for now.
|
||||||
|
// uiMsg(UIERROR_INCERRCOUNT);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Cmd->ManualPassword=true;
|
Cmd->ManualPassword=true;
|
||||||
}
|
}
|
||||||
#if !defined(SILENT)
|
#if !defined(SILENT)
|
||||||
else
|
else
|
||||||
if (!PasswordAll && !Arc.FileHead.Solid)
|
if (!GlobalPassword && !Arc.FileHead.Solid)
|
||||||
{
|
{
|
||||||
eprintf(St(MUseCurPsw),ArcFileName);
|
eprintf(St(MUseCurPsw),ArcFileName);
|
||||||
switch(Cmd->AllYes ? 1 : Ask(St(MYesNoAll)))
|
switch(Cmd->AllYes ? 1 : Ask(St(MYesNoAll)))
|
||||||
|
@ -980,7 +1013,7 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
PasswordAll=true;
|
GlobalPassword=true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1077,7 +1110,7 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName)
|
||||||
{
|
{
|
||||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
if (Cmd->SetCompressedAttr &&
|
if (Cmd->SetCompressedAttr &&
|
||||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
|
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()!=WNT_NONE)
|
||||||
SetFileCompression(DestFileName,true);
|
SetFileCompression(DestFileName,true);
|
||||||
#endif
|
#endif
|
||||||
SetFileHeaderExtra(Cmd,Arc,DestFileName);
|
SetFileHeaderExtra(Cmd,Arc,DestFileName);
|
||||||
|
|
|
@ -43,7 +43,7 @@ class CmdExtract
|
||||||
|
|
||||||
wchar ArcName[NM];
|
wchar ArcName[NM];
|
||||||
|
|
||||||
bool PasswordAll;
|
bool GlobalPassword;
|
||||||
bool PrevProcessed; // If previous file was successfully extracted or tested.
|
bool PrevProcessed; // If previous file was successfully extracted or tested.
|
||||||
wchar DestFileName[NM];
|
wchar DestFileName[NM];
|
||||||
bool PasswordCancelled;
|
bool PasswordCancelled;
|
||||||
|
|
|
@ -13,6 +13,7 @@ File::File()
|
||||||
OpenShared=false;
|
OpenShared=false;
|
||||||
AllowDelete=true;
|
AllowDelete=true;
|
||||||
AllowExceptions=true;
|
AllowExceptions=true;
|
||||||
|
PreserveAtime=false;
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
NoSequentialRead=false;
|
NoSequentialRead=false;
|
||||||
CreateMode=FMF_UNDEFINED;
|
CreateMode=FMF_UNDEFINED;
|
||||||
|
@ -56,6 +57,9 @@ bool File::Open(const wchar *Name,uint Mode)
|
||||||
if (OpenShared)
|
if (OpenShared)
|
||||||
ShareMode|=FILE_SHARE_WRITE;
|
ShareMode|=FILE_SHARE_WRITE;
|
||||||
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
|
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
|
||||||
|
FindData FD;
|
||||||
|
if (PreserveAtime)
|
||||||
|
Access|=FILE_WRITE_ATTRIBUTES; // Needed to preserve atime.
|
||||||
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
|
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
|
||||||
|
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
|
@ -86,6 +90,11 @@ bool File::Open(const wchar *Name,uint Mode)
|
||||||
}
|
}
|
||||||
if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
|
if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
|
||||||
ErrorType=FILE_NOTFOUND;
|
ErrorType=FILE_NOTFOUND;
|
||||||
|
if (PreserveAtime && hNewFile!=FILE_BAD_HANDLE)
|
||||||
|
{
|
||||||
|
FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification.
|
||||||
|
SetFileTime(hNewFile,NULL,&ft,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
|
int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
|
||||||
|
@ -94,6 +103,11 @@ bool File::Open(const wchar *Name,uint Mode)
|
||||||
#if defined(_AIX) && defined(_LARGE_FILE_API)
|
#if defined(_AIX) && defined(_LARGE_FILE_API)
|
||||||
flags|=O_LARGEFILE;
|
flags|=O_LARGEFILE;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
// NDK r20 has O_NOATIME, but fails to create files with it in Android 7+.
|
||||||
|
#if defined(O_NOATIME)
|
||||||
|
if (PreserveAtime)
|
||||||
|
flags|=O_NOATIME;
|
||||||
#endif
|
#endif
|
||||||
char NameA[NM];
|
char NameA[NM];
|
||||||
WideToChar(Name,NameA,ASIZE(NameA));
|
WideToChar(Name,NameA,ASIZE(NameA));
|
||||||
|
@ -230,7 +244,7 @@ bool File::Close()
|
||||||
{
|
{
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
// We use the standard system handle for stdout in Windows
|
// We use the standard system handle for stdout in Windows
|
||||||
// and it must not be closed here.
|
// and it must not be closed here.
|
||||||
if (HandleType==FILE_HANDLENORMAL)
|
if (HandleType==FILE_HANDLENORMAL)
|
||||||
Success=CloseHandle(hFile)==TRUE;
|
Success=CloseHandle(hFile)==TRUE;
|
||||||
#else
|
#else
|
||||||
|
@ -271,7 +285,7 @@ bool File::Rename(const wchar *NewName)
|
||||||
Success=RenameFile(FileName,NewName);
|
Success=RenameFile(FileName,NewName);
|
||||||
|
|
||||||
if (Success)
|
if (Success)
|
||||||
wcscpy(FileName,NewName);
|
wcsncpyz(FileName,NewName,ASIZE(FileName));
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
@ -387,7 +401,7 @@ int File::Read(void *Data,size_t Size)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ReadSize;
|
return ReadSize; // It can return -1 only if AllowExceptions is disabled.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -670,9 +684,11 @@ void File::GetOpenFileTime(RarTime *ft)
|
||||||
|
|
||||||
int64 File::FileLength()
|
int64 File::FileLength()
|
||||||
{
|
{
|
||||||
SaveFilePos SavePos(*this);
|
int64 SavePos=Tell();
|
||||||
Seek(0,SEEK_END);
|
Seek(0,SEEK_END);
|
||||||
return Tell();
|
int64 Length=Tell();
|
||||||
|
Seek(SavePos,SEEK_SET);
|
||||||
|
return Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ class File
|
||||||
bool NoSequentialRead;
|
bool NoSequentialRead;
|
||||||
uint CreateMode;
|
uint CreateMode;
|
||||||
#endif
|
#endif
|
||||||
|
bool PreserveAtime;
|
||||||
protected:
|
protected:
|
||||||
bool OpenShared; // Set by 'Archive' class.
|
bool OpenShared; // Set by 'Archive' class.
|
||||||
public:
|
public:
|
||||||
|
@ -99,7 +100,7 @@ class File
|
||||||
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
|
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
|
||||||
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
|
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
|
||||||
void GetOpenFileTime(RarTime *ft);
|
void GetOpenFileTime(RarTime *ft);
|
||||||
virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;}; // 'virtual' for MultiFile class.
|
virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;} // 'virtual' for MultiFile class.
|
||||||
int64 FileLength();
|
int64 FileLength();
|
||||||
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
|
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
|
||||||
FILE_HANDLETYPE GetHandleType() {return HandleType;}
|
FILE_HANDLETYPE GetHandleType() {return HandleType;}
|
||||||
|
@ -114,6 +115,7 @@ class File
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
void RemoveSequentialFlag() {NoSequentialRead=true;}
|
void RemoveSequentialFlag() {NoSequentialRead=true;}
|
||||||
#endif
|
#endif
|
||||||
|
void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;}
|
||||||
#ifdef _UNIX
|
#ifdef _UNIX
|
||||||
int GetFD()
|
int GetFD()
|
||||||
{
|
{
|
||||||
|
|
|
@ -348,7 +348,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize)
|
||||||
swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
|
swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
|
||||||
if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
|
if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
|
||||||
return NULL;
|
return NULL;
|
||||||
wcscpy(Name+Length,RndText);
|
wcsncpyz(Name+Length,RndText,MaxSize-Length);
|
||||||
if (!FileExist(Name))
|
if (!FileExist(Name))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +360,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize)
|
||||||
#if !defined(SFX_MODULE)
|
#if !defined(SFX_MODULE)
|
||||||
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
|
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
|
||||||
{
|
{
|
||||||
SaveFilePos SavePos(*SrcFile);
|
int64 SavePos=SrcFile->Tell();
|
||||||
#ifndef SILENT
|
#ifndef SILENT
|
||||||
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
|
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
|
||||||
#endif
|
#endif
|
||||||
|
@ -415,6 +415,8 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,
|
||||||
if (Size!=INT64NDF)
|
if (Size!=INT64NDF)
|
||||||
Size-=ReadSize;
|
Size-=ReadSize;
|
||||||
}
|
}
|
||||||
|
SrcFile->Seek(SavePos,SEEK_SET);
|
||||||
|
|
||||||
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
||||||
uiMsg(UIEVENT_FILESUMEND);
|
uiMsg(UIEVENT_FILESUMEND);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ FindFile::~FindFile()
|
||||||
|
|
||||||
void FindFile::SetMask(const wchar *Mask)
|
void FindFile::SetMask(const wchar *Mask)
|
||||||
{
|
{
|
||||||
wcscpy(FindMask,Mask);
|
wcsncpyz(FindMask,Mask,ASIZE(FindMask));
|
||||||
FirstCall=true;
|
FirstCall=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ bool FindFile::Next(FindData *fd,bool GetSymLink)
|
||||||
wcsncpyz(DirName,FindMask,ASIZE(DirName));
|
wcsncpyz(DirName,FindMask,ASIZE(DirName));
|
||||||
RemoveNameFromPath(DirName);
|
RemoveNameFromPath(DirName);
|
||||||
if (*DirName==0)
|
if (*DirName==0)
|
||||||
wcscpy(DirName,L".");
|
wcsncpyz(DirName,L".",ASIZE(DirName));
|
||||||
char DirNameA[NM];
|
char DirNameA[NM];
|
||||||
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
|
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
|
||||||
if ((dirp=opendir(DirNameA))==NULL)
|
if ((dirp=opendir(DirNameA))==NULL)
|
||||||
|
@ -63,32 +63,32 @@ bool FindFile::Next(FindData *fd,bool GetSymLink)
|
||||||
}
|
}
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
wchar Name[NM];
|
||||||
struct dirent *ent=readdir(dirp);
|
struct dirent *ent=readdir(dirp);
|
||||||
if (ent==NULL)
|
if (ent==NULL)
|
||||||
return false;
|
return false;
|
||||||
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
|
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
|
||||||
continue;
|
continue;
|
||||||
wchar Name[NM];
|
|
||||||
if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
|
if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
|
||||||
uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
|
uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
|
||||||
|
|
||||||
if (CmpName(FindMask,Name,MATCH_NAMES))
|
if (CmpName(FindMask,Name,MATCH_NAMES))
|
||||||
{
|
{
|
||||||
wchar FullName[NM];
|
wchar FullName[NM];
|
||||||
wcscpy(FullName,FindMask);
|
wcsncpyz(FullName,FindMask,ASIZE(FullName));
|
||||||
*PointToName(FullName)=0;
|
*PointToName(FullName)=0;
|
||||||
if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
|
if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
|
||||||
{
|
{
|
||||||
uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
|
uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
wcscat(FullName,Name);
|
wcsncatz(FullName,Name,ASIZE(FullName));
|
||||||
if (!FastFind(FullName,fd,GetSymLink))
|
if (!FastFind(FullName,fd,GetSymLink))
|
||||||
{
|
{
|
||||||
ErrHandler.OpenErrorMsg(FullName);
|
ErrHandler.OpenErrorMsg(FullName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
wcscpy(fd->Name,FullName);
|
wcsncpyz(fd->Name,FullName,ASIZE(fd->Name));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,12 @@ bool ExtractHardlink(wchar *NameNew,wchar *NameExisting,size_t NameExistingSize)
|
||||||
SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
|
SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
|
||||||
|
|
||||||
if (!FileExist(NameExisting))
|
if (!FileExist(NameExisting))
|
||||||
|
{
|
||||||
|
uiMsg(UIERROR_HLINKCREATE,NameNew);
|
||||||
|
uiMsg(UIERROR_NOLINKTARGET);
|
||||||
|
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
CreatePath(NameNew,true);
|
CreatePath(NameNew,true);
|
||||||
|
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
|
|
|
@ -53,7 +53,7 @@ DataHash::DataHash()
|
||||||
DataHash::~DataHash()
|
DataHash::~DataHash()
|
||||||
{
|
{
|
||||||
#ifdef RAR_SMP
|
#ifdef RAR_SMP
|
||||||
DestroyThreadPool(ThPool);
|
delete ThPool;
|
||||||
#endif
|
#endif
|
||||||
cleandata(&CurCRC32, sizeof(CurCRC32));
|
cleandata(&CurCRC32, sizeof(CurCRC32));
|
||||||
if (blake2ctx!=NULL)
|
if (blake2ctx!=NULL)
|
||||||
|
@ -94,7 +94,7 @@ void DataHash::Update(const void *Data,size_t DataSize)
|
||||||
{
|
{
|
||||||
#ifdef RAR_SMP
|
#ifdef RAR_SMP
|
||||||
if (MaxThreads>1 && ThPool==NULL)
|
if (MaxThreads>1 && ThPool==NULL)
|
||||||
ThPool=CreateThreadPool();
|
ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER);
|
||||||
blake2ctx->ThPool=ThPool;
|
blake2ctx->ThPool=ThPool;
|
||||||
blake2ctx->MaxThreads=MaxThreads;
|
blake2ctx->MaxThreads=MaxThreads;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,10 +14,11 @@
|
||||||
#define SIZEOF_UOHEAD 18
|
#define SIZEOF_UOHEAD 18
|
||||||
#define SIZEOF_STREAMHEAD 26
|
#define SIZEOF_STREAMHEAD 26
|
||||||
|
|
||||||
#define VER_PACK 29
|
#define VER_PACK 29U
|
||||||
#define VER_PACK5 50 // It is stored as 0, but we subtract 50 when saving an archive.
|
#define VER_PACK5 50U // It is stored as 0, but we subtract 50 when saving an archive.
|
||||||
#define VER_UNPACK 29
|
#define VER_UNPACK 29U
|
||||||
#define VER_UNPACK5 50 // It is stored as 0, but we add 50 when reading an archive.
|
#define VER_UNPACK5 50U // It is stored as 0, but we add 50 when reading an archive.
|
||||||
|
#define VER_UNKNOWN 9999U // Just some large value.
|
||||||
|
|
||||||
#define MHD_VOLUME 0x0001U
|
#define MHD_VOLUME 0x0001U
|
||||||
|
|
||||||
|
@ -174,7 +175,7 @@ struct MainHeader:BaseBlock
|
||||||
struct FileHeader:BlockHeader
|
struct FileHeader:BlockHeader
|
||||||
{
|
{
|
||||||
byte HostOS;
|
byte HostOS;
|
||||||
byte UnpVer;
|
uint UnpVer; // It is 1 byte in RAR29 and bit field in RAR5.
|
||||||
byte Method;
|
byte Method;
|
||||||
union {
|
union {
|
||||||
uint FileAttr;
|
uint FileAttr;
|
||||||
|
@ -190,7 +191,7 @@ struct FileHeader:BlockHeader
|
||||||
|
|
||||||
int64 PackSize;
|
int64 PackSize;
|
||||||
int64 UnpSize;
|
int64 UnpSize;
|
||||||
int64 MaxSize; // Reserve size bytes for vint of this size.
|
int64 MaxSize; // Reserve packed and unpacked size bytes for vint of this size.
|
||||||
|
|
||||||
HashValue FileHash;
|
HashValue FileHash;
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ void ListArchive(CommandData *Cmd)
|
||||||
*VolNumText=0;
|
*VolNumText=0;
|
||||||
while(Arc.ReadHeader()>0)
|
while(Arc.ReadHeader()>0)
|
||||||
{
|
{
|
||||||
|
Wait(); // Allow quit listing with Ctrl+C.
|
||||||
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||||
if (HeaderType==HEAD_ENDARC)
|
if (HeaderType==HEAD_ENDARC)
|
||||||
{
|
{
|
||||||
|
@ -91,7 +92,7 @@ void ListArchive(CommandData *Cmd)
|
||||||
switch(HeaderType)
|
switch(HeaderType)
|
||||||
{
|
{
|
||||||
case HEAD_FILE:
|
case HEAD_FILE:
|
||||||
FileMatched=Cmd->IsProcessFile(Arc.FileHead)!=0;
|
FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0;
|
||||||
if (FileMatched)
|
if (FileMatched)
|
||||||
{
|
{
|
||||||
ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare);
|
ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare);
|
||||||
|
@ -215,7 +216,7 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||||
|
|
||||||
wchar UnpSizeText[30],PackSizeText[30];
|
wchar UnpSizeText[30],PackSizeText[30];
|
||||||
if (hd.UnpSize==INT64NDF)
|
if (hd.UnpSize==INT64NDF)
|
||||||
wcscpy(UnpSizeText,L"?");
|
wcsncpyz(UnpSizeText,L"?",ASIZE(UnpSizeText));
|
||||||
else
|
else
|
||||||
itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||||
itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText));
|
itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText));
|
||||||
|
@ -229,13 +230,13 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||||
wchar RatioStr[10];
|
wchar RatioStr[10];
|
||||||
|
|
||||||
if (hd.SplitBefore && hd.SplitAfter)
|
if (hd.SplitBefore && hd.SplitAfter)
|
||||||
wcscpy(RatioStr,L"<->");
|
wcsncpyz(RatioStr,L"<->",ASIZE(RatioStr));
|
||||||
else
|
else
|
||||||
if (hd.SplitBefore)
|
if (hd.SplitBefore)
|
||||||
wcscpy(RatioStr,L"<--");
|
wcsncpyz(RatioStr,L"<--",ASIZE(RatioStr));
|
||||||
else
|
else
|
||||||
if (hd.SplitAfter)
|
if (hd.SplitAfter)
|
||||||
wcscpy(RatioStr,L"-->");
|
wcsncpyz(RatioStr,L"-->",ASIZE(RatioStr));
|
||||||
else
|
else
|
||||||
swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));
|
swprintf(RatioStr,ASIZE(RatioStr),L"%d%%",ToPercentUnlim(hd.PackSize,hd.UnpSize));
|
||||||
|
|
||||||
|
@ -344,7 +345,8 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||||
mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS);
|
mprintf(L"\n%12ls: %ls",St(MListHostOS),HostOS);
|
||||||
|
|
||||||
mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo),
|
mprintf(L"\n%12ls: RAR %ls(v%d) -m%d -md=%d%s",St(MListCompInfo),
|
||||||
Format==RARFMT15 ? L"3.0":L"5.0",hd.UnpVer,hd.Method,
|
Format==RARFMT15 ? L"1.5":L"5.0",
|
||||||
|
hd.UnpVer==VER_UNKNOWN ? 0 : hd.UnpVer,hd.Method,
|
||||||
hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400,
|
hd.WinSize>=0x100000 ? hd.WinSize/0x100000:hd.WinSize/0x400,
|
||||||
hd.WinSize>=0x100000 ? L"M":L"K");
|
hd.WinSize>=0x100000 ? L"M":L"K");
|
||||||
|
|
||||||
|
@ -466,7 +468,7 @@ void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSiz
|
||||||
(A & 0x0001) ? ((A & 0x200)!=0 ? 't' : 'x') : '-');
|
(A & 0x0001) ? ((A & 0x200)!=0 ? 't' : 'x') : '-');
|
||||||
break;
|
break;
|
||||||
case HSYS_UNKNOWN:
|
case HSYS_UNKNOWN:
|
||||||
wcscpy(AttrStr,L"?");
|
wcsncpyz(AttrStr,L"?",AttrSize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
#define MCHelpSwILOG L"\n ilog[name] Log errors to file"
|
#define MCHelpSwILOG L"\n ilog[name] Log errors to file"
|
||||||
#define MCHelpSwINUL L"\n inul Disable all messages"
|
#define MCHelpSwINUL L"\n inul Disable all messages"
|
||||||
#define MCHelpSwIOFF L"\n ioff[n] Turn PC off after completing an operation"
|
#define MCHelpSwIOFF L"\n ioff[n] Turn PC off after completing an operation"
|
||||||
#define MCHelpSwISND L"\n isnd Enable sound"
|
#define MCHelpSwISND L"\n isnd[-] Control notification sounds"
|
||||||
#define MCHelpSwIVER L"\n iver Display the version number"
|
#define MCHelpSwIVER L"\n iver Display the version number"
|
||||||
#define MCHelpSwK L"\n k Lock archive"
|
#define MCHelpSwK L"\n k Lock archive"
|
||||||
#define MCHelpSwKB L"\n kb Keep broken extracted files"
|
#define MCHelpSwKB L"\n kb Keep broken extracted files"
|
||||||
|
@ -127,11 +127,11 @@
|
||||||
#define MCHelpSwT L"\n t Test files after archiving"
|
#define MCHelpSwT L"\n t Test files after archiving"
|
||||||
#define MCHelpSwTK L"\n tk Keep original archive time"
|
#define MCHelpSwTK L"\n tk Keep original archive time"
|
||||||
#define MCHelpSwTL L"\n tl Set archive time to latest file"
|
#define MCHelpSwTL L"\n tl Set archive time to latest file"
|
||||||
#define MCHelpSwTN L"\n tn<time> Process files newer than <time>"
|
#define MCHelpSwTN L"\n tn[mcao]<t> Process files newer than <t> time"
|
||||||
#define MCHelpSwTO L"\n to<time> Process files older than <time>"
|
#define MCHelpSwTO L"\n to[mcao]<t> Process files older than <t> time"
|
||||||
#define MCHelpSwTA L"\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format"
|
#define MCHelpSwTA L"\n ta[mcao]<d> Process files modified after <d> YYYYMMDDHHMMSS date"
|
||||||
#define MCHelpSwTB L"\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format"
|
#define MCHelpSwTB L"\n tb[mcao]<d> Process files modified before <d> YYYYMMDDHHMMSS date"
|
||||||
#define MCHelpSwTS L"\n ts[m|c|a] Save or restore file time (modification, creation, access)"
|
#define MCHelpSwTS L"\n ts[m,c,a,p] Save or restore time (modification, creation, access, preserve)"
|
||||||
#define MCHelpSwU L"\n u Update files"
|
#define MCHelpSwU L"\n u Update files"
|
||||||
#define MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes"
|
#define MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes"
|
||||||
#define MCHelpSwVUnr L"\n v List all volumes"
|
#define MCHelpSwVUnr L"\n v List all volumes"
|
||||||
|
@ -203,7 +203,6 @@
|
||||||
#define MErrOpenFile L"file"
|
#define MErrOpenFile L"file"
|
||||||
#define MAddNoFiles L"\nWARNING: No files"
|
#define MAddNoFiles L"\nWARNING: No files"
|
||||||
#define MMdfEncrSol L"\n%s: encrypted"
|
#define MMdfEncrSol L"\n%s: encrypted"
|
||||||
#define MCannotMdfEncrSol L"\nCannot modify solid archive containing encrypted files"
|
|
||||||
#define MAddAnalyze L"\nAnalyzing archived files: "
|
#define MAddAnalyze L"\nAnalyzing archived files: "
|
||||||
#define MRepacking L"\nRepacking archived files: "
|
#define MRepacking L"\nRepacking archived files: "
|
||||||
#define MCRCFailed L"\n%-20s - checksum error"
|
#define MCRCFailed L"\n%-20s - checksum error"
|
||||||
|
@ -342,7 +341,7 @@
|
||||||
#define MFAT32Size L"\nWARNING: FAT32 file system does not support 4 GB or larger files"
|
#define MFAT32Size L"\nWARNING: FAT32 file system does not support 4 GB or larger files"
|
||||||
#define MErrChangeAttr L"\nWARNING: Cannot change attributes of %s"
|
#define MErrChangeAttr L"\nWARNING: Cannot change attributes of %s"
|
||||||
#define MWrongSFXVer L"\nERROR: default SFX module does not support RAR %d.%d archives"
|
#define MWrongSFXVer L"\nERROR: default SFX module does not support RAR %d.%d archives"
|
||||||
#define MCannotEncName L"\nCannot encrypt archive already containing encrypted files"
|
#define MHeadEncMismatch L"\nCannot change the header encryption mode in already encrypted archive"
|
||||||
#define MCannotEmail L"\nCannot email the file %s"
|
#define MCannotEmail L"\nCannot email the file %s"
|
||||||
#define MCopyrightS L"\nRAR SFX archive"
|
#define MCopyrightS L"\nRAR SFX archive"
|
||||||
#define MSHelpCmd L"\n\n<Commands>"
|
#define MSHelpCmd L"\n\n<Commands>"
|
||||||
|
@ -354,12 +353,13 @@
|
||||||
#define MCannotDelete L"\nCannot delete %s"
|
#define MCannotDelete L"\nCannot delete %s"
|
||||||
#define MRecycleFailed L"\nCannot move some files and folders to Recycle Bin"
|
#define MRecycleFailed L"\nCannot move some files and folders to Recycle Bin"
|
||||||
#define MCalcCRC L"\nCalculating the checksum"
|
#define MCalcCRC L"\nCalculating the checksum"
|
||||||
#define MTooLargeSFXArc L"\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB."
|
#define MTooLargeSFXArc L"\nToo large SFX archive. Windows cannot run the executable file exceeding 4 GB."
|
||||||
#define MCalcCRCAllVol L"\nCalculating checksums of all volumes."
|
#define MCalcCRCAllVol L"\nCalculating checksums of all volumes."
|
||||||
#define MNotEnoughDisk L"\nERROR: Not enough disk space for %s."
|
#define MNotEnoughDisk L"\nERROR: Not enough disk space for %s."
|
||||||
#define MNewerRAR L"\nYou may need a newer version of RAR."
|
#define MNewerRAR L"\nYou may need a newer version of RAR."
|
||||||
#define MUnkEncMethod L"\nUnknown encryption method in %s"
|
#define MUnkEncMethod L"\nUnknown encryption method in %s"
|
||||||
#define MWrongPassword L"\nThe specified password is incorrect."
|
#define MWrongPassword L"\nThe specified password is incorrect."
|
||||||
|
#define MWrongFilePassword L"\nIncorrect password for %s"
|
||||||
#define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x"
|
#define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x"
|
||||||
#define MBlocksRecovered L"\n%u blocks are recovered, %u blocks are relocated"
|
#define MBlocksRecovered L"\n%u blocks are recovered, %u blocks are relocated"
|
||||||
#define MRRDamaged L"\nRecovery record is corrupt."
|
#define MRRDamaged L"\nRecovery record is corrupt."
|
||||||
|
@ -375,6 +375,8 @@
|
||||||
#define MCopyingData L"\nCopying data"
|
#define MCopyingData L"\nCopying data"
|
||||||
#define MErrCreateLnkS L"\nCannot create symbolic link %s"
|
#define MErrCreateLnkS L"\nCannot create symbolic link %s"
|
||||||
#define MErrCreateLnkH L"\nCannot create hard link %s"
|
#define MErrCreateLnkH L"\nCannot create hard link %s"
|
||||||
|
#define MErrLnkTarget L"\nYou need to unpack the link target first"
|
||||||
#define MNeedAdmin L"\nYou may need to run RAR as administrator"
|
#define MNeedAdmin L"\nYou may need to run RAR as administrator"
|
||||||
#define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB."
|
#define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB."
|
||||||
#define MUseSmalllerDict L"\nPlease use a smaller compression dictionary."
|
#define MUseSmalllerDict L"\nPlease use a smaller compression dictionary."
|
||||||
|
#define MOpenErrAtime L"\nYou may need to remove -tsp switch to open this file."
|
||||||
|
|
|
@ -138,7 +138,9 @@ install: install-unrar
|
||||||
uninstall: uninstall-unrar
|
uninstall: uninstall-unrar
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f *.o *.bak *~
|
@rm -f *.bak *~
|
||||||
|
@rm -f $(OBJECTS) $(UNRAR_OBJ) $(LIB_OBJ)
|
||||||
|
@rm -f unrar libunrar.*
|
||||||
|
|
||||||
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
|
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
|
||||||
@rm -f unrar
|
@rm -f unrar
|
||||||
|
@ -154,8 +156,7 @@ sfx: clean $(OBJECTS)
|
||||||
lib: WHAT=RARDLL
|
lib: WHAT=RARDLL
|
||||||
lib: CXXFLAGS+=$(LIBFLAGS)
|
lib: CXXFLAGS+=$(LIBFLAGS)
|
||||||
lib: clean $(OBJECTS) $(LIB_OBJ)
|
lib: clean $(OBJECTS) $(LIB_OBJ)
|
||||||
@rm -f libunrar.so
|
@rm -f libunrar.*
|
||||||
@rm -f libunrar.a
|
|
||||||
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
|
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
|
||||||
$(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ)
|
$(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ)
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||||
if (CmpMode!=MATCH_NAMES)
|
if (CmpMode!=MATCH_NAMES)
|
||||||
{
|
{
|
||||||
size_t WildLength=wcslen(Wildcard);
|
size_t WildLength=wcslen(Wildcard);
|
||||||
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH &&
|
if (CmpMode!=MATCH_EXACT && CmpMode!=MATCH_EXACTPATH && CmpMode!=MATCH_ALLWILD &&
|
||||||
mwcsnicompc(Wildcard,Name,WildLength,ForceCase)==0)
|
mwcsnicompc(Wildcard,Name,WildLength,ForceCase)==0)
|
||||||
{
|
{
|
||||||
// For all modes except MATCH_NAMES, MATCH_EXACT and MATCH_EXACTPATH
|
// For all modes except MATCH_NAMES, MATCH_EXACT, MATCH_EXACTPATH, MATCH_ALLWILD,
|
||||||
// "path1" mask must match "path1\path2\filename.ext" and "path1" names.
|
// "path1" mask must match "path1\path2\filename.ext" and "path1" names.
|
||||||
wchar NextCh=Name[WildLength];
|
wchar NextCh=Name[WildLength];
|
||||||
if (NextCh==L'\\' || NextCh==L'/' || NextCh==0)
|
if (NextCh==L'\\' || NextCh==L'/' || NextCh==0)
|
||||||
|
@ -46,6 +46,8 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||||
if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) &&
|
if ((CmpMode==MATCH_EXACT || CmpMode==MATCH_EXACTPATH) &&
|
||||||
mwcsicompc(Path1,Path2,ForceCase)!=0)
|
mwcsicompc(Path1,Path2,ForceCase)!=0)
|
||||||
return(false);
|
return(false);
|
||||||
|
if (CmpMode==MATCH_ALLWILD)
|
||||||
|
return match(Wildcard,Name,ForceCase);
|
||||||
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
|
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
|
||||||
if (IsWildcard(Path1))
|
if (IsWildcard(Path1))
|
||||||
return(match(Wildcard,Name,ForceCase));
|
return(match(Wildcard,Name,ForceCase));
|
||||||
|
@ -64,8 +66,8 @@ bool CmpName(const wchar *Wildcard,const wchar *Name,int CmpMode)
|
||||||
|
|
||||||
// Always return false for RAR temporary files to exclude them
|
// Always return false for RAR temporary files to exclude them
|
||||||
// from archiving operations.
|
// from archiving operations.
|
||||||
if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
|
// if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
|
||||||
return(false);
|
// return(false);
|
||||||
|
|
||||||
if (CmpMode==MATCH_EXACT)
|
if (CmpMode==MATCH_EXACT)
|
||||||
return(mwcsicompc(Name1,Name2,ForceCase)==0);
|
return(mwcsicompc(Name1,Name2,ForceCase)==0);
|
||||||
|
|
|
@ -14,6 +14,10 @@ enum {
|
||||||
MATCH_EXACT, // Paths must match exactly.
|
MATCH_EXACT, // Paths must match exactly.
|
||||||
// Names must match exactly.
|
// Names must match exactly.
|
||||||
|
|
||||||
|
MATCH_ALLWILD, // Paths and names are compared using wildcards.
|
||||||
|
// Unlike MATCH_SUBPATH, paths do not match subdirs
|
||||||
|
// unless a wildcard tells so.
|
||||||
|
|
||||||
MATCH_EXACTPATH, // Paths must match exactly.
|
MATCH_EXACTPATH, // Paths must match exactly.
|
||||||
// Names are compared using wildcards.
|
// Names are compared using wildcards.
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ void RAROptions::Init()
|
||||||
Method=3;
|
Method=3;
|
||||||
MsgStream=MSG_STDOUT;
|
MsgStream=MSG_STDOUT;
|
||||||
ConvertNames=NAMES_ORIGINALCASE;
|
ConvertNames=NAMES_ORIGINALCASE;
|
||||||
xmtime=EXTTIME_HIGH3;
|
xmtime=EXTTIME_MAX;
|
||||||
FileSizeLess=INT64NDF;
|
FileSizeLess=INT64NDF;
|
||||||
FileSizeMore=INT64NDF;
|
FileSizeMore=INT64NDF;
|
||||||
HashType=HASH_CRC32;
|
HashType=HASH_CRC32;
|
||||||
|
|
|
@ -12,11 +12,7 @@ enum PATH_EXCL_MODE {
|
||||||
EXCL_SKIPWHOLEPATH, // -ep (exclude the path completely)
|
EXCL_SKIPWHOLEPATH, // -ep (exclude the path completely)
|
||||||
EXCL_BASEPATH, // -ep1 (exclude the base part of path)
|
EXCL_BASEPATH, // -ep1 (exclude the base part of path)
|
||||||
EXCL_SAVEFULLPATH, // -ep2 (the full path without the disk letter)
|
EXCL_SAVEFULLPATH, // -ep2 (the full path without the disk letter)
|
||||||
EXCL_ABSPATH, // -ep3 (the full path with the disk letter)
|
EXCL_ABSPATH // -ep3 (the full path with the disk letter)
|
||||||
|
|
||||||
EXCL_SKIPABSPATH // Works as EXCL_BASEPATH for fully qualified paths
|
|
||||||
// and as EXCL_UNCHANGED for relative paths.
|
|
||||||
// Used by WinRAR GUI only.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
|
enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
|
||||||
|
@ -25,7 +21,7 @@ enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4,
|
||||||
enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST};
|
enum {ARCTIME_NONE=0,ARCTIME_KEEP,ARCTIME_LATEST};
|
||||||
|
|
||||||
enum EXTTIME_MODE {
|
enum EXTTIME_MODE {
|
||||||
EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_HIGH1,EXTTIME_HIGH2,EXTTIME_HIGH3
|
EXTTIME_NONE=0,EXTTIME_1S,EXTTIME_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE};
|
enum {NAMES_ORIGINALCASE=0,NAMES_UPPERCASE,NAMES_LOWERCASE};
|
||||||
|
@ -63,11 +59,20 @@ enum SAVECOPY_MODE {
|
||||||
SAVECOPY_DUPLISTEXIT
|
SAVECOPY_DUPLISTEXIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum APPENDARCNAME_MODE
|
||||||
|
{
|
||||||
|
APPENDARCNAME_NONE=0,APPENDARCNAME_DESTPATH,APPENDARCNAME_OWNDIR
|
||||||
|
};
|
||||||
|
|
||||||
enum POWER_MODE {
|
enum POWER_MODE {
|
||||||
POWERMODE_KEEP=0,POWERMODE_OFF,POWERMODE_HIBERNATE,POWERMODE_SLEEP,
|
POWERMODE_KEEP=0,POWERMODE_OFF,POWERMODE_HIBERNATE,POWERMODE_SLEEP,
|
||||||
POWERMODE_RESTART
|
POWERMODE_RESTART
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Need "forced off" state to turn off sound in GUI command line.
|
||||||
|
enum SOUND_NOTIFY_MODE {SOUND_NOTIFY_DEFAULT=0,SOUND_NOTIFY_ON,SOUND_NOTIFY_OFF};
|
||||||
|
|
||||||
struct FilterMode
|
struct FilterMode
|
||||||
{
|
{
|
||||||
FilterState State;
|
FilterState State;
|
||||||
|
@ -87,6 +92,12 @@ class RAROptions
|
||||||
|
|
||||||
uint ExclFileAttr;
|
uint ExclFileAttr;
|
||||||
uint InclFileAttr;
|
uint InclFileAttr;
|
||||||
|
|
||||||
|
// We handle -ed and -e+d with special flags instead of attribute mask,
|
||||||
|
// so it works with both Windows and Unix archives.
|
||||||
|
bool ExclDir;
|
||||||
|
bool InclDir;
|
||||||
|
|
||||||
bool InclAttrSet;
|
bool InclAttrSet;
|
||||||
size_t WinSize;
|
size_t WinSize;
|
||||||
wchar TempPath[NM];
|
wchar TempPath[NM];
|
||||||
|
@ -112,7 +123,7 @@ class RAROptions
|
||||||
|
|
||||||
wchar LogName[NM];
|
wchar LogName[NM];
|
||||||
MESSAGE_TYPE MsgStream;
|
MESSAGE_TYPE MsgStream;
|
||||||
bool Sound;
|
SOUND_NOTIFY_MODE Sound;
|
||||||
OVERWRITE_MODE Overwrite;
|
OVERWRITE_MODE Overwrite;
|
||||||
int Method;
|
int Method;
|
||||||
HASH_TYPE HashType;
|
HASH_TYPE HashType;
|
||||||
|
@ -157,14 +168,17 @@ class RAROptions
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
bool GenerateArcName;
|
bool GenerateArcName;
|
||||||
wchar GenerateMask[MAX_GENERATE_MASK];
|
wchar GenerateMask[MAX_GENERATE_MASK];
|
||||||
|
wchar DefGenerateMask[MAX_GENERATE_MASK];
|
||||||
#endif
|
#endif
|
||||||
bool SyncFiles;
|
bool SyncFiles;
|
||||||
bool ProcessEA;
|
bool ProcessEA;
|
||||||
bool SaveStreams;
|
bool SaveStreams;
|
||||||
bool SetCompressedAttr;
|
bool SetCompressedAttr;
|
||||||
bool IgnoreGeneralAttr;
|
bool IgnoreGeneralAttr;
|
||||||
RarTime FileTimeBefore;
|
RarTime FileMtimeBefore,FileCtimeBefore,FileAtimeBefore;
|
||||||
RarTime FileTimeAfter;
|
bool FileMtimeBeforeOR,FileCtimeBeforeOR,FileAtimeBeforeOR;
|
||||||
|
RarTime FileMtimeAfter,FileCtimeAfter,FileAtimeAfter;
|
||||||
|
bool FileMtimeAfterOR,FileCtimeAfterOR,FileAtimeAfterOR;
|
||||||
int64 FileSizeLess;
|
int64 FileSizeLess;
|
||||||
int64 FileSizeMore;
|
int64 FileSizeMore;
|
||||||
bool Lock;
|
bool Lock;
|
||||||
|
@ -173,11 +187,12 @@ class RAROptions
|
||||||
FilterMode FilterModes[MAX_FILTER_TYPES];
|
FilterMode FilterModes[MAX_FILTER_TYPES];
|
||||||
wchar EmailTo[NM];
|
wchar EmailTo[NM];
|
||||||
uint VersionControl;
|
uint VersionControl;
|
||||||
bool AppendArcNameToPath;
|
APPENDARCNAME_MODE AppendArcNameToPath;
|
||||||
POWER_MODE Shutdown;
|
POWER_MODE Shutdown;
|
||||||
EXTTIME_MODE xmtime;
|
EXTTIME_MODE xmtime; // Extended time modes (time precision to store).
|
||||||
EXTTIME_MODE xctime;
|
EXTTIME_MODE xctime;
|
||||||
EXTTIME_MODE xatime;
|
EXTTIME_MODE xatime;
|
||||||
|
bool PreserveAtime;
|
||||||
wchar CompressStdin[NM];
|
wchar CompressStdin[NM];
|
||||||
|
|
||||||
uint Threads; // We use it to init hash even if RAR_SMP is not defined.
|
uint Threads; // We use it to init hash even if RAR_SMP is not defined.
|
||||||
|
|
|
@ -22,8 +22,22 @@
|
||||||
|
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
|
|
||||||
#define STRICT
|
|
||||||
|
// We got a report that just "#define STRICT" is incompatible with
|
||||||
|
// "#define STRICT 1" in Windows 10 SDK minwindef.h and depending on the order
|
||||||
|
// in which these statements are reached this may cause a compiler warning
|
||||||
|
// and build break for other projects incorporating this source.
|
||||||
|
// So we changed it to "#define STRICT 1".
|
||||||
|
#ifndef STRICT
|
||||||
|
#define STRICT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 'ifndef' check here is needed for unrar.dll header to avoid macro
|
||||||
|
// re-definition warnings in third party projects.
|
||||||
|
#ifndef UNICODE
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef WINVER
|
#undef WINVER
|
||||||
#undef _WIN32_WINNT
|
#undef _WIN32_WINNT
|
||||||
#define WINVER 0x0501
|
#define WINVER 0x0501
|
||||||
|
@ -119,7 +133,7 @@
|
||||||
|
|
||||||
#ifdef _UNIX
|
#ifdef _UNIX
|
||||||
|
|
||||||
#define NM 2048
|
#define NM 2048
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
|
@ -16,7 +16,7 @@ wchar* PointToLastChar(const wchar *Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath,size_t DestSize)
|
||||||
{
|
{
|
||||||
const wchar *DestPtr=SrcPath;
|
const wchar *DestPtr=SrcPath;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
||||||
if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
|
if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
|
||||||
DestPtr=s+4;
|
DestPtr=s+4;
|
||||||
|
|
||||||
// Remove <d>:\ and any sequence of . and \ in the beginning of path string.
|
// Remove any amount of <d>:\ and any sequence of . and \ in the beginning of path string.
|
||||||
while (*DestPtr!=0)
|
while (*DestPtr!=0)
|
||||||
{
|
{
|
||||||
const wchar *s=DestPtr;
|
const wchar *s=DestPtr;
|
||||||
|
@ -58,7 +58,7 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
||||||
// so we use the temporary buffer for copying.
|
// so we use the temporary buffer for copying.
|
||||||
wchar TmpStr[NM];
|
wchar TmpStr[NM];
|
||||||
wcsncpyz(TmpStr,DestPtr,ASIZE(TmpStr));
|
wcsncpyz(TmpStr,DestPtr,ASIZE(TmpStr));
|
||||||
wcscpy(DestPath,TmpStr);
|
wcsncpyz(DestPath,TmpStr,DestSize);
|
||||||
}
|
}
|
||||||
return (wchar *)DestPtr;
|
return (wchar *)DestPtr;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,14 @@ bool CmpExt(const wchar *Name,const wchar *Ext)
|
||||||
|
|
||||||
bool IsWildcard(const wchar *Str)
|
bool IsWildcard(const wchar *Str)
|
||||||
{
|
{
|
||||||
return Str==NULL ? false:wcspbrk(Str,L"*?")!=NULL;
|
if (Str==NULL)
|
||||||
|
return false;
|
||||||
|
#ifdef _WIN_ALL
|
||||||
|
// Not treat the special NTFS \\?\d: path prefix as a wildcard.
|
||||||
|
if (Str[0]=='\\' && Str[1]=='\\' && Str[2]=='?' && Str[3]=='\\')
|
||||||
|
Str+=4;
|
||||||
|
#endif
|
||||||
|
return wcspbrk(Str,L"*?")!=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,13 +171,16 @@ void AddEndSlash(wchar *Path,size_t MaxLength)
|
||||||
{
|
{
|
||||||
size_t Length=wcslen(Path);
|
size_t Length=wcslen(Path);
|
||||||
if (Length>0 && Path[Length-1]!=CPATHDIVIDER && Length+1<MaxLength)
|
if (Length>0 && Path[Length-1]!=CPATHDIVIDER && Length+1<MaxLength)
|
||||||
wcscat(Path,SPATHDIVIDER);
|
{
|
||||||
|
Path[Length]=CPATHDIVIDER;
|
||||||
|
Path[Length+1]=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize)
|
void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize)
|
||||||
{
|
{
|
||||||
// 'Name' and 'Pathname' can point to same memory area. This is why we use
|
// 'Path', 'Name' and 'Pathname' can point to same memory area. So we use
|
||||||
// the temporary buffer instead of constructing the name in 'Pathname'.
|
// the temporary buffer instead of constructing the name in 'Pathname'.
|
||||||
wchar OutName[NM];
|
wchar OutName[NM];
|
||||||
wcsncpyz(OutName,Path,ASIZE(OutName));
|
wcsncpyz(OutName,Path,ASIZE(OutName));
|
||||||
|
@ -303,9 +313,13 @@ void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckEx
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Returns a pointer to rightmost digit of volume number.
|
// Returns a pointer to rightmost digit of volume number or to beginning
|
||||||
|
// of file name if numeric part is missing.
|
||||||
wchar* GetVolNumPart(const wchar *ArcName)
|
wchar* GetVolNumPart(const wchar *ArcName)
|
||||||
{
|
{
|
||||||
|
if (*ArcName==0)
|
||||||
|
return (wchar *)ArcName;
|
||||||
|
|
||||||
// Pointing to last name character.
|
// Pointing to last name character.
|
||||||
const wchar *ChPtr=ArcName+wcslen(ArcName)-1;
|
const wchar *ChPtr=ArcName+wcslen(ArcName)-1;
|
||||||
|
|
||||||
|
@ -346,18 +360,33 @@ void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering)
|
||||||
ChPtr=GetExt(ArcName);
|
ChPtr=GetExt(ArcName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (ChPtr[1]==0 && wcslen(ArcName)<MaxLength-3 || wcsicomp(ChPtr+1,L"exe")==0 || wcsicomp(ChPtr+1,L"sfx")==0)
|
if (ChPtr[1]==0 || wcsicomp(ChPtr,L".exe")==0 || wcsicomp(ChPtr,L".sfx")==0)
|
||||||
wcscpy(ChPtr+1,L"rar");
|
wcsncpyz(ChPtr,L".rar",MaxLength-(ChPtr-ArcName));
|
||||||
|
|
||||||
|
if (ChPtr==NULL || *ChPtr!='.' || ChPtr[1]==0)
|
||||||
|
{
|
||||||
|
// Normally we shall have some extension here. If we don't, it means
|
||||||
|
// the name has no extension and buffer has no free space to append one.
|
||||||
|
// Let's clear the name to prevent a new call with same name and return.
|
||||||
|
*ArcName=0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!OldNumbering)
|
if (!OldNumbering)
|
||||||
{
|
{
|
||||||
ChPtr=GetVolNumPart(ArcName);
|
ChPtr=GetVolNumPart(ArcName);
|
||||||
|
|
||||||
|
// We should not check for IsDigit(*ChPtr) here and should increment
|
||||||
|
// even non-digits. If we got a corrupt archive with volume flag,
|
||||||
|
// but without numeric part, we still need to modify its name somehow,
|
||||||
|
// so while (exist(name)) {NextVolumeName()} loops do not run infinitely.
|
||||||
while ((++(*ChPtr))=='9'+1)
|
while ((++(*ChPtr))=='9'+1)
|
||||||
{
|
{
|
||||||
*ChPtr='0';
|
*ChPtr='0';
|
||||||
ChPtr--;
|
ChPtr--;
|
||||||
if (ChPtr<ArcName || !IsDigit(*ChPtr))
|
if (ChPtr<ArcName || !IsDigit(*ChPtr))
|
||||||
{
|
{
|
||||||
|
// Convert .part:.rar (.part9.rar after increment) to part10.rar.
|
||||||
for (wchar *EndPtr=ArcName+wcslen(ArcName);EndPtr!=ChPtr;EndPtr--)
|
for (wchar *EndPtr=ArcName+wcslen(ArcName);EndPtr!=ChPtr;EndPtr--)
|
||||||
*(EndPtr+1)=*EndPtr;
|
*(EndPtr+1)=*EndPtr;
|
||||||
*(ChPtr+1)='1';
|
*(ChPtr+1)='1';
|
||||||
|
@ -366,15 +395,15 @@ void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (!IsDigit(*(ChPtr+2)) || !IsDigit(*(ChPtr+3)))
|
if (!IsDigit(ChPtr[2]) || !IsDigit(ChPtr[3]))
|
||||||
wcscpy(ChPtr+2,L"00");
|
wcsncpyz(ChPtr+2,L"00",MaxLength-(ChPtr-ArcName)-2); // From .rar to .r00.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ChPtr+=3;
|
ChPtr+=wcslen(ChPtr)-1; // Set to last character.
|
||||||
while ((++(*ChPtr))=='9'+1)
|
while (++(*ChPtr)=='9'+1)
|
||||||
if (*(ChPtr-1)=='.')
|
if (ChPtr<=ArcName || *(ChPtr-1)=='.')
|
||||||
{
|
{
|
||||||
*ChPtr='A';
|
*ChPtr='a'; // From .999 to .a00 if started from .001 or for too short names.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -585,8 +614,7 @@ int ParseVersionFileName(wchar *Name,bool Truncate)
|
||||||
wchar *VerText=wcsrchr(Name,';');
|
wchar *VerText=wcsrchr(Name,';');
|
||||||
if (VerText!=NULL)
|
if (VerText!=NULL)
|
||||||
{
|
{
|
||||||
if (Version==0)
|
Version=atoiw(VerText+1);
|
||||||
Version=atoiw(VerText+1);
|
|
||||||
if (Truncate)
|
if (Truncate)
|
||||||
*VerText=0;
|
*VerText=0;
|
||||||
}
|
}
|
||||||
|
@ -652,7 +680,7 @@ wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,size_t MaxSize,b
|
||||||
|
|
||||||
|
|
||||||
#ifndef SFX_MODULE
|
#ifndef SFX_MODULE
|
||||||
static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,bool &ArcNumPresent)
|
static void GenArcName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,uint ArcNumber,bool &ArcNumPresent)
|
||||||
{
|
{
|
||||||
bool Prefix=false;
|
bool Prefix=false;
|
||||||
if (*GenerateMask=='+')
|
if (*GenerateMask=='+')
|
||||||
|
@ -713,7 +741,7 @@ static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,b
|
||||||
wchar Ext[NM],*Dot=GetExt(ArcName);
|
wchar Ext[NM],*Dot=GetExt(ArcName);
|
||||||
*Ext=0;
|
*Ext=0;
|
||||||
if (Dot==NULL)
|
if (Dot==NULL)
|
||||||
wcscpy(Ext,*PointToName(ArcName)==0 ? L".rar":L"");
|
wcsncpyz(Ext,*PointToName(ArcName)==0 ? L".rar":L"",ASIZE(Ext));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wcsncpyz(Ext,Dot,ASIZE(Ext));
|
wcsncpyz(Ext,Dot,ASIZE(Ext));
|
||||||
|
@ -749,7 +777,7 @@ static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,b
|
||||||
int CField[sizeof(Field)/sizeof(Field[0])];
|
int CField[sizeof(Field)/sizeof(Field[0])];
|
||||||
memset(CField,0,sizeof(CField));
|
memset(CField,0,sizeof(CField));
|
||||||
QuoteMode=false;
|
QuoteMode=false;
|
||||||
for (int I=0;Mask[I]!=0;I++)
|
for (uint I=0;Mask[I]!=0;I++)
|
||||||
{
|
{
|
||||||
if (Mask[I]=='{' || Mask[I]=='}')
|
if (Mask[I]=='{' || Mask[I]=='}')
|
||||||
{
|
{
|
||||||
|
@ -810,21 +838,17 @@ static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,b
|
||||||
AddEndSlash(NewName,ASIZE(NewName));
|
AddEndSlash(NewName,ASIZE(NewName));
|
||||||
wcsncatz(NewName,DateText,ASIZE(NewName));
|
wcsncatz(NewName,DateText,ASIZE(NewName));
|
||||||
wcsncatz(NewName,PointToName(ArcName),ASIZE(NewName));
|
wcsncatz(NewName,PointToName(ArcName),ASIZE(NewName));
|
||||||
wcscpy(ArcName,NewName);
|
wcsncpyz(ArcName,NewName,MaxSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wcscat(ArcName,DateText);
|
wcsncatz(ArcName,DateText,MaxSize);
|
||||||
wcscat(ArcName,Ext);
|
wcsncatz(ArcName,Ext,MaxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,bool Archiving)
|
void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,bool Archiving)
|
||||||
{
|
{
|
||||||
// Must be enough space for archive name plus all stuff in mask plus
|
wchar NewName[NM];
|
||||||
// extra overhead produced by mask 'N' (archive number) characters.
|
|
||||||
// One 'N' character can result in several numbers if we process more
|
|
||||||
// than 9 archives.
|
|
||||||
wchar NewName[NM+MAX_GENERATE_MASK+20];
|
|
||||||
|
|
||||||
uint ArcNumber=1;
|
uint ArcNumber=1;
|
||||||
while (true) // Loop for 'N' (archive number) processing.
|
while (true) // Loop for 'N' (archive number) processing.
|
||||||
|
@ -833,7 +857,7 @@ void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask
|
||||||
|
|
||||||
bool ArcNumPresent=false;
|
bool ArcNumPresent=false;
|
||||||
|
|
||||||
GenArcName(NewName,GenerateMask,ArcNumber,ArcNumPresent);
|
GenArcName(NewName,ASIZE(NewName),GenerateMask,ArcNumber,ArcNumPresent);
|
||||||
|
|
||||||
if (!ArcNumPresent)
|
if (!ArcNumPresent)
|
||||||
break;
|
break;
|
||||||
|
@ -845,7 +869,7 @@ void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask
|
||||||
// existing archive before the first unused name. So we generate
|
// existing archive before the first unused name. So we generate
|
||||||
// the name for (ArcNumber-1) below.
|
// the name for (ArcNumber-1) below.
|
||||||
wcsncpyz(NewName,NullToEmpty(ArcName),ASIZE(NewName));
|
wcsncpyz(NewName,NullToEmpty(ArcName),ASIZE(NewName));
|
||||||
GenArcName(NewName,GenerateMask,ArcNumber-1,ArcNumPresent);
|
GenArcName(NewName,ASIZE(NewName),GenerateMask,ArcNumber-1,ArcNumPresent);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -895,8 +919,8 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
||||||
{
|
{
|
||||||
if (MaxSize<=PrefixLength+SrcLength)
|
if (MaxSize<=PrefixLength+SrcLength)
|
||||||
return false;
|
return false;
|
||||||
wcsncpy(Dest,Prefix,PrefixLength);
|
wcsncpyz(Dest,Prefix,MaxSize);
|
||||||
wcscpy(Dest+PrefixLength,Src);
|
wcsncatz(Dest,Src,MaxSize); // "\\?\D:\very long path".
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -904,9 +928,9 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
||||||
{
|
{
|
||||||
if (MaxSize<=PrefixLength+SrcLength+2)
|
if (MaxSize<=PrefixLength+SrcLength+2)
|
||||||
return false;
|
return false;
|
||||||
wcsncpy(Dest,Prefix,PrefixLength);
|
wcsncpyz(Dest,Prefix,MaxSize);
|
||||||
wcscpy(Dest+PrefixLength,L"UNC");
|
wcsncatz(Dest,L"UNC",MaxSize);
|
||||||
wcscpy(Dest+PrefixLength+3,Src+1);
|
wcsncatz(Dest,Src+1,MaxSize); // "\\?\UNC\server\share".
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// We may be here only if we modify IsFullPath in the future.
|
// We may be here only if we modify IsFullPath in the future.
|
||||||
|
@ -923,9 +947,10 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
||||||
{
|
{
|
||||||
if (MaxSize<=PrefixLength+SrcLength+2)
|
if (MaxSize<=PrefixLength+SrcLength+2)
|
||||||
return false;
|
return false;
|
||||||
wcsncpy(Dest,Prefix,PrefixLength);
|
wcsncpyz(Dest,Prefix,MaxSize);
|
||||||
wcsncpy(Dest+PrefixLength,CurDir,2); // Copy drive letter 'd:'.
|
CurDir[2]=0;
|
||||||
wcscpy(Dest+PrefixLength+2,Src);
|
wcsncatz(Dest,CurDir,MaxSize); // Copy drive letter 'd:'.
|
||||||
|
wcsncatz(Dest,Src,MaxSize);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else // Paths in path\name format.
|
else // Paths in path\name format.
|
||||||
|
@ -933,8 +958,8 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
||||||
AddEndSlash(CurDir,ASIZE(CurDir));
|
AddEndSlash(CurDir,ASIZE(CurDir));
|
||||||
if (MaxSize<=PrefixLength+wcslen(CurDir)+SrcLength)
|
if (MaxSize<=PrefixLength+wcslen(CurDir)+SrcLength)
|
||||||
return false;
|
return false;
|
||||||
wcsncpy(Dest,Prefix,PrefixLength);
|
wcsncpyz(Dest,Prefix,MaxSize);
|
||||||
wcscpy(Dest+PrefixLength,CurDir);
|
wcsncatz(Dest,CurDir,MaxSize);
|
||||||
|
|
||||||
if (Src[0]=='.' && IsPathDiv(Src[1])) // Remove leading .\ in pathname.
|
if (Src[0]=='.' && IsPathDiv(Src[1])) // Remove leading .\ in pathname.
|
||||||
Src+=2;
|
Src+=2;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
wchar* PointToName(const wchar *Path);
|
wchar* PointToName(const wchar *Path);
|
||||||
wchar* PointToLastChar(const wchar *Path);
|
wchar* PointToLastChar(const wchar *Path);
|
||||||
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath);
|
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath,size_t DestSize);
|
||||||
void SetName(wchar *FullName,const wchar *Name,size_t MaxSize);
|
void SetName(wchar *FullName,const wchar *Name,size_t MaxSize);
|
||||||
void SetExt(wchar *Name,const wchar *NewExt,size_t MaxSize);
|
void SetExt(wchar *Name,const wchar *NewExt,size_t MaxSize);
|
||||||
void SetSFXExt(wchar *SFXName,size_t MaxSize);
|
void SetSFXExt(wchar *SFXName,size_t MaxSize);
|
||||||
|
|
|
@ -67,7 +67,7 @@ void QuickOpen::Load(uint64 BlockPos)
|
||||||
SeekPos=Arc->Tell();
|
SeekPos=Arc->Tell();
|
||||||
UnsyncSeekPos=false;
|
UnsyncSeekPos=false;
|
||||||
|
|
||||||
SaveFilePos SavePos(*Arc);
|
int64 SavePos=SeekPos;
|
||||||
Arc->Seek(BlockPos,SEEK_SET);
|
Arc->Seek(BlockPos,SEEK_SET);
|
||||||
|
|
||||||
// If BlockPos points to original main header, we'll have the infinite
|
// If BlockPos points to original main header, we'll have the infinite
|
||||||
|
@ -83,10 +83,14 @@ void QuickOpen::Load(uint64 BlockPos)
|
||||||
|
|
||||||
if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE ||
|
if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE ||
|
||||||
!Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN))
|
!Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN))
|
||||||
|
{
|
||||||
|
Arc->Seek(SavePos,SEEK_SET);
|
||||||
return;
|
return;
|
||||||
QLHeaderPos=Arc->CurBlockPos;
|
}
|
||||||
|
QOHeaderPos=Arc->CurBlockPos;
|
||||||
RawDataStart=Arc->Tell();
|
RawDataStart=Arc->Tell();
|
||||||
RawDataSize=Arc->SubHead.UnpSize;
|
RawDataSize=Arc->SubHead.UnpSize;
|
||||||
|
Arc->Seek(SavePos,SEEK_SET);
|
||||||
|
|
||||||
Loaded=true; // Set only after all file processing calls like Tell, Seek, ReadHeader.
|
Loaded=true; // Set only after all file processing calls like Tell, Seek, ReadHeader.
|
||||||
}
|
}
|
||||||
|
@ -172,7 +176,7 @@ bool QuickOpen::Seek(int64 Offset,int Method)
|
||||||
// archive updating involve several passes. So if we detect that file
|
// archive updating involve several passes. So if we detect that file
|
||||||
// pointer is moved back, we reload quick open data from beginning.
|
// pointer is moved back, we reload quick open data from beginning.
|
||||||
if (Method==SEEK_SET && (uint64)Offset<SeekPos && (uint64)Offset<LastReadHeaderPos)
|
if (Method==SEEK_SET && (uint64)Offset<SeekPos && (uint64)Offset<LastReadHeaderPos)
|
||||||
Load(QLHeaderPos);
|
Load(QOHeaderPos);
|
||||||
|
|
||||||
if (Method==SEEK_SET)
|
if (Method==SEEK_SET)
|
||||||
SeekPos=Offset;
|
SeekPos=Offset;
|
||||||
|
@ -201,22 +205,28 @@ bool QuickOpen::Tell(int64 *Pos)
|
||||||
|
|
||||||
uint QuickOpen::ReadBuffer()
|
uint QuickOpen::ReadBuffer()
|
||||||
{
|
{
|
||||||
SaveFilePos SavePos(*Arc);
|
int64 SavePos=Arc->Tell();
|
||||||
Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET);
|
Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET);
|
||||||
size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize);
|
size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize);
|
||||||
if (Arc->SubHead.Encrypted)
|
if (Arc->SubHead.Encrypted)
|
||||||
SizeToRead &= ~CRYPT_BLOCK_MASK;
|
SizeToRead &= ~CRYPT_BLOCK_MASK;
|
||||||
if (SizeToRead==0)
|
int ReadSize=0;
|
||||||
return 0;
|
if (SizeToRead!=0)
|
||||||
int ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
|
{
|
||||||
if (ReadSize<=0)
|
ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
|
||||||
return 0;
|
if (ReadSize<=0)
|
||||||
|
ReadSize=0;
|
||||||
|
else
|
||||||
|
{
|
||||||
#ifndef RAR_NOCRYPT
|
#ifndef RAR_NOCRYPT
|
||||||
if (Arc->SubHead.Encrypted)
|
if (Arc->SubHead.Encrypted)
|
||||||
Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
|
Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
|
||||||
#endif
|
#endif
|
||||||
RawDataPos+=ReadSize;
|
RawDataPos+=ReadSize;
|
||||||
ReadBufSize+=ReadSize;
|
ReadBufSize+=ReadSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arc->Seek(SavePos,SEEK_SET);
|
||||||
return ReadSize;
|
return ReadSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,10 +260,10 @@ bool QuickOpen::ReadRaw(RawRead &Raw)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If rest of block data crosses buffer boundary, read it in loop.
|
// If rest of block data crosses Buf boundary, read it in loop.
|
||||||
size_t DataLeft=ReadBufSize-ReadBufPos;
|
|
||||||
while (SizeToRead>0)
|
while (SizeToRead>0)
|
||||||
{
|
{
|
||||||
|
size_t DataLeft=ReadBufSize-ReadBufPos;
|
||||||
size_t CurSizeToRead=Min(DataLeft,(size_t)SizeToRead);
|
size_t CurSizeToRead=Min(DataLeft,(size_t)SizeToRead);
|
||||||
Raw.Read(Buf+ReadBufPos,CurSizeToRead);
|
Raw.Read(Buf+ReadBufPos,CurSizeToRead);
|
||||||
ReadBufPos+=CurSizeToRead;
|
ReadBufPos+=CurSizeToRead;
|
||||||
|
@ -280,9 +290,11 @@ bool QuickOpen::ReadNext()
|
||||||
uint Flags=(uint)Raw.GetV();
|
uint Flags=(uint)Raw.GetV();
|
||||||
uint64 Offset=Raw.GetV();
|
uint64 Offset=Raw.GetV();
|
||||||
size_t HeaderSize=(size_t)Raw.GetV();
|
size_t HeaderSize=(size_t)Raw.GetV();
|
||||||
|
if (HeaderSize>MAX_HEADER_SIZE_RAR5)
|
||||||
|
return false;
|
||||||
LastReadHeader.Alloc(HeaderSize);
|
LastReadHeader.Alloc(HeaderSize);
|
||||||
Raw.GetB(&LastReadHeader[0],HeaderSize);
|
Raw.GetB(&LastReadHeader[0],HeaderSize);
|
||||||
// Calculate the absolute position as offset from quick open service header.
|
// Calculate the absolute position as offset from quick open service header.
|
||||||
LastReadHeaderPos=QLHeaderPos-Offset;
|
LastReadHeaderPos=QOHeaderPos-Offset;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,24 +29,24 @@ class QuickOpen
|
||||||
QuickOpenItem *ListStart;
|
QuickOpenItem *ListStart;
|
||||||
QuickOpenItem *ListEnd;
|
QuickOpenItem *ListEnd;
|
||||||
|
|
||||||
byte *Buf;
|
byte *Buf; // Read quick open data here.
|
||||||
static const size_t MaxBufSize=0x10000; // Must be multiple of CRYPT_BLOCK_SIZE.
|
static const size_t MaxBufSize=0x10000; // Buf size, must be multiple of CRYPT_BLOCK_SIZE.
|
||||||
size_t CurBufSize;
|
size_t CurBufSize; // Current size of buffered data in write mode.
|
||||||
#ifndef RAR_NOCRYPT // For shell extension.
|
#ifndef RAR_NOCRYPT // For shell extension.
|
||||||
CryptData Crypt;
|
CryptData Crypt;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Loaded;
|
bool Loaded;
|
||||||
uint64 QLHeaderPos;
|
uint64 QOHeaderPos; // Main QO header position.
|
||||||
uint64 RawDataStart;
|
uint64 RawDataStart; // Start of QO data, just after the main header.
|
||||||
uint64 RawDataSize;
|
uint64 RawDataSize; // Size of entire QO data.
|
||||||
uint64 RawDataPos;
|
uint64 RawDataPos; // Current read position in QO data.
|
||||||
size_t ReadBufSize;
|
size_t ReadBufSize; // Size of Buf data currently read from QO.
|
||||||
size_t ReadBufPos;
|
size_t ReadBufPos; // Current read position in Buf data.
|
||||||
Array<byte> LastReadHeader;
|
Array<byte> LastReadHeader;
|
||||||
uint64 LastReadHeaderPos;
|
uint64 LastReadHeaderPos;
|
||||||
uint64 SeekPos;
|
uint64 SeekPos;
|
||||||
bool UnsyncSeekPos; // QOpen SeekPos does not match an actual file pointer.
|
bool UnsyncSeekPos; // QOpen SeekPos does not match an actual file pointer.
|
||||||
public:
|
public:
|
||||||
QuickOpen();
|
QuickOpen();
|
||||||
~QuickOpen();
|
~QuickOpen();
|
||||||
|
|
|
@ -37,7 +37,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
CommandData *Cmd=new CommandData;
|
CommandData *Cmd=new CommandData;
|
||||||
#ifdef SFX_MODULE
|
#ifdef SFX_MODULE
|
||||||
wcscpy(Cmd->Command,L"X");
|
wcsncpyz(Cmd->Command,L"X",ASIZE(Cmd->Command));
|
||||||
char *Switch=argc>1 ? argv[1]:NULL;
|
char *Switch=argc>1 ? argv[1]:NULL;
|
||||||
if (Switch!=NULL && Cmd->IsSwitch(Switch[0]))
|
if (Switch!=NULL && Cmd->IsSwitch(Switch[0]))
|
||||||
{
|
{
|
||||||
|
@ -68,6 +68,8 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
ShutdownOnClose=Cmd->Shutdown;
|
ShutdownOnClose=Cmd->Shutdown;
|
||||||
|
if (ShutdownOnClose)
|
||||||
|
ShutdownCheckAnother(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uiInit(Cmd->Sound);
|
uiInit(Cmd->Sound);
|
||||||
|
@ -75,13 +77,6 @@ int main(int argc, char *argv[])
|
||||||
ErrHandler.SetSilent(Cmd->AllYes || Cmd->MsgStream==MSG_NULL);
|
ErrHandler.SetSilent(Cmd->AllYes || Cmd->MsgStream==MSG_NULL);
|
||||||
|
|
||||||
Cmd->OutTitle();
|
Cmd->OutTitle();
|
||||||
/*
|
|
||||||
byte Buf[10000];
|
|
||||||
File Src;
|
|
||||||
Src.TOpen(L"123.rar");
|
|
||||||
int Size=Src.Read(Buf,sizeof(Buf));
|
|
||||||
Cmd->SetArcInMem(Buf,Size);
|
|
||||||
*/
|
|
||||||
Cmd->ProcessCommand();
|
Cmd->ProcessCommand();
|
||||||
delete Cmd;
|
delete Cmd;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +95,8 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||||
if (ShutdownOnClose!=POWERMODE_KEEP && ErrHandler.IsShutdownEnabled())
|
if (ShutdownOnClose!=POWERMODE_KEEP && ErrHandler.IsShutdownEnabled() &&
|
||||||
|
!ShutdownCheckAnother(false))
|
||||||
Shutdown(ShutdownOnClose);
|
Shutdown(ShutdownOnClose);
|
||||||
#endif
|
#endif
|
||||||
ErrHandler.MainExit=true;
|
ErrHandler.MainExit=true;
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#include "filestr.hpp"
|
#include "filestr.hpp"
|
||||||
#include "find.hpp"
|
#include "find.hpp"
|
||||||
#include "scantree.hpp"
|
#include "scantree.hpp"
|
||||||
#include "savepos.hpp"
|
|
||||||
#include "getbits.hpp"
|
#include "getbits.hpp"
|
||||||
#include "rdwrfn.hpp"
|
#include "rdwrfn.hpp"
|
||||||
#ifdef USE_QOPEN
|
#ifdef USE_QOPEN
|
||||||
|
@ -77,6 +76,9 @@
|
||||||
|
|
||||||
#include "rs.hpp"
|
#include "rs.hpp"
|
||||||
#include "rs16.hpp"
|
#include "rs16.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "recvol.hpp"
|
#include "recvol.hpp"
|
||||||
#include "volume.hpp"
|
#include "volume.hpp"
|
||||||
#include "smallfn.hpp"
|
#include "smallfn.hpp"
|
||||||
|
|
|
@ -21,15 +21,12 @@ typedef wchar_t wchar; // Unicode character
|
||||||
// Maximum int64 value.
|
// Maximum int64 value.
|
||||||
#define MAX_INT64 int64(INT32TO64(0x7fffffff,0xffffffff))
|
#define MAX_INT64 int64(INT32TO64(0x7fffffff,0xffffffff))
|
||||||
|
|
||||||
// Special int64 value, large enough to never be found in real life.
|
// Special int64 value, large enough to never be found in real life
|
||||||
|
// and small enough to fit to both signed and unsigned 64-bit ints.
|
||||||
// We use it in situations, when we need to indicate that parameter
|
// We use it in situations, when we need to indicate that parameter
|
||||||
// is not defined and probably should be calculated inside of function.
|
// is not defined and probably should be calculated inside of function.
|
||||||
// Lower part is intentionally 0x7fffffff, not 0xffffffff, to make it
|
// Lower part is intentionally 0x7fffffff, not 0xffffffff, to make it
|
||||||
// compatible with 32 bit int64.
|
// compatible with 32 bit int64 if 64 bit type is not supported.
|
||||||
#define INT64NDF INT32TO64(0x7fffffff,0x7fffffff)
|
#define INT64NDF INT32TO64(0x7fffffff,0x7fffffff)
|
||||||
|
|
||||||
// Maximum uint64 value.
|
|
||||||
#define MAX_UINT64 INT32TO64(0xffffffff,0xffffffff)
|
|
||||||
#define UINT64NDF MAX_UINT64
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,6 +25,7 @@ void ComprDataIO::Init()
|
||||||
NextVolumeMissing=false;
|
NextVolumeMissing=false;
|
||||||
SrcFile=NULL;
|
SrcFile=NULL;
|
||||||
DestFile=NULL;
|
DestFile=NULL;
|
||||||
|
UnpWrAddr=NULL;
|
||||||
UnpWrSize=0;
|
UnpWrSize=0;
|
||||||
Command=NULL;
|
Command=NULL;
|
||||||
Encryption=false;
|
Encryption=false;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
class CmdAdd;
|
class CmdAdd;
|
||||||
class Unpack;
|
class Unpack;
|
||||||
|
class ArcFileSearch;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// We use external i/o calls for Benchmark command.
|
// We use external i/o calls for Benchmark command.
|
||||||
|
|
|
@ -31,12 +31,12 @@ bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
// handling exceptions. So it can close and delete files on Cancel.
|
// handling exceptions. So it can close and delete files on Cancel.
|
||||||
if (Fmt==RARFMT15)
|
if (Fmt==RARFMT15)
|
||||||
{
|
{
|
||||||
RecVolumes3 RecVol(false);
|
RecVolumes3 RecVol(Cmd,false);
|
||||||
return RecVol.Restore(Cmd,Name,Silent);
|
return RecVol.Restore(Cmd,Name,Silent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RecVolumes5 RecVol(false);
|
RecVolumes5 RecVol(Cmd,false);
|
||||||
return RecVol.Restore(Cmd,Name,Silent);
|
return RecVol.Restore(Cmd,Name,Silent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,12 +100,12 @@ void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name)
|
||||||
RevFile.Close();
|
RevFile.Close();
|
||||||
if (Rev5)
|
if (Rev5)
|
||||||
{
|
{
|
||||||
RecVolumes5 RecVol(true);
|
RecVolumes5 RecVol(Cmd,true);
|
||||||
RecVol.Test(Cmd,Name);
|
RecVol.Test(Cmd,Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RecVolumes3 RecVol(true);
|
RecVolumes3 RecVol(Cmd,true);
|
||||||
RecVol.Test(Cmd,Name);
|
RecVol.Test(Cmd,Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ class RecVolumes3
|
||||||
ThreadPool *RSThreadPool;
|
ThreadPool *RSThreadPool;
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
RecVolumes3(bool TestOnly);
|
RecVolumes3(RAROptions *Cmd,bool TestOnly);
|
||||||
~RecVolumes3();
|
~RecVolumes3();
|
||||||
void Make(RAROptions *Cmd,wchar *ArcName);
|
void Make(RAROptions *Cmd,wchar *ArcName);
|
||||||
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||||
|
@ -71,11 +71,12 @@ class RecVolumes5
|
||||||
#ifdef RAR_SMP
|
#ifdef RAR_SMP
|
||||||
ThreadPool *RecThreadPool;
|
ThreadPool *RecThreadPool;
|
||||||
#endif
|
#endif
|
||||||
RecRSThreadData ThreadData[MaxPoolThreads]; // Store thread parameters.
|
uint MaxUserThreads; // Maximum number of threads defined by user.
|
||||||
|
RecRSThreadData *ThreadData; // Array to store thread parameters.
|
||||||
public: // 'public' only because called from thread functions.
|
public: // 'public' only because called from thread functions.
|
||||||
void ProcessAreaRS(RecRSThreadData *td);
|
void ProcessAreaRS(RecRSThreadData *td);
|
||||||
public:
|
public:
|
||||||
RecVolumes5(bool TestOnly);
|
RecVolumes5(RAROptions *Cmd,bool TestOnly);
|
||||||
~RecVolumes5();
|
~RecVolumes5();
|
||||||
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||||
void Test(RAROptions *Cmd,const wchar *Name);
|
void Test(RAROptions *Cmd,const wchar *Name);
|
||||||
|
|
|
@ -36,7 +36,7 @@ THREAD_PROC(RSDecodeThread)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RecVolumes3::RecVolumes3(bool TestOnly)
|
RecVolumes3::RecVolumes3(RAROptions *Cmd,bool TestOnly)
|
||||||
{
|
{
|
||||||
memset(SrcFile,0,sizeof(SrcFile));
|
memset(SrcFile,0,sizeof(SrcFile));
|
||||||
if (TestOnly)
|
if (TestOnly)
|
||||||
|
@ -50,7 +50,7 @@ RecVolumes3::RecVolumes3(bool TestOnly)
|
||||||
Buf.Alloc(TotalBufferSize);
|
Buf.Alloc(TotalBufferSize);
|
||||||
memset(SrcFile,0,sizeof(SrcFile));
|
memset(SrcFile,0,sizeof(SrcFile));
|
||||||
#ifdef RAR_SMP
|
#ifdef RAR_SMP
|
||||||
RSThreadPool=CreateThreadPool();
|
RSThreadPool=new ThreadPool(Cmd->Threads);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ RecVolumes3::~RecVolumes3()
|
||||||
for (size_t I=0;I<ASIZE(SrcFile);I++)
|
for (size_t I=0;I<ASIZE(SrcFile);I++)
|
||||||
delete SrcFile[I];
|
delete SrcFile[I];
|
||||||
#ifdef RAR_SMP
|
#ifdef RAR_SMP
|
||||||
DestroyThreadPool(RSThreadPool);
|
delete RSThreadPool;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
NewStyle=IsNewStyleRev(ArcName);
|
NewStyle=IsNewStyleRev(ArcName);
|
||||||
while (Ext>ArcName+1 && (IsDigit(*(Ext-1)) || *(Ext-1)=='_'))
|
while (Ext>ArcName+1 && (IsDigit(*(Ext-1)) || *(Ext-1)=='_'))
|
||||||
Ext--;
|
Ext--;
|
||||||
wcscpy(Ext,L"*.*");
|
wcsncpyz(Ext,L"*.*",ASIZE(ArcName)-(Ext-ArcName));
|
||||||
|
|
||||||
FindFile Find;
|
FindFile Find;
|
||||||
Find.SetMask(ArcName);
|
Find.SetMask(ArcName);
|
||||||
|
@ -235,7 +235,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
}
|
}
|
||||||
RecVolNumber=P[1];
|
RecVolNumber=P[1];
|
||||||
FileNumber=P[2];
|
FileNumber=P[2];
|
||||||
wcscpy(PrevName,CurName);
|
wcsncpyz(PrevName,CurName,ASIZE(PrevName));
|
||||||
File *NewFile=new File;
|
File *NewFile=new File;
|
||||||
NewFile->TOpen(CurName);
|
NewFile->TOpen(CurName);
|
||||||
SrcFile[FileNumber+P[0]-1]=NewFile;
|
SrcFile[FileNumber+P[0]-1]=NewFile;
|
||||||
|
@ -247,7 +247,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
if (!Silent || FoundRecVolumes!=0)
|
if (!Silent || FoundRecVolumes!=0)
|
||||||
uiMsg(UIMSG_RECVOLFOUND,FoundRecVolumes);
|
uiMsg(UIMSG_RECVOLFOUND,FoundRecVolumes);
|
||||||
if (FoundRecVolumes==0)
|
if (FoundRecVolumes==0)
|
||||||
return(false);
|
return false;
|
||||||
|
|
||||||
bool WriteFlags[256];
|
bool WriteFlags[256];
|
||||||
memset(WriteFlags,0,sizeof(WriteFlags));
|
memset(WriteFlags,0,sizeof(WriteFlags));
|
||||||
|
@ -290,8 +290,8 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
{
|
{
|
||||||
NewFile->Close();
|
NewFile->Close();
|
||||||
wchar NewName[NM];
|
wchar NewName[NM];
|
||||||
wcscpy(NewName,ArcName);
|
wcsncpyz(NewName,ArcName,ASIZE(NewName));
|
||||||
wcscat(NewName,L".bad");
|
wcsncatz(NewName,L".bad",ASIZE(NewName));
|
||||||
|
|
||||||
uiMsg(UIMSG_BADARCHIVE,ArcName);
|
uiMsg(UIMSG_BADARCHIVE,ArcName);
|
||||||
uiMsg(UIMSG_RENAMING,ArcName,NewName);
|
uiMsg(UIMSG_RENAMING,ArcName,NewName);
|
||||||
|
@ -322,7 +322,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
MissingVolumes++;
|
MissingVolumes++;
|
||||||
|
|
||||||
if (CurArcNum==FileNumber-1)
|
if (CurArcNum==FileNumber-1)
|
||||||
wcscpy(LastVolName,ArcName);
|
wcsncpyz(LastVolName,ArcName,ASIZE(LastVolName));
|
||||||
|
|
||||||
uiMsg(UIMSG_MISSINGVOL,ArcName);
|
uiMsg(UIMSG_MISSINGVOL,ArcName);
|
||||||
uiMsg(UIEVENT_NEWARCHIVE,ArcName);
|
uiMsg(UIEVENT_NEWARCHIVE,ArcName);
|
||||||
|
@ -363,11 +363,10 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
|
|
||||||
#ifdef RAR_SMP
|
#ifdef RAR_SMP
|
||||||
uint ThreadNumber=Cmd->Threads;
|
uint ThreadNumber=Cmd->Threads;
|
||||||
RSEncode rse[MaxPoolThreads];
|
|
||||||
#else
|
#else
|
||||||
uint ThreadNumber=1;
|
uint ThreadNumber=1;
|
||||||
RSEncode rse[1];
|
|
||||||
#endif
|
#endif
|
||||||
|
RSEncode *rse=new RSEncode[ThreadNumber];
|
||||||
for (uint I=0;I<ThreadNumber;I++)
|
for (uint I=0;I<ThreadNumber;I++)
|
||||||
rse[I].Init(RecVolNumber);
|
rse[I].Init(RecVolNumber);
|
||||||
|
|
||||||
|
@ -438,6 +437,8 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
if (WriteFlags[I])
|
if (WriteFlags[I])
|
||||||
SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead);
|
SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead);
|
||||||
}
|
}
|
||||||
|
delete[] rse;
|
||||||
|
|
||||||
for (int I=0;I<RecVolNumber+FileNumber;I++)
|
for (int I=0;I<RecVolNumber+FileNumber;I++)
|
||||||
if (SrcFile[I]!=NULL)
|
if (SrcFile[I]!=NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
static const uint MaxVolumes=65535;
|
static const uint MaxVolumes=65535;
|
||||||
|
|
||||||
RecVolumes5::RecVolumes5(bool TestOnly)
|
RecVolumes5::RecVolumes5(RAROptions *Cmd,bool TestOnly)
|
||||||
{
|
{
|
||||||
RealBuf=NULL;
|
RealBuf=NULL;
|
||||||
RealReadBuffer=NULL;
|
RealReadBuffer=NULL;
|
||||||
|
@ -10,7 +10,14 @@ RecVolumes5::RecVolumes5(bool TestOnly)
|
||||||
TotalCount=0;
|
TotalCount=0;
|
||||||
RecBufferSize=0;
|
RecBufferSize=0;
|
||||||
|
|
||||||
for (uint I=0;I<ASIZE(ThreadData);I++)
|
#ifdef RAR_SMP
|
||||||
|
MaxUserThreads=Cmd->Threads;
|
||||||
|
#else
|
||||||
|
MaxUserThreads=1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ThreadData=new RecRSThreadData[MaxUserThreads];
|
||||||
|
for (uint I=0;I<MaxUserThreads;I++)
|
||||||
{
|
{
|
||||||
ThreadData[I].RecRSPtr=this;
|
ThreadData[I].RecRSPtr=this;
|
||||||
ThreadData[I].RS=NULL;
|
ThreadData[I].RS=NULL;
|
||||||
|
@ -25,7 +32,7 @@ RecVolumes5::RecVolumes5(bool TestOnly)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef RAR_SMP
|
#ifdef RAR_SMP
|
||||||
RecThreadPool=CreateThreadPool();
|
RecThreadPool=new ThreadPool(MaxUserThreads);
|
||||||
#endif
|
#endif
|
||||||
RealBuf=new byte[TotalBufferSize+SSE_ALIGNMENT];
|
RealBuf=new byte[TotalBufferSize+SSE_ALIGNMENT];
|
||||||
Buf=(byte *)ALIGN_VALUE(RealBuf,SSE_ALIGNMENT);
|
Buf=(byte *)ALIGN_VALUE(RealBuf,SSE_ALIGNMENT);
|
||||||
|
@ -39,10 +46,11 @@ RecVolumes5::~RecVolumes5()
|
||||||
delete[] RealReadBuffer;
|
delete[] RealReadBuffer;
|
||||||
for (uint I=0;I<RecItems.Size();I++)
|
for (uint I=0;I<RecItems.Size();I++)
|
||||||
delete RecItems[I].f;
|
delete RecItems[I].f;
|
||||||
for (uint I=0;I<ASIZE(ThreadData);I++)
|
for (uint I=0;I<MaxUserThreads;I++)
|
||||||
delete ThreadData[I].RS;
|
delete ThreadData[I].RS;
|
||||||
|
delete[] ThreadData;
|
||||||
#ifdef RAR_SMP
|
#ifdef RAR_SMP
|
||||||
DestroyThreadPool(RecThreadPool);
|
delete RecThreadPool;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +76,7 @@ void RecVolumes5::ProcessRS(RAROptions *Cmd,uint DataNum,const byte *Data,uint M
|
||||||
RS.UpdateECC(DataNum, I, Data, Buf+I*RecBufferSize, MaxRead);
|
RS.UpdateECC(DataNum, I, Data, Buf+I*RecBufferSize, MaxRead);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef RAR_SMP
|
uint ThreadNumber=MaxUserThreads;
|
||||||
uint ThreadNumber=Cmd->Threads;
|
|
||||||
#else
|
|
||||||
uint ThreadNumber=1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint MinThreadBlock=0x1000;
|
const uint MinThreadBlock=0x1000;
|
||||||
ThreadNumber=Min(ThreadNumber,MaxRead/MinThreadBlock);
|
ThreadNumber=Min(ThreadNumber,MaxRead/MinThreadBlock);
|
||||||
|
@ -139,12 +143,10 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
wcsncpyz(ArcName,Name,ASIZE(ArcName));
|
wcsncpyz(ArcName,Name,ASIZE(ArcName));
|
||||||
|
|
||||||
wchar *Num=GetVolNumPart(ArcName);
|
wchar *Num=GetVolNumPart(ArcName);
|
||||||
if (Num==ArcName)
|
|
||||||
return false; // Number part is missing in the name.
|
|
||||||
while (Num>ArcName && IsDigit(*(Num-1)))
|
while (Num>ArcName && IsDigit(*(Num-1)))
|
||||||
Num--;
|
Num--;
|
||||||
if (Num==ArcName)
|
if (Num==ArcName)
|
||||||
return false; // Entire volume name is numeric, not possible for REV file.
|
return false; // Numeric part is missing or entire volume name is numeric, not possible for RAR or REV volume.
|
||||||
wcsncpyz(Num,L"*.*",ASIZE(ArcName)-(Num-ArcName));
|
wcsncpyz(Num,L"*.*",ASIZE(ArcName)-(Num-ArcName));
|
||||||
|
|
||||||
wchar FirstVolName[NM];
|
wchar FirstVolName[NM];
|
||||||
|
@ -240,7 +242,7 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
uiMsg(UIMSG_STRING,Item->Name);
|
uiMsg(UIMSG_STRING,Item->Name);
|
||||||
|
|
||||||
uint RevCRC;
|
uint RevCRC;
|
||||||
CalcFileSum(Item->f,&RevCRC,NULL,Cmd->Threads,INT64NDF,CALCFSUM_CURPOS);
|
CalcFileSum(Item->f,&RevCRC,NULL,MaxUserThreads,INT64NDF,CALCFSUM_CURPOS);
|
||||||
Item->Valid=RevCRC==Item->CRC;
|
Item->Valid=RevCRC==Item->CRC;
|
||||||
if (!Item->Valid)
|
if (!Item->Valid)
|
||||||
{
|
{
|
||||||
|
@ -289,8 +291,8 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||||
Item->f->Close();
|
Item->f->Close();
|
||||||
|
|
||||||
wchar NewName[NM];
|
wchar NewName[NM];
|
||||||
wcscpy(NewName,Item->Name);
|
wcsncpyz(NewName,Item->Name,ASIZE(NewName));
|
||||||
wcscat(NewName,L".bad");
|
wcsncatz(NewName,L".bad",ASIZE(NewName));
|
||||||
|
|
||||||
uiMsg(UIMSG_BADARCHIVE,Item->Name);
|
uiMsg(UIMSG_BADARCHIVE,Item->Name);
|
||||||
uiMsg(UIMSG_RENAMING,Item->Name,NewName);
|
uiMsg(UIMSG_RENAMING,Item->Name,NewName);
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef RARDLL
|
#ifndef RARDLL
|
||||||
const wchar *St(MSGID StringId)
|
const wchar* St(MSGID StringId)
|
||||||
{
|
{
|
||||||
return StringId;
|
return StringId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,11 +75,20 @@ void Rijndael::Init(bool Encrypt,const byte *key,uint keyLen,const byte * initVe
|
||||||
// Check SSE here instead of constructor, so if object is a part of some
|
// Check SSE here instead of constructor, so if object is a part of some
|
||||||
// structure memset'ed before use, this variable is not lost.
|
// structure memset'ed before use, this variable is not lost.
|
||||||
int CPUInfo[4];
|
int CPUInfo[4];
|
||||||
__cpuid(CPUInfo, 1);
|
__cpuid(CPUInfo, 0x80000000); // Get the maximum supported cpuid function.
|
||||||
AES_NI=(CPUInfo[2] & 0x2000000)!=0;
|
if ((CPUInfo[0] & 0x7fffffff)>=1)
|
||||||
|
{
|
||||||
|
__cpuid(CPUInfo, 1);
|
||||||
|
AES_NI=(CPUInfo[2] & 0x2000000)!=0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AES_NI=0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint uKeyLenInBytes;
|
// Other developers asked us to initialize it to suppress "may be used
|
||||||
|
// uninitialized" warning in code below in some compilers.
|
||||||
|
uint uKeyLenInBytes=0;
|
||||||
|
|
||||||
switch(keyLen)
|
switch(keyLen)
|
||||||
{
|
{
|
||||||
case 128:
|
case 128:
|
||||||
|
|
|
@ -27,7 +27,7 @@ RSCoder16::~RSCoder16()
|
||||||
delete[] MX;
|
delete[] MX;
|
||||||
delete[] ValidFlags;
|
delete[] ValidFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Initialize logarithms and exponents Galois field tables.
|
// Initialize logarithms and exponents Galois field tables.
|
||||||
void RSCoder16::gfInit()
|
void RSCoder16::gfInit()
|
||||||
|
@ -41,7 +41,7 @@ void RSCoder16::gfInit()
|
||||||
gfExp[L]=E;
|
gfExp[L]=E;
|
||||||
gfExp[L+gfSize]=E; // Duplicate the table to avoid gfExp overflow check.
|
gfExp[L+gfSize]=E; // Duplicate the table to avoid gfExp overflow check.
|
||||||
E<<=1;
|
E<<=1;
|
||||||
if (E>gfSize)
|
if (E>gfSize)
|
||||||
E^=0x1100B; // Irreducible field-generator polynomial.
|
E^=0x1100B; // Irreducible field-generator polynomial.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ uint RSCoder16::gfAdd(uint a,uint b) // Addition in Galois field.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint RSCoder16::gfMul(uint a,uint b) // Multiplication in Galois field.
|
uint RSCoder16::gfMul(uint a,uint b) // Multiplication in Galois field.
|
||||||
{
|
{
|
||||||
return gfExp[gfLog[a]+gfLog[b]];
|
return gfExp[gfLog[a]+gfLog[b]];
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ void RSCoder16::InvertDecoderMatrix()
|
||||||
for (uint Kr = 0, Kf = 0; Kr < NE; Kr++, Kf++)
|
for (uint Kr = 0, Kf = 0; Kr < NE; Kr++, Kf++)
|
||||||
{
|
{
|
||||||
while (ValidFlags[Kf]) // Skip trivial rows.
|
while (ValidFlags[Kf]) // Skip trivial rows.
|
||||||
Kf++;
|
Kf++;
|
||||||
MI[Kr * ND + Kf] = 1; // Set diagonal 1.
|
MI[Kr * ND + Kf] = 1; // Set diagonal 1.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ void RSCoder16::InvertDecoderMatrix()
|
||||||
// after MI[..]^=, but we do not need it for matrix inversion.
|
// after MI[..]^=, but we do not need it for matrix inversion.
|
||||||
for (uint I = 0; I < NE; I++)
|
for (uint I = 0; I < NE; I++)
|
||||||
MI[I * ND + Kf] ^= MX[I * ND + Kf];
|
MI[I * ND + Kf] ^= MX[I * ND + Kf];
|
||||||
Kf++;
|
Kf++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Kf == ND)
|
if (Kf == ND)
|
||||||
|
@ -186,14 +186,14 @@ void RSCoder16::InvertDecoderMatrix()
|
||||||
uint PInv = gfInv( MXk[Kf] ); // Pivot inverse.
|
uint PInv = gfInv( MXk[Kf] ); // Pivot inverse.
|
||||||
// Divide the pivot row by pivot, so pivot cell contains 1.
|
// Divide the pivot row by pivot, so pivot cell contains 1.
|
||||||
for (uint I = 0; I < ND; I++)
|
for (uint I = 0; I < ND; I++)
|
||||||
{
|
{
|
||||||
MXk[I] = gfMul( MXk[I], PInv );
|
MXk[I] = gfMul( MXk[I], PInv );
|
||||||
MIk[I] = gfMul( MIk[I], PInv );
|
MIk[I] = gfMul( MIk[I], PInv );
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint I = 0; I < NE; I++)
|
for (uint I = 0; I < NE; I++)
|
||||||
if (I != Kr) // For all rows except containing the pivot cell.
|
if (I != Kr) // For all rows except containing the pivot cell.
|
||||||
{
|
{
|
||||||
// Apply Gaussian elimination Mij -= Mkj * Mik / pivot.
|
// Apply Gaussian elimination Mij -= Mkj * Mik / pivot.
|
||||||
// Since pivot is already 1, it is reduced to Mij -= Mkj * Mik.
|
// Since pivot is already 1, it is reduced to Mij -= Mkj * Mik.
|
||||||
uint *MXi = MX + I * ND; // i-th row of main matrix.
|
uint *MXi = MX + I * ND; // i-th row of main matrix.
|
||||||
|
@ -361,7 +361,7 @@ bool RSCoder16::SSE_UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte
|
||||||
__m128i LowBytes1=_mm_and_si128(D[1],LowByteMask);
|
__m128i LowBytes1=_mm_and_si128(D[1],LowByteMask);
|
||||||
__m128i HighBytes=_mm_packus_epi16(HighBytes0,HighBytes1);
|
__m128i HighBytes=_mm_packus_epi16(HighBytes0,HighBytes1);
|
||||||
__m128i LowBytes=_mm_packus_epi16(LowBytes0,LowBytes1);
|
__m128i LowBytes=_mm_packus_epi16(LowBytes0,LowBytes1);
|
||||||
|
|
||||||
// Multiply bits 0..3 of low bytes. Store low and high product bytes
|
// Multiply bits 0..3 of low bytes. Store low and high product bytes
|
||||||
// separately in cumulative sum variables.
|
// separately in cumulative sum variables.
|
||||||
__m128i LowBytesLow4=_mm_and_si128(LowBytes,Low4Mask);
|
__m128i LowBytesLow4=_mm_and_si128(LowBytes,Low4Mask);
|
||||||
|
@ -377,7 +377,7 @@ bool RSCoder16::SSE_UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte
|
||||||
// Add new product to existing sum, low and high bytes separately.
|
// Add new product to existing sum, low and high bytes separately.
|
||||||
LowBytesMultSum=_mm_xor_si128(LowBytesMultSum,LowBytesHigh4MultLow);
|
LowBytesMultSum=_mm_xor_si128(LowBytesMultSum,LowBytesHigh4MultLow);
|
||||||
HighBytesMultSum=_mm_xor_si128(HighBytesMultSum,LowBytesHigh4MultHigh);
|
HighBytesMultSum=_mm_xor_si128(HighBytesMultSum,LowBytesHigh4MultHigh);
|
||||||
|
|
||||||
// Multiply bits 0..3 of high bytes. Store low and high product bytes separately.
|
// Multiply bits 0..3 of high bytes. Store low and high product bytes separately.
|
||||||
__m128i HighBytesLow4=_mm_and_si128(HighBytes,Low4Mask);
|
__m128i HighBytesLow4=_mm_and_si128(HighBytes,Low4Mask);
|
||||||
__m128i HighBytesLow4MultLow=_mm_shuffle_epi8(T2L,HighBytesLow4);
|
__m128i HighBytesLow4MultLow=_mm_shuffle_epi8(T2L,HighBytesLow4);
|
||||||
|
@ -413,7 +413,7 @@ bool RSCoder16::SSE_UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte
|
||||||
// because Data and ECC can have different alignment offsets.
|
// because Data and ECC can have different alignment offsets.
|
||||||
for (; Pos<BlockSize; Pos+=2)
|
for (; Pos<BlockSize; Pos+=2)
|
||||||
*(ushort*)(ECC+Pos) ^= gfMul( M, *(ushort*)(Data+Pos) );
|
*(ushort*)(ECC+Pos) ^= gfMul( M, *(ushort*)(Data+Pos) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,13 +14,26 @@ class SaveFilePos
|
||||||
}
|
}
|
||||||
~SaveFilePos()
|
~SaveFilePos()
|
||||||
{
|
{
|
||||||
// If file is already closed by current exception processing,
|
// Unless the file is already closed either by current exception
|
||||||
// we would get uneeded error messages and an exception inside of
|
// processing or intentionally by external code.
|
||||||
// exception and terminate if we try to seek without checking
|
|
||||||
// if file is still opened. We should not also restore the position
|
|
||||||
// if external code closed the file on purpose.
|
|
||||||
if (SaveFile->IsOpened())
|
if (SaveFile->IsOpened())
|
||||||
SaveFile->Seek(SavePos,SEEK_SET);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SaveFile->Seek(SavePos,SEEK_SET);
|
||||||
|
}
|
||||||
|
catch(RAR_EXIT)
|
||||||
|
{
|
||||||
|
// Seek() can throw an exception and it terminates process
|
||||||
|
// if we are already processing another exception. Also in C++ 11
|
||||||
|
// an exception in destructor always terminates process unless
|
||||||
|
// we mark destructor with noexcept(false). So we do not want to
|
||||||
|
// throw here. To prevent data loss we do not want to continue
|
||||||
|
// execution after seek error, so we close the file.
|
||||||
|
// Any next access to this file will return an error.
|
||||||
|
SaveFile->Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,12 @@ bool ScanTree::GetFilteredMask()
|
||||||
bool WildcardFound=false;
|
bool WildcardFound=false;
|
||||||
uint FolderWildcardCount=0;
|
uint FolderWildcardCount=0;
|
||||||
uint SlashPos=0;
|
uint SlashPos=0;
|
||||||
for (int I=0;CurMask[I]!=0;I++)
|
uint StartPos=0;
|
||||||
|
#ifdef _WIN_ALL // Not treat the special NTFS \\?\d: path prefix as a wildcard.
|
||||||
|
if (CurMask[0]=='\\' && CurMask[1]=='\\' && CurMask[2]=='?' && CurMask[3]=='\\')
|
||||||
|
StartPos=4;
|
||||||
|
#endif
|
||||||
|
for (uint I=StartPos;CurMask[I]!=0;I++)
|
||||||
{
|
{
|
||||||
if (CurMask[I]=='?' || CurMask[I]=='*')
|
if (CurMask[I]=='?' || CurMask[I]=='*')
|
||||||
WildcardFound=true;
|
WildcardFound=true;
|
||||||
|
@ -171,7 +176,7 @@ bool ScanTree::GetFilteredMask()
|
||||||
|
|
||||||
wchar Filter[NM];
|
wchar Filter[NM];
|
||||||
// Convert path\dir*\ to *\dir filter to search for 'dir' in all 'path' subfolders.
|
// Convert path\dir*\ to *\dir filter to search for 'dir' in all 'path' subfolders.
|
||||||
wcscpy(Filter,L"*");
|
wcsncpyz(Filter,L"*",ASIZE(Filter));
|
||||||
AddEndSlash(Filter,ASIZE(Filter));
|
AddEndSlash(Filter,ASIZE(Filter));
|
||||||
// SlashPos might point or not point to path separator for masks like 'dir*', '\dir*' or 'd:dir*'
|
// SlashPos might point or not point to path separator for masks like 'dir*', '\dir*' or 'd:dir*'
|
||||||
wchar *WildName=IsPathDiv(CurMask[SlashPos]) || IsDriveDiv(CurMask[SlashPos]) ? CurMask+SlashPos+1 : CurMask+SlashPos;
|
wchar *WildName=IsPathDiv(CurMask[SlashPos]) || IsDriveDiv(CurMask[SlashPos]) ? CurMask+SlashPos+1 : CurMask+SlashPos;
|
||||||
|
@ -360,7 +365,7 @@ SCAN_CODE ScanTree::FindProc(FindData *FD)
|
||||||
wcsncpyz(CurMask,Mask+1,ASIZE(CurMask));
|
wcsncpyz(CurMask,Mask+1,ASIZE(CurMask));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*(PrevSlash+1)=0;
|
*PrevSlash=0;
|
||||||
wcsncatz(CurMask,Mask,ASIZE(CurMask));
|
wcsncatz(CurMask,Mask,ASIZE(CurMask));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ class ScanTree
|
||||||
ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs);
|
ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs);
|
||||||
~ScanTree();
|
~ScanTree();
|
||||||
SCAN_CODE GetNext(FindData *FindData);
|
SCAN_CODE GetNext(FindData *FindData);
|
||||||
size_t GetSpecPathLength() {return SpecPathLength;};
|
size_t GetSpecPathLength() {return SpecPathLength;}
|
||||||
int GetErrors() {return Errors;};
|
int GetErrors() {return Errors;};
|
||||||
void SetErrArcName(const wchar *Name) {wcsncpyz(ErrArcName,Name,ASIZE(ErrArcName));}
|
void SetErrArcName(const wchar *Name) {wcsncpyz(ErrArcName,Name,ASIZE(ErrArcName));}
|
||||||
void SetCommandData(CommandData *Cmd) {ScanTree::Cmd=Cmd;}
|
void SetCommandData(CommandData *Cmd) {ScanTree::Cmd=Cmd;}
|
||||||
|
|
|
@ -241,8 +241,8 @@ uint GetDigits(uint Number)
|
||||||
|
|
||||||
bool LowAscii(const char *Str)
|
bool LowAscii(const char *Str)
|
||||||
{
|
{
|
||||||
for (int I=0;Str[I]!=0;I++)
|
for (size_t I=0;Str[I]!=0;I++)
|
||||||
if ((byte)Str[I]<32 || (byte)Str[I]>127)
|
if (/*(byte)Str[I]<32 || */(byte)Str[I]>127)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -250,11 +250,11 @@ bool LowAscii(const char *Str)
|
||||||
|
|
||||||
bool LowAscii(const wchar *Str)
|
bool LowAscii(const wchar *Str)
|
||||||
{
|
{
|
||||||
for (int I=0;Str[I]!=0;I++)
|
for (size_t I=0;Str[I]!=0;I++)
|
||||||
{
|
{
|
||||||
// We convert wchar_t to uint just in case if some compiler
|
// We convert wchar_t to uint just in case if some compiler
|
||||||
// uses signed wchar_t.
|
// uses signed wchar_t.
|
||||||
if ((uint)Str[I]<32 || (uint)Str[I]>127)
|
if (/*(uint)Str[I]<32 || */(uint)Str[I]>127)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -281,53 +281,49 @@ int wcsnicompc(const wchar *s1,const wchar *s2,size_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Safe strncpy: copies maxlen-1 max and always returns zero terminated dest.
|
// Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
|
||||||
char* strncpyz(char *dest, const char *src, size_t maxlen)
|
void strncpyz(char *dest, const char *src, size_t maxlen)
|
||||||
{
|
{
|
||||||
if (maxlen>0)
|
if (maxlen>0)
|
||||||
{
|
{
|
||||||
strncpy(dest,src,maxlen-1);
|
while (--maxlen>0 && *src!=0)
|
||||||
dest[maxlen-1]=0;
|
*dest++=*src++;
|
||||||
|
*dest=0;
|
||||||
}
|
}
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Safe wcsncpy: copies maxlen-1 max and always returns zero terminated dest.
|
// Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
|
||||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
|
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
|
||||||
{
|
{
|
||||||
if (maxlen>0)
|
if (maxlen>0)
|
||||||
{
|
{
|
||||||
wcsncpy(dest,src,maxlen-1);
|
while (--maxlen>0 && *src!=0)
|
||||||
dest[maxlen-1]=0;
|
*dest++=*src++;
|
||||||
|
*dest=0;
|
||||||
}
|
}
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Safe strncat: resulting dest length cannot exceed maxlen and dest
|
// Safe append: resulting dest length cannot exceed maxlen and dest
|
||||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
// is always zero terminated. 'maxlen' parameter defines the entire
|
||||||
// dest buffer size and is not compatible with standard strncat.
|
// dest buffer size and is not compatible with wcsncat.
|
||||||
char* strncatz(char* dest, const char* src, size_t maxlen)
|
void strncatz(char* dest, const char* src, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t Length = strlen(dest);
|
size_t length = strlen(dest);
|
||||||
int avail=int(maxlen - Length - 1);
|
if (maxlen > length)
|
||||||
if (avail > 0)
|
strncpyz(dest + length, src, maxlen - length);
|
||||||
strncat(dest, src, avail);
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Safe wcsncat: resulting dest length cannot exceed maxlen and dest
|
// Safe append: resulting dest length cannot exceed maxlen and dest
|
||||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
// is always zero terminated. 'maxlen' parameter defines the entire
|
||||||
// dest buffer size and is not compatible with standard wcsncat.
|
// dest buffer size and is not compatible with wcsncat.
|
||||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
|
void wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
|
||||||
{
|
{
|
||||||
size_t Length = wcslen(dest);
|
size_t length = wcslen(dest);
|
||||||
int avail=int(maxlen - Length - 1);
|
if (maxlen > length)
|
||||||
if (avail > 0)
|
wcsncpyz(dest + length, src, maxlen - length);
|
||||||
wcsncat(dest, src, avail);
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,10 @@ wchar* RemoveLF(wchar *Str);
|
||||||
unsigned char loctolower(unsigned char ch);
|
unsigned char loctolower(unsigned char ch);
|
||||||
unsigned char loctoupper(unsigned char ch);
|
unsigned char loctoupper(unsigned char ch);
|
||||||
|
|
||||||
char* strncpyz(char *dest, const char *src, size_t maxlen);
|
void strncpyz(char *dest, const char *src, size_t maxlen);
|
||||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
||||||
char* strncatz(char* dest, const char* src, size_t maxlen);
|
void strncatz(char* dest, const char* src, size_t maxlen);
|
||||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
void wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
||||||
|
|
||||||
unsigned char etoupper(unsigned char ch);
|
unsigned char etoupper(unsigned char ch);
|
||||||
wchar etoupperw(wchar ch);
|
wchar etoupperw(wchar ch);
|
||||||
|
|
|
@ -80,7 +80,7 @@ bool SubAllocator::StartSubAllocator(int SASize)
|
||||||
{
|
{
|
||||||
uint t=SASize << 20;
|
uint t=SASize << 20;
|
||||||
if (SubAllocatorSize == t)
|
if (SubAllocatorSize == t)
|
||||||
return TRUE;
|
return true;
|
||||||
StopSubAllocator();
|
StopSubAllocator();
|
||||||
|
|
||||||
// Original algorithm expects FIXED_UNIT_SIZE, but actual structure size
|
// Original algorithm expects FIXED_UNIT_SIZE, but actual structure size
|
||||||
|
@ -91,7 +91,7 @@ bool SubAllocator::StartSubAllocator(int SASize)
|
||||||
if ((HeapStart=(byte *)malloc(AllocSize)) == NULL)
|
if ((HeapStart=(byte *)malloc(AllocSize)) == NULL)
|
||||||
{
|
{
|
||||||
ErrHandler.MemoryError();
|
ErrHandler.MemoryError();
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HeapEnd did not present in original algorithm. We added it to control
|
// HeapEnd did not present in original algorithm. We added it to control
|
||||||
|
@ -99,7 +99,7 @@ bool SubAllocator::StartSubAllocator(int SASize)
|
||||||
HeapEnd=HeapStart+AllocSize-UNIT_SIZE;
|
HeapEnd=HeapStart+AllocSize-UNIT_SIZE;
|
||||||
|
|
||||||
SubAllocatorSize=t;
|
SubAllocatorSize=t;
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ class SubAllocator
|
||||||
inline void* ExpandUnits(void* ptr,int OldNU);
|
inline void* ExpandUnits(void* ptr,int OldNU);
|
||||||
inline void* ShrinkUnits(void* ptr,int OldNU,int NewNU);
|
inline void* ShrinkUnits(void* ptr,int OldNU,int NewNU);
|
||||||
inline void FreeUnits(void* ptr,int OldNU);
|
inline void FreeUnits(void* ptr,int OldNU);
|
||||||
long GetAllocatedMemory() {return(SubAllocatorSize);};
|
long GetAllocatedMemory() {return(SubAllocatorSize);}
|
||||||
|
|
||||||
byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
|
byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
|
||||||
};
|
};
|
||||||
|
|
|
@ -123,6 +123,28 @@ void Shutdown(POWER_MODE Mode)
|
||||||
if (Mode==POWERMODE_RESTART)
|
if (Mode==POWERMODE_RESTART)
|
||||||
ExitWindowsEx(EWX_REBOOT|EWX_FORCE,SHTDN_REASON_FLAG_PLANNED);
|
ExitWindowsEx(EWX_REBOOT|EWX_FORCE,SHTDN_REASON_FLAG_PLANNED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ShutdownCheckAnother(bool Open)
|
||||||
|
{
|
||||||
|
const wchar *EventName=L"rar -ioff";
|
||||||
|
static HANDLE hEvent=NULL;
|
||||||
|
bool Result=false; // Return false if no other RAR -ioff are running.
|
||||||
|
if (Open) // Create or open the event.
|
||||||
|
hEvent=CreateEvent(NULL,FALSE,FALSE,EventName);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (hEvent!=NULL)
|
||||||
|
CloseHandle(hEvent); // Close our event.
|
||||||
|
// Check if other copies still own the event. While race conditions
|
||||||
|
// are possible, they are improbable and their harm is minimal.
|
||||||
|
hEvent=CreateEvent(NULL,FALSE,FALSE,EventName);
|
||||||
|
Result=GetLastError()==ERROR_ALREADY_EXISTS;
|
||||||
|
if (hEvent!=NULL)
|
||||||
|
CloseHandle(hEvent);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,18 +187,29 @@ SSE_VERSION _SSE_Version=GetSSEVersion();
|
||||||
SSE_VERSION GetSSEVersion()
|
SSE_VERSION GetSSEVersion()
|
||||||
{
|
{
|
||||||
int CPUInfo[4];
|
int CPUInfo[4];
|
||||||
__cpuid(CPUInfo, 7);
|
__cpuid(CPUInfo, 0x80000000);
|
||||||
if ((CPUInfo[1] & 0x20)!=0)
|
|
||||||
return SSE_AVX2;
|
// Maximum supported cpuid function. For example, Pentium M 755 returns 4 here.
|
||||||
__cpuid(CPUInfo, 1);
|
uint MaxSupported=CPUInfo[0] & 0x7fffffff;
|
||||||
if ((CPUInfo[2] & 0x80000)!=0)
|
|
||||||
return SSE_SSE41;
|
if (MaxSupported>=7)
|
||||||
if ((CPUInfo[2] & 0x200)!=0)
|
{
|
||||||
return SSE_SSSE3;
|
__cpuid(CPUInfo, 7);
|
||||||
if ((CPUInfo[3] & 0x4000000)!=0)
|
if ((CPUInfo[1] & 0x20)!=0)
|
||||||
return SSE_SSE2;
|
return SSE_AVX2;
|
||||||
if ((CPUInfo[3] & 0x2000000)!=0)
|
}
|
||||||
return SSE_SSE;
|
if (MaxSupported>=1)
|
||||||
|
{
|
||||||
|
__cpuid(CPUInfo, 1);
|
||||||
|
if ((CPUInfo[2] & 0x80000)!=0)
|
||||||
|
return SSE_SSE41;
|
||||||
|
if ((CPUInfo[2] & 0x200)!=0)
|
||||||
|
return SSE_SSSE3;
|
||||||
|
if ((CPUInfo[3] & 0x4000000)!=0)
|
||||||
|
return SSE_SSE2;
|
||||||
|
if ((CPUInfo[3] & 0x2000000)!=0)
|
||||||
|
return SSE_SSE;
|
||||||
|
}
|
||||||
return SSE_NONE;
|
return SSE_NONE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,6 +23,7 @@ clock_t MonoClock();
|
||||||
void Wait();
|
void Wait();
|
||||||
bool EmailFile(const wchar *FileName,const wchar *MailToW);
|
bool EmailFile(const wchar *FileName,const wchar *MailToW);
|
||||||
void Shutdown(POWER_MODE Mode);
|
void Shutdown(POWER_MODE Mode);
|
||||||
|
bool ShutdownCheckAnother(bool Open);
|
||||||
|
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
HMODULE WINAPI LoadSysLibrary(const wchar *Name);
|
HMODULE WINAPI LoadSysLibrary(const wchar *Name);
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
// Typically we use the same global thread pool for all RAR modules.
|
|
||||||
static ThreadPool *GlobalPool=NULL;
|
|
||||||
static uint GlobalPoolUseCount=0;
|
|
||||||
|
|
||||||
static inline bool CriticalSectionCreate(CRITSECT_HANDLE *CritSection)
|
static inline bool CriticalSectionCreate(CRITSECT_HANDLE *CritSection)
|
||||||
{
|
{
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
|
@ -43,57 +39,6 @@ static inline void CriticalSectionEnd(CRITSECT_HANDLE *CritSection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct GlobalPoolCreateSync
|
|
||||||
{
|
|
||||||
CRITSECT_HANDLE CritSection;
|
|
||||||
GlobalPoolCreateSync() { CriticalSectionCreate(&CritSection); }
|
|
||||||
~GlobalPoolCreateSync() { CriticalSectionDelete(&CritSection); }
|
|
||||||
} PoolCreateSync;
|
|
||||||
|
|
||||||
|
|
||||||
ThreadPool* CreateThreadPool()
|
|
||||||
{
|
|
||||||
CriticalSectionStart(&PoolCreateSync.CritSection);
|
|
||||||
|
|
||||||
if (GlobalPoolUseCount++ == 0)
|
|
||||||
GlobalPool=new ThreadPool(MaxPoolThreads);
|
|
||||||
|
|
||||||
// We use a simple thread pool, which does not allow to add tasks from
|
|
||||||
// different functions and threads in the same time. It is ok for RAR,
|
|
||||||
// but UnRAR.dll can be used in multithreaded environment. So if one of
|
|
||||||
// threads requests a copy of global pool and another copy is already
|
|
||||||
// in use, we create and return a new pool instead of existing global.
|
|
||||||
if (GlobalPoolUseCount > 1)
|
|
||||||
{
|
|
||||||
ThreadPool *Pool = new ThreadPool(MaxPoolThreads);
|
|
||||||
CriticalSectionEnd(&PoolCreateSync.CritSection);
|
|
||||||
return Pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
CriticalSectionEnd(&PoolCreateSync.CritSection);
|
|
||||||
return GlobalPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DestroyThreadPool(ThreadPool *Pool)
|
|
||||||
{
|
|
||||||
if (Pool!=NULL)
|
|
||||||
{
|
|
||||||
CriticalSectionStart(&PoolCreateSync.CritSection);
|
|
||||||
|
|
||||||
if (Pool==GlobalPool && GlobalPoolUseCount > 0 && --GlobalPoolUseCount == 0)
|
|
||||||
delete GlobalPool;
|
|
||||||
|
|
||||||
// To correctly work in multithreaded environment UnRAR.dll creates
|
|
||||||
// new pools if global pool is already in use. We delete such pools here.
|
|
||||||
if (Pool!=GlobalPool)
|
|
||||||
delete Pool;
|
|
||||||
|
|
||||||
CriticalSectionEnd(&PoolCreateSync.CritSection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static THREAD_HANDLE ThreadCreate(NATIVE_THREAD_PTR Proc,void *Data)
|
static THREAD_HANDLE ThreadCreate(NATIVE_THREAD_PTR Proc,void *Data)
|
||||||
{
|
{
|
||||||
#ifdef _UNIX
|
#ifdef _UNIX
|
||||||
|
|
|
@ -170,12 +170,13 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data)
|
||||||
CreateThreads();
|
CreateThreads();
|
||||||
|
|
||||||
// If queue is full, wait until it is empty.
|
// If queue is full, wait until it is empty.
|
||||||
if ((QueueTop + 1) % ASIZE(TaskQueue) == QueueBottom)
|
if (ActiveThreads>=ASIZE(TaskQueue))
|
||||||
WaitDone();
|
WaitDone();
|
||||||
|
|
||||||
TaskQueue[QueueTop].Proc = Proc;
|
TaskQueue[QueueTop].Proc = Proc;
|
||||||
TaskQueue[QueueTop].Param = Data;
|
TaskQueue[QueueTop].Param = Data;
|
||||||
QueueTop = (QueueTop + 1) % ASIZE(TaskQueue);
|
QueueTop = (QueueTop + 1) % ASIZE(TaskQueue);
|
||||||
|
ActiveThreads++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,9 +185,6 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data)
|
||||||
// are sleeping yet.
|
// are sleeping yet.
|
||||||
void ThreadPool::WaitDone()
|
void ThreadPool::WaitDone()
|
||||||
{
|
{
|
||||||
// We add ASIZE(TaskQueue) for case if TaskQueue array size is not
|
|
||||||
// a power of two. Negative numbers would not suit our purpose here.
|
|
||||||
ActiveThreads=(QueueTop+ASIZE(TaskQueue)-QueueBottom) % ASIZE(TaskQueue);
|
|
||||||
if (ActiveThreads==0)
|
if (ActiveThreads==0)
|
||||||
return;
|
return;
|
||||||
#ifdef _WIN_ALL
|
#ifdef _WIN_ALL
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue