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 "sindresorhus/DockProgress" "v3.2.0"
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
"commitish" : "v3.2.0",
|
||||
"Mac" : [
|
||||
{
|
||||
"hash" : "13e7fe07ca491fe900ae7c858e66797a66d0a2e1dffde3a2c0b64188b211012e",
|
||||
"hash" : "19676367de93b3ec3bc61b60e454d565ca1c47fe32c4116ef78955c7ecdfcd1e",
|
||||
"name" : "DockProgress",
|
||||
"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" : [
|
||||
{
|
||||
"name" : "UnrarKit",
|
||||
"hash" : "0ee8db439c431777277ec76976faa8a1d19ba93d3f6977094746350e942215d3",
|
||||
"hash" : "e18e69a1e9f0344776a442bf542e0a45be0427977b765897399058bb766e83db",
|
||||
"linking" : "dynamic"
|
||||
}
|
||||
],
|
||||
|
@ -12,11 +12,11 @@
|
|||
"tvOS" : [
|
||||
|
||||
],
|
||||
"commitish" : "2.9",
|
||||
"commitish" : "2.10",
|
||||
"iOS" : [
|
||||
{
|
||||
"name" : "UnrarKit",
|
||||
"hash" : "2c752a88c360be277b938f55190d07bc6688ce0452932b4fbf52a12e9bfcf5d0",
|
||||
"hash" : "308b414f23c29d8599f7b214fb8ef39ea574ac8117b21b6946a7c969b9cf38b4",
|
||||
"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
|
||||
#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
|
||||
#define DOCKPROGRESS_SWIFT_H
|
||||
#pragma clang diagnostic push
|
||||
|
@ -186,6 +186,13 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
|
|||
#if !defined(IBSegueAction)
|
||||
# define IBSegueAction
|
||||
#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_warning("-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
|
||||
|
||||
#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
|
||||
#define DOCKPROGRESS_SWIFT_H
|
||||
#pragma clang diagnostic push
|
||||
|
@ -407,6 +414,13 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
|
|||
#if !defined(IBSegueAction)
|
||||
# define IBSegueAction
|
||||
#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_warning("-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">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>20E241</string>
|
||||
<string>21F5048e</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>DockProgress</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
@ -23,19 +23,19 @@
|
|||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>12E262</string>
|
||||
<string>13E500a</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>11.3</string>
|
||||
<string>12.3</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>20E214</string>
|
||||
<string>21E226</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx11.3</string>
|
||||
<string>macosx12.3</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1250</string>
|
||||
<string>1331</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>12E262</string>
|
||||
<string>13E500a</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.12</string>
|
||||
</dict>
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.9</string>
|
||||
<string>2.10-beta8</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.9</string>
|
||||
<string>2.10-beta8</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Binary file not shown.
|
@ -6,14 +6,14 @@
|
|||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UnrarKitMacros.h"
|
||||
#import <UnrarKit/UnrarKitMacros.h>
|
||||
|
||||
RarosHppIgnore
|
||||
#import "raros.hpp"
|
||||
#import <UnrarKit/raros.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
DllHppIgnore
|
||||
#import "dll.hpp"
|
||||
#import <UnrarKit/dll.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
@class URKFileInfo;
|
||||
|
@ -25,7 +25,7 @@ DllHppIgnore
|
|||
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||
|
||||
/**
|
||||
* The archive's header is empty
|
||||
* The last file of the archive has been read
|
||||
*/
|
||||
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
||||
|
||||
|
@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) {
|
|||
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
||||
|
||||
/**
|
||||
* The header is broken
|
||||
* The header's CRC doesn't match the decompressed data's CRC
|
||||
*/
|
||||
URKErrorCodeBadData = ERAR_BAD_DATA,
|
||||
|
||||
|
@ -173,6 +173,17 @@ extern NSString *URKErrorDomain;
|
|||
*/
|
||||
@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
|
||||
|
@ -475,15 +486,34 @@ extern NSString *URKErrorDomain;
|
|||
- (BOOL)validatePassword;
|
||||
|
||||
/**
|
||||
Extract each file in the archive, checking whether the data matches the CRC checksum
|
||||
stored at the time it was written
|
||||
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||
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;
|
||||
|
||||
/**
|
||||
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
|
||||
|
||||
@param filePath The file in the archive to check
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UnrarKitMacros.h"
|
||||
#import <UnrarKit/UnrarKitMacros.h>
|
||||
|
||||
RarosHppIgnore
|
||||
#import "raros.hpp"
|
||||
#import <UnrarKit/raros.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
DllHppIgnore
|
||||
#import "dll.hpp"
|
||||
#import <UnrarKit/dll.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
/* See http://www.forensicswiki.org/wiki/RAR and
|
||||
|
|
|
@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber;
|
|||
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
||||
|
||||
|
||||
#import "URKArchive.h"
|
||||
#import "URKFileInfo.h"
|
||||
#import <UnrarKit/URKArchive.h>
|
||||
#import <UnrarKit/URKFileInfo.h>
|
||||
|
|
|
@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \
|
|||
#import <os/activity.h>
|
||||
|
||||
// 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
|
||||
#define URKLogInit() \
|
||||
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _UNRAR_DLL_
|
||||
#define _UNRAR_DLL_
|
||||
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define ERAR_SUCCESS 0
|
||||
#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_FIRSTVOLUME 0x0100
|
||||
|
||||
#define ROADOF_KEEPBROKEN 0x0001
|
||||
|
||||
struct RAROpenArchiveDataEx
|
||||
{
|
||||
char *ArcName;
|
||||
|
@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx
|
|||
unsigned int Flags;
|
||||
UNRARCALLBACK Callback;
|
||||
LPARAM UserData;
|
||||
unsigned int Reserved[28];
|
||||
unsigned int OpFlags;
|
||||
wchar_t *CmtBufW;
|
||||
unsigned int Reserved[25];
|
||||
};
|
||||
|
||||
enum UNRARCALLBACK_MESSAGES {
|
||||
|
@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion();
|
|||
}
|
||||
#endif
|
||||
|
||||
#pragma pack()
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>17D47</string>
|
||||
<string>19H2</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
@ -17,7 +17,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.9</string>
|
||||
<string>2.10-beta8</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
|
@ -25,20 +25,24 @@
|
|||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.9</string>
|
||||
<string>2.10-beta8</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>9E145</string>
|
||||
<string>12A7300</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<string>10.15.6</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>17E189</string>
|
||||
<string>19G68</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.13</string>
|
||||
<string>macosx10.15</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0930</string>
|
||||
<string>1201</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>9E145</string>
|
||||
<string>12A7300</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>17D47</string>
|
||||
<string>19H2</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
@ -15,7 +15,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.9</string>
|
||||
<string>2.10-beta8</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
|
@ -23,21 +23,25 @@
|
|||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.9</string>
|
||||
<string>2.10-beta8</string>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformBuild</key>
|
||||
<string>9E145</string>
|
||||
<string>12A7300</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>macosx</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>GM</string>
|
||||
<string>10.15.6</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>17E189</string>
|
||||
<string>19G68</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>macosx10.13</string>
|
||||
<string>macosx10.15</string>
|
||||
<key>DTXcode</key>
|
||||
<string>0930</string>
|
||||
<string>1201</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>9E145</string>
|
||||
<string>12A7300</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2017 Abbey Code. All rights reserved.</string>
|
||||
</dict>
|
||||
|
|
Binary file not shown.
|
@ -13,8 +13,8 @@
|
|||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.9</string>
|
||||
<string>2.10-beta8</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.9</string>
|
||||
<string>2.10-beta8</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Binary file not shown.
|
@ -6,14 +6,14 @@
|
|||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UnrarKitMacros.h"
|
||||
#import <UnrarKit/UnrarKitMacros.h>
|
||||
|
||||
RarosHppIgnore
|
||||
#import "raros.hpp"
|
||||
#import <UnrarKit/raros.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
DllHppIgnore
|
||||
#import "dll.hpp"
|
||||
#import <UnrarKit/dll.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
@class URKFileInfo;
|
||||
|
@ -25,7 +25,7 @@ DllHppIgnore
|
|||
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||
|
||||
/**
|
||||
* The archive's header is empty
|
||||
* The last file of the archive has been read
|
||||
*/
|
||||
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
||||
|
||||
|
@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) {
|
|||
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
||||
|
||||
/**
|
||||
* The header is broken
|
||||
* The header's CRC doesn't match the decompressed data's CRC
|
||||
*/
|
||||
URKErrorCodeBadData = ERAR_BAD_DATA,
|
||||
|
||||
|
@ -173,6 +173,17 @@ extern NSString *URKErrorDomain;
|
|||
*/
|
||||
@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
|
||||
|
@ -475,15 +486,34 @@ extern NSString *URKErrorDomain;
|
|||
- (BOOL)validatePassword;
|
||||
|
||||
/**
|
||||
Extract each file in the archive, checking whether the data matches the CRC checksum
|
||||
stored at the time it was written
|
||||
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||
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;
|
||||
|
||||
/**
|
||||
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
|
||||
|
||||
@param filePath The file in the archive to check
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UnrarKitMacros.h"
|
||||
#import <UnrarKit/UnrarKitMacros.h>
|
||||
|
||||
RarosHppIgnore
|
||||
#import "raros.hpp"
|
||||
#import <UnrarKit/raros.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
DllHppIgnore
|
||||
#import "dll.hpp"
|
||||
#import <UnrarKit/dll.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
/* See http://www.forensicswiki.org/wiki/RAR and
|
||||
|
|
|
@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber;
|
|||
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
||||
|
||||
|
||||
#import "URKArchive.h"
|
||||
#import "URKFileInfo.h"
|
||||
#import <UnrarKit/URKArchive.h>
|
||||
#import <UnrarKit/URKFileInfo.h>
|
||||
|
|
|
@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \
|
|||
#import <os/activity.h>
|
||||
|
||||
// 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
|
||||
#define URKLogInit() \
|
||||
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _UNRAR_DLL_
|
||||
#define _UNRAR_DLL_
|
||||
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define ERAR_SUCCESS 0
|
||||
#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_FIRSTVOLUME 0x0100
|
||||
|
||||
#define ROADOF_KEEPBROKEN 0x0001
|
||||
|
||||
struct RAROpenArchiveDataEx
|
||||
{
|
||||
char *ArcName;
|
||||
|
@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx
|
|||
unsigned int Flags;
|
||||
UNRARCALLBACK Callback;
|
||||
LPARAM UserData;
|
||||
unsigned int Reserved[28];
|
||||
unsigned int OpFlags;
|
||||
wchar_t *CmtBufW;
|
||||
unsigned int Reserved[25];
|
||||
};
|
||||
|
||||
enum UNRARCALLBACK_MESSAGES {
|
||||
|
@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion();
|
|||
}
|
||||
#endif
|
||||
|
||||
#pragma pack()
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,7 +1,12 @@
|
|||
language: objective-c
|
||||
osx_image: xcode9.3
|
||||
osx_image: xcode12
|
||||
|
||||
branches:
|
||||
except:
|
||||
- circle-ci
|
||||
|
||||
before_script:
|
||||
- pod --version
|
||||
# Make log level less verbose. Temporarily undo if more info is needed
|
||||
- sudo log config --mode "level:default"
|
||||
|
||||
|
@ -15,7 +20,7 @@ matrix:
|
|||
- stage: Test
|
||||
env: Name=iOS
|
||||
# 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
|
||||
env: Name=ExampleAppBuild
|
||||
|
@ -32,5 +37,4 @@ matrix:
|
|||
|
||||
- stage: Release
|
||||
if: tag IS present
|
||||
before_install: brew upgrade python # Needs Python 3
|
||||
script: ./Scripts/push-output.sh
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
# 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
|
||||
|
||||
* Added support for `NSProgress` and `NSProgressReporting` in all extraction and iteration methods (Issue #34)
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UnrarKitMacros.h"
|
||||
#import <UnrarKit/UnrarKitMacros.h>
|
||||
|
||||
RarosHppIgnore
|
||||
#import "raros.hpp"
|
||||
#import <UnrarKit/raros.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
DllHppIgnore
|
||||
#import "dll.hpp"
|
||||
#import <UnrarKit/dll.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
@class URKFileInfo;
|
||||
|
@ -25,7 +25,7 @@ DllHppIgnore
|
|||
typedef NS_ENUM(NSInteger, URKErrorCode) {
|
||||
|
||||
/**
|
||||
* The archive's header is empty
|
||||
* The last file of the archive has been read
|
||||
*/
|
||||
URKErrorCodeEndOfArchive = ERAR_END_ARCHIVE,
|
||||
|
||||
|
@ -35,7 +35,7 @@ typedef NS_ENUM(NSInteger, URKErrorCode) {
|
|||
URKErrorCodeNoMemory = ERAR_NO_MEMORY,
|
||||
|
||||
/**
|
||||
* The header is broken
|
||||
* The header's CRC doesn't match the decompressed data's CRC
|
||||
*/
|
||||
URKErrorCodeBadData = ERAR_BAD_DATA,
|
||||
|
||||
|
@ -173,6 +173,17 @@ extern NSString *URKErrorDomain;
|
|||
*/
|
||||
@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
|
||||
|
@ -475,15 +486,34 @@ extern NSString *URKErrorDomain;
|
|||
- (BOOL)validatePassword;
|
||||
|
||||
/**
|
||||
Extract each file in the archive, checking whether the data matches the CRC checksum
|
||||
stored at the time it was written
|
||||
Iterate through the archive, checking for any errors, including CRC mismatches between
|
||||
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;
|
||||
|
||||
/**
|
||||
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
|
||||
|
||||
@param filePath The file in the archive to check
|
||||
|
|
|
@ -28,6 +28,11 @@ BOOL unrarkitIsAtLeast10_13SDK;
|
|||
|
||||
static NSBundle *_resources = nil;
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
URKReadHeaderLoopActionStopReading,
|
||||
URKReadHeaderLoopActionContinueReading,
|
||||
} URKReadHeaderLoopAction;
|
||||
|
||||
|
||||
@interface URKArchive ()
|
||||
|
||||
|
@ -46,6 +51,9 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
@property (strong) NSObject *threadLock;
|
||||
|
||||
@property (copy) NSString *lastArchivePath;
|
||||
@property (copy) NSString *lastFilepath;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -161,6 +169,10 @@ NS_DESIGNATED_INITIALIZER
|
|||
_password = password;
|
||||
_threadLock = [[NSObject alloc] init];
|
||||
|
||||
_lastArchivePath = nil;
|
||||
_lastFilepath = nil;
|
||||
_ignoreCRCMismatches = NO;
|
||||
|
||||
if (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]);
|
||||
}
|
||||
@catch (NSException *e) {
|
||||
URKLogError("Error checking if %{public}@ is a RAR archive: %{public}@", filePath, e);
|
||||
}
|
||||
@finally {
|
||||
[handle closeFile];
|
||||
}
|
||||
|
@ -508,8 +523,7 @@ NS_DESIGNATED_INITIALIZER
|
|||
URKLogInfo("Extracting to %{public}@", filePath);
|
||||
|
||||
URKLogDebug("Reading through RAR header looking for files...");
|
||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) {
|
||||
fileInfo = [URKFileInfo fileInfo:welf.header];
|
||||
while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) {
|
||||
URKLogDebug("Extracting %{public}@ (%{iec-bytes}lld)", fileInfo.filename, fileInfo.uncompressedSize);
|
||||
NSURL *extractedURL = [[NSURL fileURLWithPath:filePath] URLByAppendingPathComponent:fileInfo.filename];
|
||||
[progress setUserInfoObject:extractedURL
|
||||
|
@ -517,7 +531,7 @@ NS_DESIGNATED_INITIALIZER
|
|||
[progress setUserInfoObject:fileInfo
|
||||
forKey:URKProgressInfoKeyFileInfoExtracting];
|
||||
|
||||
if ([self headerContainsErrors:innerError]) {
|
||||
if ([welf headerContainsErrors:innerError]) {
|
||||
URKLogError("Header contains an error")
|
||||
result = NO;
|
||||
return;
|
||||
|
@ -525,7 +539,7 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
if (progress.isCancelled) {
|
||||
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);
|
||||
result = NO;
|
||||
return;
|
||||
|
@ -537,7 +551,7 @@ NS_DESIGNATED_INITIALIZER
|
|||
encoding:NSUTF8StringEncoding];
|
||||
if (!utf8ConversionSucceeded) {
|
||||
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?)");
|
||||
result = NO;
|
||||
return;
|
||||
|
@ -550,12 +564,13 @@ NS_DESIGNATED_INITIALIZER
|
|||
};
|
||||
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);
|
||||
|
||||
NSString *errorName = nil;
|
||||
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);
|
||||
result = NO;
|
||||
return;
|
||||
|
@ -583,9 +598,9 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
RARSetCallback(welf.rarFile, NULL, NULL);
|
||||
|
||||
if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) {
|
||||
if (![welf didReturnSuccessfully:RHCode]) {
|
||||
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);
|
||||
result = NO;
|
||||
}
|
||||
|
@ -642,14 +657,12 @@ NS_DESIGNATED_INITIALIZER
|
|||
URKFileInfo *fileInfo;
|
||||
|
||||
URKLogDebug("Reading through RAR header looking for files...");
|
||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) {
|
||||
if ([self headerContainsErrors:innerError]) {
|
||||
while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) {
|
||||
if ([welf headerContainsErrors:innerError]) {
|
||||
URKLogError("Header contains an error")
|
||||
return;
|
||||
}
|
||||
|
||||
fileInfo = [URKFileInfo fileInfo:welf.header];
|
||||
|
||||
if ([fileInfo.filename isEqualToString:filePath]) {
|
||||
URKLogDebug("Extracting %{public}@", fileInfo.filename);
|
||||
break;
|
||||
|
@ -658,7 +671,7 @@ NS_DESIGNATED_INITIALIZER
|
|||
URKLogDebug("Skipping %{public}@", fileInfo.filename);
|
||||
if ((PFCode = RARProcessFileW(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -667,7 +680,7 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
if (RHCode != ERAR_SUCCESS) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -715,14 +728,14 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
if (progress.isCancelled) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PFCode != 0) {
|
||||
if (![welf didReturnSuccessfully:PFCode]) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -813,27 +826,36 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
BOOL stop = NO;
|
||||
|
||||
NSProgress *progress = [self beginProgressOperation:totalSize.longLongValue];
|
||||
NSProgress *progress = [welf beginProgressOperation:totalSize.longLongValue];
|
||||
|
||||
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) {
|
||||
URKLogDebug("Action dictated an early stop");
|
||||
return;
|
||||
}
|
||||
|
||||
if ([self headerContainsErrors:innerError]) {
|
||||
if ([welf headerContainsErrors:innerError]) {
|
||||
URKLogError("Header contains an error")
|
||||
return;
|
||||
}
|
||||
|
||||
URKFileInfo *info = [URKFileInfo fileInfo:welf.header];
|
||||
URKLogDebug("Performing action on %{public}@", info.filename);
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -845,9 +867,9 @@ NS_DESIGNATED_INITIALIZER
|
|||
URKLogInfo("Processing file...");
|
||||
PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL);
|
||||
|
||||
if (PFCode != 0) {
|
||||
if (![welf didReturnSuccessfully:PFCode]) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -861,14 +883,14 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
if (progress.isCancelled) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) {
|
||||
if (![welf didReturnSuccessfully:RHCode]) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -897,24 +919,22 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
URKLogInfo("Looping through files, looking for %{public}@...", filePath);
|
||||
|
||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == ERAR_SUCCESS) {
|
||||
if ([self headerContainsErrors:innerError]) {
|
||||
while ([welf readHeader:&RHCode info:&fileInfo] == URKReadHeaderLoopActionContinueReading) {
|
||||
if ([welf headerContainsErrors:innerError]) {
|
||||
URKLogDebug("Header contains error")
|
||||
return;
|
||||
}
|
||||
|
||||
URKLogDebug("Getting file info from header");
|
||||
fileInfo = [URKFileInfo fileInfo:welf.header];
|
||||
|
||||
if ([fileInfo.filename isEqualToString:filePath]) {
|
||||
URKLogDebug("Found desired file");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
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;
|
||||
[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);
|
||||
return;
|
||||
}
|
||||
|
@ -924,9 +944,9 @@ NS_DESIGNATED_INITIALIZER
|
|||
long long totalBytes = fileInfo.uncompressedSize;
|
||||
progress.totalUnitCount = totalBytes;
|
||||
|
||||
if (RHCode != ERAR_SUCCESS) {
|
||||
if (![welf didReturnSuccessfully:RHCode]) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -965,14 +985,14 @@ NS_DESIGNATED_INITIALIZER
|
|||
|
||||
if (progress.isCancelled) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PFCode != 0) {
|
||||
if (![welf didReturnSuccessfully:PFCode]) {
|
||||
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);
|
||||
}
|
||||
} inMode:RAR_OM_EXTRACT error:&actionError];
|
||||
|
@ -1049,7 +1069,7 @@ NS_DESIGNATED_INITIALIZER
|
|||
int RHCode = RARReadHeaderEx(welf.rarFile, welf.header);
|
||||
int PFCode = RARProcessFile(welf.rarFile, RAR_TEST, NULL, NULL);
|
||||
|
||||
if ([self headerContainsErrors:innerError]) {
|
||||
if ([welf headerContainsErrors:innerError]) {
|
||||
if (error.code == ERAR_MISSING_PASSWORD) {
|
||||
URKLogDebug("Password invalidated by header");
|
||||
passwordIsGood = NO;
|
||||
|
@ -1062,13 +1082,18 @@ NS_DESIGNATED_INITIALIZER
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
URKLogDebug("Missing/bad password indicated by RHCode (%d) or PFCode (%d)", RHCode, PFCode);
|
||||
passwordIsGood = NO;
|
||||
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];
|
||||
|
||||
if (!success) {
|
||||
|
@ -1084,47 +1109,96 @@ NS_DESIGNATED_INITIALIZER
|
|||
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");
|
||||
|
||||
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;
|
||||
[self performOnFilesInArchive:^(URKFileInfo *fileInfo, BOOL *stop) {
|
||||
BOOL wasSuccessful = [self performActionWithArchiveOpen:^(NSError **innerError) {
|
||||
URKCreateActivity("Iterating through each file");
|
||||
corruptDataFound = NO; // Set inside here so invalid archives are marked as corrupt
|
||||
if (filePath && ![fileInfo.filename isEqualToString:filePath]) return;
|
||||
while (true) {
|
||||
URKFileInfo *fileInfo = nil;
|
||||
[welf readHeader:&RHCode info:&fileInfo];
|
||||
welf.lastFilepath = nil;
|
||||
welf.lastArchivePath = nil;
|
||||
|
||||
URKLogDebug("Extracting '%{public}@ to check its CRC...", fileInfo.filename);
|
||||
NSError *extractError = nil;
|
||||
NSData *fileData = [self extractData:fileInfo error:&extractError];
|
||||
if (!fileData) {
|
||||
URKLogError("Error extracting %{public}@: %{public}@", fileInfo.filename, extractError);
|
||||
*stop = YES;
|
||||
return;
|
||||
if (RHCode == ERAR_END_ARCHIVE) {
|
||||
RHCode = ERAR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
URKLogDebug("Checking integrity of %{public}@. Expected CRC: %010lu vs. Actual: %010lu",
|
||||
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 (RHCode == ERAR_END_ARCHIVE) {
|
||||
RHCode = ERAR_SUCCESS;
|
||||
}
|
||||
|
||||
if (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...");
|
||||
|
||||
const char *filenameData = (const char *) [rarFile UTF8String];
|
||||
self.flags->ArcName = new char[strlen(filenameData) + 1];
|
||||
strcpy(self.flags->ArcName, filenameData);
|
||||
self.flags->OpenMode = (uint)mode;
|
||||
self.flags->ArcName = strdup(rarFile.UTF8String);
|
||||
self.flags->OpenMode = (uint)mode;
|
||||
self.flags->OpFlags = self.ignoreCRCMismatches ? ROADOF_KEEPBROKEN : 0;
|
||||
|
||||
URKLogDebug("Opening archive %{public}@...", rarFile);
|
||||
|
||||
self.rarFile = RAROpenArchiveEx(self.flags);
|
||||
if (self.rarFile == 0 || self.flags->OpenResult != 0) {
|
||||
self.rarFile = RAROpenArchiveEx(self.flags);
|
||||
if (self.rarFile == 0 || self.flags->OpenResult != 0) {
|
||||
NSString *errorName = nil;
|
||||
[self assignError:error code:(NSInteger)self.flags->OpenResult errorName:&errorName];
|
||||
URKLogError("Error opening archive: %{public}@ (%d)", errorName, self.flags->OpenResult);
|
||||
return NO;
|
||||
}
|
||||
|
||||
if(aPassword != nil) {
|
||||
self.lastFilepath = nil;
|
||||
self.lastArchivePath = nil;
|
||||
|
||||
if (aPassword != nil) {
|
||||
URKLogDebug("Setting password...");
|
||||
|
||||
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...");
|
||||
|
||||
while ((RHCode = RARReadHeaderEx(welf.rarFile, welf.header)) == 0) {
|
||||
URKFileInfo *info = nil;
|
||||
while ([welf readHeader:&RHCode info:&info] == URKReadHeaderLoopActionContinueReading) {
|
||||
URKLogDebug("Calling iterateAllFileInfo handler");
|
||||
BOOL shouldStop = NO;
|
||||
URKFileInfo *info = [URKFileInfo fileInfo:welf.header];
|
||||
action(info, &shouldStop);
|
||||
|
||||
if (shouldStop) {
|
||||
|
@ -1353,15 +1429,15 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon
|
|||
URKLogDebug("Skipping to next file...");
|
||||
if ((PFCode = RARProcessFile(welf.rarFile, RAR_SKIP, NULL, NULL)) != 0) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (RHCode != ERAR_SUCCESS && RHCode != ERAR_END_ARCHIVE) {
|
||||
if (![welf didReturnSuccessfully:RHCode]) {
|
||||
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);
|
||||
}
|
||||
} inMode:RAR_OM_LIST_INCSPLIT error:error];
|
||||
|
@ -1485,7 +1561,7 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon
|
|||
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1641,4 +1717,71 @@ int CALLBACK AllowCancellationCallbackProc(UINT msg, long UserData, long P1, lon
|
|||
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
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "UnrarKitMacros.h"
|
||||
#import <UnrarKit/UnrarKitMacros.h>
|
||||
|
||||
RarosHppIgnore
|
||||
#import "raros.hpp"
|
||||
#import <UnrarKit/raros.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
DllHppIgnore
|
||||
#import "dll.hpp"
|
||||
#import <UnrarKit/dll.hpp>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
/* See http://www.forensicswiki.org/wiki/RAR and
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
_isEncryptedWithPassword = fileHeader->Flags & (1 << 2);
|
||||
//_fileHasComment = fileHeader->Flags & (1 << 3)
|
||||
|
||||
_isDirectory = fileHeader->Flags & RHDF_DIRECTORY;
|
||||
_isDirectory = (fileHeader->Flags & RHDF_DIRECTORY) ? YES : NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
|
|
@ -15,5 +15,5 @@ FOUNDATION_EXPORT double UnrarKitVersionNumber;
|
|||
FOUNDATION_EXPORT const unsigned char UnrarKitVersionString[];
|
||||
|
||||
|
||||
#import "URKArchive.h"
|
||||
#import "URKFileInfo.h"
|
||||
#import <UnrarKit/URKArchive.h>
|
||||
#import <UnrarKit/URKFileInfo.h>
|
||||
|
|
|
@ -60,7 +60,7 @@ __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 \
|
|||
#import <os/activity.h>
|
||||
|
||||
// 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
|
||||
#define URKLogInit() \
|
||||
unrarkit_log = os_log_create("com.abbey-code.UnrarKit", "General"); \
|
||||
|
|
|
@ -143,17 +143,15 @@
|
|||
29B97313FDCFA39411CA2CEA /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0930;
|
||||
LastUpgradeCheck = 1200;
|
||||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "UnrarExample" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
Japanese,
|
||||
French,
|
||||
German,
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
|
||||
projectDirPath = "";
|
||||
|
@ -257,6 +255,7 @@
|
|||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
|
@ -272,14 +271,13 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
|
||||
OTHER_LDFLAGS = (
|
||||
"-lc++",
|
||||
"-all_load",
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
|
@ -301,6 +299,7 @@
|
|||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
|
@ -316,13 +315,12 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
|
||||
OTHER_LDFLAGS = (
|
||||
"-lc++",
|
||||
"-all_load",
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = iphoneos;
|
||||
WARNING_CFLAGS = "-Wno-error=unused-command-line-argument";
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0930"
|
||||
LastUpgradeVersion = "1200"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -27,8 +27,6 @@
|
|||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
|
@ -38,8 +36,8 @@
|
|||
ReferencedContainer = "container:UnrarExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
|
@ -61,8 +59,6 @@
|
|||
ReferencedContainer = "container:UnrarExample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
|
|
@ -4,8 +4,15 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
|||
{
|
||||
if (!MainComment)
|
||||
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
|
||||
uint CmtLength;
|
||||
if (Format==RARFMT14)
|
||||
|
@ -34,7 +41,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
|||
#ifndef SFX_MODULE
|
||||
// Old style (RAR 2.9) comment header embedded into the main
|
||||
// archive header.
|
||||
if (BrokenHeader)
|
||||
if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
|
||||
{
|
||||
uiMsg(UIERROR_CMTBROKEN,FileName);
|
||||
return false;
|
||||
|
@ -57,6 +64,8 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
|||
#else
|
||||
UnpCmtLength=GetByte();
|
||||
UnpCmtLength+=(GetByte()<<8);
|
||||
if (CmtLength<2)
|
||||
return false;
|
||||
CmtLength-=2;
|
||||
DataIO.SetCmt13Encryption();
|
||||
CommHead.UnpVer=15;
|
||||
|
@ -85,15 +94,18 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
|||
byte *UnpData;
|
||||
size_t UnpDataSize;
|
||||
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
|
||||
if (UnpDataSize>0)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// If we ever decide to extend it to Android, we'll need to alloc
|
||||
// 4x memory for OEM to UTF-8 output here.
|
||||
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
|
||||
// If we ever decide to extend it to Android, we'll need to alloc
|
||||
// 4x memory for OEM to UTF-8 output here.
|
||||
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
|
||||
#endif
|
||||
CmtData->Alloc(UnpDataSize+1);
|
||||
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
|
||||
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
|
||||
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
||||
CmtData->Alloc(UnpDataSize+1);
|
||||
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
|
||||
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
|
||||
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -131,7 +143,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
|
|||
bool Archive::ReadCommentData(Array<wchar> *CmtData)
|
||||
{
|
||||
Array<byte> CmtRaw;
|
||||
if (!ReadSubData(&CmtRaw,NULL))
|
||||
if (!ReadSubData(&CmtRaw,NULL,false))
|
||||
return false;
|
||||
size_t CmtSize=CmtRaw.Size();
|
||||
CmtRaw.Push(0);
|
||||
|
|
|
@ -208,15 +208,16 @@ bool Archive::IsArchive(bool EnableBroken)
|
|||
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.
|
||||
if (FailedHeaderDecryption && !EnableBroken)
|
||||
return false;
|
||||
|
||||
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)
|
||||
return false;
|
||||
}
|
||||
|
@ -232,7 +233,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
|||
// immediately after IsArchive call.
|
||||
if (HeadersLeft && (!SilentOpen || !Encrypted))
|
||||
{
|
||||
SaveFilePos SavePos(*this);
|
||||
int64 SavePos=Tell();
|
||||
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||
HEADER_TYPE SaveCurHeaderType=CurHeaderType;
|
||||
|
||||
|
@ -261,6 +262,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
|||
CurBlockPos=SaveCurBlockPos;
|
||||
NextBlockPos=SaveNextBlockPos;
|
||||
CurHeaderType=SaveCurHeaderType;
|
||||
Seek(SavePos,SEEK_SET);
|
||||
}
|
||||
if (!Volume || FirstVolume)
|
||||
wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName));
|
||||
|
|
|
@ -20,13 +20,15 @@ enum ADDSUBDATA_FLAGS
|
|||
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
|
||||
{
|
||||
private:
|
||||
void UpdateLatestTime(FileHeader *CurBlock);
|
||||
void ConvertNameCase(wchar *Name);
|
||||
void ConvertFileHeader(FileHeader *hd);
|
||||
void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite);
|
||||
size_t ReadHeader14();
|
||||
size_t ReadHeader15();
|
||||
size_t ReadHeader50();
|
||||
|
@ -34,8 +36,8 @@ class Archive:public File
|
|||
void RequestArcPassword();
|
||||
void UnexpEndArcMsg();
|
||||
void BrokenHeaderMsg();
|
||||
void UnkEncVerMsg(const wchar *Name);
|
||||
void UnkEncVerMsg();
|
||||
void UnkEncVerMsg(const wchar *Name,const wchar *Info);
|
||||
bool DoGetComment(Array<wchar> *CmtData);
|
||||
bool ReadCommentData(Array<wchar> *CmtData);
|
||||
|
||||
#if !defined(RAR_NOCRYPT)
|
||||
|
@ -63,8 +65,6 @@ class Archive:public File
|
|||
size_t SearchBlock(HEADER_TYPE HeaderType);
|
||||
size_t SearchSubBlock(const wchar *Type);
|
||||
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();
|
||||
void CheckArc(bool EnableBroken);
|
||||
void CheckOpen(const wchar *Name);
|
||||
|
@ -81,8 +81,8 @@ class Archive:public File
|
|||
int64 GetStartPos();
|
||||
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
|
||||
const wchar *Name,uint Flags);
|
||||
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
|
||||
HEADER_TYPE GetHeaderType() {return CurHeaderType;};
|
||||
bool ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode);
|
||||
HEADER_TYPE GetHeaderType() {return CurHeaderType;}
|
||||
RAROptions* GetRAROptions() {return Cmd;}
|
||||
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
|
||||
#if 0
|
||||
|
|
|
@ -10,7 +10,10 @@ size_t Archive::ReadHeader()
|
|||
|
||||
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)
|
||||
{
|
||||
#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);
|
||||
}
|
||||
|
||||
|
@ -265,14 +268,14 @@ size_t Archive::ReadHeader15()
|
|||
uint FileTime=Raw.Get4();
|
||||
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;
|
||||
size_t NameSize=Raw.Get2();
|
||||
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;
|
||||
if (hd->Encrypted)
|
||||
switch(hd->UnpVer)
|
||||
|
@ -399,8 +402,8 @@ size_t Archive::ReadHeader15()
|
|||
if (rmode & 4)
|
||||
rlt.Second++;
|
||||
rlt.Reminder=0;
|
||||
int count=rmode&3;
|
||||
for (int J=0;J<count;J++)
|
||||
uint count=rmode&3;
|
||||
for (uint J=0;J<count;J++)
|
||||
{
|
||||
byte CurByte=Raw.Get1();
|
||||
rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
|
||||
|
@ -518,7 +521,6 @@ size_t Archive::ReadHeader15()
|
|||
{
|
||||
// Last 7 bytes of recovered volume can contain zeroes, because
|
||||
// REV files store its own information (volume number, etc.) here.
|
||||
SaveFilePos SavePos(*this);
|
||||
int64 Length=Tell();
|
||||
Seek(Length-7,SEEK_SET);
|
||||
Recovered=true;
|
||||
|
@ -563,6 +565,11 @@ size_t Archive::ReadHeader50()
|
|||
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.
|
||||
{
|
||||
RequestArcPassword();
|
||||
|
@ -572,11 +579,23 @@ size_t Archive::ReadHeader50()
|
|||
// Verify password validity.
|
||||
if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0)
|
||||
{
|
||||
// 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);
|
||||
if (GlobalPassword) // For -p<pwd> or Ctrl+P.
|
||||
{
|
||||
// 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
|
||||
// Avoid new requests for unrar.dll to prevent the infinite loop
|
||||
// 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
|
||||
// resulting in 2 MB maximum header size, so here we read 4 byte CRC32
|
||||
// followed by 3 bytes or less of header size.
|
||||
// resulting in 2 MB maximum header size (MAX_HEADER_SIZE_RAR5),
|
||||
// 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.
|
||||
if (Raw.Read(FirstReadSize)<FirstReadSize)
|
||||
{
|
||||
|
@ -685,7 +704,9 @@ size_t Archive::ReadHeader50()
|
|||
uint CryptVersion=(uint)Raw.GetV();
|
||||
if (CryptVersion>CRYPT_VERSION)
|
||||
{
|
||||
UnkEncVerMsg(FileName);
|
||||
wchar Info[20];
|
||||
swprintf(Info,ASIZE(Info),L"h%u",CryptVersion);
|
||||
UnkEncVerMsg(FileName,Info);
|
||||
return 0;
|
||||
}
|
||||
uint EncFlags=(uint)Raw.GetV();
|
||||
|
@ -693,9 +714,12 @@ size_t Archive::ReadHeader50()
|
|||
CryptHead.Lg2Count=Raw.Get1();
|
||||
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;
|
||||
}
|
||||
|
||||
Raw.GetB(CryptHead.Salt,SIZE_SALT50);
|
||||
if (CryptHead.UsePswCheck)
|
||||
{
|
||||
|
@ -798,6 +822,8 @@ size_t Archive::ReadHeader50()
|
|||
// but it was already used in RAR 1.5 and Unpack needs to distinguish
|
||||
// them.
|
||||
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();
|
||||
size_t NameSize=(size_t)Raw.GetV();
|
||||
|
@ -972,8 +998,12 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
|||
{
|
||||
FileHeader *hd=(FileHeader *)bb;
|
||||
uint EncVersion=(uint)Raw->GetV();
|
||||
if (EncVersion > CRYPT_VERSION)
|
||||
UnkEncVerMsg(hd->FileName);
|
||||
if (EncVersion>CRYPT_VERSION)
|
||||
{
|
||||
wchar Info[20];
|
||||
swprintf(Info,ASIZE(Info),L"x%u",EncVersion);
|
||||
UnkEncVerMsg(hd->FileName,Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
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->Lg2Count=Raw->Get1();
|
||||
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->InitV,SIZE_INITV);
|
||||
if (hd->UsePswCheck)
|
||||
|
@ -1222,11 +1256,13 @@ size_t Archive::ReadHeader14()
|
|||
Raw.Read(NameSize);
|
||||
|
||||
char FileName[NM];
|
||||
Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName)));
|
||||
FileName[NameSize]=0;
|
||||
size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
|
||||
Raw.GetB((byte *)FileName,ReadNameSize);
|
||||
FileName[ReadNameSize]=0;
|
||||
IntToExt(FileName,FileName,ASIZE(FileName));
|
||||
CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName));
|
||||
ConvertNameCase(FileHead.FileName);
|
||||
ConvertFileHeader(&FileHead);
|
||||
|
||||
if (Raw.Size()!=0)
|
||||
NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -1428,6 +1464,7 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
|
|||
SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
|
||||
SubDataIO.EnableShowProgress(false);
|
||||
SubDataIO.SetFiles(this,DestFile);
|
||||
SubDataIO.SetTestMode(TestMode);
|
||||
SubDataIO.UnpVolume=SubHead.SplitAfter;
|
||||
SubDataIO.SetSubHeader(&SubHead,NULL);
|
||||
Unpack.SetDestSize(SubHead.UnpSize);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#define _RAR_BLAKE2_
|
||||
|
||||
#define BLAKE2_DIGEST_SIZE 32
|
||||
#define BLAKE2_THREADS_NUMBER 8
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "rar.hpp"
|
||||
|
||||
#include "cmdfilter.cpp"
|
||||
#include "cmdmix.cpp"
|
||||
|
||||
CommandData::CommandData()
|
||||
{
|
||||
Init();
|
||||
|
@ -120,6 +123,7 @@ void CommandData::ParseArg(wchar *Arg)
|
|||
wchar CmdChar=toupperw(*Command);
|
||||
bool Add=wcschr(L"AFUM",CmdChar)!=NULL;
|
||||
bool Extract=CmdChar=='X' || CmdChar=='E';
|
||||
bool Repair=CmdChar=='R' && Command[1]==0;
|
||||
if (EndSeparator && !Add)
|
||||
wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
||||
else
|
||||
|
@ -130,15 +134,15 @@ void CommandData::ParseArg(wchar *Arg)
|
|||
FindData FileData;
|
||||
bool Found=FindFile::FastFind(Arg,&FileData);
|
||||
if ((!Found || ListMode==RCLM_ACCEPT_LISTS) &&
|
||||
ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg))
|
||||
ListMode!=RCLM_REJECT_LISTS && *Arg=='@' && !IsWildcard(Arg+1))
|
||||
{
|
||||
FileLists=true;
|
||||
|
||||
ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true);
|
||||
|
||||
}
|
||||
else
|
||||
if (Found && FileData.IsDir && Extract && *ExtrPath==0)
|
||||
else // We use 'destpath\' when extracting and reparing.
|
||||
if (Found && FileData.IsDir && (Extract || Repair) && *ExtrPath==0)
|
||||
{
|
||||
wcsncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
|
||||
AddEndSlash(ExtrPath,ASIZE(ExtrPath));
|
||||
|
@ -280,17 +284,24 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
|||
ClearArc=true;
|
||||
break;
|
||||
case 'D':
|
||||
AppendArcNameToPath=true;
|
||||
if (Switch[2]==0)
|
||||
AppendArcNameToPath=APPENDARCNAME_DESTPATH;
|
||||
else
|
||||
if (Switch[2]=='1')
|
||||
AppendArcNameToPath=APPENDARCNAME_OWNDIR;
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
case 'G':
|
||||
if (Switch[2]=='-' && Switch[3]==0)
|
||||
GenerateArcName=0;
|
||||
else
|
||||
{
|
||||
GenerateArcName=true;
|
||||
wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
|
||||
}
|
||||
if (toupperw(Switch[2])=='F')
|
||||
wcsncpyz(DefGenerateMask,Switch+3,ASIZE(DefGenerateMask));
|
||||
else
|
||||
{
|
||||
GenerateArcName=true;
|
||||
wcsncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'I':
|
||||
|
@ -302,7 +313,7 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
|||
AddArcOnly=true;
|
||||
break;
|
||||
case 'P':
|
||||
wcscpy(ArcPath,Switch+2);
|
||||
wcsncpyz(ArcPath,Switch+2,ASIZE(ArcPath));
|
||||
break;
|
||||
case 'S':
|
||||
SyncFiles=true;
|
||||
|
@ -365,11 +376,11 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
|||
default:
|
||||
if (Switch[1]=='+')
|
||||
{
|
||||
InclFileAttr|=GetExclAttr(Switch+2);
|
||||
InclFileAttr|=GetExclAttr(Switch+2,InclDir);
|
||||
InclAttrSet=true;
|
||||
}
|
||||
else
|
||||
ExclFileAttr|=GetExclAttr(Switch+1);
|
||||
ExclFileAttr|=GetExclAttr(Switch+1,ExclDir);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -407,9 +418,9 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
|||
wcsncpyz(LogName,Switch[4]!=0 ? Switch+4:DefLogName,ASIZE(LogName));
|
||||
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;
|
||||
}
|
||||
if (wcsicomp(Switch+1,L"ERR")==0)
|
||||
|
@ -805,51 +816,19 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
|||
ArcTime=ARCTIME_LATEST;
|
||||
break;
|
||||
case 'O':
|
||||
FileTimeBefore.SetAgeText(Switch+2);
|
||||
SetTimeFilters(Switch+2,true,true);
|
||||
break;
|
||||
case 'N':
|
||||
FileTimeAfter.SetAgeText(Switch+2);
|
||||
SetTimeFilters(Switch+2,false,true);
|
||||
break;
|
||||
case 'B':
|
||||
FileTimeBefore.SetIsoText(Switch+2);
|
||||
SetTimeFilters(Switch+2,true,false);
|
||||
break;
|
||||
case 'A':
|
||||
FileTimeAfter.SetIsoText(Switch+2);
|
||||
SetTimeFilters(Switch+2,false,false);
|
||||
break;
|
||||
case 'S':
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetStoreTimeMode(Switch+2);
|
||||
break;
|
||||
case '-':
|
||||
Test=false;
|
||||
|
@ -897,7 +876,7 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
|||
if (Switch[1]==0)
|
||||
{
|
||||
// If comment file is not specified, we read data from stdin.
|
||||
wcscpy(CommentFile,L"stdin");
|
||||
wcsncpyz(CommentFile,L"stdin",ASIZE(CommentFile));
|
||||
}
|
||||
else
|
||||
wcsncpyz(CommentFile,Switch+1,ASIZE(CommentFile));
|
||||
|
@ -922,309 +901,6 @@ void CommandData::BadSwitch(const wchar *Switch)
|
|||
#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()
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
|
@ -1255,7 +931,10 @@ void CommandData::ProcessCommand()
|
|||
if (wcschr(L"AFUMD",*Command)==NULL)
|
||||
{
|
||||
if (GenerateArcName)
|
||||
GenerateArchiveName(ArcName,ASIZE(ArcName),GenerateMask,false);
|
||||
{
|
||||
const wchar *Mask=*GenerateMask!=0 ? GenerateMask:DefGenerateMask;
|
||||
GenerateArchiveName(ArcName,ASIZE(ArcName),Mask,false);
|
||||
}
|
||||
|
||||
StringList ArcMasks;
|
||||
ArcMasks.AddString(ArcName);
|
||||
|
@ -1274,7 +953,6 @@ void CommandData::ProcessCommand()
|
|||
case 'X':
|
||||
case 'E':
|
||||
case 'T':
|
||||
case 'I':
|
||||
{
|
||||
CmdExtract Extract(this);
|
||||
Extract.DoExtract();
|
||||
|
@ -1317,7 +995,7 @@ bool CommandData::IsSwitch(int Ch)
|
|||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
uint CommandData::GetExclAttr(const wchar *Str)
|
||||
uint CommandData::GetExclAttr(const wchar *Str,bool &Dir)
|
||||
{
|
||||
if (IsDigit(*Str))
|
||||
return wcstol(Str,NULL,0);
|
||||
|
@ -1327,10 +1005,10 @@ uint CommandData::GetExclAttr(const wchar *Str)
|
|||
{
|
||||
switch(toupperw(*Str))
|
||||
{
|
||||
#ifdef _UNIX
|
||||
case 'D':
|
||||
Attr|=S_IFDIR;
|
||||
Dir=true;
|
||||
break;
|
||||
#ifdef _UNIX
|
||||
case 'V':
|
||||
Attr|=S_IFCHR;
|
||||
break;
|
||||
|
@ -1344,9 +1022,6 @@ uint CommandData::GetExclAttr(const wchar *Str)
|
|||
case 'S':
|
||||
Attr|=0x4;
|
||||
break;
|
||||
case 'D':
|
||||
Attr|=0x10;
|
||||
break;
|
||||
case 'A':
|
||||
Attr|=0x20;
|
||||
break;
|
||||
|
|
|
@ -6,13 +6,19 @@
|
|||
|
||||
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
|
||||
{
|
||||
private:
|
||||
void ProcessSwitchesString(const wchar *Str);
|
||||
void ProcessSwitch(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 NoMoreSwitches;
|
||||
|
@ -34,11 +40,11 @@ class CommandData:public RAROptions
|
|||
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);
|
||||
bool ExclDirByAttr(uint FileAttr);
|
||||
bool TimeCheck(RarTime &ft);
|
||||
bool TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta);
|
||||
bool SizeCheck(int64 Size);
|
||||
bool AnyFiltersActive();
|
||||
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH,
|
||||
wchar *MatchedArg=NULL,uint MatchedArgSize=0);
|
||||
int IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
|
||||
bool Flags,wchar *MatchedArg,uint MatchedArgSize);
|
||||
void ProcessCommand();
|
||||
void AddArcName(const wchar *Name);
|
||||
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[4][(byte)(StartCRC >> 24)] ^
|
||||
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[0][(byte)(NextData >> 24)];
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co
|
|||
sha1_context c;
|
||||
sha1_init(&c);
|
||||
|
||||
const int HashRounds=0x40000;
|
||||
for (int I=0;I<HashRounds;I++)
|
||||
const uint HashRounds=0x40000;
|
||||
for (uint I=0;I<HashRounds;I++)
|
||||
{
|
||||
sha1_process_rar29( &c, RawPsw, RawLength );
|
||||
byte PswNum[3];
|
||||
|
@ -47,8 +47,8 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co
|
|||
}
|
||||
uint32 digest[5];
|
||||
sha1_done( &c, digest );
|
||||
for (int I=0;I<4;I++)
|
||||
for (int J=0;J<4;J++)
|
||||
for (uint I=0;I<4;I++)
|
||||
for (uint J=0;J<4;J++)
|
||||
AESKey[I*4+J]=(byte)(digest[I]>>(J*8));
|
||||
|
||||
KDF3Cache[KDF3CachePos].Pwd=*Password;
|
||||
|
|
|
@ -42,6 +42,7 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
|||
Data->Cmd.DllError=0;
|
||||
Data->OpenMode=r->OpenMode;
|
||||
Data->Cmd.FileArgs.AddString(L"*");
|
||||
Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0;
|
||||
|
||||
char AnsiArcName[NM];
|
||||
*AnsiArcName=0;
|
||||
|
@ -94,36 +95,50 @@ HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
|||
r->Flags=0;
|
||||
|
||||
if (Data->Arc.Volume)
|
||||
r->Flags|=0x01;
|
||||
r->Flags|=ROADF_VOLUME;
|
||||
if (Data->Arc.MainComment)
|
||||
r->Flags|=ROADF_COMMENT;
|
||||
if (Data->Arc.Locked)
|
||||
r->Flags|=0x04;
|
||||
r->Flags|=ROADF_LOCK;
|
||||
if (Data->Arc.Solid)
|
||||
r->Flags|=0x08;
|
||||
r->Flags|=ROADF_SOLID;
|
||||
if (Data->Arc.NewNumbering)
|
||||
r->Flags|=0x10;
|
||||
r->Flags|=ROADF_NEWNUMBERING;
|
||||
if (Data->Arc.Signed)
|
||||
r->Flags|=0x20;
|
||||
r->Flags|=ROADF_SIGNED;
|
||||
if (Data->Arc.Protected)
|
||||
r->Flags|=0x40;
|
||||
r->Flags|=ROADF_RECOVERY;
|
||||
if (Data->Arc.Encrypted)
|
||||
r->Flags|=0x80;
|
||||
r->Flags|=ROADF_ENCHEADERS;
|
||||
if (Data->Arc.FirstVolume)
|
||||
r->Flags|=0x100;
|
||||
r->Flags|=ROADF_FIRSTVOLUME;
|
||||
|
||||
Array<wchar> CmtDataW;
|
||||
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
|
||||
{
|
||||
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;
|
||||
if (r->CmtBufW!=NULL)
|
||||
{
|
||||
CmtDataW.Push(0);
|
||||
size_t Size=wcslen(&CmtDataW[0])+1;
|
||||
|
||||
r->Flags|=2;
|
||||
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
|
||||
if (Size<=r->CmtBufSize)
|
||||
r->CmtBuf[r->CmtSize-1]=0;
|
||||
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
||||
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
||||
memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW));
|
||||
r->CmtBufW[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
|
||||
r->CmtState=r->CmtSize=0;
|
||||
|
@ -253,10 +268,7 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
|||
D->UnpSize=uint(hd->UnpSize & 0xffffffff);
|
||||
D->UnpSizeHigh=uint(hd->UnpSize>>32);
|
||||
D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
|
||||
if (Data->Arc.Format==RARFMT50)
|
||||
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->UnpVer=Data->Arc.FileHead.UnpVer;
|
||||
D->FileCRC=hd->FileHash.CRC32;
|
||||
D->FileTime=hd->mtime.GetDos();
|
||||
|
||||
|
@ -372,7 +384,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
|
|||
if (DestNameW!=NULL)
|
||||
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;
|
||||
bool Repeat=false;
|
||||
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)
|
||||
{
|
||||
#ifndef RAR_NOCRYPT
|
||||
DataSet *Data=(DataSet *)hArcData;
|
||||
wchar PasswordW[MAXPASSWORD];
|
||||
GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
|
||||
Data->Cmd.Password.Set(PasswordW);
|
||||
cleandata(PasswordW,sizeof(PasswordW));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int PASCAL RARGetDllVersion()
|
||||
|
|
|
@ -5,6 +5,7 @@ EXPORTS
|
|||
RARReadHeader
|
||||
RARReadHeaderEx
|
||||
RARProcessFile
|
||||
RARProcessFileW
|
||||
RARSetCallback
|
||||
RARSetChangeVolProc
|
||||
RARSetProcessDataProc
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _UNRAR_DLL_
|
||||
#define _UNRAR_DLL_
|
||||
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define ERAR_SUCCESS 0
|
||||
#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_FIRSTVOLUME 0x0100
|
||||
|
||||
#define ROADOF_KEEPBROKEN 0x0001
|
||||
|
||||
struct RAROpenArchiveDataEx
|
||||
{
|
||||
char *ArcName;
|
||||
|
@ -148,7 +150,9 @@ struct RAROpenArchiveDataEx
|
|||
unsigned int Flags;
|
||||
UNRARCALLBACK Callback;
|
||||
LPARAM UserData;
|
||||
unsigned int Reserved[28];
|
||||
unsigned int OpFlags;
|
||||
wchar_t *CmtBufW;
|
||||
unsigned int Reserved[25];
|
||||
};
|
||||
|
||||
enum UNRARCALLBACK_MESSAGES {
|
||||
|
@ -180,6 +184,6 @@ int PASCAL RARGetDllVersion();
|
|||
}
|
||||
#endif
|
||||
|
||||
#pragma pack()
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#include <commctrl.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 5, 60, 3, 2672
|
||||
PRODUCTVERSION 5, 60, 3, 2672
|
||||
FILEVERSION 5, 91, 100, 3470
|
||||
PRODUCTVERSION 5, 91, 100, 3470
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
{
|
||||
|
@ -14,9 +14,9 @@ FILETYPE VFT_APP
|
|||
VALUE "CompanyName", "Alexander Roshal\0"
|
||||
VALUE "ProductName", "RAR decompression library\0"
|
||||
VALUE "FileDescription", "RAR decompression library\0"
|
||||
VALUE "FileVersion", "5.60.3\0"
|
||||
VALUE "ProductVersion", "5.60.3\0"
|
||||
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2018\0"
|
||||
VALUE "FileVersion", "5.91.0\0"
|
||||
VALUE "ProductVersion", "5.91.0\0"
|
||||
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2020\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)
|
||||
{
|
||||
Wait(); // Keep GUI responsive if many files cannot be opened when archiving.
|
||||
uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
|
||||
SysErrMsg();
|
||||
SetErrorCode(RARX_OPEN);
|
||||
|
@ -270,6 +271,7 @@ void _stdfunction ProcessSignal(int SigType)
|
|||
#endif
|
||||
|
||||
ErrHandler.UserBreak=true;
|
||||
ErrHandler.SetDisableShutdown();
|
||||
mprintf(St(MBreak));
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
|
@ -293,7 +295,7 @@ void _stdfunction ProcessSignal(int SigType)
|
|||
#endif
|
||||
|
||||
#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;
|
||||
#endif
|
||||
}
|
||||
|
@ -327,7 +329,7 @@ void ErrorHandler::Throw(RAR_EXIT Code)
|
|||
|
||||
bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size)
|
||||
{
|
||||
#if !defined(SFX_MODULE) && !defined(SILENT)
|
||||
#ifndef SILENT
|
||||
#ifdef _WIN_ALL
|
||||
int ErrType=GetLastError();
|
||||
if (ErrType!=0)
|
||||
|
@ -360,7 +362,7 @@ void ErrorHandler::SysErrMsg()
|
|||
return;
|
||||
#ifdef _WIN_ALL
|
||||
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')
|
||||
CurMsg++;
|
||||
|
|
|
@ -56,11 +56,12 @@ class ErrorHandler
|
|||
uint GetErrorCount() {return ErrCount;}
|
||||
void SetSignalHandlers(bool Enable);
|
||||
void Throw(RAR_EXIT Code);
|
||||
void SetSilent(bool Mode) {Silent=Mode;};
|
||||
void SetSilent(bool Mode) {Silent=Mode;}
|
||||
bool GetSysErrMsg(wchar *Msg,size_t Size);
|
||||
void SysErrMsg();
|
||||
int GetSystemErrorCode();
|
||||
void SetSystemErrorCode(int Code);
|
||||
void SetDisableShutdown() {DisableShutdown=true;}
|
||||
bool IsShutdownEnabled() {return !DisableShutdown;}
|
||||
|
||||
bool UserBreak; // Ctrl+Break is pressed.
|
||||
|
|
|
@ -40,6 +40,8 @@ void CmdExtract::DoExtract()
|
|||
{
|
||||
if (Cmd->ManualPassword)
|
||||
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
|
||||
|
||||
ReconstructDone=false; // Must be reset here, not in ExtractArchiveInit().
|
||||
while (true)
|
||||
{
|
||||
EXTRACT_ARC_CODE Code=ExtractArchive();
|
||||
|
@ -59,7 +61,11 @@ void CmdExtract::DoExtract()
|
|||
{
|
||||
if (!PasswordCancelled)
|
||||
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
|
||||
if (!Cmd->DisableDone)
|
||||
|
@ -83,13 +89,12 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc)
|
|||
FirstFile=true;
|
||||
#endif
|
||||
|
||||
PasswordAll=(Cmd->Password.IsSet());
|
||||
GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet();
|
||||
|
||||
DataIO.UnpVolume=false;
|
||||
|
||||
PrevProcessed=false;
|
||||
AllMatchesExact=true;
|
||||
ReconstructDone=false;
|
||||
AnySolidDataUnpackedWell=false;
|
||||
|
||||
StartTime.SetCurrentTime();
|
||||
|
@ -157,7 +162,7 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
|||
// This size is necessary to display the correct total progress indicator.
|
||||
|
||||
wchar NextName[NM];
|
||||
wcscpy(NextName,Arc.FileName);
|
||||
wcsncpyz(NextName,Arc.FileName,ASIZE(NextName));
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
@ -257,15 +262,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
if (HeaderType==HEAD_ENDARC)
|
||||
if (Arc.EndArcHead.NextVolume)
|
||||
{
|
||||
#ifndef NOVOLUME
|
||||
#ifdef NOVOLUME
|
||||
return false;
|
||||
#else
|
||||
if (!MergeArchive(Arc,&DataIO,false,Command))
|
||||
{
|
||||
ErrHandler.SetErrorCode(RARX_WARNING);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
Arc.Seek(Arc.CurBlockPos,SEEK_SET);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
@ -294,7 +301,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
|
||||
bool EqualNames=false;
|
||||
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;
|
||||
#ifndef SFX_MODULE
|
||||
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))
|
||||
{
|
||||
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
|
||||
// volume name really exists, let's unpack from this first volume.
|
||||
Repeat=true;
|
||||
|
@ -340,7 +348,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
#endif
|
||||
|
||||
wchar ArcFileName[NM];
|
||||
ConvertPath(Arc.FileHead.FileName,ArcFileName);
|
||||
ConvertPath(Arc.FileHead.FileName,ArcFileName,ASIZE(ArcFileName));
|
||||
|
||||
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 &&
|
||||
!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.
|
||||
// Update appropriate code if changed.
|
||||
uiMsg(UIERROR_BADPSW,ArcFileName);
|
||||
uiMsg(UIERROR_BADPSW,Arc.FileName,ArcFileName);
|
||||
}
|
||||
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,ArcFileName);
|
||||
uiMsg(UIWAIT_BADPSW,Arc.FileName,ArcFileName);
|
||||
Cmd->Password.Clean();
|
||||
|
||||
// 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
|
||||
|
||||
if (!TestMode && !Arc.BrokenHeader &&
|
||||
(Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize &&
|
||||
uint64 Preallocated=0;
|
||||
if (!TestMode && !Arc.BrokenHeader && Arc.FileHead.UnpSize>1000000 &&
|
||||
Arc.FileHead.PackSize*1024>Arc.FileHead.UnpSize &&
|
||||
(Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
|
||||
{
|
||||
CurFile.Prealloc(Arc.FileHead.UnpSize);
|
||||
|
||||
Preallocated=Arc.FileHead.UnpSize;
|
||||
}
|
||||
CurFile.SetAllowDelete(!Cmd->KeepBroken);
|
||||
|
||||
bool FileCreateMode=!TestMode && !SkipSolid && Command!='P';
|
||||
|
@ -725,37 +736,52 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
|||
else
|
||||
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') &&
|
||||
(!LinkEntry || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) &&
|
||||
(!LinkEntry || SetAttrOnly || Arc.FileHead.RedirType==FSREDIR_FILECOPY && LinkSuccess) &&
|
||||
(!BrokenFile || Cmd->KeepBroken))
|
||||
{
|
||||
// We could preallocate more space that really written to broken file.
|
||||
if (BrokenFile)
|
||||
CurFile.Truncate();
|
||||
// Below we use DestFileName instead of CurFile.FileName,
|
||||
// so we can set file attributes also for hard links, which do not
|
||||
// have the open CurFile. These strings are the same for other items.
|
||||
|
||||
#if defined(_WIN_ALL) || defined(_EMX)
|
||||
if (Cmd->ClearArc)
|
||||
Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
|
||||
#endif
|
||||
if (!SetAttrOnly)
|
||||
{
|
||||
// We could preallocate more space that really written to broken file
|
||||
// or file with crafted header.
|
||||
if (Preallocated>0 && (BrokenFile || DataIO.CurUnpWrite!=Preallocated))
|
||||
CurFile.Truncate();
|
||||
|
||||
|
||||
CurFile.SetOpenFileTime(
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||
Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||
CurFile.Close();
|
||||
CurFile.SetOpenFileTime(
|
||||
Cmd->xmtime==EXTTIME_NONE ? NULL:&Arc.FileHead.mtime,
|
||||
Cmd->xctime==EXTTIME_NONE ? NULL:&Arc.FileHead.ctime,
|
||||
Cmd->xatime==EXTTIME_NONE ? NULL:&Arc.FileHead.atime);
|
||||
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 (Cmd->SetCompressedAttr &&
|
||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0)
|
||||
SetFileCompression(CurFile.FileName,true);
|
||||
SetFileCompression(DestFileName,true);
|
||||
if (Cmd->ClearArc)
|
||||
Arc.FileHead.FileAttr&=~FILE_ATTRIBUTE_ARCHIVE;
|
||||
#endif
|
||||
SetFileHeaderExtra(Cmd,Arc,CurFile.FileName);
|
||||
|
||||
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);
|
||||
if (!Cmd->IgnoreGeneralAttr && !SetFileAttr(DestFileName,Arc.FileHead.FileAttr))
|
||||
uiMsg(UIERROR_FILEATTR,Arc.FileName,DestFileName);
|
||||
|
||||
PrevProcessed=true;
|
||||
}
|
||||
|
@ -846,9 +872,12 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
|
|||
}
|
||||
|
||||
#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);
|
||||
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()*/)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
Cmd->ManualPassword=true;
|
||||
}
|
||||
#if !defined(SILENT)
|
||||
else
|
||||
if (!PasswordAll && !Arc.FileHead.Solid)
|
||||
if (!GlobalPassword && !Arc.FileHead.Solid)
|
||||
{
|
||||
eprintf(St(MUseCurPsw),ArcFileName);
|
||||
switch(Cmd->AllYes ? 1 : Ask(St(MYesNoAll)))
|
||||
|
@ -980,7 +1013,7 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
|
|||
return false;
|
||||
break;
|
||||
case 3:
|
||||
PasswordAll=true;
|
||||
GlobalPassword=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1077,7 +1110,7 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName)
|
|||
{
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
if (Cmd->SetCompressedAttr &&
|
||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT())
|
||||
(Arc.FileHead.FileAttr & FILE_ATTRIBUTE_COMPRESSED)!=0 && WinNT()!=WNT_NONE)
|
||||
SetFileCompression(DestFileName,true);
|
||||
#endif
|
||||
SetFileHeaderExtra(Cmd,Arc,DestFileName);
|
||||
|
|
|
@ -43,7 +43,7 @@ class CmdExtract
|
|||
|
||||
wchar ArcName[NM];
|
||||
|
||||
bool PasswordAll;
|
||||
bool GlobalPassword;
|
||||
bool PrevProcessed; // If previous file was successfully extracted or tested.
|
||||
wchar DestFileName[NM];
|
||||
bool PasswordCancelled;
|
||||
|
|
|
@ -13,6 +13,7 @@ File::File()
|
|||
OpenShared=false;
|
||||
AllowDelete=true;
|
||||
AllowExceptions=true;
|
||||
PreserveAtime=false;
|
||||
#ifdef _WIN_ALL
|
||||
NoSequentialRead=false;
|
||||
CreateMode=FMF_UNDEFINED;
|
||||
|
@ -56,6 +57,9 @@ bool File::Open(const wchar *Name,uint Mode)
|
|||
if (OpenShared)
|
||||
ShareMode|=FILE_SHARE_WRITE;
|
||||
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);
|
||||
|
||||
DWORD LastError;
|
||||
|
@ -86,6 +90,11 @@ bool File::Open(const wchar *Name,uint Mode)
|
|||
}
|
||||
if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
|
||||
ErrorType=FILE_NOTFOUND;
|
||||
if (PreserveAtime && hNewFile!=FILE_BAD_HANDLE)
|
||||
{
|
||||
FILETIME ft={0xffffffff,0xffffffff}; // This value prevents atime modification.
|
||||
SetFileTime(hNewFile,NULL,&ft,NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
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)
|
||||
flags|=O_LARGEFILE;
|
||||
#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
|
||||
char NameA[NM];
|
||||
WideToChar(Name,NameA,ASIZE(NameA));
|
||||
|
@ -230,7 +244,7 @@ bool File::Close()
|
|||
{
|
||||
#ifdef _WIN_ALL
|
||||
// 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)
|
||||
Success=CloseHandle(hFile)==TRUE;
|
||||
#else
|
||||
|
@ -271,7 +285,7 @@ bool File::Rename(const wchar *NewName)
|
|||
Success=RenameFile(FileName,NewName);
|
||||
|
||||
if (Success)
|
||||
wcscpy(FileName,NewName);
|
||||
wcsncpyz(FileName,NewName,ASIZE(FileName));
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
@ -387,7 +401,7 @@ int File::Read(void *Data,size_t Size)
|
|||
}
|
||||
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()
|
||||
{
|
||||
SaveFilePos SavePos(*this);
|
||||
int64 SavePos=Tell();
|
||||
Seek(0,SEEK_END);
|
||||
return Tell();
|
||||
int64 Length=Tell();
|
||||
Seek(SavePos,SEEK_SET);
|
||||
return Length;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ class File
|
|||
bool NoSequentialRead;
|
||||
uint CreateMode;
|
||||
#endif
|
||||
bool PreserveAtime;
|
||||
protected:
|
||||
bool OpenShared; // Set by 'Archive' class.
|
||||
public:
|
||||
|
@ -99,7 +100,7 @@ class File
|
|||
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
|
||||
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
|
||||
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();
|
||||
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
|
||||
FILE_HANDLETYPE GetHandleType() {return HandleType;}
|
||||
|
@ -114,6 +115,7 @@ class File
|
|||
#ifdef _WIN_ALL
|
||||
void RemoveSequentialFlag() {NoSequentialRead=true;}
|
||||
#endif
|
||||
void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;}
|
||||
#ifdef _UNIX
|
||||
int GetFD()
|
||||
{
|
||||
|
|
|
@ -348,7 +348,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize)
|
|||
swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
|
||||
if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
|
||||
return NULL;
|
||||
wcscpy(Name+Length,RndText);
|
||||
wcsncpyz(Name+Length,RndText,MaxSize-Length);
|
||||
if (!FileExist(Name))
|
||||
break;
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ wchar *MkTemp(wchar *Name,size_t MaxSize)
|
|||
#if !defined(SFX_MODULE)
|
||||
void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
|
||||
{
|
||||
SaveFilePos SavePos(*SrcFile);
|
||||
int64 SavePos=SrcFile->Tell();
|
||||
#ifndef SILENT
|
||||
int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
|
||||
#endif
|
||||
|
@ -415,6 +415,8 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,
|
|||
if (Size!=INT64NDF)
|
||||
Size-=ReadSize;
|
||||
}
|
||||
SrcFile->Seek(SavePos,SEEK_SET);
|
||||
|
||||
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
||||
uiMsg(UIEVENT_FILESUMEND);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ FindFile::~FindFile()
|
|||
|
||||
void FindFile::SetMask(const wchar *Mask)
|
||||
{
|
||||
wcscpy(FindMask,Mask);
|
||||
wcsncpyz(FindMask,Mask,ASIZE(FindMask));
|
||||
FirstCall=true;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ bool FindFile::Next(FindData *fd,bool GetSymLink)
|
|||
wcsncpyz(DirName,FindMask,ASIZE(DirName));
|
||||
RemoveNameFromPath(DirName);
|
||||
if (*DirName==0)
|
||||
wcscpy(DirName,L".");
|
||||
wcsncpyz(DirName,L".",ASIZE(DirName));
|
||||
char DirNameA[NM];
|
||||
WideToChar(DirName,DirNameA,ASIZE(DirNameA));
|
||||
if ((dirp=opendir(DirNameA))==NULL)
|
||||
|
@ -63,32 +63,32 @@ bool FindFile::Next(FindData *fd,bool GetSymLink)
|
|||
}
|
||||
while (1)
|
||||
{
|
||||
wchar Name[NM];
|
||||
struct dirent *ent=readdir(dirp);
|
||||
if (ent==NULL)
|
||||
return false;
|
||||
if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
|
||||
continue;
|
||||
wchar Name[NM];
|
||||
if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
|
||||
uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
|
||||
|
||||
if (CmpName(FindMask,Name,MATCH_NAMES))
|
||||
{
|
||||
wchar FullName[NM];
|
||||
wcscpy(FullName,FindMask);
|
||||
wcsncpyz(FullName,FindMask,ASIZE(FullName));
|
||||
*PointToName(FullName)=0;
|
||||
if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
|
||||
{
|
||||
uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
|
||||
return false;
|
||||
}
|
||||
wcscat(FullName,Name);
|
||||
wcsncatz(FullName,Name,ASIZE(FullName));
|
||||
if (!FastFind(FullName,fd,GetSymLink))
|
||||
{
|
||||
ErrHandler.OpenErrorMsg(FullName);
|
||||
continue;
|
||||
}
|
||||
wcscpy(fd->Name,FullName);
|
||||
wcsncpyz(fd->Name,FullName,ASIZE(fd->Name));
|
||||
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.
|
||||
|
||||
if (!FileExist(NameExisting))
|
||||
{
|
||||
uiMsg(UIERROR_HLINKCREATE,NameNew);
|
||||
uiMsg(UIERROR_NOLINKTARGET);
|
||||
ErrHandler.SetErrorCode(RARX_CREATE);
|
||||
return false;
|
||||
}
|
||||
CreatePath(NameNew,true);
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
|
|
|
@ -53,7 +53,7 @@ DataHash::DataHash()
|
|||
DataHash::~DataHash()
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(ThPool);
|
||||
delete ThPool;
|
||||
#endif
|
||||
cleandata(&CurCRC32, sizeof(CurCRC32));
|
||||
if (blake2ctx!=NULL)
|
||||
|
@ -94,7 +94,7 @@ void DataHash::Update(const void *Data,size_t DataSize)
|
|||
{
|
||||
#ifdef RAR_SMP
|
||||
if (MaxThreads>1 && ThPool==NULL)
|
||||
ThPool=CreateThreadPool();
|
||||
ThPool=new ThreadPool(BLAKE2_THREADS_NUMBER);
|
||||
blake2ctx->ThPool=ThPool;
|
||||
blake2ctx->MaxThreads=MaxThreads;
|
||||
#endif
|
||||
|
|
|
@ -14,10 +14,11 @@
|
|||
#define SIZEOF_UOHEAD 18
|
||||
#define SIZEOF_STREAMHEAD 26
|
||||
|
||||
#define VER_PACK 29
|
||||
#define VER_PACK5 50 // It is stored as 0, but we subtract 50 when saving an archive.
|
||||
#define VER_UNPACK 29
|
||||
#define VER_UNPACK5 50 // It is stored as 0, but we add 50 when reading an archive.
|
||||
#define VER_PACK 29U
|
||||
#define VER_PACK5 50U // It is stored as 0, but we subtract 50 when saving an archive.
|
||||
#define VER_UNPACK 29U
|
||||
#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
|
||||
|
||||
|
@ -174,7 +175,7 @@ struct MainHeader:BaseBlock
|
|||
struct FileHeader:BlockHeader
|
||||
{
|
||||
byte HostOS;
|
||||
byte UnpVer;
|
||||
uint UnpVer; // It is 1 byte in RAR29 and bit field in RAR5.
|
||||
byte Method;
|
||||
union {
|
||||
uint FileAttr;
|
||||
|
@ -190,7 +191,7 @@ struct FileHeader:BlockHeader
|
|||
|
||||
int64 PackSize;
|
||||
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;
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ void ListArchive(CommandData *Cmd)
|
|||
*VolNumText=0;
|
||||
while(Arc.ReadHeader()>0)
|
||||
{
|
||||
Wait(); // Allow quit listing with Ctrl+C.
|
||||
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||
if (HeaderType==HEAD_ENDARC)
|
||||
{
|
||||
|
@ -91,7 +92,7 @@ void ListArchive(CommandData *Cmd)
|
|||
switch(HeaderType)
|
||||
{
|
||||
case HEAD_FILE:
|
||||
FileMatched=Cmd->IsProcessFile(Arc.FileHead)!=0;
|
||||
FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0;
|
||||
if (FileMatched)
|
||||
{
|
||||
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];
|
||||
if (hd.UnpSize==INT64NDF)
|
||||
wcscpy(UnpSizeText,L"?");
|
||||
wcsncpyz(UnpSizeText,L"?",ASIZE(UnpSizeText));
|
||||
else
|
||||
itoa(hd.UnpSize,UnpSizeText,ASIZE(UnpSizeText));
|
||||
itoa(hd.PackSize,PackSizeText,ASIZE(PackSizeText));
|
||||
|
@ -229,13 +230,13 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
|||
wchar RatioStr[10];
|
||||
|
||||
if (hd.SplitBefore && hd.SplitAfter)
|
||||
wcscpy(RatioStr,L"<->");
|
||||
wcsncpyz(RatioStr,L"<->",ASIZE(RatioStr));
|
||||
else
|
||||
if (hd.SplitBefore)
|
||||
wcscpy(RatioStr,L"<--");
|
||||
wcsncpyz(RatioStr,L"<--",ASIZE(RatioStr));
|
||||
else
|
||||
if (hd.SplitAfter)
|
||||
wcscpy(RatioStr,L"-->");
|
||||
wcsncpyz(RatioStr,L"-->",ASIZE(RatioStr));
|
||||
else
|
||||
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: 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 ? 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') : '-');
|
||||
break;
|
||||
case HSYS_UNKNOWN:
|
||||
wcscpy(AttrStr,L"?");
|
||||
wcsncpyz(AttrStr,L"?",AttrSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
#define MCHelpSwILOG L"\n ilog[name] Log errors to file"
|
||||
#define MCHelpSwINUL L"\n inul Disable all messages"
|
||||
#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 MCHelpSwK L"\n k Lock archive"
|
||||
#define MCHelpSwKB L"\n kb Keep broken extracted files"
|
||||
|
@ -127,11 +127,11 @@
|
|||
#define MCHelpSwT L"\n t Test files after archiving"
|
||||
#define MCHelpSwTK L"\n tk Keep original archive time"
|
||||
#define MCHelpSwTL L"\n tl Set archive time to latest file"
|
||||
#define MCHelpSwTN L"\n tn<time> Process files newer than <time>"
|
||||
#define MCHelpSwTO L"\n to<time> Process files older than <time>"
|
||||
#define MCHelpSwTA L"\n ta<date> Process files modified after <date> in YYYYMMDDHHMMSS format"
|
||||
#define MCHelpSwTB L"\n tb<date> Process files modified before <date> in YYYYMMDDHHMMSS format"
|
||||
#define MCHelpSwTS L"\n ts[m|c|a] Save or restore file time (modification, creation, access)"
|
||||
#define MCHelpSwTN L"\n tn[mcao]<t> Process files newer than <t> time"
|
||||
#define MCHelpSwTO L"\n to[mcao]<t> Process files older than <t> time"
|
||||
#define MCHelpSwTA L"\n ta[mcao]<d> Process files modified after <d> YYYYMMDDHHMMSS date"
|
||||
#define MCHelpSwTB L"\n tb[mcao]<d> Process files modified before <d> YYYYMMDDHHMMSS date"
|
||||
#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 MCHelpSwV L"\n v Create volumes with size autodetection or list all volumes"
|
||||
#define MCHelpSwVUnr L"\n v List all volumes"
|
||||
|
@ -203,7 +203,6 @@
|
|||
#define MErrOpenFile L"file"
|
||||
#define MAddNoFiles L"\nWARNING: No files"
|
||||
#define MMdfEncrSol L"\n%s: encrypted"
|
||||
#define MCannotMdfEncrSol L"\nCannot modify solid archive containing encrypted files"
|
||||
#define MAddAnalyze L"\nAnalyzing archived files: "
|
||||
#define MRepacking L"\nRepacking archived files: "
|
||||
#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 MErrChangeAttr L"\nWARNING: Cannot change attributes of %s"
|
||||
#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 MCopyrightS L"\nRAR SFX archive"
|
||||
#define MSHelpCmd L"\n\n<Commands>"
|
||||
|
@ -354,12 +353,13 @@
|
|||
#define MCannotDelete L"\nCannot delete %s"
|
||||
#define MRecycleFailed L"\nCannot move some files and folders to Recycle Bin"
|
||||
#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 MNotEnoughDisk L"\nERROR: Not enough disk space for %s."
|
||||
#define MNewerRAR L"\nYou may need a newer version of RAR."
|
||||
#define MUnkEncMethod L"\nUnknown encryption method in %s"
|
||||
#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 MBlocksRecovered L"\n%u blocks are recovered, %u blocks are relocated"
|
||||
#define MRRDamaged L"\nRecovery record is corrupt."
|
||||
|
@ -375,6 +375,8 @@
|
|||
#define MCopyingData L"\nCopying data"
|
||||
#define MErrCreateLnkS L"\nCannot create symbolic 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 MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB."
|
||||
#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
|
||||
|
||||
clean:
|
||||
@rm -f *.o *.bak *~
|
||||
@rm -f *.bak *~
|
||||
@rm -f $(OBJECTS) $(UNRAR_OBJ) $(LIB_OBJ)
|
||||
@rm -f unrar libunrar.*
|
||||
|
||||
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
|
||||
@rm -f unrar
|
||||
|
@ -154,8 +156,7 @@ sfx: clean $(OBJECTS)
|
|||
lib: WHAT=RARDLL
|
||||
lib: CXXFLAGS+=$(LIBFLAGS)
|
||||
lib: clean $(OBJECTS) $(LIB_OBJ)
|
||||
@rm -f libunrar.so
|
||||
@rm -f libunrar.a
|
||||
@rm -f libunrar.*
|
||||
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// 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.
|
||||
wchar NextCh=Name[WildLength];
|
||||
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) &&
|
||||
mwcsicompc(Path1,Path2,ForceCase)!=0)
|
||||
return(false);
|
||||
if (CmpMode==MATCH_ALLWILD)
|
||||
return match(Wildcard,Name,ForceCase);
|
||||
if (CmpMode==MATCH_SUBPATH || CmpMode==MATCH_WILDSUBPATH)
|
||||
if (IsWildcard(Path1))
|
||||
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
|
||||
// from archiving operations.
|
||||
if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
|
||||
return(false);
|
||||
// if (mwcsnicompc(L"__rar_",Name2,6,false)==0)
|
||||
// return(false);
|
||||
|
||||
if (CmpMode==MATCH_EXACT)
|
||||
return(mwcsicompc(Name1,Name2,ForceCase)==0);
|
||||
|
|
|
@ -14,6 +14,10 @@ enum {
|
|||
MATCH_EXACT, // Paths 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.
|
||||
// Names are compared using wildcards.
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ void RAROptions::Init()
|
|||
Method=3;
|
||||
MsgStream=MSG_STDOUT;
|
||||
ConvertNames=NAMES_ORIGINALCASE;
|
||||
xmtime=EXTTIME_HIGH3;
|
||||
xmtime=EXTTIME_MAX;
|
||||
FileSizeLess=INT64NDF;
|
||||
FileSizeMore=INT64NDF;
|
||||
HashType=HASH_CRC32;
|
||||
|
|
|
@ -12,11 +12,7 @@ enum PATH_EXCL_MODE {
|
|||
EXCL_SKIPWHOLEPATH, // -ep (exclude the path completely)
|
||||
EXCL_BASEPATH, // -ep1 (exclude the base part of path)
|
||||
EXCL_SAVEFULLPATH, // -ep2 (the full path without 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.
|
||||
EXCL_ABSPATH // -ep3 (the full path with the disk letter)
|
||||
};
|
||||
|
||||
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 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};
|
||||
|
@ -63,11 +59,20 @@ enum SAVECOPY_MODE {
|
|||
SAVECOPY_DUPLISTEXIT
|
||||
};
|
||||
|
||||
enum APPENDARCNAME_MODE
|
||||
{
|
||||
APPENDARCNAME_NONE=0,APPENDARCNAME_DESTPATH,APPENDARCNAME_OWNDIR
|
||||
};
|
||||
|
||||
enum POWER_MODE {
|
||||
POWERMODE_KEEP=0,POWERMODE_OFF,POWERMODE_HIBERNATE,POWERMODE_SLEEP,
|
||||
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
|
||||
{
|
||||
FilterState State;
|
||||
|
@ -87,6 +92,12 @@ class RAROptions
|
|||
|
||||
uint ExclFileAttr;
|
||||
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;
|
||||
size_t WinSize;
|
||||
wchar TempPath[NM];
|
||||
|
@ -112,7 +123,7 @@ class RAROptions
|
|||
|
||||
wchar LogName[NM];
|
||||
MESSAGE_TYPE MsgStream;
|
||||
bool Sound;
|
||||
SOUND_NOTIFY_MODE Sound;
|
||||
OVERWRITE_MODE Overwrite;
|
||||
int Method;
|
||||
HASH_TYPE HashType;
|
||||
|
@ -157,14 +168,17 @@ class RAROptions
|
|||
#ifndef SFX_MODULE
|
||||
bool GenerateArcName;
|
||||
wchar GenerateMask[MAX_GENERATE_MASK];
|
||||
wchar DefGenerateMask[MAX_GENERATE_MASK];
|
||||
#endif
|
||||
bool SyncFiles;
|
||||
bool ProcessEA;
|
||||
bool SaveStreams;
|
||||
bool SetCompressedAttr;
|
||||
bool IgnoreGeneralAttr;
|
||||
RarTime FileTimeBefore;
|
||||
RarTime FileTimeAfter;
|
||||
RarTime FileMtimeBefore,FileCtimeBefore,FileAtimeBefore;
|
||||
bool FileMtimeBeforeOR,FileCtimeBeforeOR,FileAtimeBeforeOR;
|
||||
RarTime FileMtimeAfter,FileCtimeAfter,FileAtimeAfter;
|
||||
bool FileMtimeAfterOR,FileCtimeAfterOR,FileAtimeAfterOR;
|
||||
int64 FileSizeLess;
|
||||
int64 FileSizeMore;
|
||||
bool Lock;
|
||||
|
@ -173,11 +187,12 @@ class RAROptions
|
|||
FilterMode FilterModes[MAX_FILTER_TYPES];
|
||||
wchar EmailTo[NM];
|
||||
uint VersionControl;
|
||||
bool AppendArcNameToPath;
|
||||
APPENDARCNAME_MODE AppendArcNameToPath;
|
||||
POWER_MODE Shutdown;
|
||||
EXTTIME_MODE xmtime;
|
||||
EXTTIME_MODE xmtime; // Extended time modes (time precision to store).
|
||||
EXTTIME_MODE xctime;
|
||||
EXTTIME_MODE xatime;
|
||||
bool PreserveAtime;
|
||||
wchar CompressStdin[NM];
|
||||
|
||||
uint Threads; // We use it to init hash even if RAR_SMP is not defined.
|
||||
|
|
|
@ -22,8 +22,22 @@
|
|||
|
||||
#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
|
||||
#endif
|
||||
|
||||
#undef WINVER
|
||||
#undef _WIN32_WINNT
|
||||
#define WINVER 0x0501
|
||||
|
@ -119,7 +133,7 @@
|
|||
|
||||
#ifdef _UNIX
|
||||
|
||||
#define NM 2048
|
||||
#define NM 2048
|
||||
|
||||
#include <unistd.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;
|
||||
|
||||
|
@ -25,7 +25,7 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
|||
if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
|
||||
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)
|
||||
{
|
||||
const wchar *s=DestPtr;
|
||||
|
@ -58,7 +58,7 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
|
|||
// so we use the temporary buffer for copying.
|
||||
wchar TmpStr[NM];
|
||||
wcsncpyz(TmpStr,DestPtr,ASIZE(TmpStr));
|
||||
wcscpy(DestPath,TmpStr);
|
||||
wcsncpyz(DestPath,TmpStr,DestSize);
|
||||
}
|
||||
return (wchar *)DestPtr;
|
||||
}
|
||||
|
@ -120,7 +120,14 @@ bool CmpExt(const wchar *Name,const wchar *Ext)
|
|||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
// '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'.
|
||||
wchar OutName[NM];
|
||||
wcsncpyz(OutName,Path,ASIZE(OutName));
|
||||
|
@ -303,9 +313,13 @@ void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckEx
|
|||
#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)
|
||||
{
|
||||
if (*ArcName==0)
|
||||
return (wchar *)ArcName;
|
||||
|
||||
// Pointing to last name character.
|
||||
const wchar *ChPtr=ArcName+wcslen(ArcName)-1;
|
||||
|
||||
|
@ -346,18 +360,33 @@ void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering)
|
|||
ChPtr=GetExt(ArcName);
|
||||
}
|
||||
else
|
||||
if (ChPtr[1]==0 && wcslen(ArcName)<MaxLength-3 || wcsicomp(ChPtr+1,L"exe")==0 || wcsicomp(ChPtr+1,L"sfx")==0)
|
||||
wcscpy(ChPtr+1,L"rar");
|
||||
if (ChPtr[1]==0 || wcsicomp(ChPtr,L".exe")==0 || wcsicomp(ChPtr,L".sfx")==0)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
*ChPtr='0';
|
||||
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--)
|
||||
*(EndPtr+1)=*EndPtr;
|
||||
*(ChPtr+1)='1';
|
||||
|
@ -366,15 +395,15 @@ void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering)
|
|||
}
|
||||
}
|
||||
else
|
||||
if (!IsDigit(*(ChPtr+2)) || !IsDigit(*(ChPtr+3)))
|
||||
wcscpy(ChPtr+2,L"00");
|
||||
if (!IsDigit(ChPtr[2]) || !IsDigit(ChPtr[3]))
|
||||
wcsncpyz(ChPtr+2,L"00",MaxLength-(ChPtr-ArcName)-2); // From .rar to .r00.
|
||||
else
|
||||
{
|
||||
ChPtr+=3;
|
||||
while ((++(*ChPtr))=='9'+1)
|
||||
if (*(ChPtr-1)=='.')
|
||||
ChPtr+=wcslen(ChPtr)-1; // Set to last character.
|
||||
while (++(*ChPtr)=='9'+1)
|
||||
if (ChPtr<=ArcName || *(ChPtr-1)=='.')
|
||||
{
|
||||
*ChPtr='A';
|
||||
*ChPtr='a'; // From .999 to .a00 if started from .001 or for too short names.
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -585,8 +614,7 @@ int ParseVersionFileName(wchar *Name,bool Truncate)
|
|||
wchar *VerText=wcsrchr(Name,';');
|
||||
if (VerText!=NULL)
|
||||
{
|
||||
if (Version==0)
|
||||
Version=atoiw(VerText+1);
|
||||
Version=atoiw(VerText+1);
|
||||
if (Truncate)
|
||||
*VerText=0;
|
||||
}
|
||||
|
@ -652,7 +680,7 @@ wchar* VolNameToFirstName(const wchar *VolName,wchar *FirstName,size_t MaxSize,b
|
|||
|
||||
|
||||
#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;
|
||||
if (*GenerateMask=='+')
|
||||
|
@ -713,7 +741,7 @@ static void GenArcName(wchar *ArcName,const wchar *GenerateMask,uint ArcNumber,b
|
|||
wchar Ext[NM],*Dot=GetExt(ArcName);
|
||||
*Ext=0;
|
||||
if (Dot==NULL)
|
||||
wcscpy(Ext,*PointToName(ArcName)==0 ? L".rar":L"");
|
||||
wcsncpyz(Ext,*PointToName(ArcName)==0 ? L".rar":L"",ASIZE(Ext));
|
||||
else
|
||||
{
|
||||
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])];
|
||||
memset(CField,0,sizeof(CField));
|
||||
QuoteMode=false;
|
||||
for (int I=0;Mask[I]!=0;I++)
|
||||
for (uint I=0;Mask[I]!=0;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));
|
||||
wcsncatz(NewName,DateText,ASIZE(NewName));
|
||||
wcsncatz(NewName,PointToName(ArcName),ASIZE(NewName));
|
||||
wcscpy(ArcName,NewName);
|
||||
wcsncpyz(ArcName,NewName,MaxSize);
|
||||
}
|
||||
else
|
||||
wcscat(ArcName,DateText);
|
||||
wcscat(ArcName,Ext);
|
||||
wcsncatz(ArcName,DateText,MaxSize);
|
||||
wcsncatz(ArcName,Ext,MaxSize);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
// 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];
|
||||
wchar NewName[NM];
|
||||
|
||||
uint ArcNumber=1;
|
||||
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;
|
||||
|
||||
GenArcName(NewName,GenerateMask,ArcNumber,ArcNumPresent);
|
||||
GenArcName(NewName,ASIZE(NewName),GenerateMask,ArcNumber,ArcNumPresent);
|
||||
|
||||
if (!ArcNumPresent)
|
||||
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
|
||||
// the name for (ArcNumber-1) below.
|
||||
wcsncpyz(NewName,NullToEmpty(ArcName),ASIZE(NewName));
|
||||
GenArcName(NewName,GenerateMask,ArcNumber-1,ArcNumPresent);
|
||||
GenArcName(NewName,ASIZE(NewName),GenerateMask,ArcNumber-1,ArcNumPresent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -895,8 +919,8 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
|||
{
|
||||
if (MaxSize<=PrefixLength+SrcLength)
|
||||
return false;
|
||||
wcsncpy(Dest,Prefix,PrefixLength);
|
||||
wcscpy(Dest+PrefixLength,Src);
|
||||
wcsncpyz(Dest,Prefix,MaxSize);
|
||||
wcsncatz(Dest,Src,MaxSize); // "\\?\D:\very long path".
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -904,9 +928,9 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
|||
{
|
||||
if (MaxSize<=PrefixLength+SrcLength+2)
|
||||
return false;
|
||||
wcsncpy(Dest,Prefix,PrefixLength);
|
||||
wcscpy(Dest+PrefixLength,L"UNC");
|
||||
wcscpy(Dest+PrefixLength+3,Src+1);
|
||||
wcsncpyz(Dest,Prefix,MaxSize);
|
||||
wcsncatz(Dest,L"UNC",MaxSize);
|
||||
wcsncatz(Dest,Src+1,MaxSize); // "\\?\UNC\server\share".
|
||||
return true;
|
||||
}
|
||||
// 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)
|
||||
return false;
|
||||
wcsncpy(Dest,Prefix,PrefixLength);
|
||||
wcsncpy(Dest+PrefixLength,CurDir,2); // Copy drive letter 'd:'.
|
||||
wcscpy(Dest+PrefixLength+2,Src);
|
||||
wcsncpyz(Dest,Prefix,MaxSize);
|
||||
CurDir[2]=0;
|
||||
wcsncatz(Dest,CurDir,MaxSize); // Copy drive letter 'd:'.
|
||||
wcsncatz(Dest,Src,MaxSize);
|
||||
return true;
|
||||
}
|
||||
else // Paths in path\name format.
|
||||
|
@ -933,8 +958,8 @@ bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize)
|
|||
AddEndSlash(CurDir,ASIZE(CurDir));
|
||||
if (MaxSize<=PrefixLength+wcslen(CurDir)+SrcLength)
|
||||
return false;
|
||||
wcsncpy(Dest,Prefix,PrefixLength);
|
||||
wcscpy(Dest+PrefixLength,CurDir);
|
||||
wcsncpyz(Dest,Prefix,MaxSize);
|
||||
wcsncatz(Dest,CurDir,MaxSize);
|
||||
|
||||
if (Src[0]=='.' && IsPathDiv(Src[1])) // Remove leading .\ in pathname.
|
||||
Src+=2;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
wchar* PointToName(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 SetExt(wchar *Name,const wchar *NewExt,size_t MaxSize);
|
||||
void SetSFXExt(wchar *SFXName,size_t MaxSize);
|
||||
|
|
|
@ -67,7 +67,7 @@ void QuickOpen::Load(uint64 BlockPos)
|
|||
SeekPos=Arc->Tell();
|
||||
UnsyncSeekPos=false;
|
||||
|
||||
SaveFilePos SavePos(*Arc);
|
||||
int64 SavePos=SeekPos;
|
||||
Arc->Seek(BlockPos,SEEK_SET);
|
||||
|
||||
// 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 ||
|
||||
!Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN))
|
||||
{
|
||||
Arc->Seek(SavePos,SEEK_SET);
|
||||
return;
|
||||
QLHeaderPos=Arc->CurBlockPos;
|
||||
}
|
||||
QOHeaderPos=Arc->CurBlockPos;
|
||||
RawDataStart=Arc->Tell();
|
||||
RawDataSize=Arc->SubHead.UnpSize;
|
||||
Arc->Seek(SavePos,SEEK_SET);
|
||||
|
||||
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
|
||||
// pointer is moved back, we reload quick open data from beginning.
|
||||
if (Method==SEEK_SET && (uint64)Offset<SeekPos && (uint64)Offset<LastReadHeaderPos)
|
||||
Load(QLHeaderPos);
|
||||
Load(QOHeaderPos);
|
||||
|
||||
if (Method==SEEK_SET)
|
||||
SeekPos=Offset;
|
||||
|
@ -201,22 +205,28 @@ bool QuickOpen::Tell(int64 *Pos)
|
|||
|
||||
uint QuickOpen::ReadBuffer()
|
||||
{
|
||||
SaveFilePos SavePos(*Arc);
|
||||
int64 SavePos=Arc->Tell();
|
||||
Arc->File::Seek(RawDataStart+RawDataPos,SEEK_SET);
|
||||
size_t SizeToRead=(size_t)Min(RawDataSize-RawDataPos,MaxBufSize-ReadBufSize);
|
||||
if (Arc->SubHead.Encrypted)
|
||||
SizeToRead &= ~CRYPT_BLOCK_MASK;
|
||||
if (SizeToRead==0)
|
||||
return 0;
|
||||
int ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
|
||||
if (ReadSize<=0)
|
||||
return 0;
|
||||
int ReadSize=0;
|
||||
if (SizeToRead!=0)
|
||||
{
|
||||
ReadSize=Arc->File::Read(Buf+ReadBufSize,SizeToRead);
|
||||
if (ReadSize<=0)
|
||||
ReadSize=0;
|
||||
else
|
||||
{
|
||||
#ifndef RAR_NOCRYPT
|
||||
if (Arc->SubHead.Encrypted)
|
||||
Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
|
||||
if (Arc->SubHead.Encrypted)
|
||||
Crypt.DecryptBlock(Buf+ReadBufSize,ReadSize & ~CRYPT_BLOCK_MASK);
|
||||
#endif
|
||||
RawDataPos+=ReadSize;
|
||||
ReadBufSize+=ReadSize;
|
||||
RawDataPos+=ReadSize;
|
||||
ReadBufSize+=ReadSize;
|
||||
}
|
||||
}
|
||||
Arc->Seek(SavePos,SEEK_SET);
|
||||
return ReadSize;
|
||||
}
|
||||
|
||||
|
@ -250,10 +260,10 @@ bool QuickOpen::ReadRaw(RawRead &Raw)
|
|||
return false;
|
||||
}
|
||||
|
||||
// If rest of block data crosses buffer boundary, read it in loop.
|
||||
size_t DataLeft=ReadBufSize-ReadBufPos;
|
||||
// If rest of block data crosses Buf boundary, read it in loop.
|
||||
while (SizeToRead>0)
|
||||
{
|
||||
size_t DataLeft=ReadBufSize-ReadBufPos;
|
||||
size_t CurSizeToRead=Min(DataLeft,(size_t)SizeToRead);
|
||||
Raw.Read(Buf+ReadBufPos,CurSizeToRead);
|
||||
ReadBufPos+=CurSizeToRead;
|
||||
|
@ -280,9 +290,11 @@ bool QuickOpen::ReadNext()
|
|||
uint Flags=(uint)Raw.GetV();
|
||||
uint64 Offset=Raw.GetV();
|
||||
size_t HeaderSize=(size_t)Raw.GetV();
|
||||
if (HeaderSize>MAX_HEADER_SIZE_RAR5)
|
||||
return false;
|
||||
LastReadHeader.Alloc(HeaderSize);
|
||||
Raw.GetB(&LastReadHeader[0],HeaderSize);
|
||||
// Calculate the absolute position as offset from quick open service header.
|
||||
LastReadHeaderPos=QLHeaderPos-Offset;
|
||||
LastReadHeaderPos=QOHeaderPos-Offset;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -29,24 +29,24 @@ class QuickOpen
|
|||
QuickOpenItem *ListStart;
|
||||
QuickOpenItem *ListEnd;
|
||||
|
||||
byte *Buf;
|
||||
static const size_t MaxBufSize=0x10000; // Must be multiple of CRYPT_BLOCK_SIZE.
|
||||
size_t CurBufSize;
|
||||
byte *Buf; // Read quick open data here.
|
||||
static const size_t MaxBufSize=0x10000; // Buf size, must be multiple of CRYPT_BLOCK_SIZE.
|
||||
size_t CurBufSize; // Current size of buffered data in write mode.
|
||||
#ifndef RAR_NOCRYPT // For shell extension.
|
||||
CryptData Crypt;
|
||||
#endif
|
||||
|
||||
bool Loaded;
|
||||
uint64 QLHeaderPos;
|
||||
uint64 RawDataStart;
|
||||
uint64 RawDataSize;
|
||||
uint64 RawDataPos;
|
||||
size_t ReadBufSize;
|
||||
size_t ReadBufPos;
|
||||
uint64 QOHeaderPos; // Main QO header position.
|
||||
uint64 RawDataStart; // Start of QO data, just after the main header.
|
||||
uint64 RawDataSize; // Size of entire QO data.
|
||||
uint64 RawDataPos; // Current read position in QO data.
|
||||
size_t ReadBufSize; // Size of Buf data currently read from QO.
|
||||
size_t ReadBufPos; // Current read position in Buf data.
|
||||
Array<byte> LastReadHeader;
|
||||
uint64 LastReadHeaderPos;
|
||||
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:
|
||||
QuickOpen();
|
||||
~QuickOpen();
|
||||
|
|
|
@ -37,7 +37,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
CommandData *Cmd=new CommandData;
|
||||
#ifdef SFX_MODULE
|
||||
wcscpy(Cmd->Command,L"X");
|
||||
wcsncpyz(Cmd->Command,L"X",ASIZE(Cmd->Command));
|
||||
char *Switch=argc>1 ? argv[1]:NULL;
|
||||
if (Switch!=NULL && Cmd->IsSwitch(Switch[0]))
|
||||
{
|
||||
|
@ -68,6 +68,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
ShutdownOnClose=Cmd->Shutdown;
|
||||
if (ShutdownOnClose)
|
||||
ShutdownCheckAnother(true);
|
||||
#endif
|
||||
|
||||
uiInit(Cmd->Sound);
|
||||
|
@ -75,13 +77,6 @@ int main(int argc, char *argv[])
|
|||
ErrHandler.SetSilent(Cmd->AllYes || Cmd->MsgStream==MSG_NULL);
|
||||
|
||||
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();
|
||||
delete Cmd;
|
||||
}
|
||||
|
@ -100,7 +95,8 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
if (ShutdownOnClose!=POWERMODE_KEEP && ErrHandler.IsShutdownEnabled())
|
||||
if (ShutdownOnClose!=POWERMODE_KEEP && ErrHandler.IsShutdownEnabled() &&
|
||||
!ShutdownCheckAnother(false))
|
||||
Shutdown(ShutdownOnClose);
|
||||
#endif
|
||||
ErrHandler.MainExit=true;
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "filestr.hpp"
|
||||
#include "find.hpp"
|
||||
#include "scantree.hpp"
|
||||
#include "savepos.hpp"
|
||||
#include "getbits.hpp"
|
||||
#include "rdwrfn.hpp"
|
||||
#ifdef USE_QOPEN
|
||||
|
@ -77,6 +76,9 @@
|
|||
|
||||
#include "rs.hpp"
|
||||
#include "rs16.hpp"
|
||||
|
||||
|
||||
|
||||
#include "recvol.hpp"
|
||||
#include "volume.hpp"
|
||||
#include "smallfn.hpp"
|
||||
|
|
|
@ -21,15 +21,12 @@ typedef wchar_t wchar; // Unicode character
|
|||
// Maximum int64 value.
|
||||
#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
|
||||
// is not defined and probably should be calculated inside of function.
|
||||
// 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)
|
||||
|
||||
// Maximum uint64 value.
|
||||
#define MAX_UINT64 INT32TO64(0xffffffff,0xffffffff)
|
||||
#define UINT64NDF MAX_UINT64
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,7 @@ void ComprDataIO::Init()
|
|||
NextVolumeMissing=false;
|
||||
SrcFile=NULL;
|
||||
DestFile=NULL;
|
||||
UnpWrAddr=NULL;
|
||||
UnpWrSize=0;
|
||||
Command=NULL;
|
||||
Encryption=false;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
class CmdAdd;
|
||||
class Unpack;
|
||||
class ArcFileSearch;
|
||||
|
||||
#if 0
|
||||
// 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.
|
||||
if (Fmt==RARFMT15)
|
||||
{
|
||||
RecVolumes3 RecVol(false);
|
||||
RecVolumes3 RecVol(Cmd,false);
|
||||
return RecVol.Restore(Cmd,Name,Silent);
|
||||
}
|
||||
else
|
||||
{
|
||||
RecVolumes5 RecVol(false);
|
||||
RecVolumes5 RecVol(Cmd,false);
|
||||
return RecVol.Restore(Cmd,Name,Silent);
|
||||
}
|
||||
}
|
||||
|
@ -100,12 +100,12 @@ void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name)
|
|||
RevFile.Close();
|
||||
if (Rev5)
|
||||
{
|
||||
RecVolumes5 RecVol(true);
|
||||
RecVolumes5 RecVol(Cmd,true);
|
||||
RecVol.Test(Cmd,Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
RecVolumes3 RecVol(true);
|
||||
RecVolumes3 RecVol(Cmd,true);
|
||||
RecVol.Test(Cmd,Name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class RecVolumes3
|
|||
ThreadPool *RSThreadPool;
|
||||
#endif
|
||||
public:
|
||||
RecVolumes3(bool TestOnly);
|
||||
RecVolumes3(RAROptions *Cmd,bool TestOnly);
|
||||
~RecVolumes3();
|
||||
void Make(RAROptions *Cmd,wchar *ArcName);
|
||||
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||
|
@ -71,11 +71,12 @@ class RecVolumes5
|
|||
#ifdef RAR_SMP
|
||||
ThreadPool *RecThreadPool;
|
||||
#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.
|
||||
void ProcessAreaRS(RecRSThreadData *td);
|
||||
public:
|
||||
RecVolumes5(bool TestOnly);
|
||||
RecVolumes5(RAROptions *Cmd,bool TestOnly);
|
||||
~RecVolumes5();
|
||||
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||
void Test(RAROptions *Cmd,const wchar *Name);
|
||||
|
|
|
@ -36,7 +36,7 @@ THREAD_PROC(RSDecodeThread)
|
|||
}
|
||||
#endif
|
||||
|
||||
RecVolumes3::RecVolumes3(bool TestOnly)
|
||||
RecVolumes3::RecVolumes3(RAROptions *Cmd,bool TestOnly)
|
||||
{
|
||||
memset(SrcFile,0,sizeof(SrcFile));
|
||||
if (TestOnly)
|
||||
|
@ -50,7 +50,7 @@ RecVolumes3::RecVolumes3(bool TestOnly)
|
|||
Buf.Alloc(TotalBufferSize);
|
||||
memset(SrcFile,0,sizeof(SrcFile));
|
||||
#ifdef RAR_SMP
|
||||
RSThreadPool=CreateThreadPool();
|
||||
RSThreadPool=new ThreadPool(Cmd->Threads);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ RecVolumes3::~RecVolumes3()
|
|||
for (size_t I=0;I<ASIZE(SrcFile);I++)
|
||||
delete SrcFile[I];
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(RSThreadPool);
|
||||
delete RSThreadPool;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
NewStyle=IsNewStyleRev(ArcName);
|
||||
while (Ext>ArcName+1 && (IsDigit(*(Ext-1)) || *(Ext-1)=='_'))
|
||||
Ext--;
|
||||
wcscpy(Ext,L"*.*");
|
||||
wcsncpyz(Ext,L"*.*",ASIZE(ArcName)-(Ext-ArcName));
|
||||
|
||||
FindFile Find;
|
||||
Find.SetMask(ArcName);
|
||||
|
@ -235,7 +235,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
}
|
||||
RecVolNumber=P[1];
|
||||
FileNumber=P[2];
|
||||
wcscpy(PrevName,CurName);
|
||||
wcsncpyz(PrevName,CurName,ASIZE(PrevName));
|
||||
File *NewFile=new File;
|
||||
NewFile->TOpen(CurName);
|
||||
SrcFile[FileNumber+P[0]-1]=NewFile;
|
||||
|
@ -247,7 +247,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
if (!Silent || FoundRecVolumes!=0)
|
||||
uiMsg(UIMSG_RECVOLFOUND,FoundRecVolumes);
|
||||
if (FoundRecVolumes==0)
|
||||
return(false);
|
||||
return false;
|
||||
|
||||
bool WriteFlags[256];
|
||||
memset(WriteFlags,0,sizeof(WriteFlags));
|
||||
|
@ -290,8 +290,8 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
{
|
||||
NewFile->Close();
|
||||
wchar NewName[NM];
|
||||
wcscpy(NewName,ArcName);
|
||||
wcscat(NewName,L".bad");
|
||||
wcsncpyz(NewName,ArcName,ASIZE(NewName));
|
||||
wcsncatz(NewName,L".bad",ASIZE(NewName));
|
||||
|
||||
uiMsg(UIMSG_BADARCHIVE,ArcName);
|
||||
uiMsg(UIMSG_RENAMING,ArcName,NewName);
|
||||
|
@ -322,7 +322,7 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
MissingVolumes++;
|
||||
|
||||
if (CurArcNum==FileNumber-1)
|
||||
wcscpy(LastVolName,ArcName);
|
||||
wcsncpyz(LastVolName,ArcName,ASIZE(LastVolName));
|
||||
|
||||
uiMsg(UIMSG_MISSINGVOL,ArcName);
|
||||
uiMsg(UIEVENT_NEWARCHIVE,ArcName);
|
||||
|
@ -363,11 +363,10 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
|
||||
#ifdef RAR_SMP
|
||||
uint ThreadNumber=Cmd->Threads;
|
||||
RSEncode rse[MaxPoolThreads];
|
||||
#else
|
||||
uint ThreadNumber=1;
|
||||
RSEncode rse[1];
|
||||
#endif
|
||||
RSEncode *rse=new RSEncode[ThreadNumber];
|
||||
for (uint I=0;I<ThreadNumber;I++)
|
||||
rse[I].Init(RecVolNumber);
|
||||
|
||||
|
@ -438,6 +437,8 @@ bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
if (WriteFlags[I])
|
||||
SrcFile[I]->Write(&Buf[I*RecBufferSize],MaxRead);
|
||||
}
|
||||
delete[] rse;
|
||||
|
||||
for (int I=0;I<RecVolNumber+FileNumber;I++)
|
||||
if (SrcFile[I]!=NULL)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
static const uint MaxVolumes=65535;
|
||||
|
||||
RecVolumes5::RecVolumes5(bool TestOnly)
|
||||
RecVolumes5::RecVolumes5(RAROptions *Cmd,bool TestOnly)
|
||||
{
|
||||
RealBuf=NULL;
|
||||
RealReadBuffer=NULL;
|
||||
|
@ -10,7 +10,14 @@ RecVolumes5::RecVolumes5(bool TestOnly)
|
|||
TotalCount=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].RS=NULL;
|
||||
|
@ -25,7 +32,7 @@ RecVolumes5::RecVolumes5(bool TestOnly)
|
|||
else
|
||||
{
|
||||
#ifdef RAR_SMP
|
||||
RecThreadPool=CreateThreadPool();
|
||||
RecThreadPool=new ThreadPool(MaxUserThreads);
|
||||
#endif
|
||||
RealBuf=new byte[TotalBufferSize+SSE_ALIGNMENT];
|
||||
Buf=(byte *)ALIGN_VALUE(RealBuf,SSE_ALIGNMENT);
|
||||
|
@ -39,10 +46,11 @@ RecVolumes5::~RecVolumes5()
|
|||
delete[] RealReadBuffer;
|
||||
for (uint I=0;I<RecItems.Size();I++)
|
||||
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;
|
||||
#ifdef RAR_SMP
|
||||
DestroyThreadPool(RecThreadPool);
|
||||
delete RecThreadPool;
|
||||
#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);
|
||||
*/
|
||||
|
||||
#ifdef RAR_SMP
|
||||
uint ThreadNumber=Cmd->Threads;
|
||||
#else
|
||||
uint ThreadNumber=1;
|
||||
#endif
|
||||
uint ThreadNumber=MaxUserThreads;
|
||||
|
||||
const uint MinThreadBlock=0x1000;
|
||||
ThreadNumber=Min(ThreadNumber,MaxRead/MinThreadBlock);
|
||||
|
@ -139,12 +143,10 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
wcsncpyz(ArcName,Name,ASIZE(ArcName));
|
||||
|
||||
wchar *Num=GetVolNumPart(ArcName);
|
||||
if (Num==ArcName)
|
||||
return false; // Number part is missing in the name.
|
||||
while (Num>ArcName && IsDigit(*(Num-1)))
|
||||
Num--;
|
||||
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));
|
||||
|
||||
wchar FirstVolName[NM];
|
||||
|
@ -240,7 +242,7 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
uiMsg(UIMSG_STRING,Item->Name);
|
||||
|
||||
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;
|
||||
if (!Item->Valid)
|
||||
{
|
||||
|
@ -289,8 +291,8 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
|||
Item->f->Close();
|
||||
|
||||
wchar NewName[NM];
|
||||
wcscpy(NewName,Item->Name);
|
||||
wcscat(NewName,L".bad");
|
||||
wcsncpyz(NewName,Item->Name,ASIZE(NewName));
|
||||
wcsncatz(NewName,L".bad",ASIZE(NewName));
|
||||
|
||||
uiMsg(UIMSG_BADARCHIVE,Item->Name);
|
||||
uiMsg(UIMSG_RENAMING,Item->Name,NewName);
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef RARDLL
|
||||
const wchar *St(MSGID StringId)
|
||||
const wchar* St(MSGID 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
|
||||
// structure memset'ed before use, this variable is not lost.
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, 1);
|
||||
AES_NI=(CPUInfo[2] & 0x2000000)!=0;
|
||||
__cpuid(CPUInfo, 0x80000000); // Get the maximum supported cpuid function.
|
||||
if ((CPUInfo[0] & 0x7fffffff)>=1)
|
||||
{
|
||||
__cpuid(CPUInfo, 1);
|
||||
AES_NI=(CPUInfo[2] & 0x2000000)!=0;
|
||||
}
|
||||
else
|
||||
AES_NI=0;
|
||||
#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)
|
||||
{
|
||||
case 128:
|
||||
|
|
|
@ -14,13 +14,26 @@ class SaveFilePos
|
|||
}
|
||||
~SaveFilePos()
|
||||
{
|
||||
// If file is already closed by current exception processing,
|
||||
// we would get uneeded error messages and an exception inside of
|
||||
// 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.
|
||||
// Unless the file is already closed either by current exception
|
||||
// processing or intentionally by external code.
|
||||
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;
|
||||
uint FolderWildcardCount=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]=='*')
|
||||
WildcardFound=true;
|
||||
|
@ -171,7 +176,7 @@ bool ScanTree::GetFilteredMask()
|
|||
|
||||
wchar Filter[NM];
|
||||
// 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));
|
||||
// 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;
|
||||
|
@ -360,7 +365,7 @@ SCAN_CODE ScanTree::FindProc(FindData *FD)
|
|||
wcsncpyz(CurMask,Mask+1,ASIZE(CurMask));
|
||||
else
|
||||
{
|
||||
*(PrevSlash+1)=0;
|
||||
*PrevSlash=0;
|
||||
wcsncatz(CurMask,Mask,ASIZE(CurMask));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class ScanTree
|
|||
ScanTree(StringList *FileMasks,RECURSE_MODE Recurse,bool GetLinks,SCAN_DIRS GetDirs);
|
||||
~ScanTree();
|
||||
SCAN_CODE GetNext(FindData *FindData);
|
||||
size_t GetSpecPathLength() {return SpecPathLength;};
|
||||
size_t GetSpecPathLength() {return SpecPathLength;}
|
||||
int GetErrors() {return Errors;};
|
||||
void SetErrArcName(const wchar *Name) {wcsncpyz(ErrArcName,Name,ASIZE(ErrArcName));}
|
||||
void SetCommandData(CommandData *Cmd) {ScanTree::Cmd=Cmd;}
|
||||
|
|
|
@ -241,8 +241,8 @@ uint GetDigits(uint Number)
|
|||
|
||||
bool LowAscii(const char *Str)
|
||||
{
|
||||
for (int I=0;Str[I]!=0;I++)
|
||||
if ((byte)Str[I]<32 || (byte)Str[I]>127)
|
||||
for (size_t I=0;Str[I]!=0;I++)
|
||||
if (/*(byte)Str[I]<32 || */(byte)Str[I]>127)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -250,11 +250,11 @@ bool LowAscii(const char *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
|
||||
// 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 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.
|
||||
char* strncpyz(char *dest, const char *src, size_t maxlen)
|
||||
// Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
|
||||
void strncpyz(char *dest, const char *src, size_t maxlen)
|
||||
{
|
||||
if (maxlen>0)
|
||||
{
|
||||
strncpy(dest,src,maxlen-1);
|
||||
dest[maxlen-1]=0;
|
||||
while (--maxlen>0 && *src!=0)
|
||||
*dest++=*src++;
|
||||
*dest=0;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// Safe wcsncpy: copies maxlen-1 max and always returns zero terminated dest.
|
||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
|
||||
// Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
|
||||
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
|
||||
{
|
||||
if (maxlen>0)
|
||||
{
|
||||
wcsncpy(dest,src,maxlen-1);
|
||||
dest[maxlen-1]=0;
|
||||
while (--maxlen>0 && *src!=0)
|
||||
*dest++=*src++;
|
||||
*dest=0;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
// Safe strncat: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with standard strncat.
|
||||
char* strncatz(char* dest, const char* src, size_t maxlen)
|
||||
// Safe append: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with wcsncat.
|
||||
void strncatz(char* dest, const char* src, size_t maxlen)
|
||||
{
|
||||
size_t Length = strlen(dest);
|
||||
int avail=int(maxlen - Length - 1);
|
||||
if (avail > 0)
|
||||
strncat(dest, src, avail);
|
||||
return dest;
|
||||
size_t length = strlen(dest);
|
||||
if (maxlen > length)
|
||||
strncpyz(dest + length, src, maxlen - length);
|
||||
}
|
||||
|
||||
|
||||
// Safe wcsncat: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. Note that 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with standard wcsncat.
|
||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
|
||||
// Safe append: resulting dest length cannot exceed maxlen and dest
|
||||
// is always zero terminated. 'maxlen' parameter defines the entire
|
||||
// dest buffer size and is not compatible with wcsncat.
|
||||
void wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
|
||||
{
|
||||
size_t Length = wcslen(dest);
|
||||
int avail=int(maxlen - Length - 1);
|
||||
if (avail > 0)
|
||||
wcsncat(dest, src, avail);
|
||||
return dest;
|
||||
size_t length = wcslen(dest);
|
||||
if (maxlen > length)
|
||||
wcsncpyz(dest + length, src, maxlen - length);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ wchar* RemoveLF(wchar *Str);
|
|||
unsigned char loctolower(unsigned char ch);
|
||||
unsigned char loctoupper(unsigned char ch);
|
||||
|
||||
char* strncpyz(char *dest, const char *src, size_t maxlen);
|
||||
wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
||||
char* strncatz(char* dest, const char* src, size_t maxlen);
|
||||
wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
||||
void strncpyz(char *dest, const char *src, size_t maxlen);
|
||||
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
||||
void strncatz(char* dest, const char* src, size_t maxlen);
|
||||
void wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
||||
|
||||
unsigned char etoupper(unsigned char ch);
|
||||
wchar etoupperw(wchar ch);
|
||||
|
|
|
@ -80,7 +80,7 @@ bool SubAllocator::StartSubAllocator(int SASize)
|
|||
{
|
||||
uint t=SASize << 20;
|
||||
if (SubAllocatorSize == t)
|
||||
return TRUE;
|
||||
return true;
|
||||
StopSubAllocator();
|
||||
|
||||
// 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)
|
||||
{
|
||||
ErrHandler.MemoryError();
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
SubAllocatorSize=t;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ class SubAllocator
|
|||
inline void* ExpandUnits(void* ptr,int OldNU);
|
||||
inline void* ShrinkUnits(void* ptr,int OldNU,int NewNU);
|
||||
inline void FreeUnits(void* ptr,int OldNU);
|
||||
long GetAllocatedMemory() {return(SubAllocatorSize);};
|
||||
long GetAllocatedMemory() {return(SubAllocatorSize);}
|
||||
|
||||
byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
|
||||
};
|
||||
|
|
|
@ -123,6 +123,28 @@ void Shutdown(POWER_MODE Mode)
|
|||
if (Mode==POWERMODE_RESTART)
|
||||
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
|
||||
|
||||
|
||||
|
@ -165,18 +187,29 @@ SSE_VERSION _SSE_Version=GetSSEVersion();
|
|||
SSE_VERSION GetSSEVersion()
|
||||
{
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, 7);
|
||||
if ((CPUInfo[1] & 0x20)!=0)
|
||||
return SSE_AVX2;
|
||||
__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;
|
||||
__cpuid(CPUInfo, 0x80000000);
|
||||
|
||||
// Maximum supported cpuid function. For example, Pentium M 755 returns 4 here.
|
||||
uint MaxSupported=CPUInfo[0] & 0x7fffffff;
|
||||
|
||||
if (MaxSupported>=7)
|
||||
{
|
||||
__cpuid(CPUInfo, 7);
|
||||
if ((CPUInfo[1] & 0x20)!=0)
|
||||
return SSE_AVX2;
|
||||
}
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@ clock_t MonoClock();
|
|||
void Wait();
|
||||
bool EmailFile(const wchar *FileName,const wchar *MailToW);
|
||||
void Shutdown(POWER_MODE Mode);
|
||||
bool ShutdownCheckAnother(bool Open);
|
||||
|
||||
#ifdef _WIN_ALL
|
||||
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)
|
||||
{
|
||||
#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)
|
||||
{
|
||||
#ifdef _UNIX
|
||||
|
|
|
@ -170,12 +170,13 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data)
|
|||
CreateThreads();
|
||||
|
||||
// If queue is full, wait until it is empty.
|
||||
if ((QueueTop + 1) % ASIZE(TaskQueue) == QueueBottom)
|
||||
if (ActiveThreads>=ASIZE(TaskQueue))
|
||||
WaitDone();
|
||||
|
||||
TaskQueue[QueueTop].Proc = Proc;
|
||||
TaskQueue[QueueTop].Param = Data;
|
||||
QueueTop = (QueueTop + 1) % ASIZE(TaskQueue);
|
||||
ActiveThreads++;
|
||||
}
|
||||
|
||||
|
||||
|
@ -184,9 +185,6 @@ void ThreadPool::AddTask(PTHREAD_PROC Proc,void *Data)
|
|||
// are sleeping yet.
|
||||
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)
|
||||
return;
|
||||
#ifdef _WIN_ALL
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
#ifndef RAR_SMP
|
||||
const uint MaxPoolThreads=1; // For single threaded version.
|
||||
#else
|
||||
const uint MaxPoolThreads=32;
|
||||
// We need to use the processor groups API to increase it beyond 64.
|
||||
// Also be sure to check and adjust if needed per thread and total block size
|
||||
// when compressing if going above 64.
|
||||
const uint MaxPoolThreads=64;
|
||||
|
||||
|
||||
#ifdef _UNIX
|
||||
|
@ -98,9 +101,6 @@ class ThreadPool
|
|||
#endif
|
||||
};
|
||||
|
||||
ThreadPool* CreateThreadPool();
|
||||
void DestroyThreadPool(ThreadPool *Pool);
|
||||
|
||||
#endif // RAR_SMP
|
||||
|
||||
#endif // _RAR_THREADPOOL_
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue