summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Docs/bash-completion/cmake8
-rw-r--r--Docs/bash-completion/cpack4
-rw-r--r--Docs/bash-completion/ctest2
-rw-r--r--Modules/CMakeCommonLanguageInclude.cmake22
-rw-r--r--Modules/CMakeDetermineCompiler.cmake13
-rw-r--r--Modules/CMakeDetermineCompilerABI.cmake3
-rw-r--r--Modules/CMakeDetermineCompilerId.cmake48
-rw-r--r--Modules/CMakeGraphVizOptions.cmake83
-rw-r--r--Modules/CMakePrintHelpers.cmake146
-rw-r--r--Modules/CMakePushCheckState.cmake33
-rw-r--r--Modules/CMakeUnixFindMake.cmake10
-rw-r--r--Modules/Compiler/Clang.cmake1
-rw-r--r--Modules/CompilerId/VS-10.vcxproj.in15
-rw-r--r--Modules/CompilerId/VS-6.dsp.in6
-rw-r--r--Modules/CompilerId/VS-7.vcproj.in4
-rw-r--r--Modules/FindGTK2.cmake183
-rw-r--r--Modules/FindPNG.cmake33
-rw-r--r--Modules/Platform/Darwin.cmake28
-rw-r--r--Modules/Platform/QNX.cmake3
-rw-r--r--Modules/Platform/Windows-MSVC.cmake13
-rw-r--r--Modules/Qt4Macros.cmake9
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestBatchTestHandler.cxx2
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx101
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h15
-rw-r--r--Source/CTest/cmCTestRunTest.cxx8
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx7
-rw-r--r--Source/CTest/cmCTestTestHandler.h2
-rw-r--r--Source/QtDialog/CMakeLists.txt18
-rw-r--r--Source/cmAddDependenciesCommand.cxx7
-rw-r--r--Source/cmAddExecutableCommand.cxx72
-rw-r--r--Source/cmAddExecutableCommand.h13
-rw-r--r--Source/cmAddLibraryCommand.cxx80
-rw-r--r--Source/cmAddLibraryCommand.h13
-rw-r--r--Source/cmCPluginAPI.cxx5
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx4
-rw-r--r--Source/cmDocumentVariables.cxx66
-rw-r--r--Source/cmExportCommand.cxx9
-rw-r--r--Source/cmExportFileGenerator.cxx30
-rw-r--r--Source/cmExprParserHelper.cxx4
-rw-r--r--Source/cmFileCommand.h2
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx17
-rw-r--r--Source/cmGeneratorExpressionParser.cxx20
-rw-r--r--Source/cmGetPropertyCommand.cxx12
-rw-r--r--Source/cmGetTargetPropertyCommand.cxx25
-rw-r--r--Source/cmGlobalGenerator.cxx26
-rw-r--r--Source/cmGlobalGenerator.h7
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx23
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h6
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx97
-rw-r--r--Source/cmGlobalVisualStudio11Generator.h4
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx19
-rw-r--r--Source/cmGlobalVisualStudio12Generator.h3
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx11
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx24
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h8
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx26
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h5
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx7
-rw-r--r--Source/cmGlobalVisualStudio9Generator.h2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx4
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h1
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx34
-rw-r--r--Source/cmInstallCommand.cxx16
-rw-r--r--Source/cmListFileCache.cxx222
-rw-r--r--Source/cmListFileCache.h17
-rw-r--r--Source/cmListFileLexer.c411
-rw-r--r--Source/cmListFileLexer.h1
-rw-r--r--Source/cmListFileLexer.in.l26
-rw-r--r--Source/cmLocalGenerator.cxx54
-rw-r--r--Source/cmLocalGenerator.h5
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx119
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx40
-rw-r--r--Source/cmLocalVisualStudio7Generator.h2
-rw-r--r--Source/cmMacroCommand.cxx2
-rw-r--r--Source/cmMakefile.cxx103
-rw-r--r--Source/cmMakefile.h30
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx8
-rw-r--r--Source/cmPolicies.cxx6
-rw-r--r--Source/cmSetPropertyCommand.cxx5
-rw-r--r--Source/cmSetTargetPropertiesCommand.cxx5
-rw-r--r--Source/cmSystemTools.cxx8
-rw-r--r--Source/cmSystemTools.h5
-rw-r--r--Source/cmTarget.cxx86
-rw-r--r--Source/cmTarget.h3
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx5
-rw-r--r--Source/cmTargetPropCommandBase.cxx11
-rw-r--r--Source/cmVariableWatch.cxx50
-rw-r--r--Source/cmVariableWatch.h20
-rw-r--r--Source/cmVariableWatchCommand.cxx156
-rw-r--r--Source/cmVariableWatchCommand.h17
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx66
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx6
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h6
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.cxx8
-rw-r--r--Source/cmWhileCommand.cxx4
-rw-r--r--Source/cmakemain.cxx13
-rw-r--r--Source/cmcldeps.cxx33
-rw-r--r--Source/kwsys/CMakeLists.txt83
-rw-r--r--Source/kwsys/SystemInformation.cxx380
-rw-r--r--Source/kwsys/SystemInformation.hxx.in6
-rw-r--r--Source/kwsys/SystemTools.cxx209
-rw-r--r--Source/kwsys/SystemTools.hxx.in7
-rw-r--r--Source/kwsys/auto_ptr.hxx.in18
-rw-r--r--Source/kwsys/hashtable.hxx.in18
-rw-r--r--Source/kwsys/kwsysPlatformTests.cmake3
-rw-r--r--Source/kwsys/kwsysPlatformTestsCXX.cxx48
-rw-r--r--Source/kwsys/testSystemInformation.cxx21
-rw-r--r--Tests/AliasTarget/CMakeLists.txt47
-rw-r--r--Tests/AliasTarget/bat.cpp28
-rw-r--r--Tests/AliasTarget/commandgenerator.cpp15
-rw-r--r--Tests/AliasTarget/empty.cpp7
-rw-r--r--Tests/AliasTarget/object.cpp5
-rw-r--r--Tests/AliasTarget/object.h4
-rw-r--r--Tests/AliasTarget/targetgenerator.cpp13
-rw-r--r--Tests/BuildDepends/CMakeLists.txt39
-rw-r--r--Tests/BuildDepends/Project/CMakeLists.txt16
-rw-r--r--Tests/BuildDepends/Project/ninjadep.cpp6
-rw-r--r--Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt5
-rw-r--r--Tests/CMakeCommands/target_compile_options/CMakeLists.txt5
-rw-r--r--Tests/CMakeCommands/target_include_directories/CMakeLists.txt14
-rw-r--r--Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt9
-rw-r--r--Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp2
-rw-r--r--Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.h4
-rw-r--r--Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp2
-rw-r--r--Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.h4
-rw-r--r--Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib_exe.cpp8
-rw-r--r--Tests/CMakeLists.txt23
-rw-r--r--Tests/CTestTestDepends/CMakeLists.txt3
-rw-r--r--Tests/CTestTestMemcheck/CMakeLists.txt27
-rw-r--r--Tests/CTestTestMemcheck/memtester.cxx.in8
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt29
-rw-r--r--Tests/ExportImport/Export/empty.cpp4
-rw-r--r--Tests/GeneratorExpression/CMakeLists.txt10
-rw-r--r--Tests/GeneratorExpression/check-part3.cmake6
-rw-r--r--Tests/GeneratorExpression/empty.cpp6
-rw-r--r--Tests/IncludeDirectories/CMP0021/CMakeLists.txt14
-rw-r--r--Tests/IncludeDirectories/CMP0021/includes/cmp0021/cmp0021.h2
-rw-r--r--Tests/IncludeDirectories/CMP0021/main.cpp11
-rw-r--r--Tests/IncludeDirectories/CMakeLists.txt4
-rw-r--r--Tests/LinkFlags/CMakeLists.txt9
-rw-r--r--Tests/LinkFlags/LinkerFlags/CMakeLists.txt11
-rw-r--r--Tests/LinkFlags/LinkerFlagsConfig/CMakeLists.txt11
-rw-r--r--Tests/RunCMake/CMP0004/CMP0004-NEW.cmake2
-rw-r--r--Tests/RunCMake/CMP0004/CMP0004-OLD.cmake2
-rw-r--r--Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake2
-rw-r--r--Tests/RunCMake/CMP0004/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/CMP0019/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt2
-rw-r--r--Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/CTest/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/CompatibleInterface/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/CompilerChange/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Configure/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/ExportWithoutLanguage/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/ExternalData/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/FPHSA/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/File_Generate/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/GeneratorExpression/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/GeneratorToolset/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/IncompatibleQt/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Languages/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Languages/LINK_LANGUAGE-genex.cmake4
-rw-r--r--Tests/RunCMake/ObjectLibrary/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/PositionIndependentCode/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Syntax/.gitattributes1
-rw-r--r--Tests/RunCMake/Syntax/BracketWarn-stderr.txt35
-rw-r--r--Tests/RunCMake/Syntax/BracketWarn-stdout.txt1
-rw-r--r--Tests/RunCMake/Syntax/BracketWarn.cmake1
-rw-r--r--Tests/RunCMake/Syntax/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/Syntax/CommandComments-stderr.txt4
-rw-r--r--Tests/RunCMake/Syntax/CommandComments.cmake6
-rw-r--r--Tests/RunCMake/Syntax/CommandError0-result.txt (renamed from Tests/RunCMake/include_directories/TargetInterfaceIncludes-result.txt)0
-rw-r--r--Tests/RunCMake/Syntax/CommandError0-stderr.txt8
-rw-r--r--Tests/RunCMake/Syntax/CommandError0.cmake2
-rw-r--r--Tests/RunCMake/Syntax/CommandError1-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/CommandError1-stderr.txt7
-rw-r--r--Tests/RunCMake/Syntax/CommandError1.cmake1
-rw-r--r--Tests/RunCMake/Syntax/CommandNewlines-stderr.txt3
-rw-r--r--Tests/RunCMake/Syntax/CommandNewlines.cmake10
-rw-r--r--Tests/RunCMake/Syntax/CommandSpaces-stderr.txt6
-rw-r--r--Tests/RunCMake/Syntax/CommandSpaces.cmake6
-rw-r--r--Tests/RunCMake/Syntax/CommandTabs-stderr.txt6
-rw-r--r--Tests/RunCMake/Syntax/CommandTabs.cmake6
-rw-r--r--Tests/RunCMake/Syntax/ParenNoSpace-stderr.txt1
-rw-r--r--Tests/RunCMake/Syntax/ParenNoSpace-stdout.txt2
-rw-r--r--Tests/RunCMake/Syntax/ParenNoSpace.cmake2
-rw-r--r--Tests/RunCMake/Syntax/RunCMakeTest.cmake18
-rw-r--r--Tests/RunCMake/Syntax/String0-stderr.txt1
-rw-r--r--Tests/RunCMake/Syntax/String0.cmake2
-rw-r--r--Tests/RunCMake/Syntax/String1-stderr.txt3
-rw-r--r--Tests/RunCMake/Syntax/String1.cmake3
-rw-r--r--Tests/RunCMake/Syntax/StringNoSpace-stderr.txt19
-rw-r--r--Tests/RunCMake/Syntax/StringNoSpace.cmake4
-rw-r--r--Tests/RunCMake/Syntax/Unquoted0-stderr.txt1
-rw-r--r--Tests/RunCMake/Syntax/Unquoted0.cmake2
-rw-r--r--Tests/RunCMake/Syntax/Unquoted1-stderr.txt1
-rw-r--r--Tests/RunCMake/Syntax/Unquoted1.cmake1
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedCall1-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedCall1-stderr.txt7
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedCall1.cmake1
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedCall2-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedCall2-stderr.txt7
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedCall2.cmake3
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedString-result.txt1
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedString-stderr.txt8
-rw-r--r--Tests/RunCMake/Syntax/UnterminatedString.cmake1
-rw-r--r--Tests/RunCMake/TargetPolicies/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/VisibilityPreset/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/add_dependencies/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/alias_targets/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/alias_targets/RunCMakeTest.cmake20
-rw-r--r--Tests/RunCMake/alias_targets/add_dependencies-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/add_dependencies-stderr.txt5
-rw-r--r--Tests/RunCMake/alias_targets/add_dependencies.cmake9
-rw-r--r--Tests/RunCMake/alias_targets/add_executable-library-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/add_executable-library-stderr.txt5
-rw-r--r--Tests/RunCMake/alias_targets/add_executable-library.cmake6
-rw-r--r--Tests/RunCMake/alias_targets/add_library-executable-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/add_library-executable-stderr.txt5
-rw-r--r--Tests/RunCMake/alias_targets/add_library-executable.cmake6
-rw-r--r--Tests/RunCMake/alias_targets/alias-target-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/alias-target-stderr.txt5
-rw-r--r--Tests/RunCMake/alias_targets/alias-target.cmake8
-rw-r--r--Tests/RunCMake/alias_targets/empty.cpp7
-rw-r--r--Tests/RunCMake/alias_targets/exclude-from-all-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/exclude-from-all-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/exclude-from-all.cmake6
-rw-r--r--Tests/RunCMake/alias_targets/export-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/export-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/export.cmake8
-rw-r--r--Tests/RunCMake/alias_targets/imported-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/imported-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/imported-target-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/imported-target-stderr.txt5
-rw-r--r--Tests/RunCMake/alias_targets/imported-target.cmake6
-rw-r--r--Tests/RunCMake/alias_targets/imported.cmake2
-rw-r--r--Tests/RunCMake/alias_targets/install-export-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/install-export-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/install-export.cmake9
-rw-r--r--Tests/RunCMake/alias_targets/invalid-name-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/invalid-name-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/invalid-name.cmake6
-rw-r--r--Tests/RunCMake/alias_targets/invalid-target-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/invalid-target-stderr.txt5
-rw-r--r--Tests/RunCMake/alias_targets/invalid-target.cmake2
-rw-r--r--Tests/RunCMake/alias_targets/multiple-targets-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/multiple-targets-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/multiple-targets.cmake7
-rw-r--r--Tests/RunCMake/alias_targets/name-conflict-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/name-conflict-stderr.txt5
-rw-r--r--Tests/RunCMake/alias_targets/name-conflict.cmake8
-rw-r--r--Tests/RunCMake/alias_targets/no-targets-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/no-targets-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/no-targets.cmake4
-rw-r--r--Tests/RunCMake/alias_targets/set_property-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/set_property-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/set_property.cmake8
-rw-r--r--Tests/RunCMake/alias_targets/set_target_properties-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/set_target_properties-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/set_target_properties.cmake8
-rw-r--r--Tests/RunCMake/alias_targets/target_include_directories-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/target_include_directories-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/target_include_directories.cmake8
-rw-r--r--Tests/RunCMake/alias_targets/target_link_libraries-result.txt1
-rw-r--r--Tests/RunCMake/alias_targets/target_link_libraries-stderr.txt4
-rw-r--r--Tests/RunCMake/alias_targets/target_link_libraries.cmake9
-rw-r--r--Tests/RunCMake/build_command/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/find_package/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/get_filename_component/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/if/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/include/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/include_directories/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/include_directories/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/include_directories/TargetInterfaceIncludes-stderr.txt4
-rw-r--r--Tests/RunCMake/include_directories/TargetInterfaceIncludes.cmake4
-rw-r--r--Tests/RunCMake/include_directories/install_config-result.txt1
-rw-r--r--Tests/RunCMake/include_directories/install_config-stderr.txt5
-rw-r--r--Tests/RunCMake/include_directories/install_config.cmake6
-rw-r--r--Tests/RunCMake/include_external_msproject/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/list/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/target_link_libraries/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/try_compile/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/variable_watch/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/variable_watch/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/variable_watch/WatchTwice-stderr.txt2
-rw-r--r--Tests/RunCMake/variable_watch/WatchTwice.cmake11
-rw-r--r--Utilities/CMakeLists.txt10
-rw-r--r--Utilities/cmlibarchive/CMakeLists.txt326
-rw-r--r--Utilities/cmlibarchive/README-CMake.txt8
-rw-r--r--Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake22
-rw-r--r--Utilities/cmlibarchive/build/cmake/FindNettle.cmake23
-rw-r--r--Utilities/cmlibarchive/build/cmake/FindPCREPOSIX.cmake34
-rw-r--r--Utilities/cmlibarchive/build/cmake/config.h.in51
-rwxr-xr-x[-rw-r--r--]Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh47
-rw-r--r--Utilities/cmlibarchive/build/version2
-rw-r--r--Utilities/cmlibarchive/libarchive/CMakeLists.txt23
-rw-r--r--Utilities/cmlibarchive/libarchive/archive.h308
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_acl.c82
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_check_magic.c1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_cmdline.c227
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_cmdline_private.h47
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_crypto.c8
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_endian.h8
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.c81
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.h45
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_acl.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c6
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c5
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_linkify.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_paths.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_perms.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_stat.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_stat.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_time.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_getdate.c1037
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_match.c1841
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_options.c53
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_pathmatch.c459
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_pathmatch.h52
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_ppmd7.c7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_ppmd_private.h4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_private.h2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_rb.c24
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read.c422
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_append_filter.c198
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_data.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c476
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c580
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_private.h23
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c719
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_extract.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_extract.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_filter.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_format.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_free.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_header.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_new.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_open.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_open_fd.c7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_open_file.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_open_filename.c177
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_open_memory.c1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_private.h44
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_set_format.c105
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_set_options.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_set_options.c12
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c8
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c9
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_grzip.c121
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c21
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_lrzip.c132
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c486
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c188
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c5
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c28
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c33
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c260
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c283
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c70
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c456
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c45
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c230
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c468
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c260
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c19
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c734
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string.c832
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string.h10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string_composition.h945
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string_sprintf.c14
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_util.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_util.c50
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_virtual.c15
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_windows.c175
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_windows.h29
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write.c190
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter.c70
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c314
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c75
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c170
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c24
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_grzip.c135
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c208
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_lrzip.c192
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_lzop.c486
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c327
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_uuencode.c305
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c35
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_blocksize.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_data.38
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c249
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c1291
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_private.h5
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c28
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c175
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_filter.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_finish_entry.36
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_format.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_free.317
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_header.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_new.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open.38
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open_filename.c170
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_private.h11
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c153
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c76
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c78
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c155
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c250
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c1571
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c121
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c110
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c661
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c62
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c446
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_options.38
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_options.c14
-rw-r--r--Utilities/cmlibarchive/libarchive/cpio.54
-rw-r--r--Utilities/cmlibarchive/libarchive/filter_fork.h2
-rw-r--r--Utilities/cmlibarchive/libarchive/filter_fork_posix.c (renamed from Utilities/cmlibarchive/libarchive/filter_fork.c)107
-rw-r--r--Utilities/cmlibarchive/libarchive/filter_fork_windows.c143
-rw-r--r--Utilities/cmlibarchive/libarchive/libarchive-formats.5108
-rw-r--r--Utilities/cmlibarchive/libarchive/libarchive.369
-rw-r--r--Utilities/cmlibarchive/libarchive/libarchive_changes.32
-rw-r--r--Utilities/cmlibarchive/libarchive/libarchive_internals.36
-rw-r--r--Utilities/cmlibarchive/libarchive/mtree.52
-rw-r--r--Utilities/cmlibarchive/libarchive/tar.54
-rwxr-xr-xbootstrap8
445 files changed, 21969 insertions, 5230 deletions
diff --git a/Docs/bash-completion/cmake b/Docs/bash-completion/cmake
index 59b565a..5f33c09 100644
--- a/Docs/bash-completion/cmake
+++ b/Docs/bash-completion/cmake
@@ -100,11 +100,13 @@ _cmake()
return
;;
-G)
- # FIXME: doesn't work properly
local IFS=$'\n'
+ local quoted
+ printf -v quoted %q "$cur"
COMPREPLY=( $( compgen -W '$( cmake --help 2>/dev/null | sed -n \
- "/^.*[^ ].*= Generates/{s|^ *\(.*[^ ]\) *= Generates.*$|\1|;s| |\\\\ |g;p}" \
- 2>/dev/null )' -- "$cur" ) )
+ -e "1,/^Generators/d" \
+ -e "/^ *[^ =]/{s|^ *\([^=]*[^ =]\).*$|\1|;s| |\\\\ |g;p}" \
+ 2>/dev/null )' -- "$quoted" ) )
return
;;
--help-command)
diff --git a/Docs/bash-completion/cpack b/Docs/bash-completion/cpack
index a0c1f83..51638c5 100644
--- a/Docs/bash-completion/cpack
+++ b/Docs/bash-completion/cpack
@@ -8,8 +8,8 @@ _cpack()
case "$prev" in
-G)
COMPREPLY=( $( compgen -W '$( cpack --help 2>/dev/null |
- grep "^ .*= .*" 2> /dev/null | grep -v "^ -" 2>/dev/null |
- cut -d" " -f 3 )' -- "$cur" ) )
+ sed -e "1,/^Generators/d" -e "s|^ *\([^ ]*\) .*$|\1|" \
+ 2>/dev/null )' -- "$cur" ) )
return
;;
-C)
diff --git a/Docs/bash-completion/ctest b/Docs/bash-completion/ctest
index 9707f62..7433d3d 100644
--- a/Docs/bash-completion/ctest
+++ b/Docs/bash-completion/ctest
@@ -54,7 +54,7 @@ _ctest()
return
;;
-S|--script|-SP|--script-new-process)
- # FIXME ?
+ _filedir '@(cmake|ctest)'
return
;;
--interactive-debug-mode)
diff --git a/Modules/CMakeCommonLanguageInclude.cmake b/Modules/CMakeCommonLanguageInclude.cmake
index bf94f9f..e945aa7 100644
--- a/Modules/CMakeCommonLanguageInclude.cmake
+++ b/Modules/CMakeCommonLanguageInclude.cmake
@@ -68,6 +68,19 @@ if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO_INIT} CACHE STRING
"Flags used by the linker during Release with Debug Info builds.")
+ set (CMAKE_STATIC_LINKER_FLAGS_DEBUG ${CMAKE_STATIC_LINKER_FLAGS_DEBUG_INIT} CACHE STRING
+ "Flags used by the linker during debug builds.")
+
+ set (CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL ${CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL_INIT}
+ CACHE STRING
+ "Flags used by the linker during release minsize builds.")
+
+ set (CMAKE_STATIC_LINKER_FLAGS_RELEASE ${CMAKE_STATIC_LINKER_FLAGS_RELEASE_INIT} CACHE STRING
+ "Flags used by the linker during release builds.")
+
+ set (CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
+ ${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO_INIT} CACHE STRING
+ "Flags used by the linker during Release with Debug Info builds.")
endif()
# shared linker flags
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} $ENV{LDFLAGS}"
@@ -77,6 +90,10 @@ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} $ENV{LDFLAGS}"
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS_INIT} $ENV{LDFLAGS}"
CACHE STRING "Flags used by the linker during the creation of modules.")
+# static linker flags
+set (CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS_INIT}"
+ CACHE STRING "Flags used by the linker during the creation of static libraries.")
+
set(CMAKE_BUILD_TOOL ${CMAKE_MAKE_PROGRAM} CACHE INTERNAL
"What is the target build tool cmake is generating for.")
@@ -103,5 +120,10 @@ CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
CMAKE_MODULE_LINKER_FLAGS_RELEASE
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_STATIC_LINKER_FLAGS
+CMAKE_STATIC_LINKER_FLAGS_DEBUG
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
+CMAKE_STATIC_LINKER_FLAGS_RELEASE
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
)
diff --git a/Modules/CMakeDetermineCompiler.cmake b/Modules/CMakeDetermineCompiler.cmake
index 2d12c07..f522c44 100644
--- a/Modules/CMakeDetermineCompiler.cmake
+++ b/Modules/CMakeDetermineCompiler.cmake
@@ -69,4 +69,17 @@ macro(_cmake_find_compiler lang)
endif()
unset(_${lang}_COMPILER_HINTS)
unset(_languages)
+
+ # Look for a make tool provided by Xcode
+ if(CMAKE_${lang}_COMPILER STREQUAL "CMAKE_${lang}_COMPILER-NOTFOUND" AND CMAKE_HOST_APPLE)
+ foreach(comp ${CMAKE_${lang}_COMPILER_LIST})
+ execute_process(COMMAND xcrun --find ${comp}
+ OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_VARIABLE _xcrun_err)
+ if(_xcrun_out)
+ set_property(CACHE CMAKE_${lang}_COMPILER PROPERTY VALUE "${_xcrun_out}")
+ break()
+ endif()
+ endforeach()
+ endif()
endmacro()
diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake
index e9ae995..5d35ce3 100644
--- a/Modules/CMakeDetermineCompilerABI.cmake
+++ b/Modules/CMakeDetermineCompilerABI.cmake
@@ -28,9 +28,6 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
if(DEFINED CMAKE_${lang}_VERBOSE_FLAG)
set(CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_${lang}_VERBOSE_FLAG}")
endif()
- if(CMAKE_${lang}_COMPILER_TARGET)
- set(CMAKE_FLAGS "${CMAKE_FLAGS} -DCMAKE_${lang}_COMPILER_TARGET=${CMAKE_${lang}_COMPILER_TARGET}")
- endif()
try_compile(CMAKE_${lang}_ABI_COMPILED
${CMAKE_BINARY_DIR} ${src}
CMAKE_FLAGS "${CMAKE_FLAGS}"
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index ae91a29..ebd9ce0 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -109,12 +109,9 @@ Id flags: ${testflags}
# Compile the compiler identification source.
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([0-9]+)")
set(vs_version ${CMAKE_MATCH_1})
- set(id_arch ${CMAKE_VS_PLATFORM_NAME})
+ set(id_platform ${CMAKE_VS_PLATFORM_NAME})
set(id_lang "${lang}")
set(id_cl cl.exe)
- if(NOT id_arch)
- set(id_arch Win32)
- endif()
if(NOT "${vs_version}" VERSION_LESS 10)
set(v 10)
set(ext vcxproj)
@@ -126,16 +123,8 @@ Id flags: ${testflags}
set(v 6)
set(ext dsp)
endif()
- if("${id_arch}" STREQUAL "x64")
- set(id_machine_10 MachineX64)
- elseif("${id_arch}" STREQUAL "Itanium")
- set(id_machine_10 MachineIA64)
- set(id_arch ia64)
- elseif("${id_arch}" STREQUAL "ARM")
- set(id_machine_10 MachineARM)
- else()
- set(id_machine_6 x86)
- set(id_machine_10 MachineX86)
+ if("${id_platform}" STREQUAL "Itanium")
+ set(id_platform ia64)
endif()
if(CMAKE_VS_PLATFORM_TOOLSET)
set(id_toolset "<PlatformToolset>${CMAKE_VS_PLATFORM_TOOLSET}</PlatformToolset>")
@@ -149,7 +138,7 @@ Id flags: ${testflags}
set(id_subsystem 1)
endif()
if("${CMAKE_MAKE_PROGRAM}" MATCHES "[Mm][Ss][Bb][Uu][Ii][Ll][Dd]")
- set(build /p:Configuration=Debug /p:Platform=@id_arch@ /p:VisualStudioVersion=${vs_version}.0)
+ set(build /p:Configuration=Debug /p:Platform=@id_platform@ /p:VisualStudioVersion=${vs_version}.0)
elseif("${CMAKE_MAKE_PROGRAM}" MATCHES "[Mm][Ss][Dd][Ee][Vv]")
set(build /make)
else()
@@ -341,6 +330,35 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
endif()
endforeach()
+ # Detect the exact architecture from the PE header.
+ if(WIN32)
+ # The offset to the PE signature is stored at 0x3c.
+ file(READ ${file} peoffsethex LIMIT 1 OFFSET 60 HEX)
+ string(SUBSTRING "${peoffsethex}" 0 1 peoffsethex1)
+ string(SUBSTRING "${peoffsethex}" 1 1 peoffsethex2)
+ set(peoffsetexpression "${peoffsethex1} * 16 + ${peoffsethex2}")
+ string(REPLACE "a" "10" peoffsetexpression "${peoffsetexpression}")
+ string(REPLACE "b" "11" peoffsetexpression "${peoffsetexpression}")
+ string(REPLACE "c" "12" peoffsetexpression "${peoffsetexpression}")
+ string(REPLACE "d" "13" peoffsetexpression "${peoffsetexpression}")
+ string(REPLACE "e" "14" peoffsetexpression "${peoffsetexpression}")
+ string(REPLACE "f" "15" peoffsetexpression "${peoffsetexpression}")
+ math(EXPR peoffset "${peoffsetexpression}")
+
+ file(READ ${file} peheader LIMIT 6 OFFSET ${peoffset} HEX)
+ if(peheader STREQUAL "50450000a201")
+ set(ARCHITECTURE_ID "SH3")
+ elseif(peheader STREQUAL "50450000a301")
+ set(ARCHITECTURE_ID "SH3DSP")
+ elseif(peheader STREQUAL "50450000a601")
+ set(ARCHITECTURE_ID "SH4")
+ elseif(peheader STREQUAL "50450000a801")
+ set(ARCHITECTURE_ID "SH5")
+ elseif(peheader STREQUAL "50450000c201")
+ set(ARCHITECTURE_ID "THUMB")
+ endif()
+ endif()
+
# Check if a valid compiler and platform were found.
if(COMPILER_ID AND NOT COMPILER_ID_TWICE)
set(CMAKE_${lang}_COMPILER_ID "${COMPILER_ID}")
diff --git a/Modules/CMakeGraphVizOptions.cmake b/Modules/CMakeGraphVizOptions.cmake
new file mode 100644
index 0000000..e4af54c
--- /dev/null
+++ b/Modules/CMakeGraphVizOptions.cmake
@@ -0,0 +1,83 @@
+##section Variables specific to the graphviz support
+##end
+##module
+# - The builtin graphviz support of CMake.
+# CMake can generate graphviz files, showing the dependencies between
+# the targets in a project and also external libraries which are linked
+# against.
+# When CMake is run with the --graphiz=foo option, it will produce
+# * a foo.dot file showing all dependencies in the project
+# * a foo.dot.<target> file for each target, file showing on which other targets the respective target depends
+# * a foo.dot.<target>.dependers file, showing which other targets depend on the respective target
+#
+# This can result in huge graphs. Using the file CMakeGraphVizOptions.cmake
+# the look and content of the generated graphs can be influenced.
+# This file is searched first in ${CMAKE_BINARY_DIR} and then in
+# ${CMAKE_SOURCE_DIR}. If found, it is read and the variables set in it
+# are used to adjust options for the generated graphviz files.
+##end
+#
+##variable
+# GRAPHVIZ_GRAPH_TYPE - The graph type
+# Mandatory : NO
+# Default : "digraph"
+##end
+##variable
+# GRAPHVIZ_GRAPH_NAME - The graph name.
+# Mandatory : NO
+# Default : "GG"
+##end
+##variable
+# GRAPHVIZ_GRAPH_HEADER - The header written at the top of the graphviz file.
+# Mandatory : NO
+# Default : "node [n fontsize = "12"];"
+##end
+##variable
+# GRAPHVIZ_NODE_PREFIX - The prefix for each node in the graphviz file.
+# Mandatory : NO
+# Default : "node"
+##end
+##variable
+# GRAPHVIZ_EXECUTABLES - Set this to FALSE to exclude executables from the generated graphs.
+# Mandatory : NO
+# Default : TRUE
+##end
+##variable
+# GRAPHVIZ_STATIC_LIBS - Set this to FALSE to exclude static libraries from the generated graphs.
+# Mandatory : NO
+# Default : TRUE
+##end
+##variable
+# GRAPHVIZ_SHARED_LIBS - Set this to FALSE to exclude shared libraries from the generated graphs.
+# Mandatory : NO
+# Default : TRUE
+##end
+##variable
+# GRAPHVIZ_MODULE_LIBS - Set this to FALSE to exclude static libraries from the generated graphs.
+# Mandatory : NO
+# Default : TRUE
+##end
+##variable
+# GRAPHVIZ_EXTERNAL_LIBS - Set this to FALSE to exclude external libraries from the generated graphs.
+# Mandatory : NO
+# Default : TRUE
+##end
+##variable
+# GRAPHVIZ_IGNORE_TARGETS - A list of regular expressions for ignoring targets.
+# Mandatory : NO
+# Default : empty
+##end
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+# Copyright 2013 Alexander Neundorf <neundorf@kde.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
diff --git a/Modules/CMakePrintHelpers.cmake b/Modules/CMakePrintHelpers.cmake
new file mode 100644
index 0000000..ef5d857
--- /dev/null
+++ b/Modules/CMakePrintHelpers.cmake
@@ -0,0 +1,146 @@
+# - Convenience macros for printing properties and variables, useful e.g. for debugging.
+#
+#
+# CMAKE_PRINT_PROPERTIES([TARGETS target1 .. targetN]
+# [SOURCES source1 .. sourceN]
+# [DIRECTORIES dir1 .. dirN]
+# [TESTS test1 .. testN]
+# [CACHE_ENTRIES entry1 .. entryN]
+# PROPERTIES prop1 .. propN )
+#
+# This macro prints the values of the properties of the given targets,
+# source files, directories, tests or cache entries. Exactly one of the
+# scope keywords must be used.
+# Example:
+# cmake_print_properties(TARGETS foo bar PROPERTIES LOCATION INTERFACE_INCLUDE_DIRS)
+# This will print the LOCATION and INTERFACE_INCLUDE_DIRS properties for both
+# targets foo and bar.
+#
+#
+# CMAKE_PRINT_VARIABLES(var1 var2 .. varN)
+#
+# This macro will print the name of each variable followed by its value.
+# Example:
+# cmake_print_variables(CMAKE_C_COMPILER CMAKE_MAJOR_VERSION THIS_ONE_DOES_NOT_EXIST)
+# Gives:
+# -- CMAKE_C_COMPILER="/usr/bin/gcc" ; CMAKE_MAJOR_VERSION="2" ; THIS_ONE_DOES_NOT_EXIST=""
+
+#=============================================================================
+# Copyright 2013 Alexander Neundorf, <neundorf@kde.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+include(CMakeParseArguments)
+
+function(CMAKE_PRINT_VARIABLES)
+ set(msg "")
+ foreach(var ${ARGN})
+ if(msg)
+ set(msg "${msg} ; ")
+ endif()
+ set(msg "${msg}${var}=\"${${var}}\"")
+ endforeach()
+ message(STATUS "${msg}")
+endfunction()
+
+
+function(CMAKE_PRINT_PROPERTIES )
+ set(options )
+ set(oneValueArgs )
+ set(multiValueArgs TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES )
+
+ cmake_parse_arguments(CPP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(CPP_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown keywords given to cmake_print_properties(): \"${CPP_UNPARSED_ARGUMENTS}\"")
+ return()
+ endif()
+
+ if(NOT CPP_PROPERTIES)
+ message(FATAL_ERROR "Required argument PROPERTIES missing in cmake_print_properties() call")
+ return()
+ endif()
+
+ set(mode)
+ set(items)
+ set(keyword)
+
+ if(CPP_TARGETS)
+ set(items ${CPP_TARGETS})
+ set(mode ${mode} TARGETS)
+ set(keyword TARGET)
+ endif()
+
+ if(CPP_SOURCES)
+ set(items ${CPP_SOURCES})
+ set(mode ${mode} SOURCES)
+ set(keyword SOURCE)
+ endif()
+
+ if(CPP_TESTS)
+ set(items ${CPP_TESTS})
+ set(mode ${mode} TESTS)
+ set(keyword TEST)
+ endif()
+
+ if(CPP_DIRECTORIES)
+ set(items ${CPP_DIRECTORIES})
+ set(mode ${mode} DIRECTORIES)
+ set(keyword DIRECTORY)
+ endif()
+
+ if(CPP_CACHE_ENTRIES)
+ set(items ${CPP_CACHE_ENTRIES})
+ set(mode ${mode} CACHE_ENTRIES)
+ set(keyword CACHE)
+ endif()
+
+ if(NOT mode)
+ message(FATAL_ERROR "Mode keyword missing in cmake_print_properties() call, must be one of TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES")
+ return()
+ endif()
+
+ list(LENGTH mode modeLength)
+ if("${modeLength}" GREATER 1)
+ message(FATAL_ERROR "Multiple mode keyword used in cmake_print_properties() call, it must be exactly one of TARGETS SOURCES TESTS DIRECTORIES CACHE_ENTRIES PROPERTIES")
+ return()
+ endif()
+
+ set(msg "\n")
+ foreach(item ${items})
+
+ set(itemExists TRUE)
+ if(keyword STREQUAL "TARGET")
+ if(NOT TARGET ${item})
+ set(itemExists FALSE)
+ set(msg "${msg}\n No such TARGET \"${item}\" !\n\n")
+ endif()
+ endif()
+
+ if (itemExists)
+ set(msg "${msg} Properties for ${keyword} ${item}:\n")
+ foreach(prop ${CPP_PROPERTIES})
+
+ get_property(propertySet ${keyword} ${item} PROPERTY "${prop}" SET)
+
+ if(propertySet)
+ get_property(property ${keyword} ${item} PROPERTY "${prop}")
+ set(msg "${msg} ${item}.${prop} = \"${property}\"\n")
+ else()
+ set(msg "${msg} ${item}.${prop} = <NOTFOUND>\n")
+ endif()
+ endforeach()
+ endif()
+
+ endforeach()
+ message(STATUS "${msg}")
+
+endfunction()
diff --git a/Modules/CMakePushCheckState.cmake b/Modules/CMakePushCheckState.cmake
index 08809bf..b37b706 100644
--- a/Modules/CMakePushCheckState.cmake
+++ b/Modules/CMakePushCheckState.cmake
@@ -1,8 +1,10 @@
-# This module defines two macros:
+# This module defines three macros:
# CMAKE_PUSH_CHECK_STATE()
-# and
# CMAKE_POP_CHECK_STATE()
-# These two macros can be used to save and restore the state of the variables
+# and
+# CMAKE_RESET_CHECK_STATE()
+# These macros can be used to save, restore and reset (i.e., clear contents)
+# the state of the variables
# CMAKE_REQUIRED_FLAGS, CMAKE_REQUIRED_DEFINITIONS, CMAKE_REQUIRED_LIBRARIES
# and CMAKE_REQUIRED_INCLUDES used by the various Check-files coming with CMake,
# like e.g. check_function_exists() etc.
@@ -11,9 +13,16 @@
# but after the Find-module has been executed they should have the same value
# as they had before.
#
+# CMAKE_PUSH_CHECK_STATE() macro receives optional argument RESET. Whether it's specified,
+# CMAKE_PUSH_CHECK_STATE() will set all CMAKE_REQUIRED_* variables to empty values, same
+# as CMAKE_RESET_CHECK_STATE() call will do.
+#
# Usage:
-# cmake_push_check_state()
-# set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DSOME_MORE_DEF)
+# cmake_push_check_state(RESET)
+# set(CMAKE_REQUIRED_DEFINITIONS -DSOME_MORE_DEF)
+# check_function_exists(...)
+# cmake_reset_check_state()
+# set(CMAKE_REQUIRED_DEFINITIONS -DANOTHER_DEF)
# check_function_exists(...)
# cmake_pop_check_state()
@@ -31,6 +40,15 @@
# License text for the above reference.)
+macro(CMAKE_RESET_CHECK_STATE)
+
+ set(CMAKE_REQUIRED_INCLUDES)
+ set(CMAKE_REQUIRED_DEFINITIONS)
+ set(CMAKE_REQUIRED_LIBRARIES)
+ set(CMAKE_REQUIRED_FLAGS)
+
+endmacro()
+
macro(CMAKE_PUSH_CHECK_STATE)
if(NOT DEFINED _CMAKE_PUSH_CHECK_STATE_COUNTER)
@@ -43,6 +61,11 @@ macro(CMAKE_PUSH_CHECK_STATE)
set(_CMAKE_REQUIRED_DEFINITIONS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_DEFINITIONS})
set(_CMAKE_REQUIRED_LIBRARIES_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_LIBRARIES})
set(_CMAKE_REQUIRED_FLAGS_SAVE_${_CMAKE_PUSH_CHECK_STATE_COUNTER} ${CMAKE_REQUIRED_FLAGS})
+
+ if (ARGC GREATER 0 AND ARGV0 STREQUAL "RESET")
+ cmake_reset_check_state()
+ endif()
+
endmacro()
macro(CMAKE_POP_CHECK_STATE)
diff --git a/Modules/CMakeUnixFindMake.cmake b/Modules/CMakeUnixFindMake.cmake
index c75cf7c..3714926 100644
--- a/Modules/CMakeUnixFindMake.cmake
+++ b/Modules/CMakeUnixFindMake.cmake
@@ -14,3 +14,13 @@
find_program(CMAKE_MAKE_PROGRAM NAMES gmake make smake)
mark_as_advanced(CMAKE_MAKE_PROGRAM)
+
+# Look for a make tool provided by Xcode
+if(NOT CMAKE_MAKE_PROGRAM AND CMAKE_HOST_APPLE)
+ execute_process(COMMAND xcrun --find make
+ OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_VARIABLE _xcrun_err)
+ if(_xcrun_out)
+ set_property(CACHE CMAKE_MAKE_PROGRAM PROPERTY VALUE "${_xcrun_out}")
+ endif()
+endif()
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index 66b00bd..ec4562a 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -25,5 +25,4 @@ macro(__compiler_clang lang)
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
- set(CMAKE_${lang}_COMPILE_OPTION_TARGET "-target ")
endmacro()
diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in
index ab4705f..1a7a539 100644
--- a/Modules/CompilerId/VS-10.vcxproj.in
+++ b/Modules/CompilerId/VS-10.vcxproj.in
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|@id_arch@">
+ <ProjectConfiguration Include="Debug|@id_platform@">
<Configuration>Debug</Configuration>
- <Platform>@id_arch@</Platform>
+ <Platform>@id_platform@</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
@@ -12,7 +12,7 @@
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'" Label="Configuration">
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@id_toolset@
<CharacterSet>MultiByte</CharacterSet>
@@ -20,11 +20,11 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'">.\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'">$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">.\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">false</LinkIncremental>
</PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_arch@'">
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@id_platform@'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -40,7 +40,6 @@
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
- <TargetMachine>@id_machine_10@</TargetMachine>
</Link>
<PostBuildEvent>
<Command>for %%i in (@id_cl@) do %40echo CMAKE_@id_lang@_COMPILER=%%~$PATH:i</Command>
diff --git a/Modules/CompilerId/VS-6.dsp.in b/Modules/CompilerId/VS-6.dsp.in
index 4f7e676..48c9a23 100644
--- a/Modules/CompilerId/VS-6.dsp.in
+++ b/Modules/CompilerId/VS-6.dsp.in
@@ -1,7 +1,7 @@
# Microsoft Developer Studio Project File - Name="CompilerId@id_lang@" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# TARGTYPE "Win32 (@id_machine_6@) Application" 0x0101
+# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=CompilerId@id_lang@ - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
@@ -16,7 +16,7 @@ CFG=CompilerId@id_lang@ - Win32 Debug
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
-!MESSAGE "CompilerId@id_lang@ - Win32 Debug" (based on "Win32 (@id_machine_6@) Application")
+!MESSAGE "CompilerId@id_lang@ - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
@@ -29,7 +29,7 @@ CPP=cl.exe
# PROP Target_Dir ""
# ADD CPP /nologo /MDd /c
LINK32=link.exe
-# ADD LINK32 /nologo /version:0.0 /subsystem:console /machine:@id_machine_6@ /out:"CompilerId@id_lang@.exe" /IGNORE:4089
+# ADD LINK32 /nologo /version:0.0 /subsystem:console /machine:x86 /out:"CompilerId@id_lang@.exe" /IGNORE:4089
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Cmds=for %%i in (@id_cl@) do @echo CMAKE_@id_lang@_COMPILER=%%~$PATH:i
diff --git a/Modules/CompilerId/VS-7.vcproj.in b/Modules/CompilerId/VS-7.vcproj.in
index fa48cad..9e3c3c3 100644
--- a/Modules/CompilerId/VS-7.vcproj.in
+++ b/Modules/CompilerId/VS-7.vcproj.in
@@ -10,12 +10,12 @@
>
<Platforms>
<Platform
- Name="@id_arch@"
+ Name="@id_platform@"
/>
</Platforms>
<Configurations>
<Configuration
- Name="Debug|@id_arch@"
+ Name="Debug|@id_platform@"
OutputDirectory="."
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake
index de17f16..77aac6d 100644
--- a/Modules/FindGTK2.cmake
+++ b/Modules/FindGTK2.cmake
@@ -28,7 +28,6 @@
# Optional variables you can define prior to calling this module:
#
# GTK2_DEBUG - Enables verbose debugging of the module
-# GTK2_SKIP_MARK_AS_ADVANCED - Disable marking cache variables as advanced
# GTK2_ADDITIONAL_SUFFIXES - Allows defining additional directories to
# search for include files
#
@@ -67,6 +66,18 @@
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
+# Version 1.5 (UNRELEASED) (CMake 2.8.12)
+# * 14236: Detect gthread library
+# Detect pangocairo on windows
+# Detect pangocairo with gtk module instead of with gtkmm
+# * 14259: Use vc100 libraries with MSVC11
+# * 14260: Export a GTK2_DEFINITIONS variable to set /vd2 when appropriate
+# (i.e. MSVC)
+# * Use the optimized/debug syntax for _LIBRARY and _LIBRARIES variables when
+# appropriate. A new set of _RELEASE variables was also added.
+# * Remove GTK2_SKIP_MARK_AS_ADVANCED option, as now the variables are
+# marked as advanced by SelectLibraryConfigurations
+# * Detect gmodule, pangoft2 and pangoxft libraries
# Version 1.4 (10/4/2012) (CMake 2.8.10)
# * 12596: Missing paths for FindGTK2 on NetBSD
# * 12049: Fixed detection of GTK include files in the lib folder on
@@ -117,6 +128,9 @@
# _OUT_micro = Micro version number
# _gtkversion_hdr = Header file to parse
#=============================================================
+
+include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+
function(_GTK2_GET_VERSION _OUT_major _OUT_minor _OUT_micro _gtkversion_hdr)
file(STRINGS ${_gtkversion_hdr} _contents REGEX "#define GTK_M[A-Z]+_VERSION[ \t]+")
if(_contents)
@@ -145,7 +159,7 @@ endfunction()
#=============================================================
# _GTK2_FIND_INCLUDE_DIR
# Internal function to find the GTK include directories
-# _var = variable to set
+# _var = variable to set (_INCLUDE_DIR is appended)
# _hdr = header file to look for
#=============================================================
function(_GTK2_FIND_INCLUDE_DIR _var _hdr)
@@ -165,7 +179,6 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr)
cairo
cairomm-1.0
gdk-pixbuf-2.0
- gthread-2.0
gdkmm-2.4
giomm-2.4
gtk-2.0
@@ -201,7 +214,7 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr)
message(STATUS "Adding ${_gtk2_arch_dir} to search path for multiarch support")
endif()
endif()
- find_path(${_var} ${_hdr}
+ find_path(${_var}_INCLUDE_DIR ${_hdr}
PATHS
${_gtk2_arch_dir}
/usr/local/lib64
@@ -228,11 +241,8 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr)
${_suffixes}
)
- if(${_var})
- set(GTK2_INCLUDE_DIRS ${GTK2_INCLUDE_DIRS} ${${_var}} PARENT_SCOPE)
- if(NOT GTK2_SKIP_MARK_AS_ADVANCED)
- mark_as_advanced(${_var})
- endif()
+ if(${_var}_INCLUDE_DIR)
+ set(GTK2_INCLUDE_DIRS ${GTK2_INCLUDE_DIRS} ${${_var}_INCLUDE_DIR} PARENT_SCOPE)
endif()
endfunction()
@@ -240,7 +250,7 @@ endfunction()
#=============================================================
# _GTK2_FIND_LIBRARY
# Internal function to find libraries packaged with GTK2
-# _var = library variable to create
+# _var = library variable to create (_LIBRARY is appended)
#=============================================================
function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version)
@@ -322,10 +332,10 @@ function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version)
if(GTK2_DEBUG)
message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
- "While searching for ${_var}, our proposed library list is ${_lib_list}")
+ "While searching for ${_var}_LIBRARY, our proposed library list is ${_lib_list}")
endif()
- find_library(${_var}
+ find_library(${_var}_LIBRARY_RELEASE
NAMES ${_lib_list}
PATHS
/opt/gnome/lib
@@ -339,34 +349,34 @@ function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version)
if(_expand_vc AND MSVC)
if(GTK2_DEBUG)
message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
- "While searching for ${_var}_DEBUG our proposed library list is ${_libd_list}")
+ "While searching for ${_var}_LIBRARY_DEBUG our proposed library list is ${_libd_list}")
endif()
- find_library(${_var}_DEBUG
+ find_library(${_var}_LIBRARY_DEBUG
NAMES ${_libd_list}
PATHS
$ENV{GTKMM_BASEPATH}/lib
[HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]/lib
[HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]/lib
)
+ endif()
- if(${_var} AND ${_var}_DEBUG)
- if(NOT GTK2_SKIP_MARK_AS_ADVANCED)
- mark_as_advanced(${_var}_DEBUG)
- endif()
- set(GTK2_LIBRARIES ${GTK2_LIBRARIES} optimized ${${_var}} debug ${${_var}_DEBUG})
- set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE)
- endif()
- else()
- if(NOT GTK2_SKIP_MARK_AS_ADVANCED)
- mark_as_advanced(${_var})
- endif()
- set(GTK2_LIBRARIES ${GTK2_LIBRARIES} ${${_var}})
- set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE)
- # Set debug to release
- set(${_var}_DEBUG ${${_var}})
- set(${_var}_DEBUG ${${_var}} PARENT_SCOPE)
+ select_library_configurations(${_var})
+
+ set(${_var}_LIBRARY ${${_var}_LIBRARY} PARENT_SCOPE)
+
+ set(GTK2_LIBRARIES ${GTK2_LIBRARIES} ${${_var}_LIBRARY})
+ set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE)
+
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "${_var}_LIBRARY_RELEASE = \"${${_var}_LIBRARY_RELEASE}\"")
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "${_var}_LIBRARY_DEBUG = \"${${_var}_LIBRARY_DEBUG}\"")
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "${_var}_LIBRARY = \"${${_var}_LIBRARY}\"")
endif()
+
endfunction()
#=============================================================
@@ -395,7 +405,7 @@ if(GTK2_FIND_VERSION)
message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
"Searching for version ${GTK2_FIND_VERSION}")
endif()
- _GTK2_FIND_INCLUDE_DIR(GTK2_GTK_INCLUDE_DIR gtk/gtk.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GTK gtk/gtk.h)
if(GTK2_GTK_INCLUDE_DIR)
_GTK2_GET_VERSION(GTK2_MAJOR_VERSION
GTK2_MINOR_VERSION
@@ -445,90 +455,95 @@ list(APPEND GTK2_LIBRARIES ${FREETYPE_LIBRARIES})
foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
if(_GTK2_component STREQUAL "gtk")
- _GTK2_FIND_INCLUDE_DIR(GTK2_GTK_INCLUDE_DIR gtk/gtk.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GTK gtk/gtk.h)
if(UNIX)
- _GTK2_FIND_LIBRARY (GTK2_GTK_LIBRARY gtk-x11 false true)
- _GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-x11 false true)
+ _GTK2_FIND_LIBRARY (GTK2_GTK gtk-x11 false true)
+ _GTK2_FIND_LIBRARY (GTK2_GDK gdk-x11 false true)
else()
- _GTK2_FIND_LIBRARY (GTK2_GTK_LIBRARY gtk-win32 false true)
- _GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-win32 false true)
+ _GTK2_FIND_LIBRARY (GTK2_GTK gtk-win32 false true)
+ _GTK2_FIND_LIBRARY (GTK2_GDK gdk-win32 false true)
endif()
- _GTK2_FIND_INCLUDE_DIR(GTK2_GDK_INCLUDE_DIR gdk/gdk.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GDKCONFIG_INCLUDE_DIR gdkconfig.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDK gdk/gdk.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDKCONFIG gdkconfig.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_CAIRO_INCLUDE_DIR cairo.h)
- _GTK2_FIND_LIBRARY (GTK2_CAIRO_LIBRARY cairo false false)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_CAIRO cairo.h)
+ _GTK2_FIND_LIBRARY (GTK2_CAIRO cairo false false)
- _GTK2_FIND_INCLUDE_DIR(GTK2_FONTCONFIG_INCLUDE_DIR fontconfig/fontconfig.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_FONTCONFIG fontconfig/fontconfig.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_PANGO_INCLUDE_DIR pango/pango.h)
- _GTK2_FIND_LIBRARY (GTK2_PANGO_LIBRARY pango false true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_PANGO pango/pango.h)
+ _GTK2_FIND_LIBRARY (GTK2_PANGO pango false true)
- _GTK2_FIND_LIBRARY (GTK2_PANGOCAIRO_LIBRARY pangocairo false true)
+ _GTK2_FIND_LIBRARY (GTK2_PANGOCAIRO pangocairo false true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GDK_PIXBUF_INCLUDE_DIR gdk-pixbuf/gdk-pixbuf.h)
- _GTK2_FIND_LIBRARY (GTK2_GDK_PIXBUF_LIBRARY gdk_pixbuf false true)
+ _GTK2_FIND_LIBRARY (GTK2_PANGOFT2 pangoft2 false true)
- _GTK2_FIND_LIBRARY (GTK2_GTHREAD_LIBRARY gthread false true)
+ _GTK2_FIND_LIBRARY (GTK2_PANGOXFT pangoxft false true)
- _GTK2_FIND_LIBRARY (GTK2_GIO_LIBRARY gio false true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDK_PIXBUF gdk-pixbuf/gdk-pixbuf.h)
+ _GTK2_FIND_LIBRARY (GTK2_GDK_PIXBUF gdk_pixbuf false true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_ATK_INCLUDE_DIR atk/atk.h)
- _GTK2_FIND_LIBRARY (GTK2_ATK_LIBRARY atk false true)
+ _GTK2_FIND_LIBRARY (GTK2_GTHREAD gthread false true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GOBJECT_INCLUDE_DIR gobject/gobject.h)
- _GTK2_FIND_LIBRARY (GTK2_GOBJECT_LIBRARY gobject false true)
+ _GTK2_FIND_LIBRARY (GTK2_GMODULE gmodule false true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GLIB_INCLUDE_DIR glib.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBCONFIG_INCLUDE_DIR glibconfig.h)
- _GTK2_FIND_LIBRARY (GTK2_GLIB_LIBRARY glib false true)
+ _GTK2_FIND_LIBRARY (GTK2_GIO gio false true)
- elseif(_GTK2_component STREQUAL "gtkmm")
+ _GTK2_FIND_INCLUDE_DIR(GTK2_ATK atk/atk.h)
+ _GTK2_FIND_LIBRARY (GTK2_ATK atk false true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GOBJECT gobject/gobject.h)
+ _GTK2_FIND_LIBRARY (GTK2_GOBJECT gobject false true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMM_INCLUDE_DIR gtkmm.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMMCONFIG_INCLUDE_DIR gtkmmconfig.h)
- _GTK2_FIND_LIBRARY (GTK2_GTKMM_LIBRARY gtkmm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLIB glib.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBCONFIG glibconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GLIB glib false true)
+
+ elseif(_GTK2_component STREQUAL "gtkmm")
- _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMM_INCLUDE_DIR gdkmm.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMMCONFIG_INCLUDE_DIR gdkmmconfig.h)
- _GTK2_FIND_LIBRARY (GTK2_GDKMM_LIBRARY gdkmm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMM gtkmm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMMCONFIG gtkmmconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GTKMM gtkmm true true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMM_INCLUDE_DIR pangomm.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMMCONFIG_INCLUDE_DIR pangommconfig.h)
- _GTK2_FIND_LIBRARY (GTK2_PANGOMM_LIBRARY pangomm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMM gdkmm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMMCONFIG gdkmmconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GDKMM gdkmm true true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMM_INCLUDE_DIR cairomm/cairomm.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMMCONFIG_INCLUDE_DIR cairommconfig.h)
- _GTK2_FIND_LIBRARY (GTK2_CAIROMM_LIBRARY cairomm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMM pangomm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMMCONFIG pangommconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_PANGOMM pangomm true true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMM_INCLUDE_DIR giomm.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMMCONFIG_INCLUDE_DIR giommconfig.h)
- _GTK2_FIND_LIBRARY (GTK2_GIOMM_LIBRARY giomm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMM cairomm/cairomm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMMCONFIG cairommconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_CAIROMM cairomm true true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_ATKMM_INCLUDE_DIR atkmm.h)
- _GTK2_FIND_LIBRARY (GTK2_ATKMM_LIBRARY atkmm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMM giomm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMMCONFIG giommconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GIOMM giomm true true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMM_INCLUDE_DIR glibmm.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMMCONFIG_INCLUDE_DIR glibmmconfig.h)
- _GTK2_FIND_LIBRARY (GTK2_GLIBMM_LIBRARY glibmm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_ATKMM atkmm.h)
+ _GTK2_FIND_LIBRARY (GTK2_ATKMM atkmm true true)
- _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++_INCLUDE_DIR sigc++/sigc++.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++CONFIG_INCLUDE_DIR sigc++config.h)
- _GTK2_FIND_LIBRARY (GTK2_SIGC++_LIBRARY sigc true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMM glibmm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMMCONFIG glibmmconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GLIBMM glibmm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++ sigc++/sigc++.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++CONFIG sigc++config.h)
+ _GTK2_FIND_LIBRARY (GTK2_SIGC++ sigc true true)
elseif(_GTK2_component STREQUAL "glade")
- _GTK2_FIND_INCLUDE_DIR(GTK2_GLADE_INCLUDE_DIR glade/glade.h)
- _GTK2_FIND_LIBRARY (GTK2_GLADE_LIBRARY glade false true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLADE glade/glade.h)
+ _GTK2_FIND_LIBRARY (GTK2_GLADE glade false true)
elseif(_GTK2_component STREQUAL "glademm")
- _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMM_INCLUDE_DIR libglademm.h)
- _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMMCONFIG_INCLUDE_DIR libglademmconfig.h)
- _GTK2_FIND_LIBRARY (GTK2_GLADEMM_LIBRARY glademm true true)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMM libglademm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMMCONFIG libglademmconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GLADEMM glademm true true)
else()
message(FATAL_ERROR "Unknown GTK2 component ${_component}")
diff --git a/Modules/FindPNG.cmake b/Modules/FindPNG.cmake
index fef4669..33c2971 100644
--- a/Modules/FindPNG.cmake
+++ b/Modules/FindPNG.cmake
@@ -39,10 +39,37 @@ if(ZLIB_FOUND)
)
list(APPEND PNG_NAMES png libpng)
- foreach(v 16 15 14 12)
- list(APPEND PNG_NAMES png${v} libpng${v} png${v}d libpng${v}d)
+ unset(PNG_NAMES_DEBUG)
+ set(_PNG_VERSION_SUFFIXES 17 16 15 14 12)
+ if (PNG_FIND_VERSION MATCHES "^[0-9]+\\.[0-9]+(\\..*)?$")
+ string(REGEX REPLACE
+ "^([0-9]+)\\.([0-9]+).*" "\\1\\2"
+ _PNG_VERSION_SUFFIX_MIN "${PNG_FIND_VERSION}")
+ if (PNG_FIND_VERSION_EXACT)
+ set(_PNG_VERSION_SUFFIXES ${_PNG_VERSION_SUFFIX_MIN})
+ else ()
+ string(REGEX REPLACE
+ "${_PNG_VERSION_SUFFIX_MIN}.*" "${_PNG_VERSION_SUFFIX_MIN}"
+ _PNG_VERSION_SUFFIXES "${_PNG_VERSION_SUFFIXES}")
+ endif ()
+ unset(_PNG_VERSION_SUFFIX_MIN)
+ endif ()
+ foreach(v IN LISTS _PNG_VERSION_SUFFIXES)
+ list(APPEND PNG_NAMES png${v} libpng${v})
+ list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d)
endforeach()
- find_library(PNG_LIBRARY NAMES ${PNG_NAMES} )
+message(STATUS "PNG r: ${PNG_NAMES} d: ${PNG_NAMES_DEBUG}")
+ unset(_PNG_VERSION_SUFFIXES)
+ find_library(PNG_LIBRARY_RELEASE NAMES ${PNG_NAMES})
+ find_library(PNG_LIBRARY_DEBUG NAMES ${PNG_NAMES_DEBUG})
+ unset(PNG_NAMES)
+ unset(PNG_NAMES_DEBUG)
+
+ include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+ select_library_configurations(PNG)
+ # Set by select_library_configurations(), but we want the one from
+ # find_package_handle_standard_args() below.
+ unset(PNG_FOUND)
if (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR)
# png.h includes zlib.h. Sigh.
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index f0652b9..0930880 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -132,9 +132,25 @@ elseif("${CMAKE_GENERATOR}" MATCHES Xcode
# specially named SDKs.
set(_CMAKE_OSX_SDKS_VER_SUFFIX_10.4 "u")
set(_CMAKE_OSX_SDKS_VER_SUFFIX_10.3 ".9")
- set(_CMAKE_OSX_SDKS_VER ${_CURRENT_OSX_VERSION}${_CMAKE_OSX_SDKS_VER_SUFFIX_${_CURRENT_OSX_VERSION}})
- set(_CMAKE_OSX_SYSROOT_DEFAULT
- "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_SDKS_VER}.sdk")
+ if(CMAKE_OSX_DEPLOYMENT_TARGET)
+ set(_CMAKE_OSX_SDKS_VER ${CMAKE_OSX_DEPLOYMENT_TARGET}${_CMAKE_OSX_SDKS_VER_SUFFIX_${CMAKE_OSX_DEPLOYMENT_TARGET}})
+ set(_CMAKE_OSX_SYSROOT_CHECK "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_SDKS_VER}.sdk")
+ if(IS_DIRECTORY "${_CMAKE_OSX_SYSROOT_CHECK}")
+ set(_CMAKE_OSX_SYSROOT_DEFAULT "${_CMAKE_OSX_SYSROOT_CHECK}")
+ else()
+ set(_CMAKE_OSX_SDKS_VER ${_CURRENT_OSX_VERSION}${_CMAKE_OSX_SDKS_VER_SUFFIX_${_CURRENT_OSX_VERSION}})
+ set(_CMAKE_OSX_SYSROOT_DEFAULT "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_SDKS_VER}.sdk")
+ message(WARNING
+ "CMAKE_OSX_DEPLOYMENT_TARGET is '${CMAKE_OSX_DEPLOYMENT_TARGET}' "
+ "but the matching SDK does not exist at:\n \"${_CMAKE_OSX_SYSROOT_CHECK}\"\n"
+ "Instead using SDK:\n \"${_CMAKE_OSX_SYSROOT_DEFAULT}\"\n"
+ "matching the host OS X version."
+ )
+ endif()
+ else()
+ set(_CMAKE_OSX_SDKS_VER ${_CURRENT_OSX_VERSION}${_CMAKE_OSX_SDKS_VER_SUFFIX_${_CURRENT_OSX_VERSION}})
+ set(_CMAKE_OSX_SYSROOT_DEFAULT "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CMAKE_OSX_SDKS_VER}.sdk")
+ endif()
else()
# Assume developer files are in root (such as Xcode 4.5 command-line tools).
set(_CMAKE_OSX_SYSROOT_DEFAULT "")
@@ -322,6 +338,12 @@ set(CMAKE_SYSTEM_APPBUNDLE_PATH
unset(_apps_paths)
include(Platform/UnixPaths)
+if(_CMAKE_OSX_SYSROOT_PATH AND EXISTS ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
+ list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${_CMAKE_OSX_SYSROOT_PATH}/usr)
+ foreach(lang C CXX)
+ list(APPEND CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
+ endforeach()
+endif()
list(APPEND CMAKE_SYSTEM_PREFIX_PATH
/sw # Fink
/opt/local # MacPorts
diff --git a/Modules/Platform/QNX.cmake b/Modules/Platform/QNX.cmake
index 315f721..2598411 100644
--- a/Modules/Platform/QNX.cmake
+++ b/Modules/Platform/QNX.cmake
@@ -13,9 +13,6 @@ set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":")
set(CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG "-Wl,-rpath-link,")
set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,")
set(CMAKE_EXE_EXPORTS_C_FLAG "-Wl,--export-dynamic")
-# http://www.qnx.com/developers/docs/6.4.0/neutrino/utilities/q/qcc.html#examples
-set(CMAKE_C_COMPILE_OPTION_TARGET "-V")
-set(CMAKE_CXX_COMPILE_OPTION_TARGET "-V")
# Shared libraries with no builtin soname may not be linked safely by
# specifying the file path.
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index 9f97570..685638a 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -141,8 +141,12 @@ if(WINCE)
set(_RTC1 "")
set(_FLAGS_CXX " /GR /EHsc")
- set(CMAKE_C_STANDARD_LIBRARIES_INIT "coredll.lib corelibc.lib ole32.lib oleaut32.lib uuid.lib commctrl.lib")
+ set(CMAKE_C_STANDARD_LIBRARIES_INIT "coredll.lib ole32.lib oleaut32.lib uuid.lib commctrl.lib")
set(CMAKE_EXE_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT} /NODEFAULTLIB:libc.lib /NODEFAULTLIB:oldnames.lib")
+
+ if (MSVC_VERSION LESS 1500)
+ set(CMAKE_C_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT} corelibc.lib")
+ endif ()
else()
set(_PLATFORM_DEFINES "/DWIN32")
@@ -171,13 +175,6 @@ set(_MACHINE_ARCH_FLAG ${MSVC_C_ARCHITECTURE_ID})
if(NOT _MACHINE_ARCH_FLAG)
set(_MACHINE_ARCH_FLAG ${MSVC_CXX_ARCHITECTURE_ID})
endif()
-if(WINCE)
- if(_MACHINE_ARCH_FLAG MATCHES "ARM")
- set(_MACHINE_ARCH_FLAG "THUMB")
- elseif(_MACHINE_ARCH_FLAG MATCHES "SH")
- set(_MACHINE_ARCH_FLAG "SH4")
- endif()
-endif()
set (CMAKE_EXE_LINKER_FLAGS_INIT
"${CMAKE_EXE_LINKER_FLAGS_INIT} /machine:${_MACHINE_ARCH_FLAG}")
diff --git a/Modules/Qt4Macros.cmake b/Modules/Qt4Macros.cmake
index 5e13b59..f1aedd7 100644
--- a/Modules/Qt4Macros.cmake
+++ b/Modules/Qt4Macros.cmake
@@ -113,19 +113,16 @@ macro (QT4_CREATE_MOC_COMMAND infile outfile moc_flags moc_options moc_target)
set (_moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}")
string (REPLACE ";" "\n" _moc_parameters "${_moc_parameters}")
- set(targetincludes)
- set(targetdefines)
if(moc_target)
- list(APPEND targetincludes "$<TARGET_PROPERTY:${moc_target},INCLUDE_DIRECTORIES>")
- list(APPEND targetdefines "$<TARGET_PROPERTY:${moc_target},COMPILE_DEFINITIONS>")
+ set(targetincludes "$<TARGET_PROPERTY:${moc_target},INCLUDE_DIRECTORIES>")
+ set(targetdefines "$<TARGET_PROPERTY:${moc_target},COMPILE_DEFINITIONS>")
set(targetincludes "$<$<BOOL:${targetincludes}>:-I$<JOIN:${targetincludes},\n-I>\n>")
set(targetdefines "$<$<BOOL:${targetdefines}>:-D$<JOIN:${targetdefines},\n-D>\n>")
file (GENERATE
OUTPUT ${_moc_parameters_file}
- CONTENT "${targetdefines}${targetincludes}${targetoptions}${_moc_parameters}\n"
- CONDITION 1
+ CONTENT "${targetdefines}${targetincludes}${_moc_parameters}\n"
)
set(targetincludes)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index d41b10c..3db3d9e 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -2,5 +2,5 @@
set(CMake_VERSION_MAJOR 2)
set(CMake_VERSION_MINOR 8)
set(CMake_VERSION_PATCH 11)
-set(CMake_VERSION_TWEAK 20130727)
+set(CMake_VERSION_TWEAK 20130826)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CTest/cmCTestBatchTestHandler.cxx b/Source/CTest/cmCTestBatchTestHandler.cxx
index a22c7be..934481b 100644
--- a/Source/CTest/cmCTestBatchTestHandler.cxx
+++ b/Source/CTest/cmCTestBatchTestHandler.cxx
@@ -89,7 +89,7 @@ void cmCTestBatchTestHandler::WriteTestCommand(int test, std::fstream& fout)
command = cmSystemTools::ConvertToOutputPath(command.c_str());
//Prepends memcheck args to our command string if this is a memcheck
- this->TestHandler->GenerateTestCommand(processArgs);
+ this->TestHandler->GenerateTestCommand(processArgs, test);
processArgs.push_back(command);
for(std::vector<std::string>::iterator arg = processArgs.begin();
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 8baa673..3ae2ac6 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -200,6 +200,7 @@ void cmCTestMemCheckHandler::Initialize()
this->CustomMaximumPassedTestOutputSize = 0;
this->CustomMaximumFailedTestOutputSize = 0;
this->MemoryTester = "";
+ this->MemoryTesterDynamicOptions.clear();
this->MemoryTesterOptions.clear();
this->MemoryTesterStyle = UNKNOWN;
this->MemoryTesterOutputFile = "";
@@ -242,12 +243,28 @@ int cmCTestMemCheckHandler::PostProcessHandler()
//----------------------------------------------------------------------
void cmCTestMemCheckHandler::GenerateTestCommand(
- std::vector<std::string>& args)
+ std::vector<std::string>& args, int test)
{
std::vector<cmStdString>::size_type pp;
- std::string memcheckcommand = "";
- memcheckcommand
+ cmStdString index;
+ cmOStringStream stream;
+ std::string memcheckcommand
= cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str());
+ stream << test;
+ index = stream.str();
+ for ( pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp ++ )
+ {
+ cmStdString arg = this->MemoryTesterDynamicOptions[pp];
+ cmStdString::size_type pos = arg.find("??");
+ if (pos != cmStdString::npos)
+ {
+ arg.replace(pos, 2, index);
+ }
+ args.push_back(arg);
+ memcheckcommand += " \"";
+ memcheckcommand += arg;
+ memcheckcommand += "\"";
+ }
for ( pp = 0; pp < this->MemoryTesterOptions.size(); pp ++ )
{
args.push_back(this->MemoryTesterOptions[pp]);
@@ -478,7 +495,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
= cmSystemTools::ParseArguments(memoryTesterOptions.c_str());
this->MemoryTesterOutputFile
- = this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.log";
+ = this->CTest->GetBinaryDir()
+ + "/Testing/Temporary/MemoryChecker.??.log";
switch ( this->MemoryTesterStyle )
{
@@ -510,7 +528,7 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
}
std::string outputFile = "--log-file="
+ this->MemoryTesterOutputFile;
- this->MemoryTesterOptions.push_back(outputFile);
+ this->MemoryTesterDynamicOptions.push_back(outputFile);
break;
}
case cmCTestMemCheckHandler::PURIFY:
@@ -538,19 +556,19 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
outputFile = "-log-file=";
#endif
outputFile += this->MemoryTesterOutputFile;
- this->MemoryTesterOptions.push_back(outputFile);
+ this->MemoryTesterDynamicOptions.push_back(outputFile);
break;
}
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
{
this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile;
std::string dpbdFile = this->CTest->GetBinaryDir()
- + "/Testing/Temporary/MemoryChecker.DPbd";
+ + "/Testing/Temporary/MemoryChecker.??.DPbd";
this->BoundsCheckerDPBDFile = dpbdFile;
- this->MemoryTesterOptions.push_back("/B");
- this->MemoryTesterOptions.push_back(dpbdFile);
- this->MemoryTesterOptions.push_back("/X");
- this->MemoryTesterOptions.push_back(this->MemoryTesterOutputFile);
+ this->MemoryTesterDynamicOptions.push_back("/B");
+ this->MemoryTesterDynamicOptions.push_back(dpbdFile);
+ this->MemoryTesterDynamicOptions.push_back("/X");
+ this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile);
this->MemoryTesterOptions.push_back("/M");
break;
}
@@ -898,25 +916,23 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
// This method puts the bounds checker output file into the output
// for the test
void
-cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res)
+cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res,
+ int test)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"PostProcessBoundsCheckerTest for : "
<< res.Name.c_str() << std::endl);
- if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) )
+ cmStdString ofile = testOutputFileName(test);
+ if ( ofile.empty() )
{
- std::string log = "Cannot find memory tester output file: "
- + this->MemoryTesterOutputFile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
return;
}
// put a scope around this to close ifs so the file can be removed
{
- std::ifstream ifs(this->MemoryTesterOutputFile.c_str());
+ std::ifstream ifs(ofile.c_str());
if ( !ifs )
{
- std::string log = "Cannot read memory tester output file: "
- + this->MemoryTesterOutputFile;
+ std::string log = "Cannot read memory tester output file: " + ofile;
cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
return;
}
@@ -939,38 +955,39 @@ cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res)
}
void
-cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res)
+cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res,
+ int test)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"PostProcessPurifyTest for : "
<< res.Name.c_str() << std::endl);
- appendMemTesterOutput(res);
+ appendMemTesterOutput(res, test);
}
void
-cmCTestMemCheckHandler::PostProcessValgrindTest(cmCTestTestResult& res)
+cmCTestMemCheckHandler::PostProcessValgrindTest(cmCTestTestResult& res,
+ int test)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"PostProcessValgrindTest for : "
<< res.Name.c_str() << std::endl);
- appendMemTesterOutput(res);
+ appendMemTesterOutput(res, test);
}
void
-cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res)
+cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res,
+ int test)
{
- if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) )
+ cmStdString ofile = testOutputFileName(test);
+
+ if ( ofile.empty() )
{
- std::string log = "Cannot find memory tester output file: "
- + this->MemoryTesterOutputFile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
return;
}
- std::ifstream ifs(this->MemoryTesterOutputFile.c_str());
+ std::ifstream ifs(ofile.c_str());
if ( !ifs )
{
- std::string log = "Cannot read memory tester output file: "
- + this->MemoryTesterOutputFile;
+ std::string log = "Cannot read memory tester output file: " + ofile;
cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
return;
}
@@ -981,3 +998,25 @@ cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res)
res.Output += "\n";
}
}
+
+cmStdString
+cmCTestMemCheckHandler::testOutputFileName(int test)
+{
+ cmStdString index;
+ cmOStringStream stream;
+ stream << test;
+ index = stream.str();
+ cmStdString ofile = this->MemoryTesterOutputFile;
+ cmStdString::size_type pos = ofile.find("??");
+ ofile.replace(pos, 2, index);
+
+ if ( !cmSystemTools::FileExists(ofile.c_str()) )
+ {
+ std::string log = "Cannot find memory tester output file: "
+ + ofile;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
+ ofile = "";
+ }
+
+ return ofile;
+}
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index 0a8c1b3..040d2e0 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -37,7 +37,7 @@ public:
protected:
virtual int PreProcessHandler();
virtual int PostProcessHandler();
- virtual void GenerateTestCommand(std::vector<std::string>& args);
+ virtual void GenerateTestCommand(std::vector<std::string>& args, int test);
private:
@@ -89,6 +89,7 @@ private:
std::string BoundsCheckerDPBDFile;
std::string BoundsCheckerXMLFile;
std::string MemoryTester;
+ std::vector<cmStdString> MemoryTesterDynamicOptions;
std::vector<cmStdString> MemoryTesterOptions;
int MemoryTesterStyle;
std::string MemoryTesterOutputFile;
@@ -117,12 +118,16 @@ private:
bool ProcessMemCheckBoundsCheckerOutput(const std::string& str,
std::string& log, int* results);
- void PostProcessPurifyTest(cmCTestTestResult& res);
- void PostProcessBoundsCheckerTest(cmCTestTestResult& res);
- void PostProcessValgrindTest(cmCTestTestResult& res);
+ void PostProcessPurifyTest(cmCTestTestResult& res, int test);
+ void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test);
+ void PostProcessValgrindTest(cmCTestTestResult& res, int test);
///! append MemoryTesterOutputFile to the test log
- void appendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res);
+ void appendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res,
+ int test);
+
+ ///! generate the output filename for the given test index
+ cmStdString testOutputFileName(int test);
};
#endif
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index ddd7e45..0e2fa41 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -389,13 +389,13 @@ void cmCTestRunTest::MemCheckPostProcess()
switch ( handler->MemoryTesterStyle )
{
case cmCTestMemCheckHandler::VALGRIND:
- handler->PostProcessValgrindTest(this->TestResult);
+ handler->PostProcessValgrindTest(this->TestResult, this->Index);
break;
case cmCTestMemCheckHandler::PURIFY:
- handler->PostProcessPurifyTest(this->TestResult);
+ handler->PostProcessPurifyTest(this->TestResult, this->Index);
break;
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
- handler->PostProcessBoundsCheckerTest(this->TestResult);
+ handler->PostProcessBoundsCheckerTest(this->TestResult, this->Index);
break;
default:
break;
@@ -524,7 +524,7 @@ void cmCTestRunTest::ComputeArguments()
= cmSystemTools::ConvertToOutputPath(this->ActualCommand.c_str());
//Prepends memcheck args to our command string
- this->TestHandler->GenerateTestCommand(this->Arguments);
+ this->TestHandler->GenerateTestCommand(this->Arguments, this->Index);
for(std::vector<std::string>::iterator i = this->Arguments.begin();
i != this->Arguments.end(); ++i)
{
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 0508448..497774d 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1107,7 +1107,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
}
//----------------------------------------------------------------------
-void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&)
+void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&, int)
{
}
@@ -1302,10 +1302,9 @@ int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec)
for ( it = vec.begin(); it != vec.end(); ++it )
{
int retVal = 0;
- std::string cmd = cmSystemTools::ConvertToOutputPath(it->c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << cmd
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << *it
<< std::endl);
- if ( !cmSystemTools::RunSingleCommand(cmd.c_str(), 0, &retVal, 0,
+ if ( !cmSystemTools::RunSingleCommand(it->c_str(), 0, &retVal, 0,
cmSystemTools::OUTPUT_MERGE
/*this->Verbose*/) || retVal != 0 )
{
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 8e59e59..93b793b 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -153,7 +153,7 @@ protected:
// compute a final test list
virtual int PreProcessHandler();
virtual int PostProcessHandler();
- virtual void GenerateTestCommand(std::vector<std::string>& args);
+ virtual void GenerateTestCommand(std::vector<std::string>& args, int test);
int ExecuteCommands(std::vector<cmStdString>& vec);
void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result);
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 1684fb2..ef25294 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -11,6 +11,9 @@
#=============================================================================
project(QtDialog)
+if(POLICY CMP0020)
+ cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required
+endif()
find_package(Qt5Widgets QUIET)
if (Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
@@ -29,6 +32,11 @@ if (Qt5Widgets_FOUND)
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
+
+ if(WIN32 AND TARGET Qt5::Core)
+ get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION)
+ get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH)
+ endif()
else()
set(QT_MIN_VERSION "4.4.0")
find_package(Qt4 REQUIRED)
@@ -38,6 +46,13 @@ else()
endif()
include(${QT_USE_FILE})
+
+ if(WIN32 AND EXISTS "${QT_QMAKE_EXECUTABLE}")
+ get_filename_component(_Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH)
+ if(EXISTS "${_Qt_BIN_DIR}/QtCore4.dll")
+ set(Qt_BIN_DIR ${_Qt_BIN_DIR})
+ endif()
+ endif()
endif()
set(SRCS
@@ -91,6 +106,9 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS})
target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES})
+if(Qt_BIN_DIR)
+ set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR})
+endif()
if(APPLE)
set_target_properties(cmake-gui PROPERTIES
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index 04a304e..e4d7f7f 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -24,6 +24,13 @@ bool cmAddDependenciesCommand
}
std::string target_name = args[0];
+ if(this->Makefile->IsAlias(target_name.c_str()))
+ {
+ cmOStringStream e;
+ e << "Cannot add target-level dependencies to alias target \""
+ << target_name << "\".\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ }
if(cmTarget* target = this->Makefile->FindTargetToUse(target_name.c_str()))
{
std::vector<std::string>::const_iterator s = args.begin();
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index 6dd8e5c..5785259 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -30,6 +30,7 @@ bool cmAddExecutableCommand
bool excludeFromAll = false;
bool importTarget = false;
bool importGlobal = false;
+ bool isAlias = false;
while ( s != args.end() )
{
if (*s == "WIN32")
@@ -57,6 +58,11 @@ bool cmAddExecutableCommand
++s;
importGlobal = true;
}
+ else if(*s == "ALIAS")
+ {
+ ++s;
+ isAlias = true;
+ }
else
{
break;
@@ -83,6 +89,72 @@ bool cmAddExecutableCommand
}
return false;
}
+ if (isAlias)
+ {
+ if(!cmGeneratorExpression::IsValidTargetName(exename.c_str()))
+ {
+ this->SetError(("Invalid name for ALIAS: " + exename).c_str());
+ return false;
+ }
+ if(excludeFromAll)
+ {
+ this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
+ return false;
+ }
+ if(importTarget || importGlobal)
+ {
+ this->SetError("IMPORTED with ALIAS is not allowed.");
+ return false;
+ }
+ if(args.size() != 3)
+ {
+ cmOStringStream e;
+ e << "ALIAS requires exactly one target argument.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
+ const char *aliasedName = s->c_str();
+ if(this->Makefile->IsAlias(aliasedName))
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << exename
+ << "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ cmTarget *aliasedTarget =
+ this->Makefile->FindTargetToUse(aliasedName, true);
+ if(!aliasedTarget)
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << exename
+ << "\" because target \"" << aliasedName << "\" does not already "
+ "exist.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ cmTarget::TargetType type = aliasedTarget->GetType();
+ if(type != cmTarget::EXECUTABLE)
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << exename
+ << "\" because target \"" << aliasedName << "\" is not an "
+ "executable.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ if(aliasedTarget->IsImported())
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << exename
+ << "\" because target \"" << aliasedName << "\" is IMPORTED.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ this->Makefile->AddAlias(exename.c_str(), aliasedTarget);
+ return true;
+ }
// Handle imported target creation.
if(importTarget)
diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h
index 1e9f9b3..2774ce8 100644
--- a/Source/cmAddExecutableCommand.h
+++ b/Source/cmAddExecutableCommand.h
@@ -107,6 +107,19 @@ public:
"(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
"which specifies the location of the main executable file on disk. "
"See documentation of the IMPORTED_* properties for more information."
+ "\n"
+ "The signature\n"
+ " add_executable(<name> ALIAS <target>)\n"
+ "creates an alias, such that <name> can be used to refer to <target> "
+ "in subsequent commands. The <name> does not appear in the generated "
+ "buildsystem as a make target. The <target> may not be an IMPORTED "
+ "target or an ALIAS. Alias targets can be used as linkable targets, "
+ "targets to read properties from, executables for custom commands and "
+ "custom targets. They can also be tested for existance with the "
+ "regular if(TARGET) subcommand. The <name> may not be used to modify "
+ "properties of <target>, that is, it may not be used as the operand of "
+ "set_property, set_target_properties, target_link_libraries etc. An "
+ "ALIAS target may not be installed of exported."
;
}
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index fd39eec..cbc6ed1 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -43,6 +43,7 @@ bool cmAddLibraryCommand
// the type of library. Otherwise, it is treated as a source or
// source list name. There may be two keyword arguments, check for them
bool haveSpecifiedType = false;
+ bool isAlias = false;
while ( s != args.end() )
{
std::string libType = *s;
@@ -76,6 +77,11 @@ bool cmAddLibraryCommand
type = cmTarget::UNKNOWN_LIBRARY;
haveSpecifiedType = true;
}
+ else if(libType == "ALIAS")
+ {
+ ++s;
+ isAlias = true;
+ }
else if(*s == "EXCLUDE_FROM_ALL")
{
++s;
@@ -96,6 +102,80 @@ bool cmAddLibraryCommand
break;
}
}
+ if (isAlias)
+ {
+ if(!cmGeneratorExpression::IsValidTargetName(libName.c_str()))
+ {
+ this->SetError(("Invalid name for ALIAS: " + libName).c_str());
+ return false;
+ }
+ if(excludeFromAll)
+ {
+ this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
+ return false;
+ }
+ if(importTarget || importGlobal)
+ {
+ this->SetError("IMPORTED with ALIAS is not allowed.");
+ return false;
+ }
+ if(args.size() != 3)
+ {
+ cmOStringStream e;
+ e << "ALIAS requires exactly one target argument.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
+ const char *aliasedName = s->c_str();
+ if(this->Makefile->IsAlias(aliasedName))
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << libName
+ << "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ cmTarget *aliasedTarget =
+ this->Makefile->FindTargetToUse(aliasedName, true);
+ if(!aliasedTarget)
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << libName
+ << "\" because target \"" << aliasedName << "\" does not already "
+ "exist.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ cmTarget::TargetType aliasedType = aliasedTarget->GetType();
+ if(aliasedType != cmTarget::SHARED_LIBRARY
+ && aliasedType != cmTarget::STATIC_LIBRARY
+ && aliasedType != cmTarget::MODULE_LIBRARY
+ && aliasedType != cmTarget::OBJECT_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << libName
+ << "\" because target \"" << aliasedName << "\" is not a library.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ if(aliasedTarget->IsImported())
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << libName
+ << "\" because target \"" << aliasedName << "\" is IMPORTED.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ this->Makefile->AddAlias(libName.c_str(), aliasedTarget);
+ return true;
+ }
+
+ if(importTarget && excludeFromAll)
+ {
+ this->SetError("excludeFromAll with IMPORTED target makes no sense.");
+ return false;
+ }
/* ideally we should check whether for the linker language of the target
CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index e5f27cb..59354b0 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -138,6 +138,19 @@ public:
"Some native build systems may not like targets that have only "
"object files, so consider adding at least one real source file "
"to any target that references $<TARGET_OBJECTS:objlib>."
+ "\n"
+ "The signature\n"
+ " add_library(<name> ALIAS <target>)\n"
+ "creates an alias, such that <name> can be used to refer to <target> "
+ "in subsequent commands. The <name> does not appear in the generated "
+ "buildsystem as a make target. The <target> may not be an IMPORTED "
+ "target or an ALIAS. Alias targets can be used as linkable targets, "
+ "targets to read properties from. They can also be tested for "
+ "existance with the "
+ "regular if(TARGET) subcommand. The <name> may not be used to modify "
+ "properties of <target>, that is, it may not be used as the operand of "
+ "set_property, set_target_properties, target_link_libraries etc. An "
+ "ALIAS target may not be installed of exported."
;
}
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index 48ae50e..cb62f21 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -422,8 +422,9 @@ int CCONV cmExecuteCommand(void *arg, const char *name,
for(int i = 0; i < numArgs; ++i)
{
// Assume all arguments are quoted.
- lff.Arguments.push_back(cmListFileArgument(args[i], true,
- "[CMake-Plugin]", 0));
+ lff.Arguments.push_back(
+ cmListFileArgument(args[i], cmListFileArgument::Quoted,
+ "[CMake-Plugin]", 0));
}
cmExecutionStatus status;
return mf->ExecuteCommand(lff,status);
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 2f26b0c..dbeeb07 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -12,10 +12,10 @@
#include "cmCommandArgumentParserHelper.h"
#include "cmSystemTools.h"
-#include "cmCommandArgumentLexer.h"
-
#include "cmMakefile.h"
+#include "cmCommandArgumentLexer.h"
+
int cmCommandArgument_yyparse( yyscan_t yyscanner );
//
cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index cfd5e76..2c2d377 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -963,9 +963,10 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Enables tracing output for target properties.",
"This variable can be populated with a list of properties to generate "
"debug output for when evaluating target properties. Currently it can "
- "only be used when evaluating the INCLUDE_DIRECTORIES target property. "
- "In that case, it outputs a backtrace for each include directory in "
- "the build. Default is unset.",false,"Variables That Change Behavior");
+ "only be used when evaluating the INCLUDE_DIRECTORIES, "
+ "COMPILE_DEFINITIONS and COMPILE_OPTIONS target properties. "
+ "In that case, it outputs a backtrace for each entry in the target "
+ "property. Default is unset.", false, "Variables That Change Behavior");
// Variables defined by CMake that describe the system
@@ -1426,6 +1427,49 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Same as CMAKE_C_FLAGS_* but used by the linker "
"when creating executables.",false,
"Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_MODULE_LINKER_FLAGS", cmProperty::VARIABLE,
+ "Linker flags to be used to create modules.",
+ "These flags will be used by the linker when creating a module."
+ ,false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_MODULE_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
+ "Flags to be used when linking a module.",
+ "Same as CMAKE_C_FLAGS_* but used by the linker "
+ "when creating modules.",false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_SHARED_LINKER_FLAGS", cmProperty::VARIABLE,
+ "Linker flags to be used to create shared libraries.",
+ "These flags will be used by the linker when creating a shared library."
+ ,false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_SHARED_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
+ "Flags to be used when linking a shared library.",
+ "Same as CMAKE_C_FLAGS_* but used by the linker "
+ "when creating shared libraries.",false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_STATIC_LINKER_FLAGS", cmProperty::VARIABLE,
+ "Linker flags to be used to create static libraries.",
+ "These flags will be used by the linker when creating a static library."
+ ,false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_STATIC_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
+ "Flags to be used when linking a static library.",
+ "Same as CMAKE_C_FLAGS_* but used by the linker "
+ "when creating static libraries.",false,
+ "Variables that Control the Build");
+
cm->DefineProperty
("CMAKE_LIBRARY_PATH_FLAG", cmProperty::VARIABLE,
"The flag to be used to add a library search path to a compiler.",
@@ -1518,6 +1562,22 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"See that target property for additional information.",
false,
"Variables that Control the Build");
+ cm->DefineProperty
+ ("CMAKE_<LANG>_VISIBILITY_PRESET", cmProperty::VARIABLE,
+ "Default value for <LANG>_VISIBILITY_PRESET of targets.",
+ "This variable is used to initialize the "
+ "<LANG>_VISIBILITY_PRESET property on all the targets. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
+ cm->DefineProperty
+ ("CMAKE_VISIBILITY_INLINES_HIDDEN", cmProperty::VARIABLE,
+ "Default value for VISIBILITY_INLINES_HIDDEN of targets.",
+ "This variable is used to initialize the "
+ "VISIBILITY_INLINES_HIDDEN property on all the targets. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
// Variables defined when the a language is enabled These variables will
// also be defined whenever CMake has loaded its support for compiling (LANG)
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 9c3f314..f059ceb 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -114,6 +114,15 @@ bool cmExportCommand
currentTarget != this->Targets.GetVector().end();
++currentTarget)
{
+ if (this->Makefile->IsAlias(currentTarget->c_str()))
+ {
+ cmOStringStream e;
+ e << "given ALIAS target \"" << *currentTarget
+ << "\" which may not be exported.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
if(cmTarget* target =
this->Makefile->GetLocalGenerator()->
GetGlobalGenerator()->FindTarget(0, currentTarget->c_str()))
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 36802b5..ef336ea 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -287,11 +287,33 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
const char *propName = "INTERFACE_INCLUDE_DIRECTORIES";
const char *input = target->GetProperty(propName);
- if (!input && tei->InterfaceIncludeDirectories.empty())
+
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ std::string dirs = tei->InterfaceIncludeDirectories;
+ this->ReplaceInstallPrefix(dirs);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
+ std::string exportDirs = cge->Evaluate(target->GetMakefile(), 0,
+ false, target);
+
+ if (cge->GetHadContextSensitiveCondition())
+ {
+ cmMakefile* mf = target->GetMakefile();
+ cmOStringStream e;
+ e << "Target \"" << target->GetName() << "\" is installed with "
+ "INCLUDES DESTINATION set to a context sensitive path. Paths which "
+ "depend on the configuration, policy values or the link interface are "
+ "not supported. Consider using target_include_directories instead.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
+
+ if (!input && exportDirs.empty())
{
return;
}
- if (!*input && tei->InterfaceIncludeDirectories.empty())
+ if ((input && !*input) && exportDirs.empty())
{
// Set to empty
properties[propName] = "";
@@ -300,7 +322,7 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
std::string includes = (input?input:"");
const char* sep = input ? ";" : "";
- includes += sep + tei->InterfaceIncludeDirectories;
+ includes += sep + exportDirs;
std::string prepro = cmGeneratorExpression::Preprocess(includes,
preprocessRule,
true);
@@ -641,7 +663,7 @@ cmExportFileGenerator
cmMakefile *mf = target->GetMakefile();
cmOStringStream e;
e << "Target \"" << target->GetName() << "\" has policy CMP0022 enabled, "
- "but also has old-style INTERFACE_LINK_LIBRARIES properties "
+ "but also has old-style LINK_INTERFACE_LIBRARIES properties "
"populated, but it was exported without the "
"EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties";
mf->IssueMessage(cmake::FATAL_ERROR, e.str());
diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index 9c1795e..cc35f84 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -12,10 +12,10 @@
#include "cmExprParserHelper.h"
#include "cmSystemTools.h"
-#include "cmExprLexer.h"
-
#include "cmMakefile.h"
+#include "cmExprLexer.h"
+
int cmExpr_yyparse( yyscan_t yyscanner );
//
cmExprParserHelper::cmExprParserHelper()
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 586fee2..aa755d1 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -90,7 +90,7 @@ public:
" file(TIMESTAMP filename variable [<format string>] [UTC])\n"
" file(GENERATE OUTPUT output_file\n"
" <INPUT input_file|CONTENT input_content>\n"
- " CONDITION expression)\n"
+ " [CONDITION expression])\n"
"WRITE will write a message into a file called 'filename'. It "
"overwrites the file if it already exists, and creates the file "
"if it does not exist. (If the file is a build input, use "
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index b59298f..e0c8c9e 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -747,6 +747,18 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
"Target name not supported.");
return std::string();
}
+ if(propertyName == "ALIASED_TARGET")
+ {
+ if(context->Makefile->IsAlias(targetName.c_str()))
+ {
+ if(cmTarget* tgt =
+ context->Makefile->FindTargetToUse(targetName.c_str()))
+ {
+ return tgt->GetName();
+ }
+ }
+ return "";
+ }
target = context->Makefile->FindTargetToUse(
targetName.c_str());
@@ -790,11 +802,12 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
if (propertyName == "LINKER_LANGUAGE")
{
- if (dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
+ if (target->LinkLanguagePropagatesToDependents() &&
+ dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
{
reportError(context, content->GetOriginalExpression(),
"LINKER_LANGUAGE target property can not be used while evaluating "
- "link libraries");
+ "link libraries for a static library");
return std::string();
}
const char *lang = target->GetLinkerLanguage(context->Config);
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index a619cec..e1fb8f1 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -126,6 +126,9 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
commaTokens;
std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
+
+ bool emptyParamTermination = false;
+
if (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
{
@@ -133,6 +136,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
+ if(this->it == this->Tokens.end())
+ {
+ emptyParamTermination = true;
+ }
while (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
@@ -141,6 +148,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
+ if(this->it == this->Tokens.end())
+ {
+ emptyParamTermination = true;
+ }
}
while (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
@@ -164,6 +175,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
+ if(this->it == this->Tokens.end())
+ {
+ emptyParamTermination = true;
+ }
}
while (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
@@ -203,7 +218,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
assert(parameters.size() > commaTokens.size());
for ( ; pit != pend; ++pit, ++commaIt)
{
- extendResult(result, *pit);
+ if (!pit->empty() && !emptyParamTermination)
+ {
+ extendResult(result, *pit);
+ }
if (commaIt != commaTokens.end())
{
extendText(result, *commaIt);
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 985dc50..faba7cd 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -288,6 +288,18 @@ bool cmGetPropertyCommand::HandleTargetMode()
return false;
}
+ if(this->PropertyName == "ALIASED_TARGET")
+ {
+ if(this->Makefile->IsAlias(this->Name.c_str()))
+ {
+ if(cmTarget* target =
+ this->Makefile->FindTargetToUse(this->Name.c_str()))
+ {
+ return this->StoreResult(target->GetName());
+ }
+ }
+ return false;
+ }
if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
{
return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 1947139..02f00a5 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -22,17 +22,30 @@ bool cmGetTargetPropertyCommand
}
std::string var = args[0].c_str();
const char* targetName = args[1].c_str();
+ const char *prop = 0;
- if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
+ if(args[2] == "ALIASED_TARGET")
{
- cmTarget& target = *tgt;
- const char *prop = target.GetProperty(args[2].c_str());
- if (prop)
+ if(this->Makefile->IsAlias(targetName))
{
- this->Makefile->AddDefinition(var.c_str(), prop);
- return true;
+ if(cmTarget* target =
+ this->Makefile->FindTargetToUse(targetName))
+ {
+ prop = target->GetName();
+ }
}
}
+ else if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
+ {
+ cmTarget& target = *tgt;
+ prop = target.GetProperty(args[2].c_str());
+ }
+
+ if (prop)
+ {
+ this->Makefile->AddDefinition(var.c_str(), prop);
+ return true;
+ }
this->Makefile->AddDefinition(var.c_str(), (var+"-NOTFOUND").c_str());
return true;
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 9b6ac93..7f2b592 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1769,10 +1769,22 @@ cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
return 0;
}
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::AddAlias(const char *name, cmTarget *tgt)
+{
+ this->AliasTargets[name] = tgt;
+}
+
+//----------------------------------------------------------------------------
+bool cmGlobalGenerator::IsAlias(const char *name)
+{
+ return this->AliasTargets.find(name) != this->AliasTargets.end();
+}
//----------------------------------------------------------------------------
cmTarget*
-cmGlobalGenerator::FindTarget(const char* project, const char* name)
+cmGlobalGenerator::FindTarget(const char* project, const char* name,
+ bool excludeAliases)
{
// if project specific
if(project)
@@ -1780,7 +1792,8 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name)
std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
for(unsigned int i = 0; i < gens->size(); ++i)
{
- cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
+ cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name,
+ excludeAliases);
if(ret)
{
return ret;
@@ -1790,6 +1803,15 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name)
// if all projects/directories
else
{
+ if (!excludeAliases)
+ {
+ std::map<cmStdString, cmTarget*>::iterator ai
+ = this->AliasTargets.find(name);
+ if (ai != this->AliasTargets.end())
+ {
+ return ai->second;
+ }
+ }
std::map<cmStdString,cmTarget *>::iterator i =
this->TotalTargets.find ( name );
if ( i != this->TotalTargets.end() )
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 2fcdc43..18aba24 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -196,7 +196,11 @@ public:
void FindMakeProgram(cmMakefile*);
///! Find a target by name by searching the local generators.
- cmTarget* FindTarget(const char* project, const char* name);
+ cmTarget* FindTarget(const char* project, const char* name,
+ bool excludeAliases = false);
+
+ void AddAlias(const char *name, cmTarget *tgt);
+ bool IsAlias(const char *name);
/** Determine if a name resolves to a framework on disk or a built target
that is a framework. */
@@ -347,6 +351,7 @@ protected:
// All targets in the entire project.
std::map<cmStdString,cmTarget *> TotalTargets;
+ std::map<cmStdString,cmTarget *> AliasTargets;
std::map<cmStdString,cmTarget *> ImportedTargets;
std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles;
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 0837f99..b2a337c 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -30,17 +30,17 @@ public:
if(!strcmp(name, vs10Win32generatorName))
{
return new cmGlobalVisualStudio10Generator(
- vs10Win32generatorName, NULL, NULL);
+ name, NULL, NULL);
}
if(!strcmp(name, vs10Win64generatorName))
{
return new cmGlobalVisualStudio10Generator(
- vs10Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ name, "x64", "CMAKE_FORCE_WIN64");
}
if(!strcmp(name, vs10IA64generatorName))
{
return new cmGlobalVisualStudio10Generator(
- vs10IA64generatorName, "Itanium", "CMAKE_FORCE_IA64");
+ name, "Itanium", "CMAKE_FORCE_IA64");
}
return 0;
}
@@ -69,9 +69,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio8Generator(name, architectureId,
+ : cmGlobalVisualStudio8Generator(name, platformName,
additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS10FindMake.cmake";
@@ -79,6 +79,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;"
"ProductDir", vc10Express, cmSystemTools::KeyWOW64_32);
+ this->MasmEnabled = false;
}
//----------------------------------------------------------------------------
@@ -161,13 +162,23 @@ void cmGlobalVisualStudio10Generator
::EnableLanguage(std::vector<std::string>const & lang,
cmMakefile *mf, bool optional)
{
- if(this->ArchitectureId == "Itanium" || this->ArchitectureId == "x64")
+ if(this->PlatformName == "Itanium" || this->PlatformName == "x64")
{
if(this->IsExpressEdition() && !this->Find64BitTools(mf))
{
return;
}
}
+
+ for(std::vector<std::string>::const_iterator it = lang.begin();
+ it != lang.end(); ++it)
+ {
+ if(*it == "ASM_MASM")
+ {
+ this->MasmEnabled = true;
+ }
+ }
+
cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index dbe6044..0a95091 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -25,7 +25,7 @@ class cmGlobalVisualStudio10Generator :
{
public:
cmGlobalVisualStudio10Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
virtual bool SetGeneratorToolset(std::string const& ts);
@@ -54,6 +54,9 @@ public:
/** Is the installed VS an Express edition? */
bool IsExpressEdition() const { return this->ExpressEdition; }
+ /** Is the Microsoft Assembler enabled? */
+ bool IsMasmEnabled() const { return this->MasmEnabled; }
+
/** The toolset name for the target platform. */
const char* GetPlatformToolset();
@@ -83,6 +86,7 @@ protected:
std::string PlatformToolset;
bool ExpressEdition;
+ bool MasmEnabled;
bool UseFolderProperty();
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index 624d01d..8ae7331 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -13,31 +13,56 @@
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
-static const char vs11Win32generatorName[] = "Visual Studio 11";
-static const char vs11Win64generatorName[] = "Visual Studio 11 Win64";
-static const char vs11ARMgeneratorName[] = "Visual Studio 11 ARM";
+static const char vs11generatorName[] = "Visual Studio 11";
class cmGlobalVisualStudio11Generator::Factory
: public cmGlobalGeneratorFactory
{
public:
virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
- if(!strcmp(name, vs11Win32generatorName))
+ if(strstr(name, vs11generatorName) != name)
+ {
+ return 0;
+ }
+
+ const char* p = name + sizeof(vs11generatorName) - 1;
+ if(p[0] == '\0')
{
return new cmGlobalVisualStudio11Generator(
- vs11Win32generatorName, NULL, NULL);
+ name, NULL, NULL);
+ }
+
+ if(p[0] != ' ')
+ {
+ return 0;
}
- if(!strcmp(name, vs11Win64generatorName))
+
+ ++p;
+
+ if(!strcmp(p, "ARM"))
{
return new cmGlobalVisualStudio11Generator(
- vs11Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ name, "ARM", NULL);
}
- if(!strcmp(name, vs11ARMgeneratorName))
+
+ if(!strcmp(p, "Win64"))
{
return new cmGlobalVisualStudio11Generator(
- vs11ARMgeneratorName, "ARM", NULL);
+ name, "x64", "CMAKE_FORCE_WIN64");
}
- return 0;
+
+ std::set<std::string> installedSDKs =
+ cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
+
+ if(installedSDKs.find(p) == installedSDKs.end())
+ {
+ return 0;
+ }
+
+ cmGlobalVisualStudio11Generator* ret =
+ new cmGlobalVisualStudio11Generator(name, p, NULL);
+ ret->WindowsCEVersion = "8.00";
+ return ret;
}
virtual void GetDocumentation(cmDocumentationEntry& entry) const {
@@ -51,9 +76,18 @@ public:
}
virtual void GetGenerators(std::vector<std::string>& names) const {
- names.push_back(vs11Win32generatorName);
- names.push_back(vs11Win64generatorName);
- names.push_back(vs11ARMgeneratorName); }
+ names.push_back(vs11generatorName);
+ names.push_back(vs11generatorName + std::string(" ARM"));
+ names.push_back(vs11generatorName + std::string(" Win64"));
+
+ std::set<std::string> installedSDKs =
+ cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
+ for(std::set<std::string>::const_iterator i =
+ installedSDKs.begin(); i != installedSDKs.end(); ++i)
+ {
+ names.push_back("Visual Studio 11 " + *i);
+ }
+ }
};
//----------------------------------------------------------------------------
@@ -64,9 +98,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio10Generator(name, architectureId,
+ : cmGlobalVisualStudio10Generator(name, platformName,
additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS11FindMake.cmake";
@@ -109,3 +143,36 @@ bool cmGlobalVisualStudio11Generator::UseFolderProperty()
// Express editions in VS10 and earlier, but they are in VS11 Express.
return cmGlobalVisualStudio8Generator::UseFolderProperty();
}
+
+//----------------------------------------------------------------------------
+std::set<std::string>
+cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs()
+{
+ const char sdksKey[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "Windows CE Tools\\SDKs";
+
+ std::vector<std::string> subkeys;
+ cmSystemTools::GetRegistrySubKeys(sdksKey, subkeys,
+ cmSystemTools::KeyWOW64_32);
+
+ std::set<std::string> ret;
+ for(std::vector<std::string>::const_iterator i =
+ subkeys.begin(); i != subkeys.end(); ++i)
+ {
+ std::string key = sdksKey;
+ key += '\\';
+ key += *i;
+ key += ';';
+
+ std::string path;
+ if(cmSystemTools::ReadRegistryValue(key.c_str(),
+ path,
+ cmSystemTools::KeyWOW64_32) &&
+ !path.empty())
+ {
+ ret.insert(*i);
+ }
+ }
+
+ return ret;
+}
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index 174f1cc..7cc7e69 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -21,7 +21,7 @@ class cmGlobalVisualStudio11Generator:
{
public:
cmGlobalVisualStudio11Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
virtual void WriteSLNHeader(std::ostream& fout);
@@ -34,7 +34,9 @@ public:
protected:
virtual const char* GetIDEVersion() { return "11.0"; }
bool UseFolderProperty();
+ static std::set<std::string> GetInstalledWindowsCESDKs();
private:
class Factory;
+ friend class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index d77b84d..c56dfff 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -25,17 +25,17 @@ public:
if(!strcmp(name, vs12Win32generatorName))
{
return new cmGlobalVisualStudio12Generator(
- vs12Win32generatorName, NULL, NULL);
+ name, NULL, NULL);
}
if(!strcmp(name, vs12Win64generatorName))
{
return new cmGlobalVisualStudio12Generator(
- vs12Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ name, "x64", "CMAKE_FORCE_WIN64");
}
if(!strcmp(name, vs12ARMgeneratorName))
{
return new cmGlobalVisualStudio12Generator(
- vs12ARMgeneratorName, "ARM", NULL);
+ name, "ARM", NULL);
}
return 0;
}
@@ -64,9 +64,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio11Generator(name, architectureId,
+ : cmGlobalVisualStudio11Generator(name, platformName,
additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS12FindMake.cmake";
@@ -100,12 +100,3 @@ cmLocalGenerator *cmGlobalVisualStudio12Generator::CreateLocalGenerator()
lg->SetGlobalGenerator(this);
return lg;
}
-
-//----------------------------------------------------------------------------
-bool cmGlobalVisualStudio12Generator::UseFolderProperty()
-{
- // Intentionally skip over the parent class implementation and call the
- // grand-parent class's implementation. Folders are not supported by the
- // Express editions in VS10 and earlier, but they are in VS12 Express.
- return cmGlobalVisualStudio8Generator::UseFolderProperty();
-}
diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h
index 5844ee0..064e310 100644
--- a/Source/cmGlobalVisualStudio12Generator.h
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -21,7 +21,7 @@ class cmGlobalVisualStudio12Generator:
{
public:
cmGlobalVisualStudio12Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
virtual void WriteSLNHeader(std::ostream& fout);
@@ -33,7 +33,6 @@ public:
virtual std::string GetUserMacrosDirectory() { return ""; }
protected:
virtual const char* GetIDEVersion() { return "12.0"; }
- bool UseFolderProperty();
private:
class Factory;
};
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 2494f55..51efc46 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -16,7 +16,8 @@
#include "cmake.h"
//----------------------------------------------------------------------------
-cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator()
+cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator(
+ const char* platformName) : cmGlobalVisualStudio7Generator(platformName)
{
this->FindMakeProgramFile = "CMakeVS71FindMake.cmake";
this->ProjectConfigurationSectionName = "ProjectConfiguration";
@@ -281,20 +282,20 @@ void cmGlobalVisualStudio71Generator
const std::set<std::string>& configsPartOfDefaultBuild,
const char* platformMapping)
{
+ const char* platformName =
+ platformMapping ? platformMapping : this->GetPlatformName();
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
i != this->Configurations.end(); ++i)
{
fout << "\t\t{" << guid << "}." << *i
- << ".ActiveCfg = " << *i << "|"
- << (platformMapping ? platformMapping : "Win32") << std::endl;
+ << ".ActiveCfg = " << *i << "|" << platformName << std::endl;
std::set<std::string>::const_iterator
ci = configsPartOfDefaultBuild.find(*i);
if(!(ci == configsPartOfDefaultBuild.end()))
{
fout << "\t\t{" << guid << "}." << *i
- << ".Build.0 = " << *i << "|"
- << (platformMapping ? platformMapping : "Win32") << std::endl;
+ << ".Build.0 = " << *i << "|" << platformName << std::endl;
}
}
}
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 6d91f97..e136db7 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -23,7 +23,7 @@
class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator
{
public:
- cmGlobalVisualStudio71Generator();
+ cmGlobalVisualStudio71Generator(const char* platformName = NULL);
static cmGlobalGeneratorFactory* NewFactory() {
return new cmGlobalGeneratorSimpleFactory
<cmGlobalVisualStudio71Generator>(); }
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 9a34ecf..b475665 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -17,9 +17,16 @@
#include "cmMakefile.h"
#include "cmake.h"
-cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator()
+cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
+ const char* platformName)
{
this->FindMakeProgramFile = "CMakeVS7FindMake.cmake";
+
+ if (!platformName)
+ {
+ platformName = "Win32";
+ }
+ this->PlatformName = platformName;
}
@@ -144,6 +151,13 @@ cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator()
return lg;
}
+//----------------------------------------------------------------------------
+void cmGlobalVisualStudio7Generator::AddPlatformDefinitions(cmMakefile* mf)
+{
+ cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
+ mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
+}
+
void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf)
{
// process the configurations
@@ -601,20 +615,20 @@ void cmGlobalVisualStudio7Generator
const std::set<std::string>& configsPartOfDefaultBuild,
const char* platformMapping)
{
+ const char* platformName =
+ platformMapping ? platformMapping : this->GetPlatformName();
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
i != this->Configurations.end(); ++i)
{
fout << "\t\t{" << guid << "}." << *i
- << ".ActiveCfg = " << *i << "|"
- << (platformMapping ? platformMapping : "Win32") << "\n";
+ << ".ActiveCfg = " << *i << "|" << platformName << "\n";
std::set<std::string>::const_iterator
ci = configsPartOfDefaultBuild.find(*i);
if(!(ci == configsPartOfDefaultBuild.end()))
{
fout << "\t\t{" << guid << "}." << *i
- << ".Build.0 = " << *i << "|"
- << (platformMapping ? platformMapping : "Win32") << "\n";
+ << ".Build.0 = " << *i << "|" << platformName << "\n";
}
}
}
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 3ebb408..4d22cff 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -26,7 +26,7 @@ struct cmIDEFlagTable;
class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator
{
public:
- cmGlobalVisualStudio7Generator();
+ cmGlobalVisualStudio7Generator(const char* platformName = NULL);
static cmGlobalGeneratorFactory* NewFactory() {
return new cmGlobalGeneratorSimpleFactory
<cmGlobalVisualStudio7Generator>(); }
@@ -36,9 +36,14 @@ public:
return cmGlobalVisualStudio7Generator::GetActualName();}
static const char* GetActualName() {return "Visual Studio 7";}
+ ///! Get the name for the platform.
+ const char* GetPlatformName() const { return this->PlatformName.c_str(); }
+
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual void AddPlatformDefinitions(cmMakefile* mf);
+
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
@@ -153,6 +158,7 @@ protected:
// Set during OutputSLNFile with the name of the current project.
// There is one SLN file per project.
std::string CurrentProject;
+ std::string PlatformName;
};
#define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 864e8db..e4244e0 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -57,8 +57,7 @@ public:
}
cmGlobalVisualStudio8Generator* ret = new cmGlobalVisualStudio8Generator(
- name, parser.GetArchitectureFamily(), NULL);
- ret->PlatformName = p;
+ name, p, NULL);
ret->WindowsCEVersion = parser.GetOSVersion();
return ret;
}
@@ -96,16 +95,14 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
+ : cmGlobalVisualStudio71Generator(platformName)
{
this->FindMakeProgramFile = "CMakeVS8FindMake.cmake";
this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms";
this->Name = name;
- if (architectureId)
- {
- this->ArchitectureId = architectureId;
- }
+
if (additionalPlatformDefinition)
{
this->AdditionalPlatformDefinition = additionalPlatformDefinition;
@@ -113,20 +110,6 @@ cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
}
//----------------------------------------------------------------------------
-const char* cmGlobalVisualStudio8Generator::GetPlatformName() const
-{
- if (!this->PlatformName.empty())
- {
- return this->PlatformName.c_str();
- }
- if (this->ArchitectureId == "X86")
- {
- return "Win32";
- }
- return this->ArchitectureId.c_str();
-}
-
-//----------------------------------------------------------------------------
///! Create a local generator appropriate to this Global Generator
cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator()
{
@@ -142,7 +125,6 @@ cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator()
void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf)
{
cmGlobalVisualStudio71Generator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
if(this->TargetsWindowsCE())
{
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index bcbd7a0..d181742 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -24,14 +24,12 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator
{
public:
cmGlobalVisualStudio8Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
virtual const char* GetName() const {return this->Name.c_str();}
- const char* GetPlatformName() const;
-
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
@@ -87,7 +85,6 @@ protected:
const char* path, cmTarget &t);
std::string Name;
- std::string PlatformName;
std::string WindowsCEVersion;
private:
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index 2082384..fba6ed1 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -62,8 +62,7 @@ public:
}
cmGlobalVisualStudio9Generator* ret = new cmGlobalVisualStudio9Generator(
- name, parser.GetArchitectureFamily(), NULL);
- ret->PlatformName = p;
+ name, p, NULL);
ret->WindowsCEVersion = parser.GetOSVersion();
return ret;
}
@@ -102,9 +101,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio8Generator(name, architectureId,
+ : cmGlobalVisualStudio8Generator(name, platformName,
additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS9FindMake.cmake";
diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h
index 1310a93..202aa8d 100644
--- a/Source/cmGlobalVisualStudio9Generator.h
+++ b/Source/cmGlobalVisualStudio9Generator.h
@@ -25,7 +25,7 @@ class cmGlobalVisualStudio9Generator :
{
public:
cmGlobalVisualStudio9Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
///! create the correct local generator
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index f4be0ce..5931016 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -21,7 +21,6 @@
//----------------------------------------------------------------------------
cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
{
- this->ArchitectureId = "X86";
this->AdditionalPlatformDefinition = NULL;
}
@@ -499,9 +498,6 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
//----------------------------------------------------------------------------
void cmGlobalVisualStudioGenerator::AddPlatformDefinitions(cmMakefile* mf)
{
- mf->AddDefinition("MSVC_C_ARCHITECTURE_ID", this->ArchitectureId.c_str());
- mf->AddDefinition("MSVC_CXX_ARCHITECTURE_ID", this->ArchitectureId.c_str());
-
if(this->AdditionalPlatformDefinition)
{
mf->AddDefinition(this->AdditionalPlatformDefinition, "TRUE");
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 9d81170..b665158 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -104,7 +104,6 @@ protected:
std::string GetUtilityDepend(cmTarget* target);
typedef std::map<cmTarget*, cmStdString> UtilityDependsMap;
UtilityDependsMap UtilityDepends;
- std::string ArchitectureId;
const char* AdditionalPlatformDefinition;
private:
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 63de1a5..7cb2d1f 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1769,27 +1769,31 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
configName);
}
- const char* linkFlagsProp = "LINK_FLAGS";
if(target.GetType() == cmTarget::OBJECT_LIBRARY ||
target.GetType() == cmTarget::STATIC_LIBRARY)
{
- linkFlagsProp = "STATIC_LIBRARY_FLAGS";
- }
- const char* targetLinkFlags = target.GetProperty(linkFlagsProp);
- if(targetLinkFlags)
- {
- extraLinkOptions += " ";
- extraLinkOptions += targetLinkFlags;
+ this->CurrentLocalGenerator
+ ->GetStaticLibraryFlags(extraLinkOptions,
+ cmSystemTools::UpperCase(configName),
+ &target);
}
- if(configName && *configName)
+ else
{
- std::string linkFlagsVar = linkFlagsProp;
- linkFlagsVar += "_";
- linkFlagsVar += cmSystemTools::UpperCase(configName);
- if(const char* linkFlags = target.GetProperty(linkFlagsVar.c_str()))
+ const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
+ if(targetLinkFlags)
{
- extraLinkOptions += " ";
- extraLinkOptions += linkFlags;
+ this->CurrentLocalGenerator->
+ AppendFlags(extraLinkOptions, targetLinkFlags);
+ }
+ if(configName && *configName)
+ {
+ std::string linkFlagsVar = "LINK_FLAGS_";
+ linkFlagsVar += cmSystemTools::UpperCase(configName);
+ if(const char* linkFlags = target.GetProperty(linkFlagsVar.c_str()))
+ {
+ this->CurrentLocalGenerator->
+ AppendFlags(extraLinkOptions, linkFlags);
+ }
}
}
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 4649eda..3c76bd6 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -295,13 +295,6 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
return false;
}
- if(!includesArgs.GetIncludeDirs().empty() && exports.GetString().empty())
- {
- this->SetError("TARGETS given INCLUDES DESTINATION, but EXPORT set "
- "not specified.");
- return false;
- }
-
// Enforce argument rules too complex to specify for the
// general-purpose parser.
if(archiveArgs.GetNamelinkOnly() ||
@@ -369,6 +362,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
targetIt!=targetList.GetVector().end();
++targetIt)
{
+
+ if (this->Makefile->IsAlias(targetIt->c_str()))
+ {
+ cmOStringStream e;
+ e << "TARGETS given target \"" << (*targetIt)
+ << "\" which is an alias.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
// Lookup this target in the current directory.
if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
{
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 36d84f3..898f379 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -22,45 +22,58 @@
# pragma warn -8060 /* possibly incorrect assignment */
#endif
-bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
- cmListFileFunction& function,
- const char* filename);
+//----------------------------------------------------------------------------
+struct cmListFileParser
+{
+ cmListFileParser(cmListFile* lf, cmMakefile* mf, const char* filename);
+ ~cmListFileParser();
+ bool ParseFile();
+ bool ParseFunction(const char* name, long line);
+ void AddArgument(cmListFileLexer_Token* token,
+ cmListFileArgument::Delimiter delim);
+ cmListFile* ListFile;
+ cmMakefile* Makefile;
+ const char* FileName;
+ cmListFileLexer* Lexer;
+ cmListFileFunction Function;
+ enum { SeparationOkay, SeparationWarning } Separation;
+};
-bool cmListFile::ParseFile(const char* filename,
- bool topLevel,
- cmMakefile *mf)
+//----------------------------------------------------------------------------
+cmListFileParser::cmListFileParser(cmListFile* lf, cmMakefile* mf,
+ const char* filename):
+ ListFile(lf), Makefile(mf), FileName(filename),
+ Lexer(cmListFileLexer_New())
{
- if(!cmSystemTools::FileExists(filename))
- {
- return false;
- }
+}
- // Create the scanner.
- cmListFileLexer* lexer = cmListFileLexer_New();
- if(!lexer)
- {
- cmSystemTools::Error("cmListFileCache: error allocating lexer ");
- return false;
- }
+//----------------------------------------------------------------------------
+cmListFileParser::~cmListFileParser()
+{
+ cmListFileLexer_Delete(this->Lexer);
+}
+//----------------------------------------------------------------------------
+bool cmListFileParser::ParseFile()
+{
// Open the file.
- if(!cmListFileLexer_SetFileName(lexer, filename))
+ if(!cmListFileLexer_SetFileName(this->Lexer, this->FileName))
{
- cmListFileLexer_Delete(lexer);
cmSystemTools::Error("cmListFileCache: error can not open file ",
- filename);
+ this->FileName);
return false;
}
// Use a simple recursive-descent parser to process the token
// stream.
- this->ModifiedTime = cmSystemTools::ModifiedTime(filename);
- bool parseError = false;
bool haveNewline = true;
- cmListFileLexer_Token* token;
- while(!parseError && (token = cmListFileLexer_Scan(lexer)))
+ while(cmListFileLexer_Token* token =
+ cmListFileLexer_Scan(this->Lexer))
{
- if(token->type == cmListFileLexer_Token_Newline)
+ if(token->type == cmListFileLexer_Token_Space)
+ {
+ }
+ else if(token->type == cmListFileLexer_Token_Newline)
{
haveNewline = true;
}
@@ -69,51 +82,66 @@ bool cmListFile::ParseFile(const char* filename,
if(haveNewline)
{
haveNewline = false;
- cmListFileFunction inFunction;
- inFunction.Name = token->text;
- inFunction.FilePath = filename;
- inFunction.Line = token->line;
- if(cmListFileCacheParseFunction(lexer, inFunction, filename))
+ if(this->ParseFunction(token->text, token->line))
{
- this->Functions.push_back(inFunction);
+ this->ListFile->Functions.push_back(this->Function);
}
else
{
- parseError = true;
+ return false;
}
}
else
{
cmOStringStream error;
error << "Error in cmake code at\n"
- << filename << ":" << token->line << ":\n"
+ << this->FileName << ":" << token->line << ":\n"
<< "Parse error. Expected a newline, got "
- << cmListFileLexer_GetTypeAsString(lexer, token->type)
+ << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
- parseError = true;
+ return false;
}
}
else
{
cmOStringStream error;
error << "Error in cmake code at\n"
- << filename << ":" << token->line << ":\n"
+ << this->FileName << ":" << token->line << ":\n"
<< "Parse error. Expected a command name, got "
- << cmListFileLexer_GetTypeAsString(lexer, token->type)
+ << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \""
<< token->text << "\".";
cmSystemTools::Error(error.str().c_str());
- parseError = true;
+ return false;
}
}
- if (parseError)
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmListFile::ParseFile(const char* filename,
+ bool topLevel,
+ cmMakefile *mf)
+{
+ if(!cmSystemTools::FileExists(filename))
+ {
+ return false;
+ }
+
+ bool parseError = false;
+ this->ModifiedTime = cmSystemTools::ModifiedTime(filename);
+
+ {
+ cmListFileParser parser(this, mf, filename);
+ parseError = !parser.ParseFile();
+ }
+
+ if(parseError)
{
this->ModifiedTime = 0;
}
- cmListFileLexer_Delete(lexer);
-
// do we need a cmake_policy(VERSION call?
if(topLevel)
{
@@ -196,7 +224,8 @@ bool cmListFile::ParseFile(const char* filename,
{
cmListFileFunction project;
project.Name = "PROJECT";
- cmListFileArgument prj("Project", false, filename, 0);
+ cmListFileArgument prj("Project", cmListFileArgument::Unquoted,
+ filename, 0);
project.Arguments.push_back(prj);
this->Functions.insert(this->Functions.begin(),project);
}
@@ -208,17 +237,24 @@ bool cmListFile::ParseFile(const char* filename,
return true;
}
-bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
- cmListFileFunction& function,
- const char* filename)
+//----------------------------------------------------------------------------
+bool cmListFileParser::ParseFunction(const char* name, long line)
{
+ // Inintialize a new function call.
+ this->Function = cmListFileFunction();
+ this->Function.FilePath = this->FileName;
+ this->Function.Name = name;
+ this->Function.Line = line;
+
// Command name has already been parsed. Read the left paren.
cmListFileLexer_Token* token;
- if(!(token = cmListFileLexer_Scan(lexer)))
+ while((token = cmListFileLexer_Scan(this->Lexer)) &&
+ token->type == cmListFileLexer_Token_Space) {}
+ if(!token)
{
cmOStringStream error;
- error << "Error in cmake code at\n"
- << filename << ":" << cmListFileLexer_GetCurrentLine(lexer) << ":\n"
+ error << "Error in cmake code at\n" << this->FileName << ":"
+ << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Function missing opening \"(\".";
cmSystemTools::Error(error.str().c_str());
return false;
@@ -226,26 +262,33 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
if(token->type != cmListFileLexer_Token_ParenLeft)
{
cmOStringStream error;
- error << "Error in cmake code at\n"
- << filename << ":" << cmListFileLexer_GetCurrentLine(lexer) << ":\n"
+ error << "Error in cmake code at\n" << this->FileName << ":"
+ << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Expected \"(\", got "
- << cmListFileLexer_GetTypeAsString(lexer, token->type)
+ << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
return false;
}
// Arguments.
- unsigned long lastLine = cmListFileLexer_GetCurrentLine(lexer);
+ unsigned long lastLine;
unsigned long parenDepth = 0;
- while((token = cmListFileLexer_Scan(lexer)))
+ this->Separation = SeparationOkay;
+ while((lastLine = cmListFileLexer_GetCurrentLine(this->Lexer),
+ token = cmListFileLexer_Scan(this->Lexer)))
{
+ if(token->type == cmListFileLexer_Token_Space ||
+ token->type == cmListFileLexer_Token_Newline)
+ {
+ this->Separation = SeparationOkay;
+ continue;
+ }
if(token->type == cmListFileLexer_Token_ParenLeft)
{
parenDepth++;
- cmListFileArgument a("(",
- false, filename, token->line);
- function.Arguments.push_back(a);
+ this->Separation = SeparationOkay;
+ this->AddArgument(token, cmListFileArgument::Unquoted);
}
else if(token->type == cmListFileLexer_Token_ParenRight)
{
@@ -254,43 +297,39 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
return true;
}
parenDepth--;
- cmListFileArgument a(")",
- false, filename, token->line);
- function.Arguments.push_back(a);
+ this->Separation = SeparationOkay;
+ this->AddArgument(token, cmListFileArgument::Unquoted);
+ this->Separation = SeparationWarning;
}
else if(token->type == cmListFileLexer_Token_Identifier ||
token->type == cmListFileLexer_Token_ArgumentUnquoted)
{
- cmListFileArgument a(token->text,
- false, filename, token->line);
- function.Arguments.push_back(a);
+ this->AddArgument(token, cmListFileArgument::Unquoted);
+ this->Separation = SeparationWarning;
}
else if(token->type == cmListFileLexer_Token_ArgumentQuoted)
{
- cmListFileArgument a(token->text,
- true, filename, token->line);
- function.Arguments.push_back(a);
+ this->AddArgument(token, cmListFileArgument::Quoted);
+ this->Separation = SeparationWarning;
}
- else if(token->type != cmListFileLexer_Token_Newline)
+ else
{
// Error.
cmOStringStream error;
- error << "Error in cmake code at\n"
- << filename << ":" << cmListFileLexer_GetCurrentLine(lexer)
- << ":\n"
+ error << "Error in cmake code at\n" << this->FileName << ":"
+ << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Function missing ending \")\". "
<< "Instead found "
- << cmListFileLexer_GetTypeAsString(lexer, token->type)
+ << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
return false;
}
- lastLine = cmListFileLexer_GetCurrentLine(lexer);
}
cmOStringStream error;
error << "Error in cmake code at\n"
- << filename << ":" << lastLine << ":\n"
+ << this->FileName << ":" << lastLine << ":\n"
<< "Parse error. Function missing ending \")\". "
<< "End of file reached.";
cmSystemTools::Error(error.str().c_str());
@@ -299,6 +338,45 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
}
//----------------------------------------------------------------------------
+void cmListFileParser::AddArgument(cmListFileLexer_Token* token,
+ cmListFileArgument::Delimiter delim)
+{
+ cmListFileArgument a(token->text, delim, this->FileName, token->line);
+ this->Function.Arguments.push_back(a);
+ if(delim == cmListFileArgument::Unquoted)
+ {
+ // Warn about a future behavior change.
+ const char* c = a.Value.c_str();
+ if(*c++ == '[')
+ {
+ while(*c == '=')
+ { ++c; }
+ if(*c == '[')
+ {
+ cmOStringStream m;
+ m << "Syntax Warning in cmake code at\n"
+ << " " << this->FileName << ":" << token->line << ":"
+ << token->column << "\n"
+ << "A future version of CMake may treat unquoted argument:\n"
+ << " " << a.Value << "\n"
+ << "as an opening long bracket. Double-quote the argument.";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str().c_str());
+ }
+ }
+ }
+ if(this->Separation == SeparationOkay)
+ {
+ return;
+ }
+ cmOStringStream m;
+ m << "Syntax Warning in cmake code at\n"
+ << " " << this->FileName << ":" << token->line << ":"
+ << token->column << "\n"
+ << "Argument not separated from preceding token by whitespace.";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str().c_str());
+}
+
+//----------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
{
os << lfc.FilePath;
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index fec3d07..7bb3b34 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -25,22 +25,27 @@ class cmMakefile;
struct cmListFileArgument
{
- cmListFileArgument(): Value(), Quoted(false), FilePath(0), Line(0) {}
+ enum Delimiter
+ {
+ Unquoted,
+ Quoted
+ };
+ cmListFileArgument(): Value(), Delim(Unquoted), FilePath(0), Line(0) {}
cmListFileArgument(const cmListFileArgument& r):
- Value(r.Value), Quoted(r.Quoted), FilePath(r.FilePath), Line(r.Line) {}
- cmListFileArgument(const std::string& v, bool q, const char* file,
- long line): Value(v), Quoted(q),
+ Value(r.Value), Delim(r.Delim), FilePath(r.FilePath), Line(r.Line) {}
+ cmListFileArgument(const std::string& v, Delimiter d, const char* file,
+ long line): Value(v), Delim(d),
FilePath(file), Line(line) {}
bool operator == (const cmListFileArgument& r) const
{
- return (this->Value == r.Value) && (this->Quoted == r.Quoted);
+ return (this->Value == r.Value) && (this->Delim == r.Delim);
}
bool operator != (const cmListFileArgument& r) const
{
return !(*this == r);
}
std::string Value;
- bool Quoted;
+ Delimiter Delim;
const char* FilePath;
long Line;
};
diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c
index e7965b5..2841fe5 100644
--- a/Source/cmListFileLexer.c
+++ b/Source/cmListFileLexer.c
@@ -9,7 +9,7 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 31
+#define YY_FLEX_SUBMINOR_VERSION 35
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -31,7 +31,15 @@
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
@@ -46,7 +54,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -77,6 +84,8 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#endif /* ! C99 */
+
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
@@ -86,11 +95,12 @@ typedef unsigned int flex_uint32_t;
#else /* ! __cplusplus */
-#if __STDC__
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
#define YY_USE_CONST
-#endif /* __STDC__ */
+#endif /* defined (__STDC__) */
#endif /* ! __cplusplus */
#ifdef YY_USE_CONST
@@ -126,8 +136,6 @@ typedef void* yyscan_t;
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
-int cmListFileLexer_yylex_init (yyscan_t* scanner);
-
/* Enter a start condition. This macro really ought to take a parameter,
* but we do it the disgusting crufty way forced on us by the ()-less
* definition of BEGIN.
@@ -151,9 +159,21 @@ int cmListFileLexer_yylex_init (yyscan_t* scanner);
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
#endif
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
@@ -192,14 +212,9 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
} \
while ( 0 )
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
+typedef size_t yy_size_t;
#endif
#ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -354,8 +369,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 14
-#define YY_END_OF_BUFFER 15
+#define YY_NUM_RULES 16
+#define YY_END_OF_BUFFER 17
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -363,12 +378,13 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[39] =
+static yyconst flex_int16_t yy_accept[45] =
{ 0,
- 0, 0, 0, 0, 15, 6, 12, 1, 7, 2,
- 6, 3, 4, 6, 13, 8, 9, 10, 11, 6,
- 0, 6, 0, 2, 0, 5, 6, 8, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 17, 6, 14, 1, 8, 2,
+ 6, 3, 4, 6, 15, 9, 11, 12, 13, 6,
+ 0, 6, 0, 14, 2, 0, 5, 6, 9, 0,
+ 10, 0, 7, 0, 0, 0, 7, 0, 7, 0,
+ 0, 0, 0, 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -405,64 +421,70 @@ static yyconst flex_int32_t yy_ec[256] =
static yyconst flex_int32_t yy_meta[13] =
{ 0,
- 1, 1, 2, 1, 3, 1, 1, 1, 4, 4,
- 4, 1
+ 1, 2, 3, 2, 4, 1, 1, 1, 5, 5,
+ 5, 1
} ;
-static yyconst flex_int16_t yy_base[48] =
+static yyconst flex_int16_t yy_base[56] =
{ 0,
- 0, 0, 10, 20, 34, 32, 89, 89, 89, 0,
- 23, 89, 89, 35, 0, 18, 89, 89, 44, 0,
- 49, 21, 0, 0, 19, 0, 0, 15, 59, 0,
- 18, 0, 15, 12, 11, 10, 9, 89, 64, 68,
- 72, 76, 80, 13, 84, 12, 10
+ 0, 0, 10, 20, 38, 32, 0, 109, 109, 0,
+ 28, 109, 109, 35, 0, 23, 109, 109, 44, 0,
+ 49, 26, 0, 0, 0, 22, 0, 0, 18, 24,
+ 109, 0, 61, 20, 0, 18, 0, 17, 16, 0,
+ 12, 11, 10, 109, 73, 16, 78, 83, 88, 93,
+ 12, 98, 11, 103, 9
} ;
-static yyconst flex_int16_t yy_def[48] =
+static yyconst flex_int16_t yy_def[56] =
{ 0,
- 38, 1, 39, 39, 38, 38, 38, 38, 38, 40,
- 6, 38, 38, 6, 41, 42, 38, 38, 42, 6,
- 38, 6, 43, 40, 44, 14, 6, 42, 42, 21,
- 21, 45, 46, 44, 47, 46, 47, 0, 38, 38,
- 38, 38, 38, 38, 38, 38, 38
+ 44, 1, 45, 45, 44, 44, 46, 44, 44, 47,
+ 6, 44, 44, 6, 48, 49, 44, 44, 49, 6,
+ 44, 6, 50, 46, 47, 51, 14, 6, 49, 49,
+ 44, 21, 44, 21, 52, 53, 33, 51, 33, 54,
+ 55, 53, 55, 0, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44
} ;
-static yyconst flex_int16_t yy_nxt[102] =
+static yyconst flex_int16_t yy_nxt[122] =
{ 0,
6, 7, 8, 7, 9, 10, 11, 12, 13, 6,
- 14, 15, 17, 37, 18, 36, 34, 30, 20, 30,
- 27, 19, 17, 20, 18, 35, 29, 27, 33, 29,
- 25, 19, 20, 38, 38, 38, 21, 38, 22, 38,
- 38, 20, 20, 23, 26, 26, 28, 38, 28, 30,
- 30, 38, 38, 20, 38, 31, 38, 38, 30, 30,
- 32, 28, 38, 28, 16, 16, 16, 16, 24, 38,
- 24, 24, 27, 38, 27, 27, 28, 38, 38, 28,
- 20, 38, 20, 20, 30, 38, 30, 30, 5, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-
- 38
+ 14, 15, 17, 43, 18, 42, 38, 24, 32, 33,
+ 32, 19, 17, 36, 18, 37, 33, 41, 29, 30,
+ 37, 19, 20, 36, 30, 26, 21, 44, 22, 44,
+ 44, 20, 20, 23, 27, 27, 31, 44, 29, 32,
+ 32, 44, 44, 33, 44, 34, 44, 44, 32, 32,
+ 35, 33, 44, 44, 44, 21, 44, 39, 44, 44,
+ 33, 33, 40, 16, 16, 16, 16, 16, 25, 25,
+ 44, 25, 25, 28, 28, 44, 28, 28, 29, 29,
+ 44, 44, 29, 20, 20, 44, 20, 20, 32, 32,
+
+ 44, 32, 32, 33, 33, 44, 33, 33, 5, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44
} ;
-static yyconst flex_int16_t yy_chk[102] =
+static yyconst flex_int16_t yy_chk[122] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 3, 47, 3, 46, 44, 37, 36, 35,
- 34, 3, 4, 33, 4, 31, 28, 25, 22, 16,
- 11, 4, 6, 5, 0, 0, 6, 0, 6, 0,
+ 1, 1, 3, 55, 3, 53, 51, 46, 43, 42,
+ 41, 3, 4, 39, 4, 38, 36, 34, 30, 29,
+ 26, 4, 6, 22, 16, 11, 6, 5, 6, 0,
0, 6, 6, 6, 14, 14, 19, 0, 19, 21,
21, 0, 0, 21, 0, 21, 0, 0, 21, 21,
- 21, 29, 0, 29, 39, 39, 39, 39, 40, 0,
- 40, 40, 41, 0, 41, 41, 42, 0, 0, 42,
- 43, 0, 43, 43, 45, 0, 45, 45, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-
- 38
+ 21, 33, 0, 0, 0, 33, 0, 33, 0, 0,
+ 33, 33, 33, 45, 45, 45, 45, 45, 47, 47,
+ 0, 47, 47, 48, 48, 0, 48, 48, 49, 49,
+ 0, 0, 49, 50, 50, 0, 50, 50, 52, 52,
+
+ 0, 52, 52, 54, 54, 0, 54, 54, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[15] =
+static yyconst flex_int32_t yy_rule_can_match_eol[17] =
{ 0,
-1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, };
+1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, };
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
@@ -494,9 +516,11 @@ Run flex like this:
Modify cmListFileLexer.c:
- remove TABs
+ - remove use of the 'register' storage class specifier
- remove the yyunput function
- add a statement "(void)yyscanner;" to the top of these methods:
yy_fatal_error, cmListFileLexer_yyalloc, cmListFileLexer_yyrealloc, cmListFileLexer_yyfree
+ - remove statement "yyscanner = NULL;" from cmListFileLexer_yylex_destroy
- remove all YY_BREAK lines occurring right after return statements
- remove the isatty forward declaration
@@ -540,7 +564,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer);
/*--------------------------------------------------------------------------*/
-#line 568 "cmListFileLexer.c"
+#line 570 "cmListFileLexer.c"
#define INITIAL 0
#define STRING 1
@@ -591,6 +615,12 @@ struct yyguts_t
}; /* end struct yyguts_t */
+static int yy_init_globals (yyscan_t yyscanner );
+
+int cmListFileLexer_yylex_init (yyscan_t* scanner);
+
+int cmListFileLexer_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
@@ -620,6 +650,10 @@ int cmListFileLexer_yyget_lineno (yyscan_t yyscanner );
void cmListFileLexer_yyset_lineno (int line_number ,yyscan_t yyscanner );
+int cmListFileLexer_yyget_column (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_column (int column_no ,yyscan_t yyscanner );
+
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
@@ -652,7 +686,12 @@ static int input (yyscan_t yyscanner );
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
#endif
/* Copy whatever the last rule matched to the standard output. */
@@ -660,7 +699,7 @@ static int input (yyscan_t yyscanner );
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -754,14 +793,14 @@ YY_DECL
int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-#line 100 "cmListFileLexer.in.l"
+#line 82 "cmListFileLexer.in.l"
-#line 787 "cmListFileLexer.c"
+#line 804 "cmListFileLexer.c"
- if ( yyg->yy_init )
+ if ( !yyg->yy_init )
{
- yyg->yy_init = 0;
+ yyg->yy_init = 1;
#ifdef YY_USER_INIT
YY_USER_INIT;
@@ -810,13 +849,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 39 )
+ if ( yy_current_state >= 45 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 89 );
+ while ( yy_base[yy_current_state] != 109 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -855,7 +894,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
/* rule 1 can match eol */
YY_RULE_SETUP
-#line 102 "cmListFileLexer.in.l"
+#line 84 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_Newline;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -865,14 +904,14 @@ YY_RULE_SETUP
}
case 2:
YY_RULE_SETUP
-#line 110 "cmListFileLexer.in.l"
+#line 92 "cmListFileLexer.in.l"
{
lexer->column += yyleng;
}
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 114 "cmListFileLexer.in.l"
+#line 96 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ParenLeft;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -881,7 +920,7 @@ YY_RULE_SETUP
}
case 4:
YY_RULE_SETUP
-#line 121 "cmListFileLexer.in.l"
+#line 103 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ParenRight;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -890,7 +929,7 @@ YY_RULE_SETUP
}
case 5:
YY_RULE_SETUP
-#line 128 "cmListFileLexer.in.l"
+#line 110 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_Identifier;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -899,7 +938,7 @@ YY_RULE_SETUP
}
case 6:
YY_RULE_SETUP
-#line 135 "cmListFileLexer.in.l"
+#line 117 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -908,7 +947,16 @@ YY_RULE_SETUP
}
case 7:
YY_RULE_SETUP
-#line 142 "cmListFileLexer.in.l"
+#line 124 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+case 8:
+YY_RULE_SETUP
+#line 131 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
cmListFileLexerSetToken(lexer, "", 0);
@@ -916,58 +964,69 @@ YY_RULE_SETUP
BEGIN(STRING);
}
YY_BREAK
-case 8:
-/* rule 8 can match eol */
+case 9:
YY_RULE_SETUP
-#line 149 "cmListFileLexer.in.l"
+#line 138 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
YY_BREAK
-case 9:
-/* rule 9 can match eol */
+case 10:
+/* rule 10 can match eol */
YY_RULE_SETUP
-#line 154 "cmListFileLexer.in.l"
+#line 143 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
++lexer->line;
lexer->column = 1;
}
YY_BREAK
-case 10:
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 149 "cmListFileLexer.in.l"
+{
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ ++lexer->line;
+ lexer->column = 1;
+}
+ YY_BREAK
+case 12:
YY_RULE_SETUP
-#line 160 "cmListFileLexer.in.l"
+#line 155 "cmListFileLexer.in.l"
{
lexer->column += yyleng;
BEGIN(INITIAL);
return 1;
}
-case 11:
+case 13:
YY_RULE_SETUP
-#line 166 "cmListFileLexer.in.l"
+#line 161 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
YY_BREAK
case YY_STATE_EOF(STRING):
-#line 171 "cmListFileLexer.in.l"
+#line 166 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_BadString;
BEGIN(INITIAL);
return 1;
}
-case 12:
+case 14:
YY_RULE_SETUP
-#line 177 "cmListFileLexer.in.l"
+#line 172 "cmListFileLexer.in.l"
{
+ lexer->token.type = cmListFileLexer_Token_Space;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
+ return 1;
}
- YY_BREAK
-case 13:
+case 15:
YY_RULE_SETUP
-#line 181 "cmListFileLexer.in.l"
+#line 179 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_BadCharacter;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -975,18 +1034,18 @@ YY_RULE_SETUP
return 1;
}
case YY_STATE_EOF(INITIAL):
-#line 188 "cmListFileLexer.in.l"
+#line 186 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_None;
cmListFileLexerSetToken(lexer, 0, 0);
return 0;
}
-case 14:
+case 16:
YY_RULE_SETUP
-#line 194 "cmListFileLexer.in.l"
+#line 192 "cmListFileLexer.in.l"
ECHO;
YY_BREAK
-#line 1025 "cmListFileLexer.c"
+#line 1064 "cmListFileLexer.c"
case YY_END_OF_BUFFER:
{
@@ -1171,7 +1230,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
- size_t num_to_read =
+ int num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
@@ -1216,7 +1275,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Read in more data. */
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- yyg->yy_n_chars, num_to_read );
+ yyg->yy_n_chars, (size_t) num_to_read );
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
}
@@ -1240,6 +1299,14 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmListFileLexer_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
yyg->yy_n_chars += number_to_move;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
@@ -1270,7 +1337,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 39 )
+ if ( yy_current_state >= 45 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1287,7 +1354,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
int yy_is_jam;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
char *yy_cp = yyg->yy_c_buf_p;
YY_CHAR yy_c = 1;
@@ -1299,11 +1366,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 39 )
+ if ( yy_current_state >= 45 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 38);
+ yy_is_jam = (yy_current_state == 44);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -1633,6 +1700,8 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
@@ -1651,6 +1720,8 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
(yyg->yy_buffer_stack,
num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
/* zero only the new slots.*/
memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -1695,26 +1766,26 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char * base, yy_size_t size ,
/** Setup the input buffer state to scan a string. The next call to cmListFileLexer_yylex() will
* scan from a @e copy of @a str.
- * @param str a NUL-terminated string to scan
+ * @param yystr a NUL-terminated string to scan
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
* cmListFileLexer_yy_scan_bytes() instead.
*/
-YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yy_str , yyscan_t yyscanner)
+YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
{
- return cmListFileLexer_yy_scan_bytes(yy_str,strlen(yy_str) ,yyscanner);
+ return cmListFileLexer_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
}
/** Setup the input buffer state to scan the given bytes. The next call to cmListFileLexer_yylex() will
* scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * bytes, int len , yyscan_t yyscanner)
+YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
@@ -1722,15 +1793,15 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * bytes, int len ,
int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = len + 2;
+ n = _yybytes_len + 2;
buf = (char *) cmListFileLexer_yyalloc(n ,yyscanner );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_bytes()" );
- for ( i = 0; i < len; ++i )
- buf[i] = bytes[i];
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
- buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
b = cmListFileLexer_yy_scan_buffer(buf,n ,yyscanner);
if ( ! b )
@@ -1918,21 +1989,87 @@ void cmListFileLexer_yyset_debug (int bdebug , yyscan_t yyscanner)
/* Accessor methods for yylval and yylloc */
+/* User-visible API */
+
+/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* cmListFileLexer_yylex_init_extra has the same functionality as cmListFileLexer_yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to cmListFileLexer_yyalloc in
+ * the yyextra field.
+ */
+
+int cmListFileLexer_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ cmListFileLexer_yyset_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ cmListFileLexer_yyset_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
static int yy_init_globals (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Initialization is the same as for the non-reentrant scanner.
- This function is called once per scanner lifetime. */
+ * This function is called from cmListFileLexer_yylex_destroy(), so don't allocate here.
+ */
yyg->yy_buffer_stack = 0;
yyg->yy_buffer_stack_top = 0;
yyg->yy_buffer_stack_max = 0;
yyg->yy_c_buf_p = (char *) 0;
- yyg->yy_init = 1;
+ yyg->yy_init = 0;
yyg->yy_start = 0;
+
yyg->yy_start_stack_ptr = 0;
yyg->yy_start_stack_depth = 0;
- yyg->yy_start_stack = (int *) 0;
+ yyg->yy_start_stack = NULL;
/* Defined in main.c */
#ifdef YY_STDINIT
@@ -1949,33 +2086,6 @@ static int yy_init_globals (yyscan_t yyscanner)
return 0;
}
-/* User-visible API */
-
-/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals)
-
-{
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL );
-
- if (*ptr_yy_globals == NULL){
- errno = ENOMEM;
- return 1;
- }
-
- memset(*ptr_yy_globals,0,sizeof(struct yyguts_t));
-
- return yy_init_globals ( *ptr_yy_globals );
-}
-
/* cmListFileLexer_yylex_destroy is for both reentrant and non-reentrant scanners. */
int cmListFileLexer_yylex_destroy (yyscan_t yyscanner)
{
@@ -1996,6 +2106,10 @@ int cmListFileLexer_yylex_destroy (yyscan_t yyscanner)
cmListFileLexer_yyfree(yyg->yy_start_stack ,yyscanner );
yyg->yy_start_stack = NULL;
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * cmListFileLexer_yylex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
/* Destroy the main struct (reentrant only). */
cmListFileLexer_yyfree ( yyscanner , yyscanner );
return 0;
@@ -2009,7 +2123,6 @@ int cmListFileLexer_yylex_destroy (yyscan_t yyscanner)
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
int i;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@@ -2019,7 +2132,6 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
int n;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
for ( n = 0; s[n]; ++n )
;
@@ -2054,19 +2166,7 @@ void cmListFileLexer_yyfree (void * ptr , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef yytext_ptr
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-#line 194 "cmListFileLexer.in.l"
+#line 192 "cmListFileLexer.in.l"
@@ -2122,7 +2222,7 @@ static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
}
/* We need to extend the buffer. */
- temp = (char*)malloc(newSize);
+ temp = malloc(newSize);
if(lexer->token.text)
{
memcpy(temp, lexer->token.text, lexer->token.length);
@@ -2303,6 +2403,7 @@ const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
switch(type)
{
case cmListFileLexer_Token_None: return "nothing";
+ case cmListFileLexer_Token_Space: return "space";
case cmListFileLexer_Token_Newline: return "newline";
case cmListFileLexer_Token_Identifier: return "identifier";
case cmListFileLexer_Token_ParenLeft: return "left paren";
diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h
index 5f4db33..cc78b5c 100644
--- a/Source/cmListFileLexer.h
+++ b/Source/cmListFileLexer.h
@@ -15,6 +15,7 @@
typedef enum cmListFileLexer_Type_e
{
cmListFileLexer_Token_None,
+ cmListFileLexer_Token_Space,
cmListFileLexer_Token_Newline,
cmListFileLexer_Token_Identifier,
cmListFileLexer_Token_ParenLeft,
diff --git a/Source/cmListFileLexer.in.l b/Source/cmListFileLexer.in.l
index eedf494..12b53ee 100644
--- a/Source/cmListFileLexer.in.l
+++ b/Source/cmListFileLexer.in.l
@@ -24,6 +24,7 @@ Modify cmListFileLexer.c:
- remove the yyunput function
- add a statement "(void)yyscanner;" to the top of these methods:
yy_fatal_error, cmListFileLexer_yyalloc, cmListFileLexer_yyrealloc, cmListFileLexer_yyfree
+ - remove statement "yyscanner = NULL;" from cmListFileLexer_yylex_destroy
- remove all YY_BREAK lines occurring right after return statements
- remove the isatty forward declaration
@@ -75,6 +76,8 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer);
%x STRING
MAKEVAR \$\([A-Za-z0-9_]*\)
+UNQUOTED ([^ \t\r\n\(\)#\\\"]|\\.)
+LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t])*\"
%%
@@ -111,7 +114,14 @@ MAKEVAR \$\([A-Za-z0-9_]*\)
return 1;
}
-({MAKEVAR}|[^ \t\r\n\(\)#\\\"]|\\.)({MAKEVAR}|[^ \t\r\n\(\)#\\\"]|\\.|\"({MAKEVAR}|[^\r\n\(\)#\\\"]|\\.)*\")* {
+({UNQUOTED})({UNQUOTED})* {
+ lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+
+({MAKEVAR}|{UNQUOTED})({LEGACY})* {
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
@@ -125,11 +135,17 @@ MAKEVAR \$\([A-Za-z0-9_]*\)
BEGIN(STRING);
}
-<STRING>([^\\\n\"]|\\(.|\n))+ {
+<STRING>([^\\\n\"]|\\.)+ {
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
+<STRING>\\\n {
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ ++lexer->line;
+ lexer->column = 1;
+}
+
<STRING>\n {
cmListFileLexerAppend(lexer, yytext, yyleng);
++lexer->line;
@@ -153,8 +169,11 @@ MAKEVAR \$\([A-Za-z0-9_]*\)
return 1;
}
-[ \t\r] {
+[ \t\r]+ {
+ lexer->token.type = cmListFileLexer_Token_Space;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
+ return 1;
}
. {
@@ -405,6 +424,7 @@ const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
switch(type)
{
case cmListFileLexer_Token_None: return "nothing";
+ case cmListFileLexer_Token_Space: return "space";
case cmListFileLexer_Token_Newline: return "newline";
case cmListFileLexer_Token_Identifier: return "identifier";
case cmListFileLexer_Token_ParenLeft: return "left paren";
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index b187d6b..9c04109 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1038,20 +1038,11 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
// If this is the compiler then look for the extra variable
// _COMPILER_ARG1 which must be the first argument to the compiler
const char* compilerArg1 = 0;
- const char* compilerTarget = 0;
- const char* compilerOptionTarget = 0;
if(actualReplace == "CMAKE_${LANG}_COMPILER")
{
std::string arg1 = actualReplace + "_ARG1";
cmSystemTools::ReplaceString(arg1, "${LANG}", lang);
compilerArg1 = this->Makefile->GetDefinition(arg1.c_str());
- compilerTarget
- = this->Makefile->GetDefinition(
- (std::string("CMAKE_") + lang + "_COMPILER_TARGET").c_str());
- compilerOptionTarget
- = this->Makefile->GetDefinition(
- (std::string("CMAKE_") + lang +
- "_COMPILE_OPTION_TARGET").c_str());
}
if(actualReplace.find("${LANG}") != actualReplace.npos)
{
@@ -1072,11 +1063,6 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
ret += " ";
ret += compilerArg1;
}
- if (compilerTarget && compilerOptionTarget)
- {
- ret += compilerOptionTarget;
- ret += compilerTarget;
- }
return ret;
}
return replace;
@@ -1541,6 +1527,25 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
}
}
+void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
+ std::string const& config,
+ cmTarget* target)
+{
+ this->AppendFlags(flags,
+ this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS"));
+ if(!config.empty())
+ {
+ std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config;
+ this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name.c_str()));
+ }
+ this->AppendFlags(flags, target->GetProperty("STATIC_LIBRARY_FLAGS"));
+ if(!config.empty())
+ {
+ std::string name = "STATIC_LIBRARY_FLAGS_" + config;
+ this->AppendFlags(flags, target->GetProperty(name.c_str()));
+ }
+}
+
void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
std::string& flags,
std::string& linkFlags,
@@ -1557,26 +1562,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
switch(target->GetType())
{
case cmTarget::STATIC_LIBRARY:
- {
- const char* targetLinkFlags =
- target->GetProperty("STATIC_LIBRARY_FLAGS");
- if(targetLinkFlags)
- {
- linkFlags += targetLinkFlags;
- linkFlags += " ";
- }
- if(!buildType.empty())
- {
- std::string build = "STATIC_LIBRARY_FLAGS_";
- build += buildType;
- targetLinkFlags = target->GetProperty(build.c_str());
- if(targetLinkFlags)
- {
- linkFlags += targetLinkFlags;
- linkFlags += " ";
- }
- }
- }
+ this->GetStaticLibraryFlags(linkFlags, buildType, target->Target);
break;
case cmTarget::MODULE_LIBRARY:
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index ed0f6e3..10f0b1a 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -348,6 +348,11 @@ public:
std::string const& dir_max,
bool* hasSourceExtension = 0);
+ /** Fill out the static linker flags for the given target. */
+ void GetStaticLibraryFlags(std::string& flags,
+ std::string const& config,
+ cmTarget* target);
+
/** Fill out these strings for the given target. Libraries to link,
* flags, and linkflags. */
void GetTargetFlags(std::string& linkLibs,
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index df6e1f1..e5b4057 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -573,22 +573,20 @@ cmLocalVisualStudio6Generator
// Add the rule with the given dependencies and commands.
const char* no_main_dependency = 0;
- this->Makefile->AddCustomCommandToOutput(output,
- depends,
- no_main_dependency,
- origCommand.GetCommandLines(),
- comment.c_str(),
- origCommand.GetWorkingDirectory());
+ if(cmSourceFile* outsf =
+ this->Makefile->AddCustomCommandToOutput(
+ output, depends, no_main_dependency,
+ origCommand.GetCommandLines(), comment.c_str(),
+ origCommand.GetWorkingDirectory()))
+ {
+ target.AddSourceFile(outsf);
+ }
// Replace the dependencies with the output of this rule so that the
// next rule added will run after this one.
depends.clear();
depends.push_back(output);
- // Add a source file representing this output to the project.
- cmSourceFile* outsf = this->Makefile->GetSourceFileWithOutput(output);
- target.AddSourceFile(outsf);
-
// Free the fake output name.
delete [] output;
}
@@ -1171,18 +1169,42 @@ void cmLocalVisualStudio6Generator
std::string extraLinkOptionsRelWithDebInfo;
if(target.GetType() == cmTarget::EXECUTABLE)
{
- extraLinkOptions =
- this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
+ extraLinkOptions = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
+ extraLinkOptionsDebug = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_DEBUG");
+ extraLinkOptionsRelease = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_RELEASE");
+ extraLinkOptionsMinSizeRel = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_MINSIZEREL");
+ extraLinkOptionsRelWithDebInfo = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO");
}
if(target.GetType() == cmTarget::SHARED_LIBRARY)
{
- extraLinkOptions =
- this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
+ extraLinkOptions = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
+ extraLinkOptionsDebug = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_DEBUG");
+ extraLinkOptionsRelease = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_RELEASE");
+ extraLinkOptionsMinSizeRel = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL");
+ extraLinkOptionsRelWithDebInfo = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO");
}
if(target.GetType() == cmTarget::MODULE_LIBRARY)
{
- extraLinkOptions =
- this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
+ extraLinkOptions = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
+ extraLinkOptionsDebug = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_DEBUG");
+ extraLinkOptionsRelease = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_RELEASE");
+ extraLinkOptionsMinSizeRel = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL");
+ extraLinkOptionsRelWithDebInfo = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO");
}
// Get extra linker options for this target.
@@ -1435,38 +1457,39 @@ void cmLocalVisualStudio6Generator
std::string staticLibOptionsRelWithDebInfo;
if(target.GetType() == cmTarget::STATIC_LIBRARY )
{
- if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
- {
- staticLibOptions = libflags;
- staticLibOptionsDebug = libflags;
- staticLibOptionsRelease = libflags;
- staticLibOptionsMinSizeRel = libflags;
- staticLibOptionsRelWithDebInfo = libflags;
- }
- if(const char* libflagsDebug =
- target.GetProperty("STATIC_LIBRARY_FLAGS_DEBUG"))
- {
- staticLibOptionsDebug += " ";
- staticLibOptionsDebug = libflagsDebug;
- }
- if(const char* libflagsRelease =
- target.GetProperty("STATIC_LIBRARY_FLAGS_RELEASE"))
- {
- staticLibOptionsRelease += " ";
- staticLibOptionsRelease = libflagsRelease;
- }
- if(const char* libflagsMinSizeRel =
- target.GetProperty("STATIC_LIBRARY_FLAGS_MINSIZEREL"))
- {
- staticLibOptionsMinSizeRel += " ";
- staticLibOptionsMinSizeRel = libflagsMinSizeRel;
- }
- if(const char* libflagsRelWithDebInfo =
- target.GetProperty("STATIC_LIBRARY_FLAGS_RELWITHDEBINFO"))
- {
- staticLibOptionsRelWithDebInfo += " ";
- staticLibOptionsRelWithDebInfo = libflagsRelWithDebInfo;
- }
+ const char *libflagsGlobal =
+ this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS");
+ this->AppendFlags(staticLibOptions, libflagsGlobal);
+ this->AppendFlags(staticLibOptionsDebug, libflagsGlobal);
+ this->AppendFlags(staticLibOptionsRelease, libflagsGlobal);
+ this->AppendFlags(staticLibOptionsMinSizeRel, libflagsGlobal);
+ this->AppendFlags(staticLibOptionsRelWithDebInfo, libflagsGlobal);
+
+ this->AppendFlags(staticLibOptionsDebug, this->Makefile->
+ GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_DEBUG"));
+ this->AppendFlags(staticLibOptionsRelease, this->Makefile->
+ GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_RELEASE"));
+ this->AppendFlags(staticLibOptionsMinSizeRel, this->Makefile->
+ GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL"));
+ this->AppendFlags(staticLibOptionsRelWithDebInfo, this->Makefile->
+ GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO"));
+
+ const char *libflags = target.GetProperty("STATIC_LIBRARY_FLAGS");
+ this->AppendFlags(staticLibOptions, libflags);
+ this->AppendFlags(staticLibOptionsDebug, libflags);
+ this->AppendFlags(staticLibOptionsRelease, libflags);
+ this->AppendFlags(staticLibOptionsMinSizeRel, libflags);
+ this->AppendFlags(staticLibOptionsRelWithDebInfo, libflags);
+
+ this->AppendFlags(staticLibOptionsDebug,
+ target.GetProperty("STATIC_LIBRARY_FLAGS_DEBUG"));
+ this->AppendFlags(staticLibOptionsRelease,
+ target.GetProperty("STATIC_LIBRARY_FLAGS_RELEASE"));
+ this->AppendFlags(staticLibOptionsMinSizeRel,
+ target.GetProperty("STATIC_LIBRARY_FLAGS_MINSIZEREL"));
+ this->AppendFlags(staticLibOptionsRelWithDebInfo,
+ target.GetProperty("STATIC_LIBRARY_FLAGS_RELWITHDEBINFO"));
+
std::string objects;
this->OutputObjects(target, "LIB", objects);
if(!objects.empty())
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 9ecd53d..58cc6f4 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -146,11 +146,10 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
force += "/";
force += tgt.GetName();
force += "_force";
- this->Makefile->AddCustomCommandToOutput(force.c_str(), no_depends,
- no_main_dependency,
- force_commands, " ", 0, true);
if(cmSourceFile* file =
- this->Makefile->GetSourceFileWithOutput(force.c_str()))
+ this->Makefile->AddCustomCommandToOutput(
+ force.c_str(), no_depends, no_main_dependency,
+ force_commands, " ", 0, true))
{
tgt.AddSourceFile(file);
}
@@ -920,7 +919,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
}
this->OutputTargetRules(fout, configName, target, libName);
- this->OutputBuildTool(fout, configName, target, targetOptions.IsDebug());
+ this->OutputBuildTool(fout, configName, target, targetOptions);
fout << "\t\t</Configuration>\n";
}
@@ -941,9 +940,7 @@ cmLocalVisualStudio7Generator
}
void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
- const char* configName,
- cmTarget &target,
- bool isDebug)
+ const char* configName, cmTarget &target, const Options& targetOptions)
{
cmGlobalVisualStudio7Generator* gg =
static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
@@ -1039,17 +1036,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
}
}
std::string libflags;
- if(const char* flags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
- {
- libflags += flags;
- }
- std::string libFlagsConfig = "STATIC_LIBRARY_FLAGS_";
- libFlagsConfig += configTypeUpper;
- if(const char* flagsConfig = target.GetProperty(libFlagsConfig.c_str()))
- {
- libflags += " ";
- libflags += flagsConfig;
- }
+ this->GetStaticLibraryFlags(libflags, configTypeUpper, &target);
if(!libflags.empty())
{
fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
@@ -1121,7 +1108,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
temp += targetNamePDB;
fout << "\t\t\t\tProgramDatabaseFile=\"" <<
this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
- if(isDebug)
+ if(targetOptions.IsDebug())
{
fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
}
@@ -1219,7 +1206,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t\tProgramDatabaseFile=\""
<< path << "/" << targetNamePDB
<< "\"\n";
- if(isDebug)
+ if(targetOptions.IsDebug())
{
fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
}
@@ -1233,9 +1220,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
{
fout << "\t\t\t\tSubSystem=\"8\"\n";
}
- fout << "\t\t\t\tEntryPointSymbol=\""
- << (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup")
- << "\"\n";
+
+ if(!linkOptions.GetFlag("EntryPointSymbol"))
+ {
+ const char* entryPointSymbol = targetOptions.UsingUnicode() ?
+ (isWin32Executable ? "wWinMainCRTStartup" : "mainWCRTStartup") :
+ (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup");
+ fout << "\t\t\t\tEntryPointSymbol=\"" << entryPointSymbol << "\"\n";
+ }
}
else if ( this->FortranProject )
{
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index d9e2ef0..92e4d3c 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -90,7 +90,7 @@ private:
void OutputTargetRules(std::ostream& fout, const char* configName,
cmTarget &target, const char *libName);
void OutputBuildTool(std::ostream& fout, const char* configName,
- cmTarget& t, bool debug);
+ cmTarget& t, const Options& targetOptions);
void OutputLibraryDirectories(std::ostream& fout,
std::vector<std::string> const& dirs);
void WriteProjectSCC(std::ostream& fout, cmTarget& target);
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index bd7ec00..8ba612c 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -227,7 +227,7 @@ bool cmMacroHelperCommand::InvokeInitialPass
}
arg.Value = tmps;
- arg.Quoted = k->Quoted;
+ arg.Delim = k->Delim;
arg.FilePath = k->FilePath;
arg.Line = k->Line;
newLFF.Arguments.push_back(arg);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 2cd19cf..57b86fd 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -41,6 +41,7 @@
#include <stack>
#include <ctype.h> // for isspace
+#include <assert.h>
class cmMakefile::Internals
{
@@ -149,6 +150,7 @@ cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
this->Initialize();
this->CheckSystemVars = mf.CheckSystemVars;
this->ListFileStack = mf.ListFileStack;
+ this->OutputToSource = mf.OutputToSource;
}
//----------------------------------------------------------------------------
@@ -1009,11 +1011,32 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
cc->SetEscapeOldStyle(escapeOldStyle);
cc->SetEscapeAllowMakeVars(true);
file->SetCustomCommand(cc);
+ this->UpdateOutputToSourceMap(outputs, file);
}
return file;
}
//----------------------------------------------------------------------------
+void
+cmMakefile::UpdateOutputToSourceMap(std::vector<std::string> const& outputs,
+ cmSourceFile* source)
+{
+ for(std::vector<std::string>::const_iterator o = outputs.begin();
+ o != outputs.end(); ++o)
+ {
+ this->UpdateOutputToSourceMap(*o, source);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmMakefile::UpdateOutputToSourceMap(std::string const& output,
+ cmSourceFile* source)
+{
+ this->OutputToSource[output] = source;
+}
+
+//----------------------------------------------------------------------------
cmSourceFile*
cmMakefile::AddCustomCommandToOutput(const char* output,
const std::vector<std::string>& depends,
@@ -1437,6 +1460,14 @@ void cmMakefile::AddLinkDirectoryForTarget(const char *target,
cmTargets::iterator i = this->Targets.find(target);
if ( i != this->Targets.end())
{
+ if(this->IsAlias(target))
+ {
+ cmOStringStream e;
+ e << "ALIAS target \"" << target << "\" "
+ << "may not be linked into another target.";
+ this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
i->second.AddLinkDirectory( d );
}
else
@@ -1923,6 +1954,12 @@ void cmMakefile::AddGlobalLinkInformation(const char* name, cmTarget& target)
}
+void cmMakefile::AddAlias(const char* lname, cmTarget *tgt)
+{
+ this->AliasTargets[lname] = tgt;
+ this->LocalGenerator->GetGlobalGenerator()->AddAlias(lname, tgt);
+}
+
cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
const std::vector<std::string> &srcs,
bool excludeFromAll)
@@ -1979,7 +2016,7 @@ cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
return &it->second;
}
-cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
+cmSourceFile *cmMakefile::LinearGetSourceFileWithOutput(const char *cname)
{
std::string name = cname;
std::string out;
@@ -2015,6 +2052,25 @@ cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
return 0;
}
+cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
+{
+ std::string name = cname;
+
+ // If the queried path is not absolute we use the backward compatible
+ // linear-time search for an output with a matching suffix.
+ if(!cmSystemTools::FileIsFullPath(cname))
+ {
+ return LinearGetSourceFileWithOutput(cname);
+ }
+ // Otherwise we use an efficient lookup map.
+ OutputToSourceMap::iterator o = this->OutputToSource.find(name);
+ if (o != this->OutputToSource.end())
+ {
+ return (*o).second;
+ }
+ return 0;
+}
+
#if defined(CMAKE_BUILD_WITH_CMAKE)
cmSourceGroup* cmMakefile::GetSourceGroup(const std::vector<std::string>&name)
{
@@ -2784,7 +2840,7 @@ bool cmMakefile::ExpandArguments(
// If the argument is quoted, it should be one argument.
// Otherwise, it may be a list of arguments.
- if(i->Quoted)
+ if(i->Delim == cmListFileArgument::Quoted)
{
outArgs.push_back(value);
}
@@ -3363,7 +3419,11 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
std::string sinfile = infile;
this->AddCMakeDependFile(sinfile);
cmSystemTools::ConvertToUnixSlashes(soutfile);
- this->AddCMakeOutputFile(soutfile);
+ // Re-generate if non-temporary outputs are missing.
+ if(soutfile.find("CMakeTmp") == soutfile.npos)
+ {
+ this->AddCMakeOutputFile(soutfile);
+ }
mode_t perm = 0;
cmSystemTools::GetPermissions(sinfile.c_str(), perm);
std::string::size_type pos = soutfile.rfind('/');
@@ -3754,8 +3814,17 @@ const char* cmMakefile::GetFeature(const char* feature, const char* config)
return 0;
}
-cmTarget* cmMakefile::FindTarget(const char* name)
+cmTarget* cmMakefile::FindTarget(const char* name, bool excludeAliases)
{
+ if (!excludeAliases)
+ {
+ std::map<std::string, cmTarget*>::iterator i
+ = this->AliasTargets.find(name);
+ if (i != this->AliasTargets.end())
+ {
+ return i->second;
+ }
+ }
cmTargets& tgts = this->GetTargets();
cmTargets::iterator i = tgts.find ( name );
@@ -4081,7 +4150,7 @@ void cmMakefile::DefineProperties(cmake *cm)
"List of options to pass to the compiler.",
"This property specifies the list of directories given "
"so far for this property. "
- "This property exists on directories and targets. "
+ "This property exists on directories and targets."
"\n"
"The target property values are used by the generators to set "
"the options for the compiler.\n"
@@ -4180,7 +4249,7 @@ cmMakefile::AddImportedTarget(const char* name, cmTarget::TargetType type,
}
//----------------------------------------------------------------------------
-cmTarget* cmMakefile::FindTargetToUse(const char* name)
+cmTarget* cmMakefile::FindTargetToUse(const char* name, bool excludeAliases)
{
// Look for an imported target. These take priority because they
// are more local in scope and do not have to be globally unique.
@@ -4192,15 +4261,25 @@ cmTarget* cmMakefile::FindTargetToUse(const char* name)
}
// Look for a target built in this directory.
- if(cmTarget* t = this->FindTarget(name))
+ if(cmTarget* t = this->FindTarget(name, excludeAliases))
{
return t;
}
// Look for a target built in this project.
- return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name);
+ return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name,
+ excludeAliases);
+}
+
+//----------------------------------------------------------------------------
+bool cmMakefile::IsAlias(const char *name)
+{
+ if (this->AliasTargets.find(name) != this->AliasTargets.end())
+ return true;
+ return this->GetLocalGenerator()->GetGlobalGenerator()->IsAlias(name);
}
+//----------------------------------------------------------------------------
cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name)
{
cmTarget *t = this->FindTargetToUse(name);
@@ -4211,6 +4290,14 @@ cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name)
bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
bool isCustom)
{
+ if(this->IsAlias(name.c_str()))
+ {
+ cmOStringStream e;
+ e << "cannot create target \"" << name
+ << "\" because an alias with the same name already exists.";
+ msg = e.str();
+ return false;
+ }
if(cmTarget* existing = this->FindTargetToUse(name.c_str()))
{
// The name given conflicts with an existing target. Produce an
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 871fa1b..8bce9fd 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -29,6 +29,9 @@
#include <cmsys/auto_ptr.hxx>
#include <cmsys/RegularExpression.hxx>
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+# include <cmsys/hash_map.hxx>
+#endif
class cmFunctionBlocker;
class cmCommand;
@@ -337,6 +340,7 @@ public:
cmTarget* AddLibrary(const char *libname, cmTarget::TargetType type,
const std::vector<std::string> &srcs,
bool excludeFromAll = false);
+ void AddAlias(const char *libname, cmTarget *tgt);
#if defined(CMAKE_BUILD_WITH_CMAKE)
/**
@@ -536,11 +540,12 @@ public:
this->GeneratorTargets = targets;
}
- cmTarget* FindTarget(const char* name);
+ cmTarget* FindTarget(const char* name, bool excludeAliases = false);
/** Find a target to use in place of the given name. The target
returned may be imported or built within the project. */
- cmTarget* FindTargetToUse(const char* name);
+ cmTarget* FindTargetToUse(const char* name, bool excludeAliases = false);
+ bool IsAlias(const char *name);
cmGeneratorTarget* FindGeneratorTargetToUse(const char* name);
/**
@@ -902,6 +907,7 @@ protected:
// libraries, classes, and executables
cmTargets Targets;
+ std::map<std::string, cmTarget*> AliasTargets;
cmGeneratorTargetsType GeneratorTargets;
std::vector<cmSourceFile*> SourceFiles;
@@ -1036,6 +1042,26 @@ private:
bool GeneratingBuildSystem;
+ /**
+ * Old version of GetSourceFileWithOutput(const char*) kept for
+ * backward-compatibility. It implements a linear search and support
+ * relative file paths. It is used as a fall back by
+ * GetSourceFileWithOutput(const char*).
+ */
+ cmSourceFile *LinearGetSourceFileWithOutput(const char *cname);
+
+ // A map for fast output to input look up.
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ typedef cmsys::hash_map<std::string, cmSourceFile*> OutputToSourceMap;
+#else
+ typedef std::map<std::string, cmSourceFile*> OutputToSourceMap;
+#endif
+ OutputToSourceMap OutputToSource;
+
+ void UpdateOutputToSourceMap(std::vector<std::string> const& outputs,
+ cmSourceFile* source);
+ void UpdateOutputToSourceMap(std::string const& output,
+ cmSourceFile* source);
};
//----------------------------------------------------------------------------
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 347f26d..ea9663f 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -144,12 +144,8 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
}
std::string extraFlags;
- this->LocalGenerator->AppendFlags
- (extraFlags,this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
- std::string staticLibraryFlagsConfig = "STATIC_LIBRARY_FLAGS_";
- staticLibraryFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags
- (extraFlags, this->Target->GetProperty(staticLibraryFlagsConfig.c_str()));
+ this->LocalGenerator->GetStaticLibraryFlags(extraFlags,
+ cmSystemTools::UpperCase(this->ConfigName), this->Target);
this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
}
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 0ba673e..a823f05 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -543,7 +543,7 @@ cmPolicies::cmPolicies()
"the INCLUDE_DIRECTORIES target property. "
"The NEW behavior for this policy is to issue a FATAL_ERROR if "
"INCLUDE_DIRECTORIES contains a relative path.",
- 2,8,11,20130516, cmPolicies::WARN);
+ 2,8,12,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0022, "CMP0022",
@@ -574,7 +574,7 @@ cmPolicies::cmPolicies()
"The NEW behavior for this policy is to use the INTERFACE_LINK_LIBRARIES "
"property for in-build targets, and ignore the old properties matching "
"(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?.",
- 2,8,11,20130516, cmPolicies::WARN);
+ 2,8,12,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0023, "CMP0023",
@@ -600,7 +600,7 @@ cmPolicies::cmPolicies()
"target_link_libraries signatures to be mixed. "
"The NEW behavior for this policy is to not to allow mixing of the "
"keyword and plain signatures.",
- 2,8,11,20130724, cmPolicies::WARN);
+ 2,8,12,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index b5e5225..4207860 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -244,6 +244,11 @@ bool cmSetPropertyCommand::HandleTargetMode()
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
ni != this->Names.end(); ++ni)
{
+ if (this->Makefile->IsAlias(ni->c_str()))
+ {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
{
// Handle the current target.
diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx
index a2b50a8..78ef393 100644
--- a/Source/cmSetTargetPropertiesCommand.cxx
+++ b/Source/cmSetTargetPropertiesCommand.cxx
@@ -72,6 +72,11 @@ bool cmSetTargetPropertiesCommand
int i;
for(i = 0; i < numFiles; ++i)
{
+ if (this->Makefile->IsAlias(args[i].c_str()))
+ {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
bool ret = cmSetTargetPropertiesCommand::SetOneTarget
(args[i].c_str(),propertyPairs,this->Makefile);
if (!ret)
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 37344dc..9ec4938 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -638,6 +638,12 @@ bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
}
+ if (outputflag == OUTPUT_PASSTHROUGH)
+ {
+ cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
+ cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
+ }
+
cmsysProcess_SetTimeout(cp, timeout);
cmsysProcess_Execute(cp);
@@ -645,7 +651,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
char* data;
int length;
int pipe;
- if ( output || outputflag != OUTPUT_NONE )
+ if(outputflag != OUTPUT_PASSTHROUGH && (output || outputflag != OUTPUT_NONE))
{
while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0)) > 0)
{
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 9614449..9d7dae9 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -211,7 +211,7 @@ public:
* user-viewable output from the program being run will be generated.
* OUTPUT_MERGE is the legacy behaviour where stdout and stderr are merged
* into stdout. OUTPUT_NORMAL passes through the output to stdout/stderr as
- * it was received.
+ * it was received. OUTPUT_PASSTHROUGH passes through the original handles.
*
* If timeout is specified, the command will be terminated after
* timeout expires. Timeout is specified in seconds.
@@ -230,7 +230,8 @@ public:
{
OUTPUT_NONE = 0,
OUTPUT_MERGE,
- OUTPUT_NORMAL
+ OUTPUT_NORMAL,
+ OUTPUT_PASSTHROUGH
};
static bool RunSingleCommand(const char* command, std::string* output = 0,
int* retVal = 0, const char* dir = 0,
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index dd1bdde..147c332 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -304,7 +304,7 @@ void cmTarget::DefineProperties(cmake *cm)
"List of options to pass to the compiler.",
"This property specifies the list of options specified "
"so far for this property. "
- "This property exists on directories and targets. "
+ "This property exists on directories and targets."
"\n"
"The target property values are used by the generators to set "
"the options for the compiler.\n"
@@ -945,6 +945,11 @@ void cmTarget::DefineProperties(cmake *cm)
"OSX_ARCHITECTURES.");
cm->DefineProperty
+ ("NAME", cmProperty::TARGET,
+ "Logical name for the target.",
+ "Read-only logical name for the target as used by CMake.");
+
+ cm->DefineProperty
("EXPORT_NAME", cmProperty::TARGET,
"Exported name for target files.",
"This sets the name for the IMPORTED target generated when it this "
@@ -964,6 +969,12 @@ void cmTarget::DefineProperties(cmake *cm)
"This is the configuration-specific version of OUTPUT_NAME.");
cm->DefineProperty
+ ("ALIASED_TARGET", cmProperty::TARGET,
+ "Name of target aliased by this target.",
+ "If this is an ALIAS target, this property contains the name of the "
+ "target aliased.");
+
+ cm->DefineProperty
("<CONFIG>_OUTPUT_NAME", cmProperty::TARGET,
"Old per-configuration target file base name.",
"This is a configuration-specific version of OUTPUT_NAME. "
@@ -1001,22 +1012,13 @@ void cmTarget::DefineProperties(cmake *cm)
"(such as \"lib\") on a library name.");
cm->DefineProperty
- ("C_VISIBILITY_PRESET", cmProperty::TARGET,
+ ("<LANG>_VISIBILITY_PRESET", cmProperty::TARGET,
"Value for symbol visibility compile flags",
- "The C_VISIBILITY_PRESET property determines the value passed used in "
- "a visibility related compile option, such as -fvisibility=. This "
- "property only has an affect for libraries and executables with "
+ "The <LANG>_VISIBILITY_PRESET property determines the value passed in "
+ "a visibility related compile option, such as -fvisibility= for <LANG>. "
+ "This property only has an affect for libraries and executables with "
"exports. This property is initialized by the value of the variable "
- "CMAKE_C_VISIBILITY_PRESET if it is set when a target is created.");
-
- cm->DefineProperty
- ("CXX_VISIBILITY_PRESET", cmProperty::TARGET,
- "Value for symbol visibility compile flags",
- "The CXX_VISIBILITY_PRESET property determines the value passed used in "
- "a visibility related compile option, such as -fvisibility=. This "
- "property only has an affect for libraries and executables with "
- "exports. This property is initialized by the value of the variable "
- "CMAKE_CXX_VISIBILITY_PRESET if it is set when a target is created.");
+ "CMAKE_<LANG>_VISIBILITY_PRESET if it is set when a target is created.");
cm->DefineProperty
("VISIBILITY_INLINES_HIDDEN", cmProperty::TARGET,
@@ -2530,6 +2532,7 @@ void cmTarget::GetTllSignatureTraces(cmOStringStream &s,
= (sig == cmTarget::KeywordTLLSignature ? "keyword"
: "plain");
s << "The uses of the " << sigString << " signature are here:\n";
+ std::set<cmStdString> emitted;
for(std::vector<cmListFileBacktrace>::const_iterator it = sigs.begin();
it != sigs.end(); ++it)
{
@@ -2537,7 +2540,12 @@ void cmTarget::GetTllSignatureTraces(cmOStringStream &s,
if(i != it->end())
{
cmListFileContext const& lfc = *i;
- s << " * " << (lfc.Line? "": " in ") << lfc << std::endl;
+ cmOStringStream line;
+ line << " * " << (lfc.Line? "": " in ") << lfc << std::endl;
+ if (emitted.insert(line.str()).second)
+ {
+ s << line.str();
+ }
++i;
}
}
@@ -2974,7 +2982,13 @@ void cmTarget::SetProperty(const char* prop, const char* value)
{
return;
}
-
+ if (strcmp(prop, "NAME") == 0)
+ {
+ cmOStringStream e;
+ e << "NAME property is read-only\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
{
cmListFileBacktrace lfbt;
@@ -3041,6 +3055,13 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
{
return;
}
+ if (strcmp(prop, "NAME") == 0)
+ {
+ cmOStringStream e;
+ e << "NAME property is read-only\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
{
cmListFileBacktrace lfbt;
@@ -3282,7 +3303,10 @@ static void processIncludeDirectories(cmTarget *tgt,
if (!noMessage)
{
tgt->GetMakefile()->IssueMessage(messageType, e.str().c_str());
- return;
+ if (messageType == cmake::FATAL_ERROR)
+ {
+ return;
+ }
}
}
@@ -4056,6 +4080,11 @@ const char *cmTarget::GetProperty(const char* prop,
return 0;
}
+ if (strcmp(prop, "NAME") == 0)
+ {
+ return this->GetName();
+ }
+
// Watch for special "computed" properties that are dependent on
// other properties or variables. Always recompute them.
if(this->GetType() == cmTarget::EXECUTABLE ||
@@ -6248,7 +6277,7 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
// Get the link languages.
- if(this->GetType() == cmTarget::STATIC_LIBRARY)
+ if(this->LinkLanguagePropagatesToDependents())
{
std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES";
linkProp += suffix;
@@ -6474,6 +6503,15 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
break;
}
}
+ else
+ {
+ iface.Libraries = impl->Libraries;
+ if(this->LinkLanguagePropagatesToDependents())
+ {
+ // Targets using this archive need its language runtime libraries.
+ iface.Languages = impl->Languages;
+ }
+ }
}
}
@@ -6502,7 +6540,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
headTarget,
this, &dagChecker), iface.Libraries);
- if(this->GetType() == cmTarget::SHARED_LIBRARY)
+ if(this->GetType() == cmTarget::SHARED_LIBRARY
+ || this->GetType() == cmTarget::STATIC_LIBRARY)
{
// Shared libraries may have runtime implementation dependencies
// on other shared libraries that are not in the interface.
@@ -6536,6 +6575,11 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
}
}
}
+ if(this->LinkLanguagePropagatesToDependents())
+ {
+ // Targets using this archive need its language runtime libraries.
+ iface.Languages = impl->Languages;
+ }
}
}
else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN
@@ -6550,7 +6594,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
iface.ImplementationIsInterface = true;
iface.Libraries = impl->Libraries;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
- if(this->GetType() == cmTarget::STATIC_LIBRARY)
+ if(this->LinkLanguagePropagatesToDependents())
{
// Targets using this archive need its language runtime libraries.
iface.Languages = impl->Languages;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 24a71ed..27b74ca 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -549,6 +549,9 @@ public:
void FinalizeSystemIncludeDirectories();
+ bool LinkLanguagePropagatesToDependents() const
+ { return this->TargetTypeValue == STATIC_LIBRARY; }
+
private:
// The set of include directories that are marked as system include
// directories.
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 0ee9420..863b391 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -31,6 +31,11 @@ bool cmTargetLinkLibrariesCommand
return false;
}
+ if (this->Makefile->IsAlias(args[0].c_str()))
+ {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
// Lookup the target for which libraries are specified.
this->Target =
this->Makefile->GetCMakeInstance()
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 287ce46..1862cb6 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -19,13 +19,18 @@ bool cmTargetPropCommandBase
::HandleArguments(std::vector<std::string> const& args, const char *prop,
ArgumentFlags flags)
{
- if(args.size() < 3)
+ if(args.size() < 2)
{
this->SetError("called with incorrect number of arguments");
return false;
}
// Lookup the target for which libraries are specified.
+ if (this->Makefile->IsAlias(args[0].c_str()))
+ {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
this->Target =
this->Makefile->GetCMakeInstance()
->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
@@ -53,7 +58,7 @@ bool cmTargetPropCommandBase
if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM")
{
- if (args.size() < 4)
+ if (args.size() < 3)
{
this->SetError("called with incorrect number of arguments");
return false;
@@ -65,7 +70,7 @@ bool cmTargetPropCommandBase
bool prepend = false;
if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE")
{
- if (args.size() < 4)
+ if (args.size() < 3)
{
this->SetError("called with incorrect number of arguments");
return false;
diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index 3905e9b..8ad6fce 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -37,37 +37,63 @@ cmVariableWatch::cmVariableWatch()
cmVariableWatch::~cmVariableWatch()
{
+ cmVariableWatch::StringToVectorOfPairs::iterator svp_it;
+
+ for ( svp_it = this->WatchMap.begin();
+ svp_it != this->WatchMap.end(); ++svp_it )
+ {
+ cmVariableWatch::VectorOfPairs::iterator p_it;
+
+ for ( p_it = svp_it->second.begin();
+ p_it != svp_it->second.end(); ++p_it )
+ {
+ delete *p_it;
+ }
+ }
}
-void cmVariableWatch::AddWatch(const std::string& variable,
- WatchMethod method, void* client_data /*=0*/)
+bool cmVariableWatch::AddWatch(const std::string& variable,
+ WatchMethod method, void* client_data /*=0*/,
+ DeleteData delete_data /*=0*/)
{
- cmVariableWatch::Pair p;
- p.Method = method;
- p.ClientData = client_data;
+ cmVariableWatch::Pair* p = new cmVariableWatch::Pair;
+ p->Method = method;
+ p->ClientData = client_data;
+ p->DeleteDataCall = delete_data;
cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
cmVariableWatch::VectorOfPairs::size_type cc;
for ( cc = 0; cc < vp->size(); cc ++ )
{
- cmVariableWatch::Pair* pair = &(*vp)[cc];
- if ( pair->Method == method )
+ cmVariableWatch::Pair* pair = (*vp)[cc];
+ if ( pair->Method == method &&
+ client_data && client_data == pair->ClientData)
{
- (*vp)[cc] = p;
- return;
+ // Callback already exists
+ return false;
}
}
vp->push_back(p);
+ return true;
}
void cmVariableWatch::RemoveWatch(const std::string& variable,
- WatchMethod method)
+ WatchMethod method,
+ void* client_data /*=0*/)
{
+ if ( !this->WatchMap.count(variable) )
+ {
+ return;
+ }
cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
cmVariableWatch::VectorOfPairs::iterator it;
for ( it = vp->begin(); it != vp->end(); ++it )
{
- if ( it->Method == method )
+ if ( (*it)->Method == method &&
+ // If client_data is NULL, we want to disconnect all watches against
+ // the given method; otherwise match ClientData as well.
+ (!client_data || (client_data == (*it)->ClientData)))
{
+ delete *it;
vp->erase(it);
return;
}
@@ -87,7 +113,7 @@ void cmVariableWatch::VariableAccessed(const std::string& variable,
cmVariableWatch::VectorOfPairs::const_iterator it;
for ( it = vp->begin(); it != vp->end(); it ++ )
{
- it->Method(variable, access_type, it->ClientData,
+ (*it)->Method(variable, access_type, (*it)->ClientData,
newValue, mf);
}
}
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index 7dd4ac5..790c75a 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -26,6 +26,7 @@ class cmVariableWatch
public:
typedef void (*WatchMethod)(const std::string& variable, int access_type,
void* client_data, const char* newValue, const cmMakefile* mf);
+ typedef void (*DeleteData)(void* client_data);
cmVariableWatch();
~cmVariableWatch();
@@ -33,9 +34,10 @@ public:
/**
* Add watch to the variable
*/
- void AddWatch(const std::string& variable, WatchMethod method,
- void* client_data=0);
- void RemoveWatch(const std::string& variable, WatchMethod method);
+ bool AddWatch(const std::string& variable, WatchMethod method,
+ void* client_data=0, DeleteData delete_data=0);
+ void RemoveWatch(const std::string& variable, WatchMethod method,
+ void* client_data=0);
/**
* This method is called when variable is accessed
@@ -67,10 +69,18 @@ protected:
{
WatchMethod Method;
void* ClientData;
- Pair() : Method(0), ClientData(0) {}
+ DeleteData DeleteDataCall;
+ Pair() : Method(0), ClientData(0), DeleteDataCall(0) {}
+ ~Pair()
+ {
+ if (this->DeleteDataCall && this->ClientData)
+ {
+ this->DeleteDataCall(this->ClientData);
+ }
+ }
};
- typedef std::vector< Pair > VectorOfPairs;
+ typedef std::vector< Pair* > VectorOfPairs;
typedef std::map<cmStdString, VectorOfPairs > StringToVectorOfPairs;
StringToVectorOfPairs WatchMap;
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 297a92b..33e159b 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -14,63 +14,27 @@
#include "cmVariableWatch.h"
//----------------------------------------------------------------------------
-static void cmVariableWatchCommandVariableAccessed(
- const std::string& variable, int access_type, void* client_data,
- const char* newValue, const cmMakefile* mf)
+struct cmVariableWatchCallbackData
{
- cmVariableWatchCommand* command
- = static_cast<cmVariableWatchCommand*>(client_data);
- command->VariableAccessed(variable, access_type, newValue, mf);
-}
+ bool InCallback;
+ std::string Command;
+};
//----------------------------------------------------------------------------
-cmVariableWatchCommand::cmVariableWatchCommand()
+static void cmVariableWatchCommandVariableAccessed(
+ const std::string& variable, int access_type, void* client_data,
+ const char* newValue, const cmMakefile* mf)
{
- this->InCallback = false;
-}
+ cmVariableWatchCallbackData* data
+ = static_cast<cmVariableWatchCallbackData*>(client_data);
-//----------------------------------------------------------------------------
-bool cmVariableWatchCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
-{
- if ( args.size() < 1 )
- {
- this->SetError("must be called with at least one argument.");
- return false;
- }
- std::string variable = args[0];
- if ( args.size() > 1 )
- {
- std::string command = args[1];
- this->Handlers[variable].Commands.push_back(args[1]);
- }
- if ( variable == "CMAKE_CURRENT_LIST_FILE" )
- {
- cmOStringStream ostr;
- ostr << "cannot be set on the variable: " << variable.c_str();
- this->SetError(ostr.str().c_str());
- return false;
- }
-
- this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
- variable, cmVariableWatchCommandVariableAccessed, this);
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
- int access_type, const char* newValue, const cmMakefile* mf)
-{
- if ( this->InCallback )
+ if ( data->InCallback )
{
return;
}
- this->InCallback = true;
+ data->InCallback = true;
cmListFileFunction newLFF;
- cmVariableWatchCommandHandler *handler = &this->Handlers[variable];
- cmVariableWatchCommandHandler::VectorOfCommands::iterator it;
cmListFileArgument arg;
bool processed = false;
const char* accessString = cmVariableWatch::GetAccessAsString(access_type);
@@ -80,22 +44,25 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
cmMakefile* makefile = const_cast<cmMakefile*>(mf);
std::string stack = makefile->GetProperty("LISTFILE_STACK");
- for ( it = handler->Commands.begin(); it != handler->Commands.end();
- ++ it )
+ if ( !data->Command.empty() )
{
- std::string command = *it;
newLFF.Arguments.clear();
newLFF.Arguments.push_back(
- cmListFileArgument(variable, true, "unknown", 9999));
+ cmListFileArgument(variable, cmListFileArgument::Quoted,
+ "unknown", 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(accessString, true, "unknown", 9999));
+ cmListFileArgument(accessString, cmListFileArgument::Quoted,
+ "unknown", 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(newValue?newValue:"", true, "unknown", 9999));
+ cmListFileArgument(newValue?newValue:"", cmListFileArgument::Quoted,
+ "unknown", 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(currentListFile, true, "unknown", 9999));
+ cmListFileArgument(currentListFile, cmListFileArgument::Quoted,
+ "unknown", 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(stack, true, "unknown", 9999));
- newLFF.Name = command;
+ cmListFileArgument(stack, cmListFileArgument::Quoted,
+ "unknown", 9999));
+ newLFF.Name = data->Command;
newLFF.FilePath = "Some weird path";
newLFF.Line = 9999;
cmExecutionStatus status;
@@ -106,10 +73,10 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
cmOStringStream error;
error << "Error in cmake code at\n"
<< arg.FilePath << ":" << arg.Line << ":\n"
- << "A command failed during the invocation of callback\""
- << command << "\".";
+ << "A command failed during the invocation of callback \""
+ << data->Command << "\".";
cmSystemTools::Error(error.str().c_str());
- this->InCallback = false;
+ data->InCallback = false;
return;
}
processed = true;
@@ -118,8 +85,75 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
{
cmOStringStream msg;
msg << "Variable \"" << variable.c_str() << "\" was accessed using "
- << accessString << " with value \"" << newValue << "\".";
+ << accessString << " with value \"" << (newValue?newValue:"") << "\".";
makefile->IssueMessage(cmake::LOG, msg.str());
}
- this->InCallback = false;
+
+ data->InCallback = false;
+}
+
+//----------------------------------------------------------------------------
+static void deleteVariableWatchCallbackData(void* client_data)
+{
+ cmVariableWatchCallbackData* data
+ = static_cast<cmVariableWatchCallbackData*>(client_data);
+ delete data;
+}
+
+//----------------------------------------------------------------------------
+cmVariableWatchCommand::cmVariableWatchCommand()
+{
+}
+
+//----------------------------------------------------------------------------
+cmVariableWatchCommand::~cmVariableWatchCommand()
+{
+ std::set<std::string>::const_iterator it;
+ for ( it = this->WatchedVariables.begin();
+ it != this->WatchedVariables.end();
+ ++it )
+ {
+ this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
+ *it, cmVariableWatchCommandVariableAccessed);
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmVariableWatchCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+ if ( args.size() < 1 )
+ {
+ this->SetError("must be called with at least one argument.");
+ return false;
+ }
+ std::string variable = args[0];
+ std::string command;
+ if ( args.size() > 1 )
+ {
+ command = args[1];
+ }
+ if ( variable == "CMAKE_CURRENT_LIST_FILE" )
+ {
+ cmOStringStream ostr;
+ ostr << "cannot be set on the variable: " << variable.c_str();
+ this->SetError(ostr.str().c_str());
+ return false;
+ }
+
+ cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;
+
+ data->InCallback = false;
+ data->Command = command;
+
+ this->WatchedVariables.insert(variable);
+ if ( !this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
+ variable, cmVariableWatchCommandVariableAccessed,
+ data, deleteVariableWatchCallbackData) )
+ {
+ deleteVariableWatchCallbackData(data);
+ return false;
+ }
+
+ return true;
}
diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h
index 3abc088..545535c 100644
--- a/Source/cmVariableWatchCommand.h
+++ b/Source/cmVariableWatchCommand.h
@@ -14,13 +14,6 @@
#include "cmCommand.h"
-class cmVariableWatchCommandHandler
-{
-public:
- typedef std::vector<std::string> VectorOfCommands;
- VectorOfCommands Commands;
-};
-
/** \class cmVariableWatchCommand
* \brief Watch when the variable changes and invoke command
*
@@ -39,6 +32,9 @@ public:
//! Default constructor
cmVariableWatchCommand();
+ //! Destructor.
+ ~cmVariableWatchCommand();
+
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
@@ -83,13 +79,8 @@ public:
cmTypeMacro(cmVariableWatchCommand, cmCommand);
- void VariableAccessed(const std::string& variable, int access_type,
- const char* newValue, const cmMakefile* mf);
-
protected:
- std::map<std::string, cmVariableWatchCommandHandler> Handlers;
-
- bool InCallback;
+ std::set<std::string> WatchedVariables;
};
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index d59de11..ea05347 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -307,6 +307,11 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WriteString(
"<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n", 1);
this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
+ if (this->GlobalGenerator->IsMasmEnabled())
+ {
+ this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
+ "BuildCustomizations\\masm.props\" />\n", 2);
+ }
this->WriteString("</ImportGroup>\n", 1);
this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1);
this->WriteString("<Import Project=\"" VS10_USER_PROPS "\""
@@ -326,6 +331,11 @@ void cmVisualStudio10TargetGenerator::Generate()
"<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\""
" />\n", 1);
this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
+ if (this->GlobalGenerator->IsMasmEnabled())
+ {
+ this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
+ "BuildCustomizations\\masm.targets\" />\n", 2);
+ }
this->WriteString("</ImportGroup>\n", 1);
this->WriteString("</Project>", 0);
// The groups are stored in a separate file for VS 10
@@ -982,24 +992,37 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
si != this->GeneratorTarget->ObjectSources.end(); ++si)
{
const char* lang = (*si)->GetLanguage();
- bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0;
- bool rc = strcmp(lang, "RC") == 0;
- const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None");
- this->WriteSource(tool, *si, " ");
- // ouput any flags specific to this source file
- if(cl && this->OutputSourceSpecificFlags(*si))
+ const char* tool = NULL;
+ if (strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0)
+ {
+ tool = "ClCompile";
+ }
+ else if (strcmp(lang, "ASM_MASM") == 0 &&
+ this->GlobalGenerator->IsMasmEnabled())
+ {
+ tool = "MASM";
+ }
+ else if (strcmp(lang, "RC") == 0)
{
- // if the source file has specific flags the tag
- // is ended on a new line
- this->WriteString("</ClCompile>\n", 2);
+ tool = "ResourceCompile";
}
- else if(rc && this->OutputSourceSpecificFlags(*si))
+
+ if (tool)
{
- this->WriteString("</ResourceCompile>\n", 2);
+ this->WriteSource(tool, *si, " ");
+ if (this->OutputSourceSpecificFlags(*si))
+ {
+ this->WriteString("</", 2);
+ (*this->BuildFileStream ) << tool << ">\n";
+ }
+ else
+ {
+ (*this->BuildFileStream ) << " />\n";
+ }
}
else
{
- (*this->BuildFileStream ) << " />\n";
+ this->WriteSource("None", *si);
}
}
@@ -1389,7 +1412,7 @@ OutputIncludes(std::vector<std::string> const & includes)
for(std::vector<std::string>::const_iterator i = includes.begin();
i != includes.end(); ++i)
{
- *this->BuildFileStream << *i << ";";
+ *this->BuildFileStream << cmVS10EscapeXML(*i) << ";";
}
this->WriteString("%(AdditionalIncludeDirectories)"
"</AdditionalIncludeDirectories>\n", 0);
@@ -1417,20 +1440,17 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config)
{
return;
}
- const char* libflags = this->Target->GetProperty("STATIC_LIBRARY_FLAGS");
- std::string flagsConfigVar = "STATIC_LIBRARY_FLAGS_";
- flagsConfigVar += cmSystemTools::UpperCase(config);
- const char* libflagsConfig =
- this->Target->GetProperty(flagsConfigVar.c_str());
- if(libflags || libflagsConfig)
+ std::string libflags;
+ this->LocalGenerator->GetStaticLibraryFlags(libflags,
+ cmSystemTools::UpperCase(config), this->Target);
+ if(!libflags.empty())
{
this->WriteString("<Lib>\n", 2);
cmVisualStudioGeneratorOptions
libOptions(this->LocalGenerator,
cmVisualStudioGeneratorOptions::Linker,
cmVSGetLibFlagTable(this->LocalGenerator), 0, this);
- libOptions.Parse(libflags?libflags:"");
- libOptions.Parse(libflagsConfig?libflagsConfig:"");
+ libOptions.Parse(libflags.c_str());
libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
libOptions.OutputFlagMap(*this->BuildFileStream, " ");
this->WriteString("</Lib>\n", 2);
@@ -1523,11 +1543,11 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
}
if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") )
{
- flags += " /SUBSYSTEM:WINDOWS";
+ linkOptions.AddFlag("SubSystem", "Windows");
}
else
{
- flags += " /SUBSYSTEM:CONSOLE";
+ linkOptions.AddFlag("SubSystem", "Console");
}
std::string standardLibsVar = "CMAKE_";
standardLibsVar += linkLanguage;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index f4df1a9..6aca787 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -100,13 +100,13 @@ void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose)
}
}
-bool cmVisualStudioGeneratorOptions::IsDebug()
+bool cmVisualStudioGeneratorOptions::IsDebug() const
{
return this->FlagMap.find("DebugInformationFormat") != this->FlagMap.end();
}
//----------------------------------------------------------------------------
-bool cmVisualStudioGeneratorOptions::UsingUnicode()
+bool cmVisualStudioGeneratorOptions::UsingUnicode() const
{
// Look for the a _UNICODE definition.
for(std::vector<std::string>::const_iterator di = this->Defines.begin();
@@ -120,7 +120,7 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode()
return false;
}
//----------------------------------------------------------------------------
-bool cmVisualStudioGeneratorOptions::UsingSBCS()
+bool cmVisualStudioGeneratorOptions::UsingSBCS() const
{
// Look for the a _SBCS definition.
for(std::vector<std::string>::const_iterator di = this->Defines.begin();
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index a1a55da..90f7667 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -47,10 +47,10 @@ public:
void SetVerboseMakefile(bool verbose);
// Check for specific options.
- bool UsingUnicode();
- bool UsingSBCS();
+ bool UsingUnicode() const;
+ bool UsingSBCS() const;
- bool IsDebug();
+ bool IsDebug() const;
// Write options to output.
void OutputPreprocessorDefinitions(std::ostream& fout,
const char* prefix,
diff --git a/Source/cmVisualStudioWCEPlatformParser.cxx b/Source/cmVisualStudioWCEPlatformParser.cxx
index b302246..219a5eb 100644
--- a/Source/cmVisualStudioWCEPlatformParser.cxx
+++ b/Source/cmVisualStudioWCEPlatformParser.cxx
@@ -20,8 +20,12 @@ int cmVisualStudioWCEPlatformParser::ParseVersion(const char* version)
const std::string vckey = registryBase + "\\Setup\\VC;ProductDir";
const std::string vskey = registryBase + "\\Setup\\VS;ProductDir";
- if(!cmSystemTools::ReadRegistryValue(vckey.c_str(), this->VcInstallDir) ||
- !cmSystemTools::ReadRegistryValue(vskey.c_str(), this->VsInstallDir))
+ if(!cmSystemTools::ReadRegistryValue(vckey.c_str(),
+ this->VcInstallDir,
+ cmSystemTools::KeyWOW64_32) ||
+ !cmSystemTools::ReadRegistryValue(vskey.c_str(),
+ this->VsInstallDir,
+ cmSystemTools::KeyWOW64_32))
{
return 0;
}
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index 4000345..7d2eead 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -49,9 +49,9 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
unsigned int i;
for(i =0; i < this->Args.size(); ++i)
{
- err += (this->Args[i].Quoted?"\"":"");
+ err += (this->Args[i].Delim?"\"":"");
err += this->Args[i].Value;
- err += (this->Args[i].Quoted?"\"":"");
+ err += (this->Args[i].Delim?"\"":"");
err += " ";
}
err += "(";
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 77a5e43..68d8339 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -62,7 +62,10 @@ static const char * cmDocumentationDescription[][3] =
" --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
" --clean-first = Build target 'clean' first, then build.\n" \
" (To clean only, use --target 'clean'.)\n" \
- " --use-stderr = Don't merge stdout/stderr.\n" \
+ " --use-stderr = Don't merge stdout/stderr output and pass the\n" \
+ " original stdout/stderr handles to the native\n" \
+ " tool so it can use the capabilities of the\n" \
+ " calling terminal (e.g. colored output).\n" \
" -- = Pass remaining options to the native tool.\n"
//----------------------------------------------------------------------------
@@ -108,9 +111,11 @@ static const char * cmDocumentationOptions[][3] =
"to stdout. This can be used to use cmake instead of pkg-config to find "
"installed libraries in plain Makefile-based projects or in "
"autoconf-based projects (via share/aclocal/cmake.m4)."},
- {"--graphviz=[file]", "Generate graphviz of dependencies.",
+ {"--graphviz=[file]", "Generate graphviz of dependencies, see "
+ "CMakeGraphVizOptions.cmake for more.",
"Generate a graphviz input file that will contain all the library and "
- "executable dependencies in the project."},
+ "executable dependencies in the project. See the documentation for "
+ "CMakeGraphVizOptions.cmake for more details. "},
{"--system-information [file]", "Dump information about this system.",
"Dump a wide range of information about the current system. If run "
"from the top of a binary tree for a CMake project it will dump "
@@ -604,7 +609,7 @@ static int do_build(int ac, char** av)
}
else if(strcmp(av[i], "--use-stderr") == 0)
{
- outputflag = cmSystemTools::OUTPUT_NORMAL;
+ outputflag = cmSystemTools::OUTPUT_PASSTHROUGH;
}
else if(strcmp(av[i], "--") == 0)
{
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 262d83b..8571557 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -62,8 +62,8 @@ static std::string trimLeadingSpace(const std::string& cmdline) {
return cmdline.substr(i);
}
-static void doEscape(std::string& str, const std::string& search,
- const std::string& repl) {
+static void replaceAll(std::string& str, const std::string& search,
+ const std::string& repl) {
std::string::size_type pos = 0;
while ((pos = str.find(search, pos)) != std::string::npos) {
str.replace(pos, search.size(), repl);
@@ -71,6 +71,10 @@ static void doEscape(std::string& str, const std::string& search,
}
}
+bool startsWith(const std::string& str, const std::string& what) {
+ return str.compare(0, what.size(), what) == 0;
+}
+
// Strips one argument from the cmdline and returns it. "surrounding quotes"
// are removed from the argument if there were any.
static std::string getArg(std::string& cmdline) {
@@ -117,6 +121,13 @@ static void parseCommandLine(LPTSTR wincmdline,
rest = trimLeadingSpace(cmdline);
}
+// Not all backslashes need to be escaped in a depfile, but it's easier that
+// way. See the re2c grammar in ninja's source code for more info.
+static void escapePath(std::string &path) {
+ replaceAll(path, "\\", "\\\\");
+ replaceAll(path, " ", "\\ ");
+}
+
static void outputDepFile(const std::string& dfile, const std::string& objfile,
std::vector<std::string>& incs) {
@@ -132,16 +143,24 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile,
// FIXME should this be fatal or not? delete obj? delete d?
if (!out)
return;
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ replaceAll(cwd, "/", "\\");
+ cwd += "\\";
std::string tmp = objfile;
- doEscape(tmp, " ", "\\ ");
+ escapePath(tmp);
fprintf(out, "%s: \\\n", tmp.c_str());
std::vector<std::string>::iterator it = incs.begin();
for (; it != incs.end(); ++it) {
tmp = *it;
- doEscape(tmp, "\\", "/");
- doEscape(tmp, " ", "\\ ");
+ // The paths need to match the ones used to identify build artifacts in the
+ // build.ninja file. Therefore we need to canonicalize the path to use
+ // backward slashes and relativize the path to the build directory.
+ replaceAll(tmp, "/", "\\");
+ if (startsWith(tmp, cwd))
+ tmp = tmp.substr(cwd.size());
+ escapePath(tmp);
fprintf(out, "%s \\\n", tmp.c_str());
}
@@ -150,10 +169,6 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile,
}
-bool startsWith(const std::string& str, const std::string& what) {
- return str.compare(0, what.size(), what) == 0;
-}
-
bool contains(const std::string& str, const std::string& what) {
return str.find(what) != std::string::npos;
}
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 6f0281d..0f27836 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -649,6 +649,68 @@ IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1)
ENDIF()
+ IF(UNIX)
+ INCLUDE(CheckIncludeFileCXX)
+ # check for simple stack trace
+ # usually it's in libc but on FreeBSD
+ # it's in libexecinfo
+ FIND_LIBRARY(EXECINFO_LIB "execinfo")
+ IF (NOT EXECINFO_LIB)
+ SET(EXECINFO_LIB "")
+ ENDIF()
+ CHECK_INCLUDE_FILE_CXX("execinfo.h" KWSYS_CXX_HAS_EXECINFOH)
+ IF (KWSYS_CXX_HAS_EXECINFOH)
+ # we have the backtrace header check if it
+ # can be used with this compiler
+ SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${EXECINFO_LIB})
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BACKTRACE
+ "Checking whether backtrace works with this C++ compiler" DIRECT)
+ SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES)
+ IF (KWSYS_CXX_HAS_BACKTRACE)
+ # backtrace is supported by this system and compiler.
+ # now check for the more advanced capabilities.
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE=1)
+ # check for symbol lookup using dladdr
+ CHECK_INCLUDE_FILE_CXX("dlfcn.h" KWSYS_CXX_HAS_DLFCNH)
+ IF (KWSYS_CXX_HAS_DLFCNH)
+ # we have symbol lookup libraries and headers
+ # check if they can be used with this compiler
+ SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${CMAKE_DL_LIBS})
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_DLADDR
+ "Checking whether dladdr works with this C++ compiler" DIRECT)
+ SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES)
+ IF (KWSYS_CXX_HAS_DLADDR)
+ # symbol lookup is supported by this system
+ # and compiler.
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP=1)
+ ENDIF()
+ ENDIF()
+ # c++ demangling support
+ # check for cxxabi headers
+ CHECK_INCLUDE_FILE_CXX("cxxabi.h" KWSYS_CXX_HAS_CXXABIH)
+ IF (KWSYS_CXX_HAS_CXXABIH)
+ # check if cxxabi can be used with this
+ # system and compiler.
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CXXABI
+ "Checking whether cxxabi works with this C++ compiler" DIRECT)
+ IF (KWSYS_CXX_HAS_CXXABI)
+ # c++ demangle using cxxabi is supported with
+ # this system and compiler
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE=1)
+ ENDIF()
+ ENDIF()
+ # basic backtrace works better with release build
+ # don't bother with advanced features for release
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS_DEBUG KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS_RELWITHDEBINFO KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1)
+ ENDIF()
+ ENDIF()
+ ENDIF()
IF(BORLAND)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM
"Checking whether Borland CXX compiler supports assembler instructions" DIRECT)
@@ -913,12 +975,23 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
ENDIF(UNIX)
ENDIF(KWSYS_USE_DynamicLoader)
- IF(KWSYS_USE_SystemInformation AND WIN32)
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32)
- IF(KWSYS_SYS_HAS_PSAPI)
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi)
+ IF(KWSYS_USE_SystemInformation)
+ IF(WIN32)
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32)
+ IF(KWSYS_SYS_HAS_PSAPI)
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi)
+ ENDIF()
+ ELSEIF(UNIX)
+ IF (EXECINFO_LIB AND KWSYS_CXX_HAS_BACKTRACE)
+ # backtrace on FreeBSD is not in libc
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${EXECINFO_LIB})
+ ENDIF()
+ IF (KWSYS_CXX_HAS_DLADDR)
+ # for symbol lookup using dladdr
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS})
+ ENDIF()
ENDIF()
- ENDIF(KWSYS_USE_SystemInformation AND WIN32)
+ ENDIF()
# Apply user-defined target properties to the library.
IF(KWSYS_PROPERTIES_CXX)
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 9db1dee..beefd7d 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -18,6 +18,10 @@
# include <winsock.h> // WSADATA, include before sys/types.h
#endif
+#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+#endif
+
// TODO:
// We need an alternative implementation for many functions in this file
// when USE_ASM_INSTRUCTIONS gets defined as 0.
@@ -114,8 +118,15 @@ typedef int siginfo_t;
# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
# endif
# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050
-# include <execinfo.h>
-# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+# include <execinfo.h>
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# include <cxxabi.h>
+# endif
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# include <dlfcn.h>
+# endif
+# endif
# endif
#endif
@@ -130,10 +141,13 @@ typedef int siginfo_t;
# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
# endif
# endif
-# if defined(__GNUC__)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
# include <execinfo.h>
-# if !(defined(__LSB_VERSION__) && __LSB_VERSION__ < 41)
-# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# include <cxxabi.h>
+# endif
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# include <dlfcn.h>
# endif
# endif
# if defined(KWSYS_CXX_HAS_RLIMIT64)
@@ -357,6 +371,10 @@ public:
static
void SetStackTraceOnError(int enable);
+ // get current stack
+ static
+ kwsys_stl::string GetProgramStack(int firstFrame, int wholePath);
+
/** Run the different checks */
void RunCPUCheck();
void RunOSCheck();
@@ -812,6 +830,11 @@ void SystemInformation::SetStackTraceOnError(int enable)
SystemInformationImplementation::SetStackTraceOnError(enable);
}
+kwsys_stl::string SystemInformation::GetProgramStack(int firstFrame, int wholePath)
+{
+ return SystemInformationImplementation::GetProgramStack(firstFrame, wholePath);
+}
+
/** Run the different checks */
void SystemInformation::RunCPUCheck()
{
@@ -908,6 +931,12 @@ int LoadLines(
}
continue;
}
+ char *pBuf=buf;
+ while(*pBuf)
+ {
+ if (*pBuf=='\n') *pBuf='\0';
+ pBuf+=1;
+ }
lines.push_back(buf);
++nRead;
}
@@ -1046,12 +1075,29 @@ void StacktraceSignalHandler(
#if defined(__linux) || defined(__APPLE__)
kwsys_ios::ostringstream oss;
oss
+ << kwsys_ios::endl
<< "=========================================================" << kwsys_ios::endl
<< "Process id " << getpid() << " ";
switch (sigNo)
{
+ case SIGINT:
+ oss << "Caught SIGINT";
+ break;
+
+ case SIGTERM:
+ oss << "Caught SIGTERM";
+ break;
+
+ case SIGABRT:
+ oss << "Caught SIGABRT";
+ break;
+
case SIGFPE:
- oss << "Caught SIGFPE ";
+ oss
+ << "Caught SIGFPE at "
+ << (sigInfo->si_addr==0?"0x":"")
+ << sigInfo->si_addr
+ << " ";
switch (sigInfo->si_code)
{
# if defined(FPE_INTDIV)
@@ -1099,7 +1145,11 @@ void StacktraceSignalHandler(
break;
case SIGSEGV:
- oss << "Caught SIGSEGV ";
+ oss
+ << "Caught SIGSEGV at "
+ << (sigInfo->si_addr==0?"0x":"")
+ << sigInfo->si_addr
+ << " ";
switch (sigInfo->si_code)
{
case SEGV_MAPERR:
@@ -1116,16 +1166,12 @@ void StacktraceSignalHandler(
}
break;
- case SIGINT:
- oss << "Caught SIGTERM";
- break;
-
- case SIGTERM:
- oss << "Caught SIGTERM";
- break;
-
case SIGBUS:
- oss << "Caught SIGBUS type ";
+ oss
+ << "Caught SIGBUS at "
+ << (sigInfo->si_addr==0?"0x":"")
+ << sigInfo->si_addr
+ << " ";
switch (sigInfo->si_code)
{
case BUS_ADRALN:
@@ -1134,13 +1180,25 @@ void StacktraceSignalHandler(
# if defined(BUS_ADRERR)
case BUS_ADRERR:
- oss << "non-exestent physical address";
+ oss << "nonexistent physical address";
break;
# endif
# if defined(BUS_OBJERR)
case BUS_OBJERR:
- oss << "object specific hardware error";
+ oss << "object-specific hardware error";
+ break;
+# endif
+
+# if defined(BUS_MCEERR_AR)
+ case BUS_MCEERR_AR:
+ oss << "Hardware memory error consumed on a machine check; action required.";
+ break;
+# endif
+
+# if defined(BUS_MCEERR_AO)
+ case BUS_MCEERR_AO:
+ oss << "Hardware memory error detected in process but not consumed; action optional.";
break;
# endif
@@ -1151,7 +1209,11 @@ void StacktraceSignalHandler(
break;
case SIGILL:
- oss << "Caught SIGILL ";
+ oss
+ << "Caught SIGILL at "
+ << (sigInfo->si_addr==0?"0x":"")
+ << sigInfo->si_addr
+ << " ";
switch (sigInfo->si_code)
{
case ILL_ILLOPC:
@@ -1205,20 +1267,16 @@ void StacktraceSignalHandler(
oss << "Caught " << sigNo << " code " << sigInfo->si_code;
break;
}
- oss << kwsys_ios::endl;
-#if defined(KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE)
- oss << "Program Stack:" << kwsys_ios::endl;
- void *stackSymbols[128];
- int n=backtrace(stackSymbols,128);
- char **stackText=backtrace_symbols(stackSymbols,n);
- for (int i=0; i<n; ++i)
- {
- oss << " " << stackText[i] << kwsys_ios::endl;
- }
-#endif
oss
- << "=========================================================" << kwsys_ios::endl;
+ << kwsys_ios::endl
+ << "Program Stack:" << kwsys_ios::endl
+ << SystemInformationImplementation::GetProgramStack(2,0)
+ << "=========================================================" << kwsys_ios::endl;
kwsys_ios::cerr << oss.str() << kwsys_ios::endl;
+
+ // restore the previously registered handlers
+ // and abort
+ SystemInformationImplementation::SetStackTraceOnError(0);
abort();
#else
// avoid warning C4100
@@ -1227,8 +1285,213 @@ void StacktraceSignalHandler(
#endif
}
#endif
+
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+#define safes(_arg)((_arg)?(_arg):"???")
+
+// Description:
+// A container for symbol properties. Each instance
+// must be Initialized.
+class SymbolProperties
+{
+public:
+ SymbolProperties();
+
+ // Description:
+ // The SymbolProperties instance must be initialized by
+ // passing a stack address.
+ void Initialize(void *address);
+
+ // Description:
+ // Get the symbol's stack address.
+ void *GetAddress() const { return this->Address; }
+
+ // Description:
+ // If not set paths will be removed. eg, from a binary
+ // or source file.
+ void SetReportPath(int rp){ this->ReportPath=rp; }
+
+ // Description:
+ // Set/Get the name of the binary file that the symbol
+ // is found in.
+ void SetBinary(const char *binary)
+ { this->Binary=safes(binary); }
+
+ kwsys_stl::string GetBinary() const;
+
+ // Description:
+ // Set the name of the function that the symbol is found in.
+ // If c++ demangling is supported it will be demangled.
+ void SetFunction(const char *function)
+ { this->Function=this->Demangle(function); }
+
+ kwsys_stl::string GetFunction() const
+ { return this->Function; }
+
+ // Description:
+ // Set/Get the name of the source file where the symbol
+ // is defined.
+ void SetSourceFile(const char *sourcefile)
+ { this->SourceFile=safes(sourcefile); }
+
+ kwsys_stl::string GetSourceFile() const
+ { return this->GetFileName(this->SourceFile); }
+
+ // Description:
+ // Set/Get the line number where the symbol is defined
+ void SetLineNumber(long linenumber){ this->LineNumber=linenumber; }
+ long GetLineNumber() const { return this->LineNumber; }
+
+ // Description:
+ // Set the address where the biinary image is mapped
+ // into memory.
+ void SetBinaryBaseAddress(void *address)
+ { this->BinaryBaseAddress=address; }
+
+private:
+ void *GetRealAddress() const
+ { return (void*)((char*)this->Address-(char*)this->BinaryBaseAddress); }
+
+ kwsys_stl::string GetFileName(const kwsys_stl::string &path) const;
+ kwsys_stl::string Demangle(const char *symbol) const;
+
+private:
+ kwsys_stl::string Binary;
+ void *BinaryBaseAddress;
+ void *Address;
+ kwsys_stl::string SourceFile;
+ kwsys_stl::string Function;
+ long LineNumber;
+ int ReportPath;
+};
+
+// --------------------------------------------------------------------------
+kwsys_ios::ostream &operator<<(
+ kwsys_ios::ostream &os,
+ const SymbolProperties &sp)
+{
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+ os
+ << kwsys_ios::hex << sp.GetAddress() << " : "
+ << sp.GetFunction()
+ << " [(" << sp.GetBinary() << ") "
+ << sp.GetSourceFile() << ":"
+ << kwsys_ios::dec << sp.GetLineNumber() << "]";
+#elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+ void *addr = sp.GetAddress();
+ char **syminfo = backtrace_symbols(&addr,1);
+ os << safes(syminfo[0]);
+ free(syminfo);
+#else
+ (void)os;
+ (void)sp;
+#endif
+ return os;
+}
+
+// --------------------------------------------------------------------------
+SymbolProperties::SymbolProperties()
+{
+ // not using an initializer list
+ // to avoid some PGI compiler warnings
+ this->SetBinary("???");
+ this->SetBinaryBaseAddress(NULL);
+ this->Address = NULL;
+ this->SetSourceFile("???");
+ this->SetFunction("???");
+ this->SetLineNumber(-1);
+ this->SetReportPath(0);
+ // avoid PGI compiler warnings
+ this->GetRealAddress();
+ this->GetFunction();
+ this->GetSourceFile();
+ this->GetLineNumber();
+}
+
+// --------------------------------------------------------------------------
+kwsys_stl::string SymbolProperties::GetFileName(const kwsys_stl::string &path) const
+{
+ kwsys_stl::string file(path);
+ if (!this->ReportPath)
+ {
+ size_t at = file.rfind("/");
+ if (at!=kwsys_stl::string::npos)
+ {
+ file = file.substr(at+1,kwsys_stl::string::npos);
+ }
+ }
+ return file;
+}
+
+// --------------------------------------------------------------------------
+kwsys_stl::string SymbolProperties::GetBinary() const
+{
+// only linux has proc fs
+#if defined(__linux__)
+ if (this->Binary=="/proc/self/exe")
+ {
+ kwsys_stl::string binary;
+ char buf[1024]={'\0'};
+ ssize_t ll=0;
+ if ((ll=readlink("/proc/self/exe",buf,1024))>0)
+ {
+ buf[ll]='\0';
+ binary=buf;
+ }
+ else
+ {
+ binary="/proc/self/exe";
+ }
+ return this->GetFileName(binary);
+ }
+#endif
+ return this->GetFileName(this->Binary);
+}
+
+// --------------------------------------------------------------------------
+kwsys_stl::string SymbolProperties::Demangle(const char *symbol) const
+{
+ kwsys_stl::string result = safes(symbol);
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+ int status = 0;
+ size_t bufferLen = 1024;
+ char *buffer = (char*)malloc(1024);
+ char *demangledSymbol =
+ abi::__cxa_demangle(symbol, buffer, &bufferLen, &status);
+ if (!status)
+ {
+ result = demangledSymbol;
+ }
+ free(buffer);
+#else
+ (void)symbol;
+#endif
+ return result;
+}
+
+// --------------------------------------------------------------------------
+void SymbolProperties::Initialize(void *address)
+{
+ this->Address = address;
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+ // first fallback option can demangle c++ functions
+ Dl_info info;
+ int ierr=dladdr(this->Address,&info);
+ if (ierr && info.dli_sname && info.dli_saddr)
+ {
+ this->SetBinary(info.dli_fname);
+ this->SetFunction(info.dli_sname);
+ }
+#else
+ // second fallback use builtin backtrace_symbols
+ // to decode the bactrace.
+#endif
+}
+#endif // don't define this class if we're not using it
+
} // anonymous namespace
+
SystemInformationImplementation::SystemInformationImplementation()
{
this->TotalVirtualMemory = 0;
@@ -3336,12 +3599,61 @@ SystemInformationImplementation::GetProcessId()
}
/**
+return current program stack in a string
+demangle cxx symbols if possible.
+*/
+kwsys_stl::string SystemInformationImplementation::GetProgramStack(
+ int firstFrame,
+ int wholePath)
+{
+ kwsys_stl::string programStack = ""
+#if !defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+ "WARNING: The stack could not be examined "
+ "because backtrace is not supported.\n"
+#elif !defined(KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD)
+ "WARNING: The stack trace will not use advanced "
+ "capabilities because this is a release build.\n"
+#else
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+ "WARNING: Function names will not be demangled because "
+ "dladdr is not available.\n"
+# endif
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+ "WARNING: Function names will not be demangled "
+ "because cxxabi is not available.\n"
+# endif
+#endif
+ ;
+
+ kwsys_ios::ostringstream oss;
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+ void *stackSymbols[256];
+ int nFrames=backtrace(stackSymbols,256);
+ for (int i=firstFrame; i<nFrames; ++i)
+ {
+ SymbolProperties symProps;
+ symProps.SetReportPath(wholePath);
+ symProps.Initialize(stackSymbols[i]);
+ oss << symProps << kwsys_ios::endl;
+ }
+#else
+ (void)firstFrame;
+ (void)wholePath;
+#endif
+ programStack += oss.str();
+
+ return programStack;
+}
+
+
+/**
when set print stack trace in response to common signals.
*/
void SystemInformationImplementation::SetStackTraceOnError(int enable)
{
#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
static int saOrigValid=0;
+ static struct sigaction saABRTOrig;
static struct sigaction saSEGVOrig;
static struct sigaction saTERMOrig;
static struct sigaction saINTOrig;
@@ -3349,9 +3661,11 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
static struct sigaction saBUSOrig;
static struct sigaction saFPEOrig;
+
if (enable && !saOrigValid)
{
// save the current actions
+ sigaction(SIGABRT,0,&saABRTOrig);
sigaction(SIGSEGV,0,&saSEGVOrig);
sigaction(SIGTERM,0,&saTERMOrig);
sigaction(SIGINT,0,&saINTOrig);
@@ -3365,9 +3679,10 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
// install ours
struct sigaction sa;
sa.sa_sigaction=(SigAction)StacktraceSignalHandler;
- sa.sa_flags=SA_SIGINFO|SA_RESTART;
+ sa.sa_flags=SA_SIGINFO|SA_RESTART|SA_RESETHAND;
sigemptyset(&sa.sa_mask);
+ sigaction(SIGABRT,&sa,0);
sigaction(SIGSEGV,&sa,0);
sigaction(SIGTERM,&sa,0);
sigaction(SIGINT,&sa,0);
@@ -3379,6 +3694,7 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
if (!enable && saOrigValid)
{
// restore previous actions
+ sigaction(SIGABRT,&saABRTOrig,0);
sigaction(SIGSEGV,&saSEGVOrig,0);
sigaction(SIGTERM,&saTERMOrig,0);
sigaction(SIGINT,&saINTOrig,0);
diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in
index f7c454e..a9fd05d 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -136,6 +136,12 @@ public:
static
void SetStackTraceOnError(int enable);
+ // format and return the current program stack in a string. In
+ // order to produce an informative stack trace the application
+ // should be dynamically linked and compiled with debug symbols.
+ static
+ kwsys_stl::string GetProgramStack(int firstFrame, int wholePath);
+
/** Run the different checks */
void RunCPUCheck();
void RunOSCheck();
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 935b836..e9a1fd3 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -695,6 +695,52 @@ void SystemTools::ReplaceString(kwsys_stl::string& source,
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
+static bool SystemToolsParseRegistryKey(const char* key,
+ HKEY& primaryKey,
+ kwsys_stl::string& second,
+ kwsys_stl::string& valuename)
+{
+ kwsys_stl::string primary = key;
+
+ size_t start = primary.find("\\");
+ if (start == kwsys_stl::string::npos)
+ {
+ return false;
+ }
+
+ size_t valuenamepos = primary.find(";");
+ if (valuenamepos != kwsys_stl::string::npos)
+ {
+ valuename = primary.substr(valuenamepos+1);
+ }
+
+ second = primary.substr(start+1, valuenamepos-start-1);
+ primary = primary.substr(0, start);
+
+ if (primary == "HKEY_CURRENT_USER")
+ {
+ primaryKey = HKEY_CURRENT_USER;
+ }
+ if (primary == "HKEY_CURRENT_CONFIG")
+ {
+ primaryKey = HKEY_CURRENT_CONFIG;
+ }
+ if (primary == "HKEY_CLASSES_ROOT")
+ {
+ primaryKey = HKEY_CLASSES_ROOT;
+ }
+ if (primary == "HKEY_LOCAL_MACHINE")
+ {
+ primaryKey = HKEY_LOCAL_MACHINE;
+ }
+ if (primary == "HKEY_USERS")
+ {
+ primaryKey = HKEY_USERS;
+ }
+
+ return true;
+}
+
static DWORD SystemToolsMakeRegistryMode(DWORD mode,
SystemTools::KeyWOW64 view)
{
@@ -718,6 +764,55 @@ static DWORD SystemToolsMakeRegistryMode(DWORD mode,
}
#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
+bool
+SystemTools::GetRegistrySubKeys(const char *key,
+ kwsys_stl::vector<kwsys_stl::string>& subkeys,
+ KeyWOW64 view)
+{
+ HKEY primaryKey = HKEY_CURRENT_USER;
+ kwsys_stl::string second;
+ kwsys_stl::string valuename;
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
+ {
+ return false;
+ }
+
+ HKEY hKey;
+ if(RegOpenKeyEx(primaryKey,
+ second.c_str(),
+ 0,
+ SystemToolsMakeRegistryMode(KEY_READ, view),
+ &hKey) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+ else
+ {
+ char name[1024];
+ DWORD dwNameSize = sizeof(name)/sizeof(name[0]);
+
+ DWORD i = 0;
+ while (RegEnumKey(hKey, i, name, dwNameSize) == ERROR_SUCCESS)
+ {
+ subkeys.push_back(name);
+ ++i;
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ return true;
+}
+#else
+bool SystemTools::GetRegistrySubKeys(const char *,
+ kwsys_stl::vector<kwsys_stl::string>&,
+ KeyWOW64)
+{
+ return false;
+}
+#endif
+
// Read a registry value.
// Example :
// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
@@ -730,47 +825,14 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
KeyWOW64 view)
{
bool valueset = false;
- kwsys_stl::string primary = key;
+ HKEY primaryKey = HKEY_CURRENT_USER;
kwsys_stl::string second;
kwsys_stl::string valuename;
-
- size_t start = primary.find("\\");
- if (start == kwsys_stl::string::npos)
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
{
return false;
}
- size_t valuenamepos = primary.find(";");
- if (valuenamepos != kwsys_stl::string::npos)
- {
- valuename = primary.substr(valuenamepos+1);
- }
-
- second = primary.substr(start+1, valuenamepos-start-1);
- primary = primary.substr(0, start);
-
- HKEY primaryKey = HKEY_CURRENT_USER;
- if (primary == "HKEY_CURRENT_USER")
- {
- primaryKey = HKEY_CURRENT_USER;
- }
- if (primary == "HKEY_CURRENT_CONFIG")
- {
- primaryKey = HKEY_CURRENT_CONFIG;
- }
- if (primary == "HKEY_CLASSES_ROOT")
- {
- primaryKey = HKEY_CLASSES_ROOT;
- }
- if (primary == "HKEY_LOCAL_MACHINE")
- {
- primaryKey = HKEY_LOCAL_MACHINE;
- }
- if (primary == "HKEY_USERS")
- {
- primaryKey = HKEY_USERS;
- }
-
HKEY hKey;
if(RegOpenKeyEx(primaryKey,
second.c_str(),
@@ -834,47 +896,14 @@ bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &,
bool SystemTools::WriteRegistryValue(const char *key, const char *value,
KeyWOW64 view)
{
- kwsys_stl::string primary = key;
+ HKEY primaryKey = HKEY_CURRENT_USER;
kwsys_stl::string second;
kwsys_stl::string valuename;
-
- size_t start = primary.find("\\");
- if (start == kwsys_stl::string::npos)
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
{
return false;
}
- size_t valuenamepos = primary.find(";");
- if (valuenamepos != kwsys_stl::string::npos)
- {
- valuename = primary.substr(valuenamepos+1);
- }
-
- second = primary.substr(start+1, valuenamepos-start-1);
- primary = primary.substr(0, start);
-
- HKEY primaryKey = HKEY_CURRENT_USER;
- if (primary == "HKEY_CURRENT_USER")
- {
- primaryKey = HKEY_CURRENT_USER;
- }
- if (primary == "HKEY_CURRENT_CONFIG")
- {
- primaryKey = HKEY_CURRENT_CONFIG;
- }
- if (primary == "HKEY_CLASSES_ROOT")
- {
- primaryKey = HKEY_CLASSES_ROOT;
- }
- if (primary == "HKEY_LOCAL_MACHINE")
- {
- primaryKey = HKEY_LOCAL_MACHINE;
- }
- if (primary == "HKEY_USERS")
- {
- primaryKey = HKEY_USERS;
- }
-
HKEY hKey;
DWORD dwDummy;
char lpClass[] = "";
@@ -919,47 +948,14 @@ bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64)
#if defined(_WIN32) && !defined(__CYGWIN__)
bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view)
{
- kwsys_stl::string primary = key;
+ HKEY primaryKey = HKEY_CURRENT_USER;
kwsys_stl::string second;
kwsys_stl::string valuename;
-
- size_t start = primary.find("\\");
- if (start == kwsys_stl::string::npos)
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
{
return false;
}
- size_t valuenamepos = primary.find(";");
- if (valuenamepos != kwsys_stl::string::npos)
- {
- valuename = primary.substr(valuenamepos+1);
- }
-
- second = primary.substr(start+1, valuenamepos-start-1);
- primary = primary.substr(0, start);
-
- HKEY primaryKey = HKEY_CURRENT_USER;
- if (primary == "HKEY_CURRENT_USER")
- {
- primaryKey = HKEY_CURRENT_USER;
- }
- if (primary == "HKEY_CURRENT_CONFIG")
- {
- primaryKey = HKEY_CURRENT_CONFIG;
- }
- if (primary == "HKEY_CLASSES_ROOT")
- {
- primaryKey = HKEY_CLASSES_ROOT;
- }
- if (primary == "HKEY_LOCAL_MACHINE")
- {
- primaryKey = HKEY_LOCAL_MACHINE;
- }
- if (primary == "HKEY_USERS")
- {
- primaryKey = HKEY_USERS;
- }
-
HKEY hKey;
if(RegOpenKeyEx(primaryKey,
second.c_str(),
@@ -4869,7 +4865,8 @@ static int SystemToolsDebugReport(int, char* message, int*)
void SystemTools::EnableMSVCDebugHook()
{
- if (getenv("DART_TEST_FROM_DART"))
+ if (getenv("DART_TEST_FROM_DART") ||
+ getenv("DASHBOARD_TEST_FROM_CTEST"))
{
_CrtSetReportHook(SystemToolsDebugReport);
}
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index e55d431..d6dae39 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -716,6 +716,13 @@ public:
enum KeyWOW64 { KeyWOW64_Default, KeyWOW64_32, KeyWOW64_64 };
/**
+ * Get a list of subkeys.
+ */
+ static bool GetRegistrySubKeys(const char *key,
+ kwsys_stl::vector<kwsys_stl::string>& subkeys,
+ KeyWOW64 view = KeyWOW64_Default);
+
+ /**
* Read a registry value
*/
static bool ReadRegistryValue(const char *key, kwsys_stl::string &value,
diff --git a/Source/kwsys/auto_ptr.hxx.in b/Source/kwsys/auto_ptr.hxx.in
index 857b1db..ad9654c 100644
--- a/Source/kwsys/auto_ptr.hxx.in
+++ b/Source/kwsys/auto_ptr.hxx.in
@@ -31,6 +31,17 @@
# define @KWSYS_NAMESPACE@_AUTO_PTR_CAST(a) a
#endif
+// In C++11, clang will warn about using dynamic exception specifications
+// as they are deprecated. But as this class is trying to faithfully
+// mimic std::auto_ptr, we want to keep the 'throw()' decorations below.
+// So we suppress the warning.
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated"
+# endif
+#endif
+
namespace @KWSYS_NAMESPACE@
{
@@ -198,4 +209,11 @@ public:
} // namespace @KWSYS_NAMESPACE@
+// Undo warning suppression.
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic pop
+# endif
+#endif
+
#endif
diff --git a/Source/kwsys/hashtable.hxx.in b/Source/kwsys/hashtable.hxx.in
index c835503..651de82 100644
--- a/Source/kwsys/hashtable.hxx.in
+++ b/Source/kwsys/hashtable.hxx.in
@@ -62,6 +62,17 @@
# pragma set woff 3970 /* pointer to int conversion */ 3321 3968
#endif
+// In C++11, clang will warn about using dynamic exception specifications
+// as they are deprecated. But as this class is trying to faithfully
+// mimic unordered_set and unordered_map, we want to keep the 'throw()'
+// decorations below. So we suppress the warning.
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated"
+# endif
+#endif
+
#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE
# define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::allocator< T >
#elif @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE
@@ -1268,6 +1279,13 @@ using @KWSYS_NAMESPACE@::operator==;
using @KWSYS_NAMESPACE@::operator!=;
#endif
+// Undo warning suppression.
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic pop
+# endif
+#endif
+
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake
index d042450..f9ee254 100644
--- a/Source/kwsys/kwsysPlatformTests.cmake
+++ b/Source/kwsys/kwsysPlatformTests.cmake
@@ -19,6 +19,7 @@ MACRO(KWSYS_PLATFORM_TEST lang var description invert)
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}}
COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS}
+ CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${KWSYS_PLATFORM_TEST_LINK_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
IF(${var}_COMPILED)
FILE(APPEND
@@ -150,9 +151,11 @@ ENDMACRO(KWSYS_PLATFORM_C_TEST_RUN)
MACRO(KWSYS_PLATFORM_CXX_TEST var description invert)
SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES})
SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS})
+ SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES ${KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES})
KWSYS_PLATFORM_TEST(CXX "${var}" "${description}" "${invert}")
SET(KWSYS_PLATFORM_TEST_DEFINES)
SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS)
+ SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES)
ENDMACRO(KWSYS_PLATFORM_CXX_TEST)
MACRO(KWSYS_PLATFORM_CXX_TEST_RUN var description invert)
diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx
index a7e3b50..be7a09e 100644
--- a/Source/kwsys/kwsysPlatformTestsCXX.cxx
+++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx
@@ -513,6 +513,54 @@ int main()
}
#endif
+#ifdef TEST_KWSYS_CXX_HAS_BACKTRACE
+#if defined(__PATHSCALE__) || defined(__PATHCC__) \
+ || (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41))
+backtrace doesnt work with this compiler or os
+#endif
+#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+#endif
+#include <execinfo.h>
+int main()
+{
+ void *stackSymbols[256];
+ backtrace(stackSymbols,256);
+ backtrace_symbols(&stackSymbols[0],1);
+ return 0;
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_DLADDR
+#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+#endif
+#include <dlfcn.h>
+int main()
+{
+ Dl_info info;
+ int ierr=dladdr((void*)main,&info);
+ return 0;
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_CXXABI
+#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+#endif
+#include <cxxabi.h>
+int main()
+{
+ int status = 0;
+ size_t bufferLen = 512;
+ char buffer[512] = {'\0'};
+ const char *function="_ZN5kwsys17SystemInformation15GetProgramStackEii";
+ char *demangledFunction =
+ abi::__cxa_demangle(function, buffer, &bufferLen, &status);
+ return status;
+}
+#endif
+
#ifdef TEST_KWSYS_CXX_TYPE_INFO
/* Collect fundamental type information and save it to a CMake script. */
diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx
index 738043f..53d51ac 100644
--- a/Source/kwsys/testSystemInformation.cxx
+++ b/Source/kwsys/testSystemInformation.cxx
@@ -95,7 +95,24 @@ int testSystemInformation(int, char*[])
kwsys_ios::cout << "CPU feature " << i << "\n";
}
}
- //int GetProcessorCacheXSize(long int);
-// bool DoesCPUSupportFeature(long int);
+
+ /* test stack trace
+ */
+ kwsys_ios::cout
+ << "Program Stack:" << kwsys_ios::endl
+ << kwsys::SystemInformation::GetProgramStack(0,0) << kwsys_ios::endl
+ << kwsys_ios::endl;
+
+ /* test segv handler
+ info.SetStackTraceOnError(1);
+ double *d = (double*)100;
+ *d=0;
+ */
+
+ /* test abort handler
+ info.SetStackTraceOnError(1);
+ abort();
+ */
+
return 0;
}
diff --git a/Tests/AliasTarget/CMakeLists.txt b/Tests/AliasTarget/CMakeLists.txt
new file mode 100644
index 0000000..a5eb0f6
--- /dev/null
+++ b/Tests/AliasTarget/CMakeLists.txt
@@ -0,0 +1,47 @@
+
+cmake_minimum_required(VERSION 2.8.11)
+project(AliasTarget)
+
+add_library(foo SHARED empty.cpp)
+add_library(PREFIX::Foo ALIAS foo)
+add_library(Another::Alias ALIAS foo)
+
+add_library(objects OBJECT object.cpp)
+add_library(Alias::Objects ALIAS objects)
+
+target_compile_definitions(foo PUBLIC FOO_DEFINE)
+
+add_library(bar SHARED empty.cpp)
+target_compile_definitions(bar PUBLIC BAR_DEFINE)
+
+target_link_libraries(foo LINK_PUBLIC $<$<STREQUAL:$<TARGET_PROPERTY:PREFIX::Foo,ALIASED_TARGET>,foo>:bar>)
+
+add_executable(AliasTarget commandgenerator.cpp $<TARGET_OBJECTS:Alias::Objects>)
+add_executable(PREFIX::AliasTarget ALIAS AliasTarget)
+add_executable(Generator::Command ALIAS AliasTarget)
+
+add_custom_command(OUTPUT commandoutput.h COMMAND Generator::Command)
+
+add_library(bat SHARED bat.cpp "${CMAKE_CURRENT_BINARY_DIR}/commandoutput.h")
+target_link_libraries(bat PREFIX::Foo)
+target_include_directories(bat PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
+
+add_executable(targetgenerator targetgenerator.cpp)
+add_executable(Generator::Target ALIAS targetgenerator)
+
+add_custom_target(usealias Generator::Target)
+add_dependencies(bat usealias)
+
+if (NOT TARGET Another::Alias)
+ message(SEND_ERROR "Another::Alias is not considered a target.")
+endif()
+
+get_target_property(_alt PREFIX::Foo ALIASED_TARGET)
+if (NOT ${_alt} STREQUAL foo)
+ message(SEND_ERROR "ALIASED_TARGET is not foo: ${_alt}")
+endif()
+
+get_property(_alt2 TARGET PREFIX::Foo PROPERTY ALIASED_TARGET)
+if (NOT ${_alt2} STREQUAL foo)
+ message(SEND_ERROR "ALIASED_TARGET is not foo.")
+endif()
diff --git a/Tests/AliasTarget/bat.cpp b/Tests/AliasTarget/bat.cpp
new file mode 100644
index 0000000..1063c21
--- /dev/null
+++ b/Tests/AliasTarget/bat.cpp
@@ -0,0 +1,28 @@
+
+#ifndef FOO_DEFINE
+#error Expected FOO_DEFINE
+#endif
+
+#ifndef BAR_DEFINE
+#error Expected Bar_DEFINE
+#endif
+
+#include "commandoutput.h"
+
+#ifndef COMMANDOUTPUT_DEFINE
+#error Expected COMMANDOUTPUT_DEFINE
+#endif
+
+#include "targetoutput.h"
+
+#ifndef TARGETOUTPUT_DEFINE
+#error Expected TARGETOUTPUT_DEFINE
+#endif
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int bar()
+{
+ return 0;
+}
diff --git a/Tests/AliasTarget/commandgenerator.cpp b/Tests/AliasTarget/commandgenerator.cpp
new file mode 100644
index 0000000..23560a4
--- /dev/null
+++ b/Tests/AliasTarget/commandgenerator.cpp
@@ -0,0 +1,15 @@
+
+#include <fstream>
+
+#include "object.h"
+
+int main(int argc, char **argv)
+{
+ std::fstream fout;
+ fout.open("commandoutput.h", std::ios::out);
+ if (!fout)
+ return 1;
+ fout << "#define COMMANDOUTPUT_DEFINE\n";
+ fout.close();
+ return object();
+}
diff --git a/Tests/AliasTarget/empty.cpp b/Tests/AliasTarget/empty.cpp
new file mode 100644
index 0000000..b19427a
--- /dev/null
+++ b/Tests/AliasTarget/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/AliasTarget/object.cpp b/Tests/AliasTarget/object.cpp
new file mode 100644
index 0000000..df09c20
--- /dev/null
+++ b/Tests/AliasTarget/object.cpp
@@ -0,0 +1,5 @@
+
+int object(void)
+{
+ return 0;
+}
diff --git a/Tests/AliasTarget/object.h b/Tests/AliasTarget/object.h
new file mode 100644
index 0000000..e935f14
--- /dev/null
+++ b/Tests/AliasTarget/object.h
@@ -0,0 +1,4 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int object(void);
diff --git a/Tests/AliasTarget/targetgenerator.cpp b/Tests/AliasTarget/targetgenerator.cpp
new file mode 100644
index 0000000..3362414
--- /dev/null
+++ b/Tests/AliasTarget/targetgenerator.cpp
@@ -0,0 +1,13 @@
+
+#include <fstream>
+
+int main(int argc, char **argv)
+{
+ std::fstream fout;
+ fout.open("targetoutput.h", std::ios::out);
+ if (!fout)
+ return 1;
+ fout << "#define TARGETOUTPUT_DEFINE\n";
+ fout.close();
+ return 0;
+}
diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt
index 2792751..3af0fda 100644
--- a/Tests/BuildDepends/CMakeLists.txt
+++ b/Tests/BuildDepends/CMakeLists.txt
@@ -53,6 +53,8 @@ write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in
"static const char* zot = \"zot\";\n")
+file(WRITE ${BuildDepends_BINARY_DIR}/Project/dir/header.txt
+ "#define HEADER_STRING \"ninja\"\n" )
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_custom.hxx.in
"static const char* zot_custom = \"zot_custom\";\n")
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_macro_dir.hxx
@@ -93,6 +95,26 @@ if(NOT RESULT)
message(SEND_ERROR "Could not build test project (1)!")
endif()
+# find and save the ninjadep executable
+set(ninjadep ${BuildDepends_BINARY_DIR}/Project/ninjadep${CMAKE_EXECUTABLE_SUFFIX})
+if(EXISTS
+ "${BuildDepends_BINARY_DIR}/Project/Debug/ninjadep${CMAKE_EXECUTABLE_SUFFIX}" )
+ message("found debug")
+ set(ninjadep
+ "${BuildDepends_BINARY_DIR}/Project/Debug/ninjadep${CMAKE_EXECUTABLE_SUFFIX}")
+endif()
+message("Running ${ninjadep} ")
+execute_process(COMMAND ${ninjadep} OUTPUT_VARIABLE out RESULT_VARIABLE runResult)
+string(REGEX REPLACE "[\r\n]" " " out "${out}")
+message("Run result: ${runResult} Output: \"${out}\"")
+
+if("${out}" STREQUAL "HEADER_STRING: ninja ")
+ message("Worked!")
+else()
+ message(SEND_ERROR "Project did not rebuild properly. Output[${out}]\n"
+ " expected [HEADER_STRING: ninja]")
+endif()
+
set(bar ${BuildDepends_BINARY_DIR}/Project/bar${CMAKE_EXECUTABLE_SUFFIX})
if(EXISTS
"${BuildDepends_BINARY_DIR}/Project/Debug/bar${CMAKE_EXECUTABLE_SUFFIX}" )
@@ -151,6 +173,8 @@ execute_process(COMMAND ${bar} -infinite TIMEOUT 3 OUTPUT_VARIABLE out)
message("Modifying Project/foo.cxx")
write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx
"const char* foo() { return \"foo changed\";}" )
+file(WRITE "${BuildDepends_BINARY_DIR}/Project/dir/header.txt"
+ "#define HEADER_STRING \"ninja changed\"\n" )
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in
"static const char* zot = \"zot changed\";\n")
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_custom.hxx.in
@@ -204,6 +228,21 @@ if(EXISTS
message("found debug")
endif()
+message("Running ${ninjadep} ")
+execute_process(COMMAND ${ninjadep} OUTPUT_VARIABLE out RESULT_VARIABLE runResult)
+string(REGEX REPLACE "[\r\n]" " " out "${out}")
+message("Run result: ${runResult} Output: \"${out}\"")
+
+if("${out}" STREQUAL "HEADER_STRING: ninja changed ")
+ message("Worked!")
+elseif(CMAKE_GENERATOR STREQUAL "Visual Studio 6")
+ # Tolerate failure because VS 6 does not seem to recompile ninjadep.cpp
+ # when the "dir/header.h" it includes changes.
+else()
+ message(SEND_ERROR "Project did not rebuild properly. Output[${out}]\n"
+ " expected [HEADER_STRING: ninja changed]")
+endif()
+
message("Running ${bar} ")
execute_process(COMMAND ${bar} OUTPUT_VARIABLE out RESULT_VARIABLE runResult)
string(REGEX REPLACE "[\r\n]" " " out "${out}")
diff --git a/Tests/BuildDepends/Project/CMakeLists.txt b/Tests/BuildDepends/Project/CMakeLists.txt
index f8a3d15..b4c6a07 100644
--- a/Tests/BuildDepends/Project/CMakeLists.txt
+++ b/Tests/BuildDepends/Project/CMakeLists.txt
@@ -123,3 +123,19 @@ add_custom_target(link_depends_no_shared_check ALL
-P ${CMAKE_CURRENT_SOURCE_DIR}/link_depends_no_shared_check.cmake
)
add_dependencies(link_depends_no_shared_check link_depends_no_shared_exe)
+
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dir/header.h
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dir/header.txt
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_CURRENT_BINARY_DIR}/dir/header.txt
+ ${CMAKE_CURRENT_BINARY_DIR}/dir/header.h
+ )
+
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/dir/header.h
+ PROPERTIES GENERATED 1)
+
+add_custom_target(header_tgt DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dir/header.h)
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+add_executable(ninjadep ninjadep.cpp)
+add_dependencies(ninjadep header_tgt)
diff --git a/Tests/BuildDepends/Project/ninjadep.cpp b/Tests/BuildDepends/Project/ninjadep.cpp
new file mode 100644
index 0000000..8d61336
--- /dev/null
+++ b/Tests/BuildDepends/Project/ninjadep.cpp
@@ -0,0 +1,6 @@
+#include <stdio.h>
+#include "dir/header.h"
+
+int main() {
+ printf("HEADER_STRING: %s\n", HEADER_STRING);
+}
diff --git a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
index 6d0e646..900dbd0 100644
--- a/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_definitions/CMakeLists.txt
@@ -20,3 +20,8 @@ target_compile_definitions(consumer
PRIVATE $<TARGET_PROPERTY:target_compile_definitions,INTERFACE_COMPILE_DEFINITIONS>
-DDASH_D_DEFINE
)
+
+# Test no items
+target_compile_definitions(consumer
+ PRIVATE
+)
diff --git a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
index 06a48fb..1d04639 100644
--- a/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compile_options/CMakeLists.txt
@@ -33,3 +33,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
"DO_GNU_TESTS"
)
endif()
+
+# Test no items
+target_compile_options(consumer
+ PRIVATE
+)
diff --git a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
index c03f0f8..21b8e15 100644
--- a/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_include_directories/CMakeLists.txt
@@ -47,3 +47,17 @@ target_include_directories(consumer
$<TARGET_PROPERTY:target_include_directories,INTERFACE_INCLUDE_DIRECTORIES>
relative_dir
)
+
+# Test no items
+target_include_directories(consumer
+ PRIVATE
+)
+target_include_directories(consumer
+ BEFORE PRIVATE
+)
+target_include_directories(consumer
+ SYSTEM BEFORE PRIVATE
+)
+target_include_directories(consumer
+ SYSTEM PRIVATE
+)
diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt
index dd6ab41..07d7c43 100644
--- a/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/CMakeLists.txt
@@ -16,3 +16,12 @@ assert_property(cmp0022ifacelib INTERFACE_LINK_LIBRARIES "")
add_executable(cmp0022exe cmp0022exe.cpp)
target_link_libraries(cmp0022exe cmp0022lib)
+
+add_library(staticlib1 STATIC staticlib1.cpp)
+generate_export_header(staticlib1)
+add_library(staticlib2 STATIC staticlib2.cpp)
+generate_export_header(staticlib2)
+target_link_libraries(staticlib1 LINK_PUBLIC staticlib2)
+
+add_executable(staticlib_exe staticlib_exe.cpp)
+target_link_libraries(staticlib_exe staticlib1)
diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp
new file mode 100644
index 0000000..a253c46
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.cpp
@@ -0,0 +1,2 @@
+
+int staticlib1() { return 0; }
diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.h b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.h
new file mode 100644
index 0000000..4bbf23f
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib1.h
@@ -0,0 +1,4 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int staticlib1();
diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp
new file mode 100644
index 0000000..4e38063
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.cpp
@@ -0,0 +1,2 @@
+
+int staticlib2() { return 0; }
diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.h b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.h
new file mode 100644
index 0000000..a4e07b6
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib2.h
@@ -0,0 +1,4 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int staticlib2();
diff --git a/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib_exe.cpp b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib_exe.cpp
new file mode 100644
index 0000000..97adc40
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/cmp0022/staticlib_exe.cpp
@@ -0,0 +1,8 @@
+
+#include "staticlib1.h"
+#include "staticlib2.h"
+
+int main()
+{
+ return staticlib1() + staticlib2();
+}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 440cdf0..9c3ed59 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -245,6 +245,7 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(CompileDefinitions CompileDefinitions)
ADD_TEST_MACRO(CompileOptions CompileOptions)
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
+ ADD_TEST_MACRO(AliasTarget AliasTarget)
set_tests_properties(EmptyLibrary PROPERTIES
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test")
ADD_TEST_MACRO(CrossCompile CrossCompile)
@@ -394,10 +395,20 @@ if(BUILD_TESTING)
endmacro()
ADD_LINK_FLAGS_TEST(lib prepare)
ADD_LINK_FLAGS_TEST(dll lib)
- ADD_LINK_FLAGS_TEST(exe dll)
+ ADD_LINK_FLAGS_TEST(mod dll)
+ ADD_LINK_FLAGS_TEST(exe mod)
ADD_LINK_FLAGS_TEST(lib_config exe)
ADD_LINK_FLAGS_TEST(dll_config lib_config)
- ADD_LINK_FLAGS_TEST(exe_config dll_config)
+ ADD_LINK_FLAGS_TEST(mod_config dll_config)
+ ADD_LINK_FLAGS_TEST(exe_config mod_config)
+ ADD_LINK_FLAGS_TEST(lib_flags exe_config)
+ ADD_LINK_FLAGS_TEST(dll_flags lib_flags)
+ ADD_LINK_FLAGS_TEST(mod_flags dll_flags)
+ ADD_LINK_FLAGS_TEST(exe_flags mod_flags)
+ ADD_LINK_FLAGS_TEST(lib_flags_config exe_flags)
+ ADD_LINK_FLAGS_TEST(dll_flags_config lib_flags_config)
+ ADD_LINK_FLAGS_TEST(mod_flags_config dll_flags_config)
+ ADD_LINK_FLAGS_TEST(exe_flags_config mod_flags_config)
# If we are running right now with a UnixMakefiles based generator,
# build the "Simple" test with the ExtraGenerators, if available
@@ -2045,9 +2056,11 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
--output-log "${CMake_BINARY_DIR}/Tests/CTestTestParallel/testOutput.log"
)
- set(CTestLimitDashJ_EXTRA_OPTIONS --force-new-ctest-process)
- add_test_macro(CTestLimitDashJ ${CMAKE_CTEST_COMMAND} -j 4
- --output-on-failure -C "\${CTestTest_CONFIG}")
+ if(NOT BORLAND)
+ set(CTestLimitDashJ_EXTRA_OPTIONS --force-new-ctest-process)
+ add_test_macro(CTestLimitDashJ ${CMAKE_CTEST_COMMAND} -j 4
+ --output-on-failure -C "\${CTestTest_CONFIG}")
+ endif()
add_test(CTestTestPrintLabels ${CMAKE_CTEST_COMMAND} --print-labels)
set_tests_properties(CTestTestPrintLabels PROPERTIES LABELS "Label1;Label2")
diff --git a/Tests/CTestTestDepends/CMakeLists.txt b/Tests/CTestTestDepends/CMakeLists.txt
index 26367a6..5cd6d66 100644
--- a/Tests/CTestTestDepends/CMakeLists.txt
+++ b/Tests/CTestTestDepends/CMakeLists.txt
@@ -3,7 +3,8 @@ project(CTestTestDepends)
include(CTest)
add_executable (simple simple.cxx)
-add_test (one simple)
+add_executable (TestExe::Simple ALIAS simple)
+add_test (NAME one COMMAND TestExe::Simple)
add_test (two simple)
add_test (three simple)
diff --git a/Tests/CTestTestMemcheck/CMakeLists.txt b/Tests/CTestTestMemcheck/CMakeLists.txt
index ff02883..86d7385 100644
--- a/Tests/CTestTestMemcheck/CMakeLists.txt
+++ b/Tests/CTestTestMemcheck/CMakeLists.txt
@@ -66,6 +66,7 @@ function(gen_mc_test NAME CHECKER)
-D PSEUDO_PURIFY=$<TARGET_FILE:pseudo_purify>
-D PSEUDO_VALGRIND=$<TARGET_FILE:pseudo_valgrind>
-D ERROR_COMMAND=$<TARGET_FILE:memcheck_fail>
+ ${ARGN}
)
endfunction(gen_mc_test)
@@ -74,10 +75,11 @@ function(gen_mcnl_test NAME CHECKER)
-D PSEUDO_BC=$<TARGET_FILE:pseudonl_BC>
-D PSEUDO_PURIFY=$<TARGET_FILE:pseudonl_purify>
-D PSEUDO_VALGRIND=$<TARGET_FILE:pseudonl_valgrind>
+ ${ARGN}
)
set_tests_properties(CTestTestMemcheck${NAME}
PROPERTIES
- PASS_REGULAR_EXPRESSION "\nCannot find memory tester output file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/${NAME}/Testing/Temporary/MemoryChecker.log\n(.*\n)?Error in read script: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/${NAME}/test.cmake\n")
+ PASS_REGULAR_EXPRESSION "\nCannot find memory tester output file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/${NAME}/Testing/Temporary/MemoryChecker.1.log\n(.*\n)?Error in read script: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/${NAME}/test.cmake\n")
endfunction(gen_mcnl_test)
unset(CTEST_EXTRA_CONFIG)
@@ -91,7 +93,11 @@ gen_mcnl_test(DummyPurifyNoLogfile "\${PSEUDO_PURIFY}")
gen_mcnl_test(DummyValgrindNoLogfile "\${PSEUDO_VALGRIND}")
gen_mcnl_test(DummyBCNoLogfile "\${PSEUDO_BC}")
-set(CTEST_EXTRA_CODE "set(CTEST_CUSTOM_PRE_MEMCHECK \"\${CTEST_MEMORYCHECK_COMMAND}\")\nset(CTEST_CUSTOM_POST_MEMCHECK \"\${CTEST_MEMORYCHECK_COMMAND}\")")
+set(CTEST_EXTRA_CODE "string(REPLACE \" \" \"\\\\ \" PRE_POST_COMMAND \"\${CTEST_MEMORYCHECK_COMMAND}\")
+
+set(CTEST_CUSTOM_PRE_MEMCHECK \"\${PRE_POST_COMMAND} pre command\")
+set(CTEST_CUSTOM_POST_MEMCHECK \"\${PRE_POST_COMMAND} post command \")
+")
gen_mc_test(DummyValgrindPrePost "\${PSEUDO_VALGRIND}")
set(CTEST_EXTRA_CODE "set(CTEST_CUSTOM_POST_MEMCHECK \"\${ERROR_COMMAND}\")")
@@ -105,14 +111,17 @@ set(CTEST_EXTRA_CONFIG "set(CTEST_CUSTOM_MEMCHECK_IGNORE RunCMakeAgain)\n")
set(CMAKELISTS_EXTRA_CODE "add_test(NAME RunCMakeAgain COMMAND \"\${CMAKE_COMMAND}\" --version)")
gen_mc_test(DummyValgrindIgnoreMemcheck "\${PSEUDO_VALGRIND}")
+unset(CTEST_EXTRA_CONFIG)
+gen_mc_test(DummyValgrindTwoTargets "\${PSEUDO_VALGRIND}" "-VV")
+
set(CTEST_EXTRA_CONFIG "set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE \"\${CMAKE_CURRENT_BINARY_DIR}/does-not-exist\")")
unset(CMAKELISTS_EXTRA_CODE)
gen_mc_test(DummyValgrindInvalidSupFile "\${PSEUDO_VALGRIND}")
-# CTest will add the logfile option as last option. Tell the dummy memcheck
-# to ignore that argument. This will cause the logfile to be missing, which
-# will be the prove for us that the custom option is indeed used.
-set(CTEST_EXTRA_CONFIG "set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"--\")")
+# CTest will add the logfile option before any custom options. Set the logfile
+# again, this time to an empty string. This will cause the logfile to be
+# missing, which will be the prove for us that the custom option is indeed used.
+set(CTEST_EXTRA_CONFIG "set(CTEST_MEMORYCHECK_COMMAND_OPTIONS \"--log-file=\")")
gen_mc_test(DummyValgrindCustomOptions "\${PSEUDO_VALGRIND}")
unset(CTEST_EXTRA_CONFIG)
@@ -157,4 +166,8 @@ set_tests_properties(CTestTestMemcheckDummyValgrindInvalidSupFile PROPERTIES
PASS_REGULAR_EXPRESSION "\nCannot find memory checker suppression file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/does-not-exist\n")
set_tests_properties(CTestTestMemcheckDummyValgrindCustomOptions PROPERTIES
- PASS_REGULAR_EXPRESSION "\nCannot find memory tester output file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindCustomOptions/Testing/Temporary/MemoryChecker.log\n(.*\n)?Error in read script: ${CMAKE_CURRENT_BINARY_DIR}/DummyValgrindCustomOptions/test.cmake\n")
+ PASS_REGULAR_EXPRESSION "\nCannot find memory tester output file: ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindCustomOptions/Testing/Temporary/MemoryChecker.1.log\n(.*\n)?Error in read script: ${CMAKE_CURRENT_BINARY_DIR}/DummyValgrindCustomOptions/test.cmake\n")
+
+set_tests_properties(CTestTestMemcheckDummyValgrindTwoTargets PROPERTIES
+ PASS_REGULAR_EXPRESSION
+ "\nMemory check project ${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets\n.*\n *Start 1: RunCMake\n(.*\n)?Memory check command: .* \"--log-file=${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets/Testing/Temporary/MemoryChecker.1.log\" \"-q\".*\n *Start 2: RunCMakeAgain\n(.*\n)?Memory check command: .* \"--log-file=${CTEST_ESCAPED_CMAKE_CURRENT_BINARY_DIR}/DummyValgrindTwoTargets/Testing/Temporary/MemoryChecker.2.log\" \"-q\".*\n")
diff --git a/Tests/CTestTestMemcheck/memtester.cxx.in b/Tests/CTestTestMemcheck/memtester.cxx.in
index da6f5a4..55a34e3 100644
--- a/Tests/CTestTestMemcheck/memtester.cxx.in
+++ b/Tests/CTestTestMemcheck/memtester.cxx.in
@@ -28,12 +28,6 @@ main(int argc, char **argv)
std::string logfile;
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
- // stop processing options, this allows to force
- // the logfile to be ignored
- if (arg == "--")
- {
- break;
- }
if (arg.find(logarg) == 0)
{
if (nextarg)
@@ -46,7 +40,7 @@ main(int argc, char **argv)
{
logfile = arg.substr(logarg.length());
}
- break;
+ // keep searching, it may be overridden later to provoke an error
}
}
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index 49f1c58..b5b2027 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -99,7 +99,6 @@ macro(add_include_lib _libName)
set_property(TARGET ${_libName} APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/${_libName}>"
- "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/${_libName}>"
)
if (NOT "${ARGV1}" STREQUAL "NO_HEADER")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}/${_libName}.h" "// no content\n")
@@ -188,8 +187,7 @@ install(FILES
DESTINATION include/testSharedLibRequired
)
set_property(TARGET testSharedLibRequired APPEND PROPERTY
- INTERFACE_INCLUDE_DIRECTORIES "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/testSharedLibRequired>"
- "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
+ INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>"
)
set_property(TARGET testSharedLibRequired APPEND PROPERTY
INTERFACE_COMPILE_DEFINITIONS USING_TESTSHAREDLIBREQUIRED
@@ -270,18 +268,27 @@ set_property(TARGET cmp0022NEW APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2
set_property(TARGET cmp0022OLD APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2)
set_property(TARGET cmp0022OLD APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLib3)
+add_library(noIncludesInterface empty.cpp)
+
install(TARGETS testLibRequired
- testLibIncludeRequired1
- testLibIncludeRequired2
- testLibIncludeRequired3
- testLibIncludeRequired4
- testLibIncludeRequired5
- testLibIncludeRequired6
- testSharedLibRequired
EXPORT RequiredExp DESTINATION lib
INCLUDES DESTINATION
installIncludesTest
- $<INSTALL_PREFIX>/installIncludesTest2)
+ $<INSTALL_PREFIX>/installIncludesTest2
+ )
+install(TARGETS
+ testLibIncludeRequired1
+ testLibIncludeRequired2
+ testLibIncludeRequired3
+ testLibIncludeRequired4
+ testLibIncludeRequired5
+ testLibIncludeRequired6
+ testSharedLibRequired
+ noIncludesInterface
+ EXPORT RequiredExp DESTINATION lib
+ INCLUDES DESTINATION
+ $<INSTALL_PREFIX>/include/$<TARGET_PROPERTY:NAME>
+)
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredTargets.cmake DESTINATION lib/cmake/testLibRequired)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/installIncludesTest")
diff --git a/Tests/ExportImport/Export/empty.cpp b/Tests/ExportImport/Export/empty.cpp
new file mode 100644
index 0000000..1787013
--- /dev/null
+++ b/Tests/ExportImport/Export/empty.cpp
@@ -0,0 +1,4 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty() { return 0; }
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index 7ac6ede..4d8d7ed 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -163,6 +163,11 @@ add_library(imported4 SHARED IMPORTED)
set_property(TARGET imported4 APPEND PROPERTY
INCLUDE_DIRECTORIES $<TARGET_PROPERTY:imported3,INTERFACE_INCLUDE_DIRECTORIES>)
+add_executable(someexe empty.cpp)
+add_executable(Alias::SomeExe ALIAS someexe)
+
+add_library(Alias::SomeLib ALIAS empty1)
+
add_custom_target(check-part3 ALL
COMMAND ${CMAKE_COMMAND}
-Dtest_version_greater_1=$<VERSION_GREATER:1.0,1.1.1>
@@ -176,6 +181,11 @@ add_custom_target(check-part3 ALL
-Dtest_imported_release=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES>
-Dtest_imported_relwithdebinfo=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES>
-Dtest_imported_minsizerel=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES>
+ -Dtest_alias_file_exe=$<STREQUAL:$<TARGET_FILE:Alias::SomeExe>,$<TARGET_FILE:someexe>>
+ -Dtest_alias_file_lib=$<STREQUAL:$<TARGET_FILE:Alias::SomeLib>,$<TARGET_FILE:empty1>>
+ -Dtest_alias_target_name=$<STREQUAL:$<TARGET_PROPERTY:Alias::SomeLib,NAME>,$<TARGET_PROPERTY:empty1,NAME>>
+ -Dtest_early_termination_1=$<$<1:>:
+ -Dtest_early_termination_2=$<$<1:>:,
-P ${CMAKE_CURRENT_SOURCE_DIR}/check-part3.cmake
COMMAND ${CMAKE_COMMAND} -E echo "check done (part 3 of 3)"
VERBATIM
diff --git a/Tests/GeneratorExpression/check-part3.cmake b/Tests/GeneratorExpression/check-part3.cmake
index af290a5..74a596c 100644
--- a/Tests/GeneratorExpression/check-part3.cmake
+++ b/Tests/GeneratorExpression/check-part3.cmake
@@ -20,3 +20,9 @@ foreach(c debug release relwithdebinfo minsizerel)
endif()
endif()
endforeach()
+
+check(test_alias_file_exe "1")
+check(test_alias_file_lib "1")
+check(test_alias_target_name "1")
+check(test_early_termination_1 "$<:")
+check(test_early_termination_2 "$<:,")
diff --git a/Tests/GeneratorExpression/empty.cpp b/Tests/GeneratorExpression/empty.cpp
index c539901..f8732a4 100644
--- a/Tests/GeneratorExpression/empty.cpp
+++ b/Tests/GeneratorExpression/empty.cpp
@@ -1,2 +1,4 @@
-
-// empty
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int main() { return 0; }
diff --git a/Tests/IncludeDirectories/CMP0021/CMakeLists.txt b/Tests/IncludeDirectories/CMP0021/CMakeLists.txt
new file mode 100644
index 0000000..0b9aee8
--- /dev/null
+++ b/Tests/IncludeDirectories/CMP0021/CMakeLists.txt
@@ -0,0 +1,14 @@
+
+cmake_policy(SET CMP0021 OLD)
+add_executable(cmp0021exe main.cpp)
+
+if(NOT CMAKE_CURRENT_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/includes")
+ execute_process(COMMAND ${CMAKE_COMMAND} -E
+ copy_directory
+ "${CMAKE_CURRENT_SOURCE_DIR}/includes"
+ "${CMAKE_CURRENT_BINARY_DIR}/includes"
+ )
+endif()
+set_property(TARGET cmp0021exe PROPERTY
+ INCLUDE_DIRECTORIES includes/cmp0021)
diff --git a/Tests/IncludeDirectories/CMP0021/includes/cmp0021/cmp0021.h b/Tests/IncludeDirectories/CMP0021/includes/cmp0021/cmp0021.h
new file mode 100644
index 0000000..3d49b31
--- /dev/null
+++ b/Tests/IncludeDirectories/CMP0021/includes/cmp0021/cmp0021.h
@@ -0,0 +1,2 @@
+
+#define CMP0021_DEFINE
diff --git a/Tests/IncludeDirectories/CMP0021/main.cpp b/Tests/IncludeDirectories/CMP0021/main.cpp
new file mode 100644
index 0000000..f886c46
--- /dev/null
+++ b/Tests/IncludeDirectories/CMP0021/main.cpp
@@ -0,0 +1,11 @@
+
+#include "cmp0021.h"
+
+#ifndef CMP0021_DEFINE
+#error Expected CMP0021_DEFINE
+#endif
+
+int main(int, char **)
+{
+ return 0;
+}
diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt
index 596a280..35ad8dc 100644
--- a/Tests/IncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/CMakeLists.txt
@@ -86,3 +86,7 @@ get_target_property(incs empty_entry_test INCLUDE_DIRECTORIES)
if (NOT incs STREQUAL ";/one/two")
message(SEND_ERROR "Empty include_directories entry was not ignored.")
endif()
+
+if(NOT CMAKE_GENERATOR STREQUAL Xcode AND NOT CMAKE_GENERATOR STREQUAL Ninja)
+ add_subdirectory(CMP0021)
+endif()
diff --git a/Tests/LinkFlags/CMakeLists.txt b/Tests/LinkFlags/CMakeLists.txt
index e06020c..4607035 100644
--- a/Tests/LinkFlags/CMakeLists.txt
+++ b/Tests/LinkFlags/CMakeLists.txt
@@ -13,6 +13,9 @@ set_property(TARGET LinkFlags_lib PROPERTY STATIC_LIBRARY_FLAGS ${pre}BADFLAG${o
add_library(LinkFlags_dll SHARED LinkFlagsLib.c)
set_property(TARGET LinkFlags_dll PROPERTY LINK_FLAGS ${pre}BADFLAG${obj})
+add_library(LinkFlags_mod MODULE LinkFlagsLib.c)
+set_property(TARGET LinkFlags_mod PROPERTY LINK_FLAGS ${pre}BADFLAG${obj})
+
add_executable(LinkFlags_exe LinkFlagsExe.c)
set_property(TARGET LinkFlags_exe PROPERTY LINK_FLAGS ${pre}BADFLAG${obj})
@@ -22,7 +25,13 @@ set_property(TARGET LinkFlags_lib_config PROPERTY STATIC_LIBRARY_FLAGS_${TEST_CO
add_library(LinkFlags_dll_config SHARED LinkFlagsLib.c)
set_property(TARGET LinkFlags_dll_config PROPERTY LINK_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG_${TEST_CONFIG}${obj})
+add_library(LinkFlags_mod_config MODULE LinkFlagsLib.c)
+set_property(TARGET LinkFlags_mod_config PROPERTY LINK_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG_${TEST_CONFIG}${obj})
+
add_executable(LinkFlags_exe_config LinkFlagsExe.c)
set_property(TARGET LinkFlags_exe_config PROPERTY LINK_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG_${TEST_CONFIG}${obj})
add_executable(LinkFlags LinkFlags.c)
+
+add_subdirectory(LinkerFlags)
+add_subdirectory(LinkerFlagsConfig)
diff --git a/Tests/LinkFlags/LinkerFlags/CMakeLists.txt b/Tests/LinkFlags/LinkerFlags/CMakeLists.txt
new file mode 100644
index 0000000..4707f47
--- /dev/null
+++ b/Tests/LinkFlags/LinkerFlags/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(CMAKE_STATIC_LINKER_FLAGS ${pre}BADFLAG${obj})
+add_library(LinkFlags_lib_flags STATIC ../LinkFlagsLib.c)
+
+set(CMAKE_SHARED_LINKER_FLAGS ${pre}BADFLAG${obj})
+add_library(LinkFlags_dll_flags SHARED ../LinkFlagsLib.c)
+
+set(CMAKE_MODULE_LINKER_FLAGS ${pre}BADFLAG${obj})
+add_library(LinkFlags_mod_flags MODULE ../LinkFlagsLib.c)
+
+set(CMAKE_EXE_LINKER_FLAGS ${pre}BADFLAG${obj})
+add_executable(LinkFlags_exe_flags ../LinkFlagsExe.c)
diff --git a/Tests/LinkFlags/LinkerFlagsConfig/CMakeLists.txt b/Tests/LinkFlags/LinkerFlagsConfig/CMakeLists.txt
new file mode 100644
index 0000000..2854fe7
--- /dev/null
+++ b/Tests/LinkFlags/LinkerFlagsConfig/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(CMAKE_STATIC_LINKER_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG${obj})
+add_library(LinkFlags_lib_flags_config STATIC ../LinkFlagsLib.c)
+
+set(CMAKE_SHARED_LINKER_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG${obj})
+add_library(LinkFlags_dll_flags_config SHARED ../LinkFlagsLib.c)
+
+set(CMAKE_MODULE_LINKER_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG${obj})
+add_library(LinkFlags_mod_flags_config MODULE ../LinkFlagsLib.c)
+
+set(CMAKE_EXE_LINKER_FLAGS_${TEST_CONFIG_UPPER} ${pre}BADFLAG${obj})
+add_executable(LinkFlags_exe_flags_config ../LinkFlagsExe.c)
diff --git a/Tests/RunCMake/CMP0004/CMP0004-NEW.cmake b/Tests/RunCMake/CMP0004/CMP0004-NEW.cmake
index 7c61961..f42d8e4 100644
--- a/Tests/RunCMake/CMP0004/CMP0004-NEW.cmake
+++ b/Tests/RunCMake/CMP0004/CMP0004-NEW.cmake
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
cmake_policy(SET CMP0004 NEW)
diff --git a/Tests/RunCMake/CMP0004/CMP0004-OLD.cmake b/Tests/RunCMake/CMP0004/CMP0004-OLD.cmake
index d6ed72c..3fa58b6 100644
--- a/Tests/RunCMake/CMP0004/CMP0004-OLD.cmake
+++ b/Tests/RunCMake/CMP0004/CMP0004-OLD.cmake
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
cmake_policy(SET CMP0004 OLD)
diff --git a/Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake b/Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake
index eab680a..2970476 100644
--- a/Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake
+++ b/Tests/RunCMake/CMP0004/CMP0004-policy-genex.cmake
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
cmake_policy(SET CMP0004 NEW)
diff --git a/Tests/RunCMake/CMP0004/CMakeLists.txt b/Tests/RunCMake/CMP0004/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/CMP0004/CMakeLists.txt
+++ b/Tests/RunCMake/CMP0004/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0019/CMakeLists.txt b/Tests/RunCMake/CMP0019/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/CMP0019/CMakeLists.txt
+++ b/Tests/RunCMake/CMP0019/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt
index 6c29057..ae7627e 100644
--- a/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt
+++ b/Tests/RunCMake/CMP0022/CMP0022-export-stderr.txt
@@ -1,4 +1,4 @@
CMake Error at CMP0022-export.cmake:11 \(export\):
Target "cmp0022NEW" has policy CMP0022 enabled, but also has old-style
- INTERFACE_LINK_LIBRARIES properties populated, but it was exported without
+ LINK_INTERFACE_LIBRARIES properties populated, but it was exported without
the EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties
diff --git a/Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt b/Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt
index 3425e8e..405dd8d 100644
--- a/Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt
+++ b/Tests/RunCMake/CMP0022/CMP0022-install-export-stderr.txt
@@ -1,4 +1,4 @@
CMake Error in CMakeLists.txt:
Target "cmp0022NEW" has policy CMP0022 enabled, but also has old-style
- INTERFACE_LINK_LIBRARIES properties populated, but it was exported without
+ LINK_INTERFACE_LIBRARIES properties populated, but it was exported without
the EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 6d1bca2..e45aba3 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -85,6 +85,7 @@ if(NOT WIN32)
endif()
endif()
add_RunCMake_test(CompatibleInterface)
+add_RunCMake_test(Syntax)
add_RunCMake_test(add_dependencies)
add_RunCMake_test(build_command)
@@ -98,6 +99,7 @@ add_RunCMake_test(try_compile)
add_RunCMake_test(variable_watch)
add_RunCMake_test(CMP0004)
add_RunCMake_test(TargetPolicies)
+add_RunCMake_test(alias_targets)
find_package(Qt4 QUIET)
find_package(Qt5Core QUIET)
diff --git a/Tests/RunCMake/CTest/CMakeLists.txt b/Tests/RunCMake/CTest/CMakeLists.txt
index f6e84c0..73e6a78 100644
--- a/Tests/RunCMake/CTest/CMakeLists.txt
+++ b/Tests/RunCMake/CTest/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
if(NOT NoProject)
project(${RunCMake_TEST} NONE)
endif()
diff --git a/Tests/RunCMake/CompatibleInterface/CMakeLists.txt b/Tests/RunCMake/CompatibleInterface/CMakeLists.txt
index 68dd8d6..f452db1 100644
--- a/Tests/RunCMake/CompatibleInterface/CMakeLists.txt
+++ b/Tests/RunCMake/CompatibleInterface/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CompilerChange/CMakeLists.txt b/Tests/RunCMake/CompilerChange/CMakeLists.txt
index 3b92518..b4b3016 100644
--- a/Tests/RunCMake/CompilerChange/CMakeLists.txt
+++ b/Tests/RunCMake/CompilerChange/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
if(NOT RunCMake_TEST)
set(RunCMake_TEST "$ENV{RunCMake_TEST}") # needed when cache is deleted
endif()
diff --git a/Tests/RunCMake/Configure/CMakeLists.txt b/Tests/RunCMake/Configure/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/Configure/CMakeLists.txt
+++ b/Tests/RunCMake/Configure/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/ExportWithoutLanguage/CMakeLists.txt b/Tests/RunCMake/ExportWithoutLanguage/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/ExportWithoutLanguage/CMakeLists.txt
+++ b/Tests/RunCMake/ExportWithoutLanguage/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/ExternalData/CMakeLists.txt b/Tests/RunCMake/ExternalData/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/ExternalData/CMakeLists.txt
+++ b/Tests/RunCMake/ExternalData/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/FPHSA/CMakeLists.txt b/Tests/RunCMake/FPHSA/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/FPHSA/CMakeLists.txt
+++ b/Tests/RunCMake/FPHSA/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/File_Generate/CMakeLists.txt b/Tests/RunCMake/File_Generate/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/File_Generate/CMakeLists.txt
+++ b/Tests/RunCMake/File_Generate/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/GeneratorExpression/CMakeLists.txt b/Tests/RunCMake/GeneratorExpression/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/GeneratorExpression/CMakeLists.txt
+++ b/Tests/RunCMake/GeneratorExpression/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/GeneratorToolset/CMakeLists.txt b/Tests/RunCMake/GeneratorToolset/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/GeneratorToolset/CMakeLists.txt
+++ b/Tests/RunCMake/GeneratorToolset/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/IncompatibleQt/CMakeLists.txt b/Tests/RunCMake/IncompatibleQt/CMakeLists.txt
index 68dd8d6..f452db1 100644
--- a/Tests/RunCMake/IncompatibleQt/CMakeLists.txt
+++ b/Tests/RunCMake/IncompatibleQt/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/Languages/CMakeLists.txt b/Tests/RunCMake/Languages/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/Languages/CMakeLists.txt
+++ b/Tests/RunCMake/Languages/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/Languages/LINK_LANGUAGE-genex.cmake b/Tests/RunCMake/Languages/LINK_LANGUAGE-genex.cmake
index d4e31cd..64f394c 100644
--- a/Tests/RunCMake/Languages/LINK_LANGUAGE-genex.cmake
+++ b/Tests/RunCMake/Languages/LINK_LANGUAGE-genex.cmake
@@ -1,4 +1,4 @@
-add_library(foo SHARED empty.cpp)
-add_library(bar SHARED empty.cpp)
+add_library(foo STATIC empty.cpp)
+add_library(bar STATIC empty.cpp)
target_link_libraries(foo $<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,anything>:bar>)
diff --git a/Tests/RunCMake/ObjectLibrary/CMakeLists.txt b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt
index a7f0779..a17c8cd 100644
--- a/Tests/RunCMake/ObjectLibrary/CMakeLists.txt
+++ b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} C)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt b/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt
index 22577da..90afc12 100644
--- a/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt
+++ b/Tests/RunCMake/PositionIndependentCode/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} CXX)
# MSVC creates extra targets which pollute the stderr unless we set this.
diff --git a/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt b/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt
+++ b/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/Syntax/.gitattributes b/Tests/RunCMake/Syntax/.gitattributes
new file mode 100644
index 0000000..fc9ebff
--- /dev/null
+++ b/Tests/RunCMake/Syntax/.gitattributes
@@ -0,0 +1 @@
+CommandTabs.cmake whitespace=-tab-in-indent
diff --git a/Tests/RunCMake/Syntax/BracketWarn-stderr.txt b/Tests/RunCMake/Syntax/BracketWarn-stderr.txt
new file mode 100644
index 0000000..4a9cca6
--- /dev/null
+++ b/Tests/RunCMake/Syntax/BracketWarn-stderr.txt
@@ -0,0 +1,35 @@
+CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+ Syntax Warning in cmake code at
+
+ .*/Tests/RunCMake/Syntax/BracketWarn.cmake:1:16
+
+ A future version of CMake may treat unquoted argument:
+
+ \[\[
+
+ as an opening long bracket. Double-quote the argument.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+ Syntax Warning in cmake code at
+
+ .*/Tests/RunCMake/Syntax/BracketWarn.cmake:1:19
+
+ A future version of CMake may treat unquoted argument:
+
+ \[=\[
+
+ as an opening long bracket. Double-quote the argument.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+ Syntax Warning in cmake code at
+
+ .*/Tests/RunCMake/Syntax/BracketWarn.cmake:1:27
+
+ A future version of CMake may treat unquoted argument:
+
+ \[==\[x
+
+ as an opening long bracket. Double-quote the argument.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/Syntax/BracketWarn-stdout.txt b/Tests/RunCMake/Syntax/BracketWarn-stdout.txt
new file mode 100644
index 0000000..01b2caa
--- /dev/null
+++ b/Tests/RunCMake/Syntax/BracketWarn-stdout.txt
@@ -0,0 +1 @@
+-- \[\[\[=\[\[=x\[==\[x
diff --git a/Tests/RunCMake/Syntax/BracketWarn.cmake b/Tests/RunCMake/Syntax/BracketWarn.cmake
new file mode 100644
index 0000000..8f33946
--- /dev/null
+++ b/Tests/RunCMake/Syntax/BracketWarn.cmake
@@ -0,0 +1 @@
+message(STATUS [[ [=[ [=x [==[x)
diff --git a/Tests/RunCMake/Syntax/CMakeLists.txt b/Tests/RunCMake/Syntax/CMakeLists.txt
new file mode 100644
index 0000000..618473a
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.9)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/Syntax/CommandComments-stderr.txt b/Tests/RunCMake/Syntax/CommandComments-stderr.txt
new file mode 100644
index 0000000..df72cc5
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandComments-stderr.txt
@@ -0,0 +1,4 @@
+Example Message
+Example Message
+Example Message
+Second Line of Example
diff --git a/Tests/RunCMake/Syntax/CommandComments.cmake b/Tests/RunCMake/Syntax/CommandComments.cmake
new file mode 100644
index 0000000..0fd7484
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandComments.cmake
@@ -0,0 +1,6 @@
+message("Example Message"#)
+ )
+message ("Example Message" # )
+ )
+message( "Example Message\n" # "Commented" )
+ "Second Line of Example")
diff --git a/Tests/RunCMake/include_directories/TargetInterfaceIncludes-result.txt b/Tests/RunCMake/Syntax/CommandError0-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/include_directories/TargetInterfaceIncludes-result.txt
+++ b/Tests/RunCMake/Syntax/CommandError0-result.txt
diff --git a/Tests/RunCMake/Syntax/CommandError0-stderr.txt b/Tests/RunCMake/Syntax/CommandError0-stderr.txt
new file mode 100644
index 0000000..24d7997
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandError0-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error: Error in cmake code at
+.*/Tests/RunCMake/Syntax/CommandError0.cmake:2:
+Parse error. Expected "\(", got newline with text "
+".
+CMake Error at CMakeLists.txt:3 \(include\):
+ include could not find load file:
+
+ CommandError0.cmake
diff --git a/Tests/RunCMake/Syntax/CommandError0.cmake b/Tests/RunCMake/Syntax/CommandError0.cmake
new file mode 100644
index 0000000..3222a97
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandError0.cmake
@@ -0,0 +1,2 @@
+message
+ ("Example Message")
diff --git a/Tests/RunCMake/Syntax/CommandError1-result.txt b/Tests/RunCMake/Syntax/CommandError1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandError1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/CommandError1-stderr.txt b/Tests/RunCMake/Syntax/CommandError1-stderr.txt
new file mode 100644
index 0000000..599f600
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandError1-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error: Error in cmake code at
+.*/Tests/RunCMake/Syntax/CommandError1.cmake:1:
+Parse error. Expected a newline, got identifier with text "message".
+CMake Error at CMakeLists.txt:3 \(include\):
+ include could not find load file:
+
+ CommandError1.cmake
diff --git a/Tests/RunCMake/Syntax/CommandError1.cmake b/Tests/RunCMake/Syntax/CommandError1.cmake
new file mode 100644
index 0000000..f8661a1
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandError1.cmake
@@ -0,0 +1 @@
+message("Example Message") message("Second Message")
diff --git a/Tests/RunCMake/Syntax/CommandNewlines-stderr.txt b/Tests/RunCMake/Syntax/CommandNewlines-stderr.txt
new file mode 100644
index 0000000..571b152
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandNewlines-stderr.txt
@@ -0,0 +1,3 @@
+Example Message
+Example Message
+Example Message
diff --git a/Tests/RunCMake/Syntax/CommandNewlines.cmake b/Tests/RunCMake/Syntax/CommandNewlines.cmake
new file mode 100644
index 0000000..0587afb
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandNewlines.cmake
@@ -0,0 +1,10 @@
+message(
+ "Example Message")
+message (
+ "Example Message"
+ )
+message(
+
+ "Example Message"
+
+ )
diff --git a/Tests/RunCMake/Syntax/CommandSpaces-stderr.txt b/Tests/RunCMake/Syntax/CommandSpaces-stderr.txt
new file mode 100644
index 0000000..54a8b38
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandSpaces-stderr.txt
@@ -0,0 +1,6 @@
+Example Message
+Example Message
+Example Message
+Example Message
+Example Message
+Example Message
diff --git a/Tests/RunCMake/Syntax/CommandSpaces.cmake b/Tests/RunCMake/Syntax/CommandSpaces.cmake
new file mode 100644
index 0000000..5bd4294
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandSpaces.cmake
@@ -0,0 +1,6 @@
+message("Example Message")
+message ("Example Message")
+message( "Example Message" )
+message( "Example Message")
+ message ( "Example Message")
+message ( Example " " Message )
diff --git a/Tests/RunCMake/Syntax/CommandTabs-stderr.txt b/Tests/RunCMake/Syntax/CommandTabs-stderr.txt
new file mode 100644
index 0000000..54a8b38
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandTabs-stderr.txt
@@ -0,0 +1,6 @@
+Example Message
+Example Message
+Example Message
+Example Message
+Example Message
+Example Message
diff --git a/Tests/RunCMake/Syntax/CommandTabs.cmake b/Tests/RunCMake/Syntax/CommandTabs.cmake
new file mode 100644
index 0000000..93876f8
--- /dev/null
+++ b/Tests/RunCMake/Syntax/CommandTabs.cmake
@@ -0,0 +1,6 @@
+message("Example Message")
+message ("Example Message")
+message( "Example Message" )
+message( "Example Message")
+ message ( "Example Message")
+message ( Example " " Message )
diff --git a/Tests/RunCMake/Syntax/ParenNoSpace-stderr.txt b/Tests/RunCMake/Syntax/ParenNoSpace-stderr.txt
new file mode 100644
index 0000000..10f3293
--- /dev/null
+++ b/Tests/RunCMake/Syntax/ParenNoSpace-stderr.txt
@@ -0,0 +1 @@
+^$
diff --git a/Tests/RunCMake/Syntax/ParenNoSpace-stdout.txt b/Tests/RunCMake/Syntax/ParenNoSpace-stdout.txt
new file mode 100644
index 0000000..72addd7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/ParenNoSpace-stdout.txt
@@ -0,0 +1,2 @@
+-- unquoted\(unquoted\)
+-- quoted\(quoted\)
diff --git a/Tests/RunCMake/Syntax/ParenNoSpace.cmake b/Tests/RunCMake/Syntax/ParenNoSpace.cmake
new file mode 100644
index 0000000..c690d96
--- /dev/null
+++ b/Tests/RunCMake/Syntax/ParenNoSpace.cmake
@@ -0,0 +1,2 @@
+message(STATUS unquoted(unquoted))
+message(STATUS "quoted"("quoted"))
diff --git a/Tests/RunCMake/Syntax/RunCMakeTest.cmake b/Tests/RunCMake/Syntax/RunCMakeTest.cmake
new file mode 100644
index 0000000..94963f3
--- /dev/null
+++ b/Tests/RunCMake/Syntax/RunCMakeTest.cmake
@@ -0,0 +1,18 @@
+include(RunCMake)
+
+run_cmake(CommandSpaces)
+run_cmake(CommandTabs)
+run_cmake(CommandNewlines)
+run_cmake(CommandComments)
+run_cmake(CommandError0)
+run_cmake(CommandError1)
+run_cmake(String0)
+run_cmake(String1)
+run_cmake(StringNoSpace)
+run_cmake(Unquoted0)
+run_cmake(Unquoted1)
+run_cmake(ParenNoSpace)
+run_cmake(UnterminatedCall1)
+run_cmake(UnterminatedCall2)
+run_cmake(UnterminatedString)
+run_cmake(BracketWarn)
diff --git a/Tests/RunCMake/Syntax/String0-stderr.txt b/Tests/RunCMake/Syntax/String0-stderr.txt
new file mode 100644
index 0000000..8eea069
--- /dev/null
+++ b/Tests/RunCMake/Syntax/String0-stderr.txt
@@ -0,0 +1 @@
+^1 2;3 4$
diff --git a/Tests/RunCMake/Syntax/String0.cmake b/Tests/RunCMake/Syntax/String0.cmake
new file mode 100644
index 0000000..95281d7
--- /dev/null
+++ b/Tests/RunCMake/Syntax/String0.cmake
@@ -0,0 +1,2 @@
+set(var 2 3)
+message("1 ${var} 4")
diff --git a/Tests/RunCMake/Syntax/String1-stderr.txt b/Tests/RunCMake/Syntax/String1-stderr.txt
new file mode 100644
index 0000000..07e98da
--- /dev/null
+++ b/Tests/RunCMake/Syntax/String1-stderr.txt
@@ -0,0 +1,3 @@
+^
+ 1 \${var} 4
+ $
diff --git a/Tests/RunCMake/Syntax/String1.cmake b/Tests/RunCMake/Syntax/String1.cmake
new file mode 100644
index 0000000..a94c9ff
--- /dev/null
+++ b/Tests/RunCMake/Syntax/String1.cmake
@@ -0,0 +1,3 @@
+message("
+ 1 \${var} 4
+ ")
diff --git a/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt b/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt
new file mode 100644
index 0000000..89c2d2a
--- /dev/null
+++ b/Tests/RunCMake/Syntax/StringNoSpace-stderr.txt
@@ -0,0 +1,19 @@
+CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+ Syntax Warning in cmake code at
+
+ .*/Tests/RunCMake/Syntax/StringNoSpace.cmake:2:28
+
+ Argument not separated from preceding token by whitespace.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\) at CMakeLists.txt:3 \(include\):
+ Syntax Warning in cmake code at
+
+ .*/Tests/RunCMake/Syntax/StringNoSpace.cmake:2:31
+
+ Argument not separated from preceding token by whitespace.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+\[1 \${var} \\n 4\]
+\[x\]
+\[y\]$
diff --git a/Tests/RunCMake/Syntax/StringNoSpace.cmake b/Tests/RunCMake/Syntax/StringNoSpace.cmake
new file mode 100644
index 0000000..76f22db
--- /dev/null
+++ b/Tests/RunCMake/Syntax/StringNoSpace.cmake
@@ -0,0 +1,4 @@
+# Quoted arguments may be immediately followed by another argument.
+foreach(x "1 \${var} \\n 4""x"y)
+ message("[${x}]")
+endforeach()
diff --git a/Tests/RunCMake/Syntax/Unquoted0-stderr.txt b/Tests/RunCMake/Syntax/Unquoted0-stderr.txt
new file mode 100644
index 0000000..ea68ebf
--- /dev/null
+++ b/Tests/RunCMake/Syntax/Unquoted0-stderr.txt
@@ -0,0 +1 @@
+^1234$
diff --git a/Tests/RunCMake/Syntax/Unquoted0.cmake b/Tests/RunCMake/Syntax/Unquoted0.cmake
new file mode 100644
index 0000000..c5314c9
--- /dev/null
+++ b/Tests/RunCMake/Syntax/Unquoted0.cmake
@@ -0,0 +1,2 @@
+set(var 2 3)
+message(1 ${var} 4)
diff --git a/Tests/RunCMake/Syntax/Unquoted1-stderr.txt b/Tests/RunCMake/Syntax/Unquoted1-stderr.txt
new file mode 100644
index 0000000..ff8194a
--- /dev/null
+++ b/Tests/RunCMake/Syntax/Unquoted1-stderr.txt
@@ -0,0 +1 @@
+^\[\]\[=\]\[\$\$\(MV\)-DSTR=" \[="\[;\]$
diff --git a/Tests/RunCMake/Syntax/Unquoted1.cmake b/Tests/RunCMake/Syntax/Unquoted1.cmake
new file mode 100644
index 0000000..0344fbd
--- /dev/null
+++ b/Tests/RunCMake/Syntax/Unquoted1.cmake
@@ -0,0 +1 @@
+message([] [=] [$ $(MV) -DSTR=" [=" [;])
diff --git a/Tests/RunCMake/Syntax/UnterminatedCall1-result.txt b/Tests/RunCMake/Syntax/UnterminatedCall1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedCall1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/UnterminatedCall1-stderr.txt b/Tests/RunCMake/Syntax/UnterminatedCall1-stderr.txt
new file mode 100644
index 0000000..281ce0d
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedCall1-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error: Error in cmake code at
+.*/Syntax/UnterminatedCall1.cmake:2:
+Parse error. Function missing ending "\)". End of file reached.
+CMake Error at CMakeLists.txt:3 \(include\):
+ include could not find load file:
+
+ UnterminatedCall1.cmake
diff --git a/Tests/RunCMake/Syntax/UnterminatedCall1.cmake b/Tests/RunCMake/Syntax/UnterminatedCall1.cmake
new file mode 100644
index 0000000..1166109
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedCall1.cmake
@@ -0,0 +1 @@
+message(
diff --git a/Tests/RunCMake/Syntax/UnterminatedCall2-result.txt b/Tests/RunCMake/Syntax/UnterminatedCall2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedCall2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/UnterminatedCall2-stderr.txt b/Tests/RunCMake/Syntax/UnterminatedCall2-stderr.txt
new file mode 100644
index 0000000..065de30
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedCall2-stderr.txt
@@ -0,0 +1,7 @@
+CMake Error: Error in cmake code at
+.*/Syntax/UnterminatedCall2.cmake:4:
+Parse error. Function missing ending "\)". End of file reached.
+CMake Error at CMakeLists.txt:3 \(include\):
+ include could not find load file:
+
+ UnterminatedCall2.cmake
diff --git a/Tests/RunCMake/Syntax/UnterminatedCall2.cmake b/Tests/RunCMake/Syntax/UnterminatedCall2.cmake
new file mode 100644
index 0000000..26e9e62
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedCall2.cmake
@@ -0,0 +1,3 @@
+set(var "\
+")
+message(
diff --git a/Tests/RunCMake/Syntax/UnterminatedString-result.txt b/Tests/RunCMake/Syntax/UnterminatedString-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedString-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/Syntax/UnterminatedString-stderr.txt b/Tests/RunCMake/Syntax/UnterminatedString-stderr.txt
new file mode 100644
index 0000000..d925032
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedString-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error: Error in cmake code at
+.*/Syntax/UnterminatedString.cmake:2:
+Parse error. Function missing ending "\)". Instead found unterminated string with text "\)
+".
+CMake Error at CMakeLists.txt:3 \(include\):
+ include could not find load file:
+
+ UnterminatedString.cmake$
diff --git a/Tests/RunCMake/Syntax/UnterminatedString.cmake b/Tests/RunCMake/Syntax/UnterminatedString.cmake
new file mode 100644
index 0000000..721ae75
--- /dev/null
+++ b/Tests/RunCMake/Syntax/UnterminatedString.cmake
@@ -0,0 +1 @@
+set(var ")
diff --git a/Tests/RunCMake/TargetPolicies/CMakeLists.txt b/Tests/RunCMake/TargetPolicies/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/TargetPolicies/CMakeLists.txt
+++ b/Tests/RunCMake/TargetPolicies/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt
index 22577da..90afc12 100644
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} CXX)
# MSVC creates extra targets which pollute the stderr unless we set this.
diff --git a/Tests/RunCMake/VisibilityPreset/CMakeLists.txt b/Tests/RunCMake/VisibilityPreset/CMakeLists.txt
index 22577da..90afc12 100644
--- a/Tests/RunCMake/VisibilityPreset/CMakeLists.txt
+++ b/Tests/RunCMake/VisibilityPreset/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} CXX)
# MSVC creates extra targets which pollute the stderr unless we set this.
diff --git a/Tests/RunCMake/add_dependencies/CMakeLists.txt b/Tests/RunCMake/add_dependencies/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/add_dependencies/CMakeLists.txt
+++ b/Tests/RunCMake/add_dependencies/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/alias_targets/CMakeLists.txt b/Tests/RunCMake/alias_targets/CMakeLists.txt
new file mode 100644
index 0000000..12cd3c7
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.4)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/alias_targets/RunCMakeTest.cmake b/Tests/RunCMake/alias_targets/RunCMakeTest.cmake
new file mode 100644
index 0000000..9a5eaaf
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/RunCMakeTest.cmake
@@ -0,0 +1,20 @@
+include(RunCMake)
+
+run_cmake(no-targets)
+run_cmake(multiple-targets)
+run_cmake(exclude-from-all)
+run_cmake(imported)
+run_cmake(invalid-name)
+run_cmake(invalid-target)
+run_cmake(imported-target)
+run_cmake(alias-target)
+run_cmake(set_property)
+run_cmake(set_target_properties)
+run_cmake(target_link_libraries)
+run_cmake(target_include_directories)
+run_cmake(export)
+run_cmake(install-export)
+run_cmake(name-conflict)
+run_cmake(add_dependencies)
+run_cmake(add_executable-library)
+run_cmake(add_library-executable)
diff --git a/Tests/RunCMake/alias_targets/add_dependencies-result.txt b/Tests/RunCMake/alias_targets/add_dependencies-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_dependencies-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/add_dependencies-stderr.txt b/Tests/RunCMake/alias_targets/add_dependencies-stderr.txt
new file mode 100644
index 0000000..53f2487
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_dependencies-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at add_dependencies.cmake:9 \(add_dependencies\):
+ Cannot add target-level dependencies to alias target "alias".
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/add_dependencies.cmake b/Tests/RunCMake/alias_targets/add_dependencies.cmake
new file mode 100644
index 0000000..7436371
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_dependencies.cmake
@@ -0,0 +1,9 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+add_library(bar empty.cpp)
+
+add_library(alias ALIAS foo)
+
+add_dependencies(alias bar)
diff --git a/Tests/RunCMake/alias_targets/add_executable-library-result.txt b/Tests/RunCMake/alias_targets/add_executable-library-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_executable-library-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/add_executable-library-stderr.txt b/Tests/RunCMake/alias_targets/add_executable-library-stderr.txt
new file mode 100644
index 0000000..eb22b3d
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_executable-library-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at add_executable-library.cmake:6 \(add_executable\):
+ add_executable cannot create ALIAS target "alias" because target "foo" is
+ not an executable.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/add_executable-library.cmake b/Tests/RunCMake/alias_targets/add_executable-library.cmake
new file mode 100644
index 0000000..e30f112
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_executable-library.cmake
@@ -0,0 +1,6 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_executable(alias ALIAS foo)
diff --git a/Tests/RunCMake/alias_targets/add_library-executable-result.txt b/Tests/RunCMake/alias_targets/add_library-executable-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_library-executable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/add_library-executable-stderr.txt b/Tests/RunCMake/alias_targets/add_library-executable-stderr.txt
new file mode 100644
index 0000000..ee290e4
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_library-executable-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at add_library-executable.cmake:6 \(add_library\):
+ add_library cannot create ALIAS target "alias" because target "foo" is not
+ a library.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/add_library-executable.cmake b/Tests/RunCMake/alias_targets/add_library-executable.cmake
new file mode 100644
index 0000000..22457a9
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/add_library-executable.cmake
@@ -0,0 +1,6 @@
+
+enable_language(CXX)
+
+add_executable(foo empty.cpp)
+
+add_library(alias ALIAS foo)
diff --git a/Tests/RunCMake/alias_targets/alias-target-result.txt b/Tests/RunCMake/alias_targets/alias-target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/alias-target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/alias-target-stderr.txt b/Tests/RunCMake/alias_targets/alias-target-stderr.txt
new file mode 100644
index 0000000..eae227a
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/alias-target-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at alias-target.cmake:8 \(add_library\):
+ add_library cannot create ALIAS target "next_alias" because target "alias"
+ is itself an ALIAS.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/alias-target.cmake b/Tests/RunCMake/alias_targets/alias-target.cmake
new file mode 100644
index 0000000..0b8da60
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/alias-target.cmake
@@ -0,0 +1,8 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(alias ALIAS foo)
+
+add_library(next_alias ALIAS alias)
diff --git a/Tests/RunCMake/alias_targets/empty.cpp b/Tests/RunCMake/alias_targets/empty.cpp
new file mode 100644
index 0000000..bfbbdde
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/alias_targets/exclude-from-all-result.txt b/Tests/RunCMake/alias_targets/exclude-from-all-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/exclude-from-all-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/exclude-from-all-stderr.txt b/Tests/RunCMake/alias_targets/exclude-from-all-stderr.txt
new file mode 100644
index 0000000..fce15d3
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/exclude-from-all-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at exclude-from-all.cmake:6 \(add_library\):
+ add_library EXCLUDE_FROM_ALL with ALIAS makes no sense.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/exclude-from-all.cmake b/Tests/RunCMake/alias_targets/exclude-from-all.cmake
new file mode 100644
index 0000000..0091918
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/exclude-from-all.cmake
@@ -0,0 +1,6 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(alias ALIAS EXCLUDE_FROM_ALL foo)
diff --git a/Tests/RunCMake/alias_targets/export-result.txt b/Tests/RunCMake/alias_targets/export-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/export-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/export-stderr.txt b/Tests/RunCMake/alias_targets/export-stderr.txt
new file mode 100644
index 0000000..848b984
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/export-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at export.cmake:8 \(export\):
+ export given ALIAS target "alias" which may not be exported.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/export.cmake b/Tests/RunCMake/alias_targets/export.cmake
new file mode 100644
index 0000000..dd84a80
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/export.cmake
@@ -0,0 +1,8 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(alias ALIAS foo)
+
+export(TARGETS alias FILE someFile.cmake)
diff --git a/Tests/RunCMake/alias_targets/imported-result.txt b/Tests/RunCMake/alias_targets/imported-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/imported-stderr.txt b/Tests/RunCMake/alias_targets/imported-stderr.txt
new file mode 100644
index 0000000..b905847
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at imported.cmake:2 \(add_library\):
+ add_library IMPORTED with ALIAS is not allowed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/imported-target-result.txt b/Tests/RunCMake/alias_targets/imported-target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/imported-target-stderr.txt b/Tests/RunCMake/alias_targets/imported-target-stderr.txt
new file mode 100644
index 0000000..bbff29a
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-target-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at imported-target.cmake:6 \(add_library\):
+ add_library cannot create ALIAS target "alias" because target "foo" is
+ IMPORTED.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/imported-target.cmake b/Tests/RunCMake/alias_targets/imported-target.cmake
new file mode 100644
index 0000000..7259ab0
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-target.cmake
@@ -0,0 +1,6 @@
+
+enable_language(CXX)
+
+add_library(foo SHARED IMPORTED)
+
+add_library(alias ALIAS foo)
diff --git a/Tests/RunCMake/alias_targets/imported.cmake b/Tests/RunCMake/alias_targets/imported.cmake
new file mode 100644
index 0000000..6a60591
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported.cmake
@@ -0,0 +1,2 @@
+
+add_library(alias IMPORTED ALIAS)
diff --git a/Tests/RunCMake/alias_targets/install-export-result.txt b/Tests/RunCMake/alias_targets/install-export-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/install-export-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/install-export-stderr.txt b/Tests/RunCMake/alias_targets/install-export-stderr.txt
new file mode 100644
index 0000000..3c3c0ed
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/install-export-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at install-export.cmake:8 \(install\):
+ install TARGETS given target "alias" which is an alias.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/install-export.cmake b/Tests/RunCMake/alias_targets/install-export.cmake
new file mode 100644
index 0000000..b1c6a4f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/install-export.cmake
@@ -0,0 +1,9 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(alias ALIAS foo)
+
+install(TARGETS alias EXPORT theTargets DESTINATION prefix)
+install(EXPORT theTargets DESTINATION lib/cmake)
diff --git a/Tests/RunCMake/alias_targets/invalid-name-result.txt b/Tests/RunCMake/alias_targets/invalid-name-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/invalid-name-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/invalid-name-stderr.txt b/Tests/RunCMake/alias_targets/invalid-name-stderr.txt
new file mode 100644
index 0000000..d33b57c
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/invalid-name-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at invalid-name.cmake:6 \(add_library\):
+ add_library Invalid name for ALIAS: invalid\$name
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/invalid-name.cmake b/Tests/RunCMake/alias_targets/invalid-name.cmake
new file mode 100644
index 0000000..bbd39e3
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/invalid-name.cmake
@@ -0,0 +1,6 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(invalid$name ALIAS foo)
diff --git a/Tests/RunCMake/alias_targets/invalid-target-result.txt b/Tests/RunCMake/alias_targets/invalid-target-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/invalid-target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/invalid-target-stderr.txt b/Tests/RunCMake/alias_targets/invalid-target-stderr.txt
new file mode 100644
index 0000000..342d488
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/invalid-target-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at invalid-target.cmake:2 \(add_library\):
+ add_library cannot create ALIAS target "alias" because target "foo" does
+ not already exist.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/invalid-target.cmake b/Tests/RunCMake/alias_targets/invalid-target.cmake
new file mode 100644
index 0000000..c43da61
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/invalid-target.cmake
@@ -0,0 +1,2 @@
+
+add_library(alias ALIAS foo)
diff --git a/Tests/RunCMake/alias_targets/multiple-targets-result.txt b/Tests/RunCMake/alias_targets/multiple-targets-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/multiple-targets-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/multiple-targets-stderr.txt b/Tests/RunCMake/alias_targets/multiple-targets-stderr.txt
new file mode 100644
index 0000000..596f404
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/multiple-targets-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at multiple-targets.cmake:7 \(add_library\):
+ add_library ALIAS requires exactly one target argument.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/multiple-targets.cmake b/Tests/RunCMake/alias_targets/multiple-targets.cmake
new file mode 100644
index 0000000..811eb7a
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/multiple-targets.cmake
@@ -0,0 +1,7 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+add_library(bar empty.cpp)
+
+add_library(alias ALIAS foo bar)
diff --git a/Tests/RunCMake/alias_targets/name-conflict-result.txt b/Tests/RunCMake/alias_targets/name-conflict-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/name-conflict-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/name-conflict-stderr.txt b/Tests/RunCMake/alias_targets/name-conflict-stderr.txt
new file mode 100644
index 0000000..3c0faa9
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/name-conflict-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at name-conflict.cmake:8 \(add_library\):
+ add_library cannot create target "bar" because an alias with the same name
+ already exists.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/name-conflict.cmake b/Tests/RunCMake/alias_targets/name-conflict.cmake
new file mode 100644
index 0000000..d21a092
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/name-conflict.cmake
@@ -0,0 +1,8 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(bar ALIAS foo)
+
+add_library(bar empty.cpp)
diff --git a/Tests/RunCMake/alias_targets/no-targets-result.txt b/Tests/RunCMake/alias_targets/no-targets-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/no-targets-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/no-targets-stderr.txt b/Tests/RunCMake/alias_targets/no-targets-stderr.txt
new file mode 100644
index 0000000..cdf7e57
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/no-targets-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at no-targets.cmake:4 \(add_library\):
+ add_library ALIAS requires exactly one target argument.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/no-targets.cmake b/Tests/RunCMake/alias_targets/no-targets.cmake
new file mode 100644
index 0000000..a5c5ee5
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/no-targets.cmake
@@ -0,0 +1,4 @@
+
+enable_language(CXX)
+
+add_library(alias ALIAS)
diff --git a/Tests/RunCMake/alias_targets/set_property-result.txt b/Tests/RunCMake/alias_targets/set_property-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/set_property-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/set_property-stderr.txt b/Tests/RunCMake/alias_targets/set_property-stderr.txt
new file mode 100644
index 0000000..e85aa56
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/set_property-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at set_property.cmake:8 \(set_property\):
+ set_property can not be used on an ALIAS target.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/set_property.cmake b/Tests/RunCMake/alias_targets/set_property.cmake
new file mode 100644
index 0000000..1f5e475
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/set_property.cmake
@@ -0,0 +1,8 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(alias ALIAS foo)
+
+set_property(TARGET alias PROPERTY ANYTHING 1)
diff --git a/Tests/RunCMake/alias_targets/set_target_properties-result.txt b/Tests/RunCMake/alias_targets/set_target_properties-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/set_target_properties-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/set_target_properties-stderr.txt b/Tests/RunCMake/alias_targets/set_target_properties-stderr.txt
new file mode 100644
index 0000000..8922c0d
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/set_target_properties-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at set_target_properties.cmake:8 \(set_target_properties\):
+ set_target_properties can not be used on an ALIAS target.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/set_target_properties.cmake b/Tests/RunCMake/alias_targets/set_target_properties.cmake
new file mode 100644
index 0000000..ee44d45
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/set_target_properties.cmake
@@ -0,0 +1,8 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(alias ALIAS foo)
+
+set_target_properties(alias PROPERTIES ANYTHING 1)
diff --git a/Tests/RunCMake/alias_targets/target_include_directories-result.txt b/Tests/RunCMake/alias_targets/target_include_directories-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/target_include_directories-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/target_include_directories-stderr.txt b/Tests/RunCMake/alias_targets/target_include_directories-stderr.txt
new file mode 100644
index 0000000..b8903b2
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/target_include_directories-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at target_include_directories.cmake:8 \(target_include_directories\):
+ target_include_directories can not be used on an ALIAS target.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/target_include_directories.cmake b/Tests/RunCMake/alias_targets/target_include_directories.cmake
new file mode 100644
index 0000000..c26830e
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/target_include_directories.cmake
@@ -0,0 +1,8 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+
+add_library(alias ALIAS foo)
+
+target_include_directories(alias PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
diff --git a/Tests/RunCMake/alias_targets/target_link_libraries-result.txt b/Tests/RunCMake/alias_targets/target_link_libraries-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/target_link_libraries-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/alias_targets/target_link_libraries-stderr.txt b/Tests/RunCMake/alias_targets/target_link_libraries-stderr.txt
new file mode 100644
index 0000000..2d7ff20
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/target_link_libraries-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at target_link_libraries.cmake:9 \(target_link_libraries\):
+ target_link_libraries can not be used on an ALIAS target.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/alias_targets/target_link_libraries.cmake b/Tests/RunCMake/alias_targets/target_link_libraries.cmake
new file mode 100644
index 0000000..b7b9e60
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/target_link_libraries.cmake
@@ -0,0 +1,9 @@
+
+enable_language(CXX)
+
+add_library(foo empty.cpp)
+add_library(bar empty.cpp)
+
+add_library(alias ALIAS foo)
+
+target_link_libraries(alias bar)
diff --git a/Tests/RunCMake/build_command/CMakeLists.txt b/Tests/RunCMake/build_command/CMakeLists.txt
index f6e84c0..73e6a78 100644
--- a/Tests/RunCMake/build_command/CMakeLists.txt
+++ b/Tests/RunCMake/build_command/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
if(NOT NoProject)
project(${RunCMake_TEST} NONE)
endif()
diff --git a/Tests/RunCMake/find_package/CMakeLists.txt b/Tests/RunCMake/find_package/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/find_package/CMakeLists.txt
+++ b/Tests/RunCMake/find_package/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/get_filename_component/CMakeLists.txt b/Tests/RunCMake/get_filename_component/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/get_filename_component/CMakeLists.txt
+++ b/Tests/RunCMake/get_filename_component/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/if/CMakeLists.txt b/Tests/RunCMake/if/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/if/CMakeLists.txt
+++ b/Tests/RunCMake/if/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/include/CMakeLists.txt b/Tests/RunCMake/include/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/include/CMakeLists.txt
+++ b/Tests/RunCMake/include/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/include_directories/CMakeLists.txt b/Tests/RunCMake/include_directories/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/include_directories/CMakeLists.txt
+++ b/Tests/RunCMake/include_directories/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/include_directories/RunCMakeTest.cmake b/Tests/RunCMake/include_directories/RunCMakeTest.cmake
index e582960..f0704f4 100644
--- a/Tests/RunCMake/include_directories/RunCMakeTest.cmake
+++ b/Tests/RunCMake/include_directories/RunCMakeTest.cmake
@@ -9,4 +9,4 @@ run_cmake(RelativePathInInterface)
run_cmake(ImportedTarget)
run_cmake(RelativePathInGenex)
run_cmake(CMP0021)
-run_cmake(TargetInterfaceIncludes)
+run_cmake(install_config)
diff --git a/Tests/RunCMake/include_directories/TargetInterfaceIncludes-stderr.txt b/Tests/RunCMake/include_directories/TargetInterfaceIncludes-stderr.txt
deleted file mode 100644
index d153927..0000000
--- a/Tests/RunCMake/include_directories/TargetInterfaceIncludes-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-CMake Error at TargetInterfaceIncludes.cmake:3 \(install\):
- install TARGETS given INCLUDES DESTINATION, but EXPORT set not specified.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/include_directories/TargetInterfaceIncludes.cmake b/Tests/RunCMake/include_directories/TargetInterfaceIncludes.cmake
deleted file mode 100644
index 92f31fc..0000000
--- a/Tests/RunCMake/include_directories/TargetInterfaceIncludes.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-
-add_library(empty empty.cpp)
-install(TARGETS empty DESTINATION lib INCLUDES DESTINATION include)
-# install(EXPORT )
diff --git a/Tests/RunCMake/include_directories/install_config-result.txt b/Tests/RunCMake/include_directories/install_config-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/include_directories/install_config-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/include_directories/install_config-stderr.txt b/Tests/RunCMake/include_directories/install_config-stderr.txt
new file mode 100644
index 0000000..ac7b7b0
--- /dev/null
+++ b/Tests/RunCMake/include_directories/install_config-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error in CMakeLists.txt:
+ Target "foo" is installed with INCLUDES DESTINATION set to a context
+ sensitive path. Paths which depend on the configuration, policy values or
+ the link interface are not supported. Consider using
+ target_include_directories instead.
diff --git a/Tests/RunCMake/include_directories/install_config.cmake b/Tests/RunCMake/include_directories/install_config.cmake
new file mode 100644
index 0000000..46c626c
--- /dev/null
+++ b/Tests/RunCMake/include_directories/install_config.cmake
@@ -0,0 +1,6 @@
+
+enable_language(CXX)
+
+add_executable(foo empty.cpp)
+install(TARGETS foo EXPORT fooTargets DESTINATION . INCLUDES DESTINATION include/$<CONFIGURATION>)
+install(EXPORT fooTargets DESTINATION lib/cmake)
diff --git a/Tests/RunCMake/include_external_msproject/CMakeLists.txt b/Tests/RunCMake/include_external_msproject/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/include_external_msproject/CMakeLists.txt
+++ b/Tests/RunCMake/include_external_msproject/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/list/CMakeLists.txt b/Tests/RunCMake/list/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/list/CMakeLists.txt
+++ b/Tests/RunCMake/list/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/target_link_libraries/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/target_link_libraries/CMakeLists.txt
+++ b/Tests/RunCMake/target_link_libraries/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/try_compile/CMakeLists.txt b/Tests/RunCMake/try_compile/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/try_compile/CMakeLists.txt
+++ b/Tests/RunCMake/try_compile/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/variable_watch/CMakeLists.txt b/Tests/RunCMake/variable_watch/CMakeLists.txt
index e8db6b0..12cd3c7 100644
--- a/Tests/RunCMake/variable_watch/CMakeLists.txt
+++ b/Tests/RunCMake/variable_watch/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/variable_watch/RunCMakeTest.cmake b/Tests/RunCMake/variable_watch/RunCMakeTest.cmake
index 8d20476..9becb4c 100644
--- a/Tests/RunCMake/variable_watch/RunCMakeTest.cmake
+++ b/Tests/RunCMake/variable_watch/RunCMakeTest.cmake
@@ -2,3 +2,4 @@ include(RunCMake)
run_cmake(ModifiedAccess)
run_cmake(NoWatcher)
+run_cmake(WatchTwice)
diff --git a/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt b/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt
new file mode 100644
index 0000000..fa7d347
--- /dev/null
+++ b/Tests/RunCMake/variable_watch/WatchTwice-stderr.txt
@@ -0,0 +1,2 @@
+From watch1
+From watch2
diff --git a/Tests/RunCMake/variable_watch/WatchTwice.cmake b/Tests/RunCMake/variable_watch/WatchTwice.cmake
new file mode 100644
index 0000000..540cfc1
--- /dev/null
+++ b/Tests/RunCMake/variable_watch/WatchTwice.cmake
@@ -0,0 +1,11 @@
+function (watch1)
+ message("From watch1")
+endfunction ()
+
+function (watch2)
+ message("From watch2")
+endfunction ()
+
+variable_watch(watched watch1)
+variable_watch(watched watch2)
+set(access "${watched}")
diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt
index b8f6b3c..91965e9 100644
--- a/Utilities/CMakeLists.txt
+++ b/Utilities/CMakeLists.txt
@@ -72,11 +72,11 @@ macro(ADD_DOCS target dependency)
endmacro()
# Help cmake-gui find the Qt DLLs on Windows.
-set(WIN_SHELL_GENS "Visual Studio|NMake|MinGW|Watcom|Borland")
-if(BUILD_QtDialog AND "${CMAKE_GENERATOR}" MATCHES "${WIN_SHELL_GENS}"
- AND EXISTS "${QT_QMAKE_EXECUTABLE}" AND NOT CMAKE_NO_AUTO_QT_ENV)
- get_filename_component(Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH)
- if(EXISTS "${Qt_BIN_DIR}/QtCore4.dll")
+if(TARGET cmake-gui)
+ get_property(Qt_BIN_DIR TARGET cmake-gui PROPERTY Qt_BIN_DIR)
+ set(WIN_SHELL_GENS "Visual Studio|NMake|MinGW|Watcom|Borland")
+ if(Qt_BIN_DIR AND "${CMAKE_GENERATOR}" MATCHES "${WIN_SHELL_GENS}"
+ AND NOT CMAKE_NO_AUTO_QT_ENV)
# Tell the macro to set the path before running cmake-gui.
string(REPLACE ";" "\\;" _PATH "PATH=${Qt_BIN_DIR};%PATH%")
set(cmake-gui-PATH COMMAND set "${_PATH}")
diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index ebf28ae..621888c 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -1,8 +1,5 @@
-#
-#
PROJECT(libarchive C)
#
-CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake")
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin)
@@ -39,13 +36,24 @@ SET(LIBARCHIVE_VERSION_STRING "${VERSION}")
# libarchive 2.8 == interface version 10 = 2 + 8
# libarchive 2.9 == interface version 11 = 2 + 9
# libarchive 3.0 == interface version 12
-# libarchive 3.x == interface version 12 + x
-math(EXPR INTERFACE_VERSION "12 + ${_minor}")
+# libarchive 3.1 == interface version 13
+math(EXPR INTERFACE_VERSION "13 + ${_minor}")
# Set SOVERSION == Interface version
# ?? Should there be more here ??
SET(SOVERSION "${INTERFACE_VERSION}")
+# Enalbe CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros
+# saving and restoring the state of the variables.
+INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake)
+
+# Initialize the state of the variables. This initialization is not
+# necessary but this shows you what value the variables initially have.
+SET(CMAKE_REQUIRED_DEFINITIONS)
+SET(CMAKE_REQUIRED_INCLUDES)
+SET(CMAKE_REQUIRED_LIBRARIES)
+SET(CMAKE_REQUIRED_FLAGS)
+
# Disable warnings to avoid changing 3rd party code.
IF("${CMAKE_C_COMPILER_ID}" MATCHES
"^(GNU|Clang|XL|VisualAge|SunPro|MIPSpro|HP|Intel)$")
@@ -125,7 +133,38 @@ MACRO (INSTALL_MAN __mans)
INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}")
ENDFOREACH (_man)
ENDMACRO (INSTALL_MAN __mans)
-
+#
+# Find out what macro is needed to use libraries on Windows.
+#
+MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES
+ TRY_TYPE SAMPLE_SOURCE MACRO_LIST)
+ IF(WIN32 AND NOT CYGWIN)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ SET(CMAKE_REQUIRED_INCLUDES ${INCLUDES})
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES})
+ FOREACH(VAR ${MACRO_LIST})
+ # Clear ${VAR} from CACHE If the libraries which ${VAR} was
+ # checked with are changed.
+ SET(VAR_WITH_LIB "${VAR}_WITH_LIB")
+ GET_PROPERTY(PREV_VAR_WITH_LIB VARIABLE PROPERTY ${VAR_WITH_LIB})
+ IF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}")
+ UNSET(${VAR} CACHE)
+ ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}")
+ # Check if the library can be used with the macro.
+ IF("${TRY_TYPE}" MATCHES "COMPILES")
+ CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR})
+ ELSEIF("${TRY_TYPE}" MATCHES "RUNS")
+ CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR})
+ ELSE("${TRY_TYPE}" MATCHES "COMPILES")
+ MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE")
+ ENDIF("${TRY_TYPE}" MATCHES "COMPILES")
+ # Save the libraries which ${VAR} is checked with.
+ SET(${VAR_WITH_LIB} "${LIBRARIES}" CACHE INTERNAL
+ "Macro ${VAR} is checked with")
+ ENDFOREACH(VAR)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ ENDIF(WIN32 AND NOT CYGWIN)
+ENDMACRO (TRY_MACRO_FOR_LIBRARY)
#
# Check compress/decompress libraries
#
@@ -172,13 +211,27 @@ IF(ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${ZLIB_LIBRARIES})
IF(WIN32 AND NOT CYGWIN)
- SET(CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIR})
- SET(CMAKE_REQUIRED_LIBRARIES ${ZLIB_LIBRARIES})
- CHECK_C_SOURCE_Runs(
- "#ifndef ZLIB_WINAPI\n#define ZLIB_WINAPI\n#endif\n#include <zlib.h>\nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }"
+ #
+ # Test if ZLIB_WINAPI macro is needed to use.
+ #
+ TRY_MACRO_FOR_LIBRARY(
+ "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}"
+ RUNS
+ "#include <zlib.h>\nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }"
ZLIB_WINAPI)
- SET(CMAKE_REQUIRED_INCLUDES)
- SET(CMAKE_REQUIRED_LIBRARIES)
+ IF(ZLIB_WINAPI)
+ ADD_DEFINITIONS(-DZLIB_WINAPI)
+ ELSE(ZLIB_WINAPI)
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}"
+ COMPILES
+ "#include <zlib.h>\nint main() {return zlibVersion()?1:0; }"
+ "ZLIB_DLL;WITHOUT_ZLIB_DLL")
+ IF(ZLIB_DLL)
+ ADD_DEFINITIONS(-DZLIB_DLL)
+ ENDIF(ZLIB_DLL)
+ ENDIF(ZLIB_WINAPI)
ENDIF(WIN32 AND NOT CYGWIN)
ELSE(ZLIB_FOUND)
MESSAGE(FATAL_ERROR "CMake requires zlib to be available to libarchive")
@@ -192,11 +245,21 @@ IF(BZIP2_FOUND)
SET(HAVE_BZLIB_H 1)
INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${BZIP2_LIBRARIES})
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${BZIP2_INCLUDE_DIR}" "${BZIP2_LIBRARIES}"
+ COMPILES
+ "#include <bzlib.h>\nint main() {return BZ2_bzlibVersion()?1:0; }"
+ "USE_BZIP2_DLL;USE_BZIP2_STATIC")
+ IF(USE_BZIP2_DLL)
+ ADD_DEFINITIONS(-DUSE_BZIP2_DLL)
+ ELSEIF(USE_BZIP2_STATIC)
+ ADD_DEFINITIONS(-DUSE_BZIP2_STATIC)
+ ENDIF(USE_BZIP2_DLL)
ENDIF(BZIP2_FOUND)
MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR)
-MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARY)
-
-IF(0) # CMake does not need LZMA support in libarchive
+MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES)
+IF(0) # CMake does not need LZMA or LZO2 support in libarchive
#
# Find LZMA
#
@@ -206,12 +269,45 @@ IF(LZMA_FOUND)
SET(HAVE_LZMA_H 1)
INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES})
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}"
+ COMPILES
+ "#include <lzma.h>\nint main() {return (int)lzma_version_number(); }"
+ "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC")
+ IF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC)
+ ADD_DEFINITIONS(-DLZMA_API_STATIC)
+ ENDIF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC)
ELSEIF(LZMADEC_FOUND)
SET(HAVE_LIBLZMADEC 1)
SET(HAVE_LZMADEC_H 1)
INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
ENDIF(LZMA_FOUND)
+#
+# Find LZO2
+#
+IF (LZO2_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZO2_FIND_QUIETLY TRUE)
+ENDIF (LZO2_INCLUDE_DIR)
+
+FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
+FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
+IF(LZO2_FOUND)
+ SET(HAVE_LIBLZO2 1)
+ SET(HAVE_LZO_LZOCONF_H 1)
+ SET(HAVE_LZO_LZO1X_H 1)
+ INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY})
+ #
+ # TODO: test for static library.
+ #
+ENDIF(LZO2_FOUND)
+MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY)
ENDIF()
#
@@ -261,6 +357,7 @@ LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H)
LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H)
LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H)
+LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H)
LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H)
LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H)
LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H)
@@ -311,14 +408,17 @@ CHECK_C_SOURCE_COMPILES(
# Find Nettle
#
IF(ENABLE_NETTLE)
- CHECK_LIBRARY_EXISTS(nettle "nettle_sha1_digest" "" NETTLE_FOUND)
+ FIND_PACKAGE(Nettle)
IF(NETTLE_FOUND)
- SET(CMAKE_REQUIRED_LIBRARIES "nettle")
- FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle)
- LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARY})
- ELSE(NETTLE_FOUND)
- SET(ENABLE_NETTLE OFF)
+ SET(HAVE_LIBNETTLE 1)
+ SET(HAVE_NETTLE_MD5_H 1)
+ SET(HAVE_NETTLE_RIPEMD160_H 1)
+ SET(HAVE_NETTLE_SHA_H 1)
+ INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES})
ENDIF(NETTLE_FOUND)
+ MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
+ MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
ENDIF(ENABLE_NETTLE)
#
@@ -332,12 +432,16 @@ ELSE()
ENDIF()
# FreeBSD libmd
-CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)
-IF(LIBMD_FOUND)
- SET(CMAKE_REQUIRED_LIBRARIES "md")
- FIND_LIBRARY(LIBMD_LIBRARY NAMES md)
- LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY})
-ENDIF(LIBMD_FOUND)
+IF(NOT OPENSSL_FOUND)
+ CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)
+ IF(LIBMD_FOUND)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ SET(CMAKE_REQUIRED_LIBRARIES "md")
+ FIND_LIBRARY(LIBMD_LIBRARY NAMES md)
+ LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY})
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ ENDIF(LIBMD_FOUND)
+ENDIF(NOT OPENSSL_FOUND)
#
# How to prove that CRYPTO functions, which have several names on various
@@ -345,13 +449,8 @@ ENDIF(LIBMD_FOUND)
# required libraries.
#
MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
- IF(HAVE_SYS_TYPES_H)
- SET(CRYPTO_HEADER_CONFIG "#define HAVE_SYS_TYPES_H 1\n")
- ELSE(HAVE_SYS_TYPES_H)
- SET(CRYPTO_HEADER_CONFIG "")
- ENDIF(HAVE_SYS_TYPES_H)
-
FOREACH(ALGORITHM ${ALGORITHMS})
+ IF(NOT ARCHIVE_CRYPTO_${ALGORITHM})
STRING(TOLOWER "${ALGORITHM}" lower_algorithm)
STRING(TOUPPER "${ALGORITHM}" algorithm)
IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND)
@@ -364,7 +463,7 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
# Probe the local implementation for whether this
# crypto implementation is available on this platform.
SET(TRY_CRYPTO_REQUIRED_INCLUDES
- "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
SET(TRY_CRYPTO_REQUIRED_LIBS)
IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
SET(TRY_CRYPTO_REQUIRED_INCLUDES
@@ -372,6 +471,8 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
SET(TRY_CRYPTO_REQUIRED_LIBS
"-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}")
ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NETTLE_FOUND)
+ SET(TRY_CRYPTO_REQUIRED_INCLUDES
+ "${TRY_CRYPTO_REQUIRED_INCLUDES};${NETTLE_INCLUDE_DIR}")
SET(TRY_CRYPTO_REQUIRED_LIBS
"-DLINK_LIBRARIES:STRING=${NETTLE_LIBRARY}")
ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND)
@@ -379,10 +480,15 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
"-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}")
ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
+ FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
+ CONFDEFS_H)
FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/libarchive/archive_crypto.c"
ARCHIVE_CRYPTO_C)
- SET(SOURCE "
+ SET(SOURCE "${CONFDEFS_H}
+
#define ARCHIVE_${algorithm}_COMPILE_TEST
#define ARCHIVE_CRYPTO_${algorithm}_${IMPLEMENTATION}
#define PLATFORM_CONFIG_H \"check_crypto_md.h\"
@@ -392,10 +498,10 @@ ${ARCHIVE_CRYPTO_C}
int
main(int argc, char **argv)
{
- archive_${lower_crypto}_ctx ctx;
- archive_${lower_crypto}_init(&ctx);
- archive_${lower_crypto}_update(&ctx, *argv, argc);
- archive_${lower_crypto}_final(&ctx, NULL);
+ archive_${lower_algorithm}_ctx ctx;
+ archive_${lower_algorithm}_init(&ctx);
+ archive_${lower_algorithm}_update(&ctx, *argv, argc);
+ archive_${lower_algorithm}_final(&ctx, NULL);
return 0;
}
")
@@ -404,10 +510,16 @@ main(int argc, char **argv)
FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}")
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}")
+ IF(CMAKE_REQUIRED_LINKER_FLAGS)
+ SET(CHECK_CRYPTO_ADD_LINKER_FLAGS
+ "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
+ ELSE(CMAKE_REQUIRED_LINKER_FLAGS)
+ SET(CHECK_CRYPTO_ADD_LINKER_FLAGS)
+ ENDIF(CMAKE_REQUIRED_LINKER_FLAGS)
TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c
- CMAKE_FLAGS
+ CMAKE_FLAGS ${CHECK_CRYPTO_ADD_LINKER_FLAGS}
"${TRY_CRYPTO_REQUIRED_LIBS}"
"${TRY_CRYPTO_REQUIRED_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
@@ -415,6 +527,7 @@ main(int argc, char **argv)
# Inform user whether or not we found it; if not, log why we didn't.
IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- found")
+ SET(ARCHIVE_CRYPTO_${ALGORITHM} 1)
ELSE (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- not found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
@@ -433,6 +546,7 @@ main(int argc, char **argv)
LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS)
ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+ ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM})
ENDFOREACH(ALGORITHM ${ALGORITHMS})
ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
@@ -448,6 +562,7 @@ ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
IF(WIN32 AND NOT CYGWIN)
FOREACH(CRYPTO ${CRYPTO_LIST})
+ IF(NOT ARCHIVE_CRYPTO_${CRYPTO})
IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
STRING(TOUPPER "${CRYPTO}" crypto)
SET(ALGID "")
@@ -467,9 +582,14 @@ MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
SET(ALGID "CALG_SHA_512")
ENDIF ("${CRYPTO}" MATCHES "^SHA512$")
- SET(SOURCE "#define ${crypto}_COMPILE_TEST
-#define _WIN32_WINNT ${_WIN32_WINNT}
-#define WINVER ${WINVER}
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
+ FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
+ CONFDEFS_H)
+
+ SET(SOURCE "${CONFDEFS_H}
+
+#define ${crypto}_COMPILE_TEST
#include <windows.h>
#include <wincrypt.h>
@@ -484,15 +604,22 @@ main(int argc, char **argv)
FILE(WRITE "${SOURCE_FILE}" "${SOURCE}")
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN")
+ IF(CMAKE_REQUIRED_LINKER_FLAGS)
+ SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS
+ "-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
+ ELSE(CMAKE_REQUIRED_LINKER_FLAGS)
+ SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS)
+ ENDIF(CMAKE_REQUIRED_LINKER_FLAGS)
TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN
${CMAKE_BINARY_DIR}
${SOURCE_FILE}
- CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive"
+ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" ${CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS}
OUTPUT_VARIABLE OUTPUT)
IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
MESSAGE(STATUS
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found")
+ SET(ARCHIVE_CRYPTO_${CRYPTO} 1)
ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
MESSAGE(STATUS
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found")
@@ -504,6 +631,7 @@ main(int argc, char **argv)
ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
+ ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO})
ENDFOREACH(CRYPTO)
ENDIF(WIN32 AND NOT CYGWIN)
ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
@@ -517,6 +645,20 @@ ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
#
MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
IF(NOT HAVE_ICONV)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
+ #
+ # During checking iconv proto type, we should use -Werror to avoid the
+ # success of iconv detection with a warnig which success is a miss
+ # detection. So this needs for all build mode(even it's a release mode).
+ #
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
+ ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
+ IF (MSVC)
+ # NOTE: /WX option is the same as gcc's -Werror option.
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX")
+ ENDIF (MSVC)
+ #
CHECK_C_SOURCE_COMPILES(
"#include <stdlib.h>
#include <iconv.h>
@@ -532,10 +674,12 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
SET(HAVE_ICONV true)
SET(ICONV_CONST ${TRY_ICONV_CONST})
ENDIF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST})
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ENDIF(NOT HAVE_ICONV)
ENDMACRO(CHECK_ICONV TRY_ICONV_CONST)
IF(ENABLE_ICONV)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
MARK_AS_ADVANCED(ICONV_INCLUDE_DIR)
IF(ICONV_INCLUDE_DIR)
@@ -547,9 +691,30 @@ IF(ENABLE_ICONV)
CHECK_ICONV("libc" "")
# If iconv isn't in libc and we have a libiconv, try that.
- FIND_LIBRARY(LIBICONV_PATH iconv)
+ FIND_LIBRARY(LIBICONV_PATH NAMES iconv libiconv)
IF(NOT HAVE_ICONV AND LIBICONV_PATH)
LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH})
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${ICONV_INCLUDE_DIR}" "${LIBICONV_PATH}"
+ COMPILES
+ "#include <iconv.h>\nint main() {return iconv_close((iconv_t)0);}"
+ "WITHOUT_LIBICONV_STATIC;LIBICONV_STATIC")
+ IF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC)
+ ADD_DEFINITIONS(-DLIBICONV_STATIC)
+ ENDIF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC)
+ #
+ # Set up CMAKE_REQUIRED_* for CHECK_ICONV
+ #
+ SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH})
+ IF(LIBICONV_STATIC)
+ # LIBICONV_STATIC is necessary for the success of CHECK_ICONV
+ # on Windows.
+ SET(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC")
+ ELSE(LIBICONV_STATIC)
+ SET(CMAKE_REQUIRED_DEFINITIONS)
+ ENDIF(LIBICONV_STATIC)
CHECK_ICONV("libiconv" "const")
CHECK_ICONV("libiconv" "")
IF (HAVE_ICONV)
@@ -561,19 +726,36 @@ IF(ENABLE_ICONV)
# Find locale_charset() for libiconv.
#
IF(LIBICONV_PATH)
+ SET(CMAKE_REQUIRED_DEFINITIONS)
+ SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_LIBRARIES)
CHECK_INCLUDE_FILES("localcharset.h" HAVE_LOCALCHARSET_H)
- CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET)
- IF(NOT HAVE_LOCALE_CHARSET)
- FIND_LIBRARY(LIBCHARSET_PATH charset)
- IF(LIBCHARSET_PATH)
- SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH})
+ FIND_LIBRARY(LIBCHARSET_PATH NAMES charset libcharset)
+ IF(LIBCHARSET_PATH)
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH})
+ IF(WIN32 AND NOT CYGWIN)
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${ICONV_INCLUDE_DIR}" "${LIBCHARSET_PATH}"
+ COMPILES
+ "#include <localcharset.h>\nint main() {return locale_charset()?1:0;}"
+ "WITHOUT_LIBCHARSET_STATIC;LIBCHARSET_STATIC")
+ IF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC)
+ ADD_DEFINITIONS(-DLIBCHARSET_STATIC)
+ ENDIF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC)
+ IF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC)
+ SET(HAVE_LOCALE_CHARSET ON CACHE INTERNAL
+ "Have function locale_charset")
+ ENDIF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC)
+ ELSE(WIN32 AND NOT CYGWIN)
CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET)
- IF(HAVE_LOCALE_CHARSET)
- LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH})
- ENDIF(HAVE_LOCALE_CHARSET)
- ENDIF(LIBCHARSET_PATH)
- ENDIF(NOT HAVE_LOCALE_CHARSET)
+ ENDIF(WIN32 AND NOT CYGWIN)
+ IF(HAVE_LOCALE_CHARSET)
+ LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH})
+ ENDIF(HAVE_LOCALE_CHARSET)
+ ENDIF(LIBCHARSET_PATH)
ENDIF(LIBICONV_PATH)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ELSE(ENABLE_ICONV)
# Make sure ICONV variables are not in CACHE after ENABLE_ICONV disabled
# (once enabled).
@@ -585,6 +767,10 @@ ELSE(ENABLE_ICONV)
UNSET(HAVE_ICONV_libiconv_const CACHE)
UNSET(ICONV_INCLUDE_DIR CACHE)
UNSET(LIBICONV_PATH CACHE)
+ UNSET(LIBICONV_DLL CACHE)
+ UNSET(LIBICONV_STATIC CACHE)
+ UNSET(LIBCHARSET_DLL CACHE)
+ UNSET(LIBCHARSET_STATIC CACHE)
ENDIF(ENABLE_ICONV)
IF(0) # CMake does not need XML support in libarchive
@@ -593,6 +779,7 @@ IF(0) # CMake does not need XML support in libarchive
#
FIND_PACKAGE(LibXml2)
IF(LIBXML2_FOUND)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LIBXML2_LIBRARIES})
SET(HAVE_LIBXML2 1)
@@ -600,31 +787,45 @@ IF(LIBXML2_FOUND)
SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H)
CHECK_INCLUDE_FILES("libxml/xmlwriter.h" HAVE_LIBXML_XMLWRITER_H)
- SET(CMAKE_REQUIRED_INCLUDES "")
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}"
+ "ws2_32.lib;${ZLIB_LIBRARIES};${LIBICONV_PATH};${LIBXML2_LIBRARIES}"
+ COMPILES
+ "#include <stddef.h>\n#include <libxml/xmlreader.h>\nint main() {return xmlTextReaderRead((xmlTextReaderPtr)(void *)0);}"
+ "WITHOUT_LIBXML_STATIC;LIBXML_STATIC")
+ IF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC)
+ ADD_DEFINITIONS(-DLIBXML_STATIC)
+ ENDIF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ELSE(LIBXML2_FOUND)
#
# Find Expat
#
FIND_PACKAGE(EXPAT)
IF(EXPAT_FOUND)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES})
SET(HAVE_LIBEXPAT 1)
LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ENDIF(EXPAT_FOUND)
ENDIF(LIBXML2_FOUND)
+MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES)
ENDIF()
#
# Check functions
#
+CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
#
# During checking functions, we should use -fno-builtin to avoid the
# failure of function detection which failure is an error "conflicting
# types for built-in function" caused by using -Werror option.
#
- SET(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-builtin")
ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode)
@@ -632,6 +833,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN)
CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
+CHECK_FUNCTION_EXISTS_GLIBC(dirfd HAVE_DIRFD)
CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD)
@@ -663,7 +865,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R)
CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT)
CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES)
CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC)
-CHECK_FUNCTION_EXISTS_GLIBC(mbsnrtowcs HAVE_MBSNRTOWCS)
CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE)
CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR)
CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO)
@@ -673,6 +874,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO)
CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT)
CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
+CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP)
CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT)
CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV)
@@ -697,7 +899,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB)
CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP)
CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY)
CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN)
-CHECK_FUNCTION_EXISTS_GLIBC(wcsnrtombs HAVE_WCSNRTOMBS)
CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB)
CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S)
CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64)
@@ -714,10 +915,7 @@ CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF)
CHECK_FUNCTION_EXISTS(wmemcmp HAVE_WMEMCMP)
CHECK_FUNCTION_EXISTS(wmemcpy HAVE_WMEMCPY)
-# Restore CMAKE_REQUIRED_FLAGS
-IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
- SET(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS})
-ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
+CMAKE_POP_CHECK_STATE() # Restore the state of the variables
# Make sure we have the POSIX version of readdir_r, not the
# older 2-argument version.
@@ -1036,6 +1234,8 @@ IF(ENABLE_ACL)
CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK)
CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
+ CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
+ CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
# MacOS has an acl.h that isn't POSIX. It can be detected by
# checking for ACL_USER
diff --git a/Utilities/cmlibarchive/README-CMake.txt b/Utilities/cmlibarchive/README-CMake.txt
index 45cb093..ab105f0 100644
--- a/Utilities/cmlibarchive/README-CMake.txt
+++ b/Utilities/cmlibarchive/README-CMake.txt
@@ -11,7 +11,7 @@ branch, but it is merged into our history.
Update libarchive from upstream as follows. Create a local branch to
explicitly reference the upstream snapshot branch head:
- git branch libarchive-upstream 4f4fe6e5
+ git branch libarchive-upstream 35df7c8b
Use a temporary directory to checkout the branch:
@@ -24,7 +24,7 @@ Use a temporary directory to checkout the branch:
Now place the (reduced) libarchive content in this directory. See
instructions shown by
- git log 4f4fe6e5
+ git log 35df7c8b
for help extracting the content from the upstream svn repo. Then run
the following commands to commit the new version. Substitute the
@@ -34,8 +34,8 @@ appropriate date and version number:
GIT_AUTHOR_NAME='LibArchive Upstream' \
GIT_AUTHOR_EMAIL='libarchive-discuss@googlegroups.com' \
- GIT_AUTHOR_DATE='2011-12-31 13:54:34 -0500' \
- git commit -m 'libarchive 3.0.2-r4051 (reduced)' &&
+ GIT_AUTHOR_DATE='2013-02-09 12:17:57 -0500' \
+ git commit -m 'libarchive 3.1.2 (reduced)' &&
git commit --amend
Edit the commit message to describe the procedure used to obtain the
diff --git a/Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake b/Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake
new file mode 100644
index 0000000..7985f2b
--- /dev/null
+++ b/Utilities/cmlibarchive/build/cmake/FindLibGCC.cmake
@@ -0,0 +1,22 @@
+# - Find libgcc
+# Find the libgcc library.
+#
+# LIBGCC_LIBRARIES - List of libraries when using libgcc
+# LIBGCC_FOUND - True if libgcc found.
+
+IF (LIBGCC_LIBRARY)
+ # Already in cache, be silent
+ SET(LIBGCC_FIND_QUIETLY TRUE)
+ENDIF (LIBGCC_LIBRARY)
+
+FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc)
+
+# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY)
+
+IF(LIBGCC_FOUND)
+ SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY})
+ SET(HAVE_LIBGCC 1)
+ENDIF(LIBGCC_FOUND)
diff --git a/Utilities/cmlibarchive/build/cmake/FindNettle.cmake b/Utilities/cmlibarchive/build/cmake/FindNettle.cmake
new file mode 100644
index 0000000..1f66610
--- /dev/null
+++ b/Utilities/cmlibarchive/build/cmake/FindNettle.cmake
@@ -0,0 +1,23 @@
+# - Find Nettle
+# Find the Nettle include directory and library
+#
+# NETTLE_INCLUDE_DIR - where to find <nettle/sha.h>, etc.
+# NETTLE_LIBRARIES - List of libraries when using libnettle.
+# NETTLE_FOUND - True if libnettle found.
+
+IF (NETTLE_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(NETTLE_FIND_QUIETLY TRUE)
+ENDIF (NETTLE_INCLUDE_DIR)
+
+FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h)
+FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle)
+
+# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR)
+
+IF(NETTLE_FOUND)
+ SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY})
+ENDIF(NETTLE_FOUND)
diff --git a/Utilities/cmlibarchive/build/cmake/FindPCREPOSIX.cmake b/Utilities/cmlibarchive/build/cmake/FindPCREPOSIX.cmake
new file mode 100644
index 0000000..7cc40ec
--- /dev/null
+++ b/Utilities/cmlibarchive/build/cmake/FindPCREPOSIX.cmake
@@ -0,0 +1,34 @@
+# - Find pcreposix
+# Find the native PCRE and PCREPOSIX include and libraries
+#
+# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc.
+# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix.
+# PCRE_LIBRARIES - List of libraries when using libpcre.
+# PCREPOSIX_FOUND - True if libpcreposix found.
+# PCRE_FOUND - True if libpcre found.
+
+IF (PCRE_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(PCRE_FIND_QUIETLY TRUE)
+ENDIF (PCRE_INCLUDE_DIR)
+
+FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h)
+FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix)
+FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre)
+
+# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY)
+
+IF(PCREPOSIX_FOUND)
+ SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY})
+ SET(HAVE_LIBPCREPOSIX 1)
+ SET(HAVE_PCREPOSIX_H 1)
+ENDIF(PCREPOSIX_FOUND)
+
+IF(PCRE_FOUND)
+ SET(PCRE_LIBRARIES ${PCRE_LIBRARY})
+ SET(HAVE_LIBPCRE 1)
+ENDIF(PCRE_FOUND)
diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in
index ff97cbd..750ae66 100644
--- a/Utilities/cmlibarchive/build/cmake/config.h.in
+++ b/Utilities/cmlibarchive/build/cmake/config.h.in
@@ -393,6 +393,9 @@ typedef uint64_t uintmax_t;
*/
#cmakedefine HAVE_DIRENT_H 1
+/* Define to 1 if you have the `dirfd' function. */
+#cmakedefine HAVE_DIRFD 1
+
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
@@ -579,12 +582,27 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `expat' library (-lexpat). */
#cmakedefine HAVE_LIBEXPAT 1
+/* Define to 1 if you have the `gcc' library (-lgcc). */
+#cmakedefine HAVE_LIBGCC 1
+
/* Define to 1 if you have the `lzma' library (-llzma). */
#cmakedefine HAVE_LIBLZMA 1
/* Define to 1 if you have the `lzmadec' library (-llzmadec). */
#cmakedefine HAVE_LIBLZMADEC 1
+/* Define to 1 if you have the `lzo2' library (-llzo2). */
+#cmakedefine HAVE_LIBLZO2 1
+
+/* Define to 1 if you have the `nettle' library (-lnettle). */
+#cmakedefine HAVE_LIBNETTLE 1
+
+/* Define to 1 if you have the `pcre' library (-lpcre). */
+#cmakedefine HAVE_LIBPCRE 1
+
+/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */
+#cmakedefine HAVE_LIBPCREPOSIX 1
+
/* Define to 1 if you have the `xml2' library (-lxml2). */
#cmakedefine HAVE_LIBXML2 1
@@ -615,6 +633,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <linux/magic.h> header file. */
#cmakedefine HAVE_LINUX_MAGIC_H 1
+/* Define to 1 if you have the <linux/types.h> header file. */
+#cmakedefine HAVE_LINUX_TYPES_H 1
+
/* Define to 1 if you have the `listea' function. */
#cmakedefine HAVE_LISTEA 1
@@ -664,12 +685,15 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <lzma.h> header file. */
#cmakedefine HAVE_LZMA_H 1
+/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
+#cmakedefine HAVE_LZO_LZO1X_H 1
+
+/* Define to 1 if you have the <lzo/lzoconf.h> header file. */
+#cmakedefine HAVE_LZO_LZOCONF_H 1
+
/* Define to 1 if you have the `mbrtowc' function. */
#cmakedefine HAVE_MBRTOWC 1
-/* Define to 1 if you have the `mbsnrtowcs' function. */
-#cmakedefine HAVE_MBSNRTOWCS 1
-
/* Define to 1 if you have the `memmove' function. */
#cmakedefine HAVE_MEMMOVE 1
@@ -691,6 +715,15 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#cmakedefine HAVE_NDIR_H 1
+/* Define to 1 if you have the <nettle/md5.h> header file. */
+#cmakedefine HAVE_NETTLE_MD5_H 1
+
+/* Define to 1 if you have the <nettle/ripemd160.h> header file. */
+#cmakedefine HAVE_NETTLE_RIPEMD160_H 1
+
+/* Define to 1 if you have the <nettle/sha.h> header file. */
+#cmakedefine HAVE_NETTLE_SHA_H 1
+
/* Define to 1 if you have the `nl_langinfo' function. */
#cmakedefine HAVE_NL_LANGINFO 1
@@ -700,6 +733,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <paths.h> header file. */
#cmakedefine HAVE_PATHS_H 1
+/* Define to 1 if you have the <pcreposix.h> header file. */
+#cmakedefine HAVE_PCREPOSIX_H 1
+
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1
@@ -709,6 +745,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <poll.h> header file. */
#cmakedefine HAVE_POLL_H 1
+/* Define to 1 if you have the `posix_spawnp' function. */
+#cmakedefine HAVE_POSIX_SPAWNP 1
+
/* Define to 1 if you have the <process.h> header file. */
#cmakedefine HAVE_PROCESS_H 1
@@ -742,6 +781,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <signal.h> header file. */
#cmakedefine HAVE_SIGNAL_H 1
+/* Define to 1 if you have the <spawn.h> header file. */
+#cmakedefine HAVE_SPAWN_H 1
+
/* Define to 1 if you have the `statfs' function. */
#cmakedefine HAVE_STATFS 1
@@ -952,9 +994,6 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `wcslen' function. */
#cmakedefine HAVE_WCSLEN 1
-/* Define to 1 if you have the `wcsnrtombs' function. */
-#cmakedefine HAVE_WCSNRTOMBS 1
-
/* Define to 1 if you have the `wctomb' function. */
#cmakedefine HAVE_WCTOMB 1
diff --git a/Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh b/Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh
index 95dbe16..925de5c 100644..100755
--- a/Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh
+++ b/Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh
@@ -1,10 +1,13 @@
#!/bin/sh
#
-# This needs http://unicode.org/Public/UNIDATA/UnicodeData.txt
+# This needs http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
#
inputfile="$1" # Expect UnicodeData.txt
outfile=archive_string_composition.h
pickout=/tmp/mk_unicode_composition_tbl$$.awk
+pickout2=/tmp/mk_unicode_composition_tbl2$$.awk
+#nfdtmp=/tmp/mk_unicode_decomposition_tmp$$.txt
+nfdtmp="nfdtmpx"
#################################################################################
#
# Append the file header of "archive_string_composition.h"
@@ -14,7 +17,7 @@ append_copyright()
{
cat > ${outfile} <<CR_END
/*-
- * Copyright (c) 2011 libarchive Project
+ * Copyright (c) 2011-2012 libarchive Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +47,7 @@ cat > ${outfile} <<CR_END
/*
* ATTENTION!
* This file is generated by build/utils/gen_archive_string_composition_h.sh
- * from http://unicode.org/Public/UNIDATA/UnicodeData.txt
+ * from http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
*
* See also http://unicode.org/report/tr15/
*/
@@ -76,6 +79,7 @@ BEGIN {
min = "";
max = "";
cmd="sort | awk -F ' ' '{printf \"\\\\t{ 0x%s , 0x%s , 0x%s },\\\\n\",\$1,\$2,\$3}'"
+ nfdtbl="${nfdtmp}"
print "static const struct unicode_composition_table u_composition_table[] = {"
}
END {
@@ -178,7 +182,6 @@ END {
}
print "};"
print ""
- print "#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */"
}
#
#
@@ -241,7 +244,7 @@ function hextoi(hex)
#}
#
# Exclusion code points specified by
-# http://unicode.org/Public/UNIDATA/CompositionExclusions.txt
+# http://unicode.org/Public/6.0.0/ucd/CompositionExclusions.txt
##
# 1. Script Specifices
##
@@ -404,6 +407,35 @@ function hextoi(hex)
print "0"cp[1], "0"cp[2], "0"\$1 | cmd
else
print cp[1], cp[2], \$1 | cmd
+ # NFC ==> NFD table.
+ if (length(\$1) == 4)
+ print "0"\$1, "0"cp[1], "0"cp[2] >>nfdtbl
+ else
+ print \$1, cp[1], cp[2] >>nfdtbl
+}
+AWK_END
+#################################################################################
+# awk script
+#
+#################################################################################
+cat > ${pickout2} <<AWK_END
+#
+BEGIN {
+ FS = " "
+ print "struct unicode_decomposition_table {"
+ print "\tuint32_t nfc;"
+ print "\tuint32_t cp1;"
+ print "\tuint32_t cp2;"
+ print "};"
+ print ""
+ print "static const struct unicode_decomposition_table u_decomposition_table[] = {"
+}
+END {
+ print "};"
+ print ""
+}
+{
+printf "\t{ 0x%s , 0x%s , 0x%s },\n", \$1, \$2, \$3;
}
AWK_END
#################################################################################
@@ -413,6 +445,11 @@ AWK_END
#################################################################################
append_copyright
awk -f ${pickout} ${inputfile} >> ${outfile}
+awk -f ${pickout2} ${nfdtmp} >> ${outfile}
+echo "#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */" >> ${outfile}
+echo "" >> ${outfile}
#
# Remove awk the script.
rm ${pickout}
+rm ${pickout2}
+rm ${nfdtmp}
diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version
index ee575c8..937b126 100644
--- a/Utilities/cmlibarchive/build/version
+++ b/Utilities/cmlibarchive/build/version
@@ -1 +1 @@
-3000002
+3001002
diff --git a/Utilities/cmlibarchive/libarchive/CMakeLists.txt b/Utilities/cmlibarchive/libarchive/CMakeLists.txt
index 7384195..42781bc 100644
--- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt
@@ -15,6 +15,9 @@ SET(include_HEADERS
SET(libarchive_SOURCES
archive_acl.c
archive_check_magic.c
+ archive_cmdline.c
+ archive_cmdline_private.h
+ archive_crc32.h
archive_crypto.c
archive_crypto_private.h
archive_endian.h
@@ -28,8 +31,12 @@ SET(libarchive_SOURCES
archive_entry_stat.c
archive_entry_strmode.c
archive_entry_xattr.c
+ archive_getdate.c
+ archive_match.c
archive_options.c
archive_options_private.h
+ archive_pathmatch.c
+ archive_pathmatch.h
archive_platform.h
archive_ppmd_private.h
archive_ppmd7.c
@@ -38,6 +45,7 @@ SET(libarchive_SOURCES
archive_rb.c
archive_rb.h
archive_read.c
+ archive_read_append_filter.c
archive_read_data_into_fd.c
archive_read_disk_entry_from_file.c
archive_read_disk_posix.c
@@ -49,11 +57,15 @@ SET(libarchive_SOURCES
archive_read_open_filename.c
archive_read_open_memory.c
archive_read_private.h
+ archive_read_set_format.c
archive_read_set_options.c
archive_read_support_filter_all.c
archive_read_support_filter_bzip2.c
archive_read_support_filter_compress.c
archive_read_support_filter_gzip.c
+ archive_read_support_filter_grzip.c
+ archive_read_support_filter_lrzip.c
+ archive_read_support_filter_lzop.c
archive_read_support_filter_none.c
archive_read_support_filter_program.c
archive_read_support_filter_rpm.c
@@ -81,6 +93,7 @@ SET(libarchive_SOURCES
archive_util.c
archive_virtual.c
archive_write.c
+ archive_write_disk_acl.c
archive_write_disk_posix.c
archive_write_disk_private.h
archive_write_disk_set_standard_lookup.c
@@ -89,11 +102,18 @@ SET(libarchive_SOURCES
archive_write_open_file.c
archive_write_open_filename.c
archive_write_open_memory.c
+ archive_write_add_filter.c
+ archive_write_add_filter_b64encode.c
+ archive_write_add_filter_by_name.c
archive_write_add_filter_bzip2.c
archive_write_add_filter_compress.c
+ archive_write_add_filter_grzip.c
archive_write_add_filter_gzip.c
+ archive_write_add_filter_lrzip.c
+ archive_write_add_filter_lzop.c
archive_write_add_filter_none.c
archive_write_add_filter_program.c
+ archive_write_add_filter_uuencode.c
archive_write_add_filter_xz.c
archive_write_set_format.c
archive_write_set_format_7zip.c
@@ -107,10 +127,11 @@ SET(libarchive_SOURCES
archive_write_set_format_pax.c
archive_write_set_format_shar.c
archive_write_set_format_ustar.c
+ archive_write_set_format_v7tar.c
archive_write_set_format_xar.c
archive_write_set_format_zip.c
archive_write_set_options.c
- filter_fork.c
+ filter_fork_posix.c
filter_fork.h
)
diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h
index 9b6b1b0..1a1d32a 100644
--- a/Utilities/cmlibarchive/libarchive/archive.h
+++ b/Utilities/cmlibarchive/libarchive/archive.h
@@ -63,13 +63,6 @@
# else
# define __LA_SSIZE_T long
# endif
-# if defined(__BORLANDC__)
-# define __LA_UID_T uid_t
-# define __LA_GID_T gid_t
-# else
-# define __LA_UID_T short
-# define __LA_GID_T short
-# endif
#else
# include <unistd.h> /* ssize_t, uid_t, and gid_t */
# if defined(_SCO_DS) || defined(__osf__)
@@ -78,8 +71,6 @@
# define __LA_INT64_T int64_t
# endif
# define __LA_SSIZE_T ssize_t
-# define __LA_UID_T uid_t
-# define __LA_GID_T gid_t
#endif
/*
@@ -113,6 +104,9 @@
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
#endif
+/* CMake uses some deprecated APIs to build with old libarchive versions. */
+#define __LA_DEPRECATED
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -134,13 +128,13 @@ extern "C" {
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3000002
+#define ARCHIVE_VERSION_NUMBER 3001002
__LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_STRING "libarchive 3.0.2"
+#define ARCHIVE_VERSION_STRING "libarchive 3.1.2"
__LA_DECL const char * archive_version_string(void);
/* Declare our basic types. */
@@ -210,6 +204,13 @@ typedef int archive_open_callback(struct archive *, void *_client_data);
typedef int archive_close_callback(struct archive *, void *_client_data);
+/* Switches from one client data object to the next/prev client data object.
+ * This is useful for reading from different data blocks such as a set of files
+ * that make up one large file.
+ */
+typedef int archive_switch_callback(struct archive *, void *_client_data1,
+ void *_client_data2);
+
/*
* Codes to identify various stream filters.
*/
@@ -223,6 +224,9 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_FILTER_UU 7
#define ARCHIVE_FILTER_RPM 8
#define ARCHIVE_FILTER_LZIP 9
+#define ARCHIVE_FILTER_LRZIP 10
+#define ARCHIVE_FILTER_LZOP 11
+#define ARCHIVE_FILTER_GRZIP 12
#if ARCHIVE_VERSION_NUMBER < 4000000
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
@@ -235,6 +239,7 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU
#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM
#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP
+#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP
#endif
/*
@@ -307,37 +312,49 @@ __LA_DECL struct archive *archive_read_new(void);
*/
#if ARCHIVE_VERSION_NUMBER < 4000000
-__LA_DECL int archive_read_support_compression_all(struct archive *);
-__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
-__LA_DECL int archive_read_support_compression_compress(struct archive *);
-__LA_DECL int archive_read_support_compression_gzip(struct archive *);
-__LA_DECL int archive_read_support_compression_lzip(struct archive *);
-__LA_DECL int archive_read_support_compression_lzma(struct archive *);
-__LA_DECL int archive_read_support_compression_none(struct archive *);
+__LA_DECL int archive_read_support_compression_all(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_bzip2(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_compress(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_gzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_lzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_lzma(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_none(struct archive *)
+ __LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_program(struct archive *,
- const char *command);
+ const char *command) __LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_program_signature
(struct archive *, const char *,
- const void * /* match */, size_t);
-
-__LA_DECL int archive_read_support_compression_rpm(struct archive *);
-__LA_DECL int archive_read_support_compression_uu(struct archive *);
-__LA_DECL int archive_read_support_compression_xz(struct archive *);
+ const void * /* match */, size_t) __LA_DEPRECATED;
+
+__LA_DECL int archive_read_support_compression_rpm(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_uu(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_xz(struct archive *)
+ __LA_DEPRECATED;
#endif
__LA_DECL int archive_read_support_filter_all(struct archive *);
__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
__LA_DECL int archive_read_support_filter_compress(struct archive *);
__LA_DECL int archive_read_support_filter_gzip(struct archive *);
+__LA_DECL int archive_read_support_filter_grzip(struct archive *);
+__LA_DECL int archive_read_support_filter_lrzip(struct archive *);
__LA_DECL int archive_read_support_filter_lzip(struct archive *);
__LA_DECL int archive_read_support_filter_lzma(struct archive *);
+__LA_DECL int archive_read_support_filter_lzop(struct archive *);
__LA_DECL int archive_read_support_filter_none(struct archive *);
__LA_DECL int archive_read_support_filter_program(struct archive *,
const char *command);
__LA_DECL int archive_read_support_filter_program_signature
- (struct archive *, const char *,
+ (struct archive *, const char * /* cmd */,
const void * /* match */, size_t);
-
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
__LA_DECL int archive_read_support_filter_uu(struct archive *);
__LA_DECL int archive_read_support_filter_xz(struct archive *);
@@ -359,6 +376,17 @@ __LA_DECL int archive_read_support_format_tar(struct archive *);
__LA_DECL int archive_read_support_format_xar(struct archive *);
__LA_DECL int archive_read_support_format_zip(struct archive *);
+/* Functions to manually set the format and filters to be used. This is
+ * useful to bypass the bidding process when the format and filters to use
+ * is known in advance.
+ */
+__LA_DECL int archive_read_set_format(struct archive *, int);
+__LA_DECL int archive_read_append_filter(struct archive *, int);
+__LA_DECL int archive_read_append_filter_program(struct archive *,
+ const char *);
+__LA_DECL int archive_read_append_filter_program_signature
+ (struct archive *, const char *, const void * /* match */, size_t);
+
/* Set various callbacks. */
__LA_DECL int archive_read_set_open_callback(struct archive *,
archive_open_callback *);
@@ -370,8 +398,23 @@ __LA_DECL int archive_read_set_skip_callback(struct archive *,
archive_skip_callback *);
__LA_DECL int archive_read_set_close_callback(struct archive *,
archive_close_callback *);
-/* The callback data is provided to all of the callbacks above. */
+/* Callback used to switch between one data object to the next */
+__LA_DECL int archive_read_set_switch_callback(struct archive *,
+ archive_switch_callback *);
+
+/* This sets the first data object. */
__LA_DECL int archive_read_set_callback_data(struct archive *, void *);
+/* This sets data object at specified index */
+__LA_DECL int archive_read_set_callback_data2(struct archive *, void *,
+ unsigned int);
+/* This adds a data object at the specified index. */
+__LA_DECL int archive_read_add_callback_data(struct archive *, void *,
+ unsigned int);
+/* This appends a data object to the end of list */
+__LA_DECL int archive_read_append_callback_data(struct archive *, void *);
+/* This prepends a data object to the beginning of list */
+__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *);
+
/* Opening freezes the callbacks. */
__LA_DECL int archive_read_open1(struct archive *);
@@ -391,11 +434,15 @@ __LA_DECL int archive_read_open2(struct archive *, void *_client_data,
/* Use this if you know the filename. Note: NULL indicates stdin. */
__LA_DECL int archive_read_open_filename(struct archive *,
const char *_filename, size_t _block_size);
+/* Use this for reading multivolume files by filenames.
+ * NOTE: Must be NULL terminated. Sorting is NOT done. */
+__LA_DECL int archive_read_open_filenames(struct archive *,
+ const char **_filenames, size_t _block_size);
__LA_DECL int archive_read_open_filename_w(struct archive *,
const wchar_t *_filename, size_t _block_size);
/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
__LA_DECL int archive_read_open_file(struct archive *,
- const char *_filename, size_t _block_size);
+ const char *_filename, size_t _block_size) __LA_DEPRECATED;
/* Read an archive that's stored in memory. */
__LA_DECL int archive_read_open_memory(struct archive *,
void * buff, size_t size);
@@ -427,6 +474,9 @@ __LA_DECL __LA_INT64_T archive_read_header_position(struct archive *);
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
void *, size_t);
+/* Seek within the body of an entry. Similar to lseek(2). */
+__LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int);
+
/*
* A zero-copy version of archive_read_data that also exposes the file offset
* of each returned block. Note that the client has no way to specify
@@ -510,6 +560,12 @@ __LA_DECL int archive_read_set_options(struct archive *_a,
/* Default: Do not restore Mac extended metadata. */
/* This has no effect except on Mac OS. */
#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000)
+/* Default: Use HFS+ compression if it was compressed. */
+/* This has no effect except on Mac OS v10.6 or later. */
+#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000)
+/* Default: Do not use HFS+ compression if it was not compressed. */
+/* This has no effect except on Mac OS v10.6 or later. */
+#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000)
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
int flags);
@@ -530,7 +586,7 @@ __LA_DECL int archive_read_close(struct archive *);
__LA_DECL int archive_read_free(struct archive *);
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Synonym for archive_read_free() for backwards compatibility. */
-__LA_DECL int archive_read_finish(struct archive *);
+__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED;
#endif
/*-
@@ -563,25 +619,41 @@ __LA_DECL int archive_write_set_skip_file(struct archive *,
__LA_INT64_T, __LA_INT64_T);
#if ARCHIVE_VERSION_NUMBER < 4000000
-__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
-__LA_DECL int archive_write_set_compression_compress(struct archive *);
-__LA_DECL int archive_write_set_compression_gzip(struct archive *);
-__LA_DECL int archive_write_set_compression_lzip(struct archive *);
-__LA_DECL int archive_write_set_compression_lzma(struct archive *);
-__LA_DECL int archive_write_set_compression_none(struct archive *);
+__LA_DECL int archive_write_set_compression_bzip2(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_compress(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_gzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_lzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_lzma(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_none(struct archive *)
+ __LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_program(struct archive *,
- const char *cmd);
-__LA_DECL int archive_write_set_compression_xz(struct archive *);
+ const char *cmd) __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_xz(struct archive *)
+ __LA_DEPRECATED;
#endif
+/* A convenience function to set the filter based on the code. */
+__LA_DECL int archive_write_add_filter(struct archive *, int filter_code);
+__LA_DECL int archive_write_add_filter_by_name(struct archive *,
+ const char *name);
+__LA_DECL int archive_write_add_filter_b64encode(struct archive *);
__LA_DECL int archive_write_add_filter_bzip2(struct archive *);
__LA_DECL int archive_write_add_filter_compress(struct archive *);
+__LA_DECL int archive_write_add_filter_grzip(struct archive *);
__LA_DECL int archive_write_add_filter_gzip(struct archive *);
+__LA_DECL int archive_write_add_filter_lrzip(struct archive *);
__LA_DECL int archive_write_add_filter_lzip(struct archive *);
__LA_DECL int archive_write_add_filter_lzma(struct archive *);
+__LA_DECL int archive_write_add_filter_lzop(struct archive *);
__LA_DECL int archive_write_add_filter_none(struct archive *);
__LA_DECL int archive_write_add_filter_program(struct archive *,
const char *cmd);
+__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
__LA_DECL int archive_write_add_filter_xz(struct archive *);
@@ -598,14 +670,18 @@ __LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
__LA_DECL int archive_write_set_format_gnutar(struct archive *);
__LA_DECL int archive_write_set_format_iso9660(struct archive *);
__LA_DECL int archive_write_set_format_mtree(struct archive *);
+__LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
__LA_DECL int archive_write_set_format_pax(struct archive *);
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
__LA_DECL int archive_write_set_format_shar(struct archive *);
__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
__LA_DECL int archive_write_set_format_ustar(struct archive *);
+__LA_DECL int archive_write_set_format_v7tar(struct archive *);
__LA_DECL int archive_write_set_format_xar(struct archive *);
__LA_DECL int archive_write_set_format_zip(struct archive *);
+__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
+__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
__LA_DECL int archive_write_open(struct archive *, void *,
archive_open_callback *, archive_write_callback *,
archive_close_callback *);
@@ -614,7 +690,8 @@ __LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
__LA_DECL int archive_write_open_filename_w(struct archive *,
const wchar_t *_file);
/* A deprecated synonym for archive_write_open_filename() */
-__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
+__LA_DECL int archive_write_open_file(struct archive *, const char *_file)
+ __LA_DEPRECATED;
__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
/* _buffSize is the size of the buffer, _used refers to a variable that
* will be updated after each write into the buffer. */
@@ -636,12 +713,16 @@ __LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
__LA_DECL int archive_write_finish_entry(struct archive *);
__LA_DECL int archive_write_close(struct archive *);
+/* Marks the archive as FATAL so that a subsequent free() operation
+ * won't try to close() cleanly. Provides a fast abort capability
+ * when the client discovers that things have gone wrong. */
+__LA_DECL int archive_write_fail(struct archive *);
/* This can fail if the archive wasn't already closed, in which case
* archive_write_free() will implicitly call archive_write_close(). */
__LA_DECL int archive_write_free(struct archive *);
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Synonym for archive_write_free() for backwards compatibility. */
-__LA_DECL int archive_write_finish(struct archive *);
+__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED;
#endif
/*
@@ -765,11 +846,42 @@ __LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *);
* traversal.
*/
__LA_DECL int archive_read_disk_descend(struct archive *);
+__LA_DECL int archive_read_disk_can_descend(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *);
/* Request that the access time of the entry visited by travesal be restored. */
__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
+/*
+ * Set behavior. The "flags" argument selects optional behavior.
+ */
+/* Request that the access time of the entry visited by travesal be restored.
+ * This is the same as archive_read_disk_set_atime_restored. */
+#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001)
+/* Default: Do not skip an entry which has nodump flags. */
+#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002)
+/* Default: Skip a mac resource fork file whose prefix is "._" because of
+ * using copyfile. */
+#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004)
+/* Default: Do not traverse mount points. */
+#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008)
+
+__LA_DECL int archive_read_disk_set_behavior(struct archive *,
+ int flags);
+
+/*
+ * Set archive_match object that will be used in archive_read_disk to
+ * know whether an entry should be skipped. The callback function
+ * _excluded_func will be invoked when an entry is skipped by the result
+ * of archive_match.
+ */
+__LA_DECL int archive_read_disk_set_matching(struct archive *,
+ struct archive *_matching, void (*_excluded_func)
+ (struct archive *, void *, struct archive_entry *),
+ void *_client_data);
+__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *,
+ int (*_metadata_filter_func)(struct archive *, void *,
+ struct archive_entry *), void *_client_data);
/*
* Accessor functions to read/set various information in
@@ -789,13 +901,17 @@ __LA_DECL const char * archive_filter_name(struct archive *, int);
/* These don't properly handle multiple filters, so are deprecated and
* will eventually be removed. */
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
-__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *);
+__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *)
+ __LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
-__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *);
+__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *)
+ __LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
-__LA_DECL const char *archive_compression_name(struct archive *);
+__LA_DECL const char *archive_compression_name(struct archive *)
+ __LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */
-__LA_DECL int archive_compression(struct archive *);
+__LA_DECL int archive_compression(struct archive *)
+ __LA_DEPRECATED;
#endif
__LA_DECL int archive_errno(struct archive *);
@@ -809,14 +925,116 @@ __LA_DECL void archive_copy_error(struct archive *dest,
struct archive *src);
__LA_DECL int archive_file_count(struct archive *);
+/*
+ * ARCHIVE_MATCH API
+ */
+__LA_DECL struct archive *archive_match_new(void);
+__LA_DECL int archive_match_free(struct archive *);
+
+/*
+ * Test if archive_entry is excluded.
+ * This is a convenience function. This is the same as calling all
+ * archive_match_path_excluded, archive_match_time_excluded
+ * and archive_match_owner_excluded.
+ */
+__LA_DECL int archive_match_excluded(struct archive *,
+ struct archive_entry *);
+
+/*
+ * Test if pathname is excluded. The conditions are set by following functions.
+ */
+__LA_DECL int archive_match_path_excluded(struct archive *,
+ struct archive_entry *);
+/* Add exclusion pathname pattern. */
+__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *);
+__LA_DECL int archive_match_exclude_pattern_w(struct archive *,
+ const wchar_t *);
+/* Add exclusion pathname pattern from file. */
+__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *,
+ const char *, int _nullSeparator);
+__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *,
+ const wchar_t *, int _nullSeparator);
+/* Add inclusion pathname pattern. */
+__LA_DECL int archive_match_include_pattern(struct archive *, const char *);
+__LA_DECL int archive_match_include_pattern_w(struct archive *,
+ const wchar_t *);
+/* Add inclusion pathname pattern from file. */
+__LA_DECL int archive_match_include_pattern_from_file(struct archive *,
+ const char *, int _nullSeparator);
+__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *,
+ const wchar_t *, int _nullSeparator);
+/*
+ * How to get statistic information for inclusion patterns.
+ */
+/* Return the amount number of unmatched inclusion patterns. */
+__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *);
+/* Return the pattern of unmatched inclusion with ARCHIVE_OK.
+ * Return ARCHIVE_EOF if there is no inclusion pattern. */
+__LA_DECL int archive_match_path_unmatched_inclusions_next(
+ struct archive *, const char **);
+__LA_DECL int archive_match_path_unmatched_inclusions_next_w(
+ struct archive *, const wchar_t **);
+
+/*
+ * Test if a file is excluded by its time stamp.
+ * The conditions are set by following functions.
+ */
+__LA_DECL int archive_match_time_excluded(struct archive *,
+ struct archive_entry *);
+
+/*
+ * Flags to tell a matching type of time stamps. These are used for
+ * following functinos.
+ */
+/* Time flag: mtime to be tested. */
+#define ARCHIVE_MATCH_MTIME (0x0100)
+/* Time flag: ctime to be tested. */
+#define ARCHIVE_MATCH_CTIME (0x0200)
+/* Comparison flag: Match the time if it is newer than. */
+#define ARCHIVE_MATCH_NEWER (0x0001)
+/* Comparison flag: Match the time if it is older than. */
+#define ARCHIVE_MATCH_OLDER (0x0002)
+/* Comparison flag: Match the time if it is equal to. */
+#define ARCHIVE_MATCH_EQUAL (0x0010)
+/* Set inclusion time. */
+__LA_DECL int archive_match_include_time(struct archive *, int _flag,
+ time_t _sec, long _nsec);
+/* Set inclusion time by a date string. */
+__LA_DECL int archive_match_include_date(struct archive *, int _flag,
+ const char *_datestr);
+__LA_DECL int archive_match_include_date_w(struct archive *, int _flag,
+ const wchar_t *_datestr);
+/* Set inclusion time by a particluar file. */
+__LA_DECL int archive_match_include_file_time(struct archive *,
+ int _flag, const char *_pathname);
+__LA_DECL int archive_match_include_file_time_w(struct archive *,
+ int _flag, const wchar_t *_pathname);
+/* Add exclusion entry. */
+__LA_DECL int archive_match_exclude_entry(struct archive *,
+ int _flag, struct archive_entry *);
+
+/*
+ * Test if a file is excluded by its uid ,gid, uname or gname.
+ * The conditions are set by following functions.
+ */
+__LA_DECL int archive_match_owner_excluded(struct archive *,
+ struct archive_entry *);
+/* Add inclusion uid, gid, uname and gname. */
+__LA_DECL int archive_match_include_uid(struct archive *, __LA_INT64_T);
+__LA_DECL int archive_match_include_gid(struct archive *, __LA_INT64_T);
+__LA_DECL int archive_match_include_uname(struct archive *, const char *);
+__LA_DECL int archive_match_include_uname_w(struct archive *,
+ const wchar_t *);
+__LA_DECL int archive_match_include_gname(struct archive *, const char *);
+__LA_DECL int archive_match_include_gname_w(struct archive *,
+ const wchar_t *);
+
#ifdef __cplusplus
}
#endif
/* These are meaningless outside of this header. */
#undef __LA_DECL
-#undef __LA_GID_T
-#undef __LA_UID_T
/* These need to remain defined because they're used in the
* callback type definitions. XXX Fix this. This is ugly. XXX */
diff --git a/Utilities/cmlibarchive/libarchive/archive_acl.c b/Utilities/cmlibarchive/libarchive/archive_acl.c
index 4747a4c..bf4b610 100644
--- a/Utilities/cmlibarchive/libarchive/archive_acl.c
+++ b/Utilities/cmlibarchive/libarchive/archive_acl.c
@@ -52,6 +52,9 @@ static int acl_special(struct archive_acl *acl,
int type, int permset, int tag);
static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl,
int type, int permset, int tag, int id);
+static int archive_acl_add_entry_len_l(struct archive_acl *acl,
+ int type, int permset, int tag, int id, const char *name,
+ size_t len, struct archive_string_conv *sc);
static int isint_w(const wchar_t *start, const wchar_t *end, int *result);
static int ismode_w(const wchar_t *start, const wchar_t *end, int *result);
static void next_field_w(const wchar_t **wp, const wchar_t **start,
@@ -65,7 +68,7 @@ static int isint(const char *start, const char *end, int *result);
static int ismode(const char *start, const char *end, int *result);
static void next_field(const char **p, const char **start,
const char **end, char *sep);
-static int prefix(const char *start, const char *end,
+static int prefix_c(const char *start, const char *end,
const char *test);
static void append_entry(char **p, const char *prefix, int tag,
const char *name, int perm, int id);
@@ -152,7 +155,7 @@ archive_acl_add_entry_w_len(struct archive_acl *acl,
return ARCHIVE_OK;
}
-int
+static int
archive_acl_add_entry_len_l(struct archive_acl *acl,
int type, int permset, int tag, int id, const char *name, size_t len,
struct archive_string_conv *sc)
@@ -419,8 +422,11 @@ archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int
*permset = acl->acl_p->permset;
*tag = acl->acl_p->tag;
*id = acl->acl_p->id;
- if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0)
+ if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0) {
+ if (errno == ENOMEM)
+ return (ARCHIVE_FATAL);
*name = NULL;
+ }
acl->acl_p = acl->acl_p->next;
return (ARCHIVE_OK);
}
@@ -438,7 +444,7 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
const wchar_t *prefix;
wchar_t separator;
struct archive_acl_entry *ap;
- int id;
+ int id, r;
wchar_t *wp;
if (acl->acl_text_w != NULL) {
@@ -458,9 +464,11 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
length += 8; /* "default:" */
length += 5; /* tag name */
length += 1; /* colon */
- if (archive_mstring_get_wcs(a, &ap->name, &wname) == 0 &&
- wname != NULL)
+ r = archive_mstring_get_wcs(a, &ap->name, &wname);
+ if (r == 0 && wname != NULL)
length += wcslen(wname);
+ else if (r < 0 && errno == ENOMEM)
+ return (NULL);
else
length += sizeof(uid_t) * 3 + 1;
length ++; /* colon */
@@ -484,7 +492,7 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
/* Now, allocate the string and actually populate it. */
wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t));
if (wp == NULL)
- __archive_errx(1, "No memory to generate the text version of the ACL");
+ return (NULL);
count = 0;
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
@@ -499,16 +507,19 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
ap = acl->acl_head;
while (ap != NULL) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0 &&
- archive_mstring_get_wcs(a, &ap->name, &wname) == 0) {
- *wp++ = separator;
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
- id = ap->id;
- else
- id = -1;
- append_entry_w(&wp, NULL, ap->tag, wname,
- ap->permset, id);
- count++;
+ if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
+ r = archive_mstring_get_wcs(a, &ap->name, &wname);
+ if (r == 0) {
+ *wp++ = separator;
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+ id = ap->id;
+ else
+ id = -1;
+ append_entry_w(&wp, NULL, ap->tag, wname,
+ ap->permset, id);
+ count++;
+ } else if (r < 0 && errno == ENOMEM)
+ return (NULL);
}
ap = ap->next;
}
@@ -523,17 +534,20 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
ap = acl->acl_head;
count = 0;
while (ap != NULL) {
- if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 &&
- archive_mstring_get_wcs(a, &ap->name, &wname) == 0) {
- if (count > 0)
- *wp++ = separator;
- if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
- id = ap->id;
- else
- id = -1;
- append_entry_w(&wp, prefix, ap->tag,
- wname, ap->permset, id);
- count ++;
+ if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
+ r = archive_mstring_get_wcs(a, &ap->name, &wname);
+ if (r == 0) {
+ if (count > 0)
+ *wp++ = separator;
+ if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
+ id = ap->id;
+ else
+ id = -1;
+ append_entry_w(&wp, prefix, ap->tag,
+ wname, ap->permset, id);
+ count ++;
+ } else if (r < 0 && errno == ENOMEM)
+ return (NULL);
}
ap = ap->next;
}
@@ -672,7 +686,7 @@ archive_acl_text_l(struct archive_acl *acl, int flags,
/* Now, allocate the string and actually populate it. */
p = acl->acl_text = (char *)malloc(length);
if (p == NULL)
- __archive_errx(1, "No memory to generate the text version of the ACL");
+ return (-1);
count = 0;
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
@@ -1088,7 +1102,7 @@ archive_acl_parse_l(struct archive_acl *acl,
type = default_type;
name.start = name.end = NULL;
- if (prefix(field[0].start, field[0].end, "user")) {
+ if (prefix_c(field[0].start, field[0].end, "user")) {
if (!ismode(field[2].start, field[2].end, &permset))
return (ARCHIVE_WARN);
if (id != -1 || field[1].start < field[1].end) {
@@ -1096,7 +1110,7 @@ archive_acl_parse_l(struct archive_acl *acl,
name = field[1];
} else
tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- } else if (prefix(field[0].start, field[0].end, "group")) {
+ } else if (prefix_c(field[0].start, field[0].end, "group")) {
if (!ismode(field[2].start, field[2].end, &permset))
return (ARCHIVE_WARN);
if (id != -1 || field[1].start < field[1].end) {
@@ -1104,7 +1118,7 @@ archive_acl_parse_l(struct archive_acl *acl,
name = field[1];
} else
tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- } else if (prefix(field[0].start, field[0].end, "other")) {
+ } else if (prefix_c(field[0].start, field[0].end, "other")) {
if (fields == 2
&& field[1].start < field[1].end
&& ismode(field[1].start, field[1].end, &permset)) {
@@ -1117,7 +1131,7 @@ archive_acl_parse_l(struct archive_acl *acl,
} else
return (ARCHIVE_WARN);
tag = ARCHIVE_ENTRY_ACL_OTHER;
- } else if (prefix(field[0].start, field[0].end, "mask")) {
+ } else if (prefix_c(field[0].start, field[0].end, "mask")) {
if (fields == 2
&& field[1].start < field[1].end
&& ismode(field[1].start, field[1].end, &permset)) {
@@ -1246,7 +1260,7 @@ next_field(const char **p, const char **start,
* This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
*/
static int
-prefix(const char *start, const char *end, const char *test)
+prefix_c(const char *start, const char *end, const char *test)
{
if (start == end)
return (0);
diff --git a/Utilities/cmlibarchive/libarchive/archive_check_magic.c b/Utilities/cmlibarchive/libarchive/archive_check_magic.c
index 9122955..c695e58 100644
--- a/Utilities/cmlibarchive/libarchive/archive_check_magic.c
+++ b/Utilities/cmlibarchive/libarchive/archive_check_magic.c
@@ -94,6 +94,7 @@ archive_handle_type_name(unsigned m)
case ARCHIVE_READ_MAGIC: return ("archive_read");
case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk");
case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk");
+ case ARCHIVE_MATCH_MAGIC: return ("archive_match");
default: return NULL;
}
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_cmdline.c b/Utilities/cmlibarchive/libarchive/archive_cmdline.c
new file mode 100644
index 0000000..7d3bac5
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_cmdline.c
@@ -0,0 +1,227 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#include "archive.h"
+#include "archive_cmdline_private.h"
+#include "archive_string.h"
+
+static int cmdline_set_path(struct archive_cmdline *, const char *);
+static int cmdline_add_arg(struct archive_cmdline *, const char *);
+
+static ssize_t
+extract_quotation(struct archive_string *as, const char *p)
+{
+ const char *s;
+
+ for (s = p + 1; *s;) {
+ if (*s == '\\') {
+ if (s[1] != '\0') {
+ archive_strappend_char(as, s[1]);
+ s += 2;
+ } else
+ s++;
+ } else if (*s == '"')
+ break;
+ else {
+ archive_strappend_char(as, s[0]);
+ s++;
+ }
+ }
+ if (*s != '"')
+ return (ARCHIVE_FAILED);/* Invalid sequence. */
+ return ((ssize_t)(s + 1 - p));
+}
+
+static ssize_t
+get_argument(struct archive_string *as, const char *p)
+{
+ const char *s = p;
+
+ archive_string_empty(as);
+
+ /* Skip beginning space characters. */
+ while (*s != '\0' && *s == ' ')
+ s++;
+ /* Copy non-space characters. */
+ while (*s != '\0' && *s != ' ') {
+ if (*s == '\\') {
+ if (s[1] != '\0') {
+ archive_strappend_char(as, s[1]);
+ s += 2;
+ } else {
+ s++;/* Ignore this character.*/
+ break;
+ }
+ } else if (*s == '"') {
+ ssize_t q = extract_quotation(as, s);
+ if (q < 0)
+ return (ARCHIVE_FAILED);/* Invalid sequence. */
+ s += q;
+ } else {
+ archive_strappend_char(as, s[0]);
+ s++;
+ }
+ }
+ return ((ssize_t)(s - p));
+}
+
+/*
+ * Set up command line arguments.
+ * Returns ARChIVE_OK if everything okey.
+ * Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
+ * empty command line.
+ * Returns ARChIVE_FATAL if no memory.
+ */
+int
+__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
+{
+ struct archive_string as;
+ const char *p;
+ ssize_t al;
+ int r;
+
+ archive_string_init(&as);
+
+ /* Get first argument as a command path. */
+ al = get_argument(&as, cmd);
+ if (al < 0) {
+ r = ARCHIVE_FAILED;/* Invalid sequence. */
+ goto exit_function;
+ }
+ if (archive_strlen(&as) == 0) {
+ r = ARCHIVE_FAILED;/* An empty command path. */
+ goto exit_function;
+ }
+ r = cmdline_set_path(data, as.s);
+ if (r != ARCHIVE_OK)
+ goto exit_function;
+ p = strrchr(as.s, '/');
+ if (p == NULL)
+ p = as.s;
+ else
+ p++;
+ r = cmdline_add_arg(data, p);
+ if (r != ARCHIVE_OK)
+ goto exit_function;
+ cmd += al;
+
+ for (;;) {
+ al = get_argument(&as, cmd);
+ if (al < 0) {
+ r = ARCHIVE_FAILED;/* Invalid sequence. */
+ goto exit_function;
+ }
+ if (al == 0)
+ break;
+ cmd += al;
+ if (archive_strlen(&as) == 0 && *cmd == '\0')
+ break;
+ r = cmdline_add_arg(data, as.s);
+ if (r != ARCHIVE_OK)
+ goto exit_function;
+ }
+ r = ARCHIVE_OK;
+exit_function:
+ archive_string_free(&as);
+ return (r);
+}
+
+/*
+ * Set the program path.
+ */
+static int
+cmdline_set_path(struct archive_cmdline *data, const char *path)
+{
+ char *newptr;
+
+ newptr = realloc(data->path, strlen(path) + 1);
+ if (newptr == NULL)
+ return (ARCHIVE_FATAL);
+ data->path = newptr;
+ strcpy(data->path, path);
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Add a argument for the program.
+ */
+static int
+cmdline_add_arg(struct archive_cmdline *data, const char *arg)
+{
+ char **newargv;
+
+ if (data->path == NULL)
+ return (ARCHIVE_FAILED);
+
+ newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
+ if (newargv == NULL)
+ return (ARCHIVE_FATAL);
+ data->argv = newargv;
+ data->argv[data->argc] = strdup(arg);
+ if (data->argv[data->argc] == NULL)
+ return (ARCHIVE_FATAL);
+ /* Set the terminator of argv. */
+ data->argv[++data->argc] = NULL;
+ return (ARCHIVE_OK);
+}
+
+struct archive_cmdline *
+__archive_cmdline_allocate(void)
+{
+ return (struct archive_cmdline *)
+ calloc(1, sizeof(struct archive_cmdline));
+}
+
+/*
+ * Release the resources.
+ */
+int
+__archive_cmdline_free(struct archive_cmdline *data)
+{
+
+ if (data) {
+ free(data->path);
+ if (data->argv != NULL) {
+ int i;
+ for (i = 0; data->argv[i] != NULL; i++)
+ free(data->argv[i]);
+ free(data->argv);
+ }
+ free(data);
+ }
+ return (ARCHIVE_OK);
+}
+
diff --git a/Utilities/cmlibarchive/libarchive/archive_cmdline_private.h b/Utilities/cmlibarchive/libarchive/archive_cmdline_private.h
new file mode 100644
index 0000000..4e409e8
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_cmdline_private.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST
+#error This header is only to be used internally to libarchive.
+#endif
+#endif
+
+#ifndef ARCHIVE_CMDLINE_PRIVATE_H
+#define ARCHIVE_CMDLINE_PRIVATE_H
+
+struct archive_cmdline {
+ char *path;
+ char **argv;
+ int argc;
+};
+
+struct archive_cmdline *__archive_cmdline_allocate(void);
+int __archive_cmdline_parse(struct archive_cmdline *, const char *);
+int __archive_cmdline_free(struct archive_cmdline *);
+
+#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_crypto.c b/Utilities/cmlibarchive/libarchive/archive_crypto.c
index 2caf571..85aba3a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_crypto.c
+++ b/Utilities/cmlibarchive/libarchive/archive_crypto.c
@@ -90,7 +90,7 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
static int
win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
{
- DWORD siglen = bufsize;
+ DWORD siglen = (DWORD)bufsize;
if (!ctx->valid)
return (ARCHIVE_FAILED);
@@ -1222,8 +1222,10 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
* 2. libc2
* 3. libc3
* 4. libSystem
- * 5. OpenSSL
- * 6. Windows API
+ * 5. Nettle
+ * 6. OpenSSL
+ * 7. libmd
+ * 8. Windows API
*/
const struct archive_crypto __archive_crypto =
{
diff --git a/Utilities/cmlibarchive/libarchive/archive_endian.h b/Utilities/cmlibarchive/libarchive/archive_endian.h
index 3c039f7..1c48563 100644
--- a/Utilities/cmlibarchive/libarchive/archive_endian.h
+++ b/Utilities/cmlibarchive/libarchive/archive_endian.h
@@ -160,8 +160,8 @@ archive_be64enc(void *pp, uint64_t u)
{
unsigned char *p = (unsigned char *)pp;
- archive_be32enc(p, u >> 32);
- archive_be32enc(p + 4, u & 0xffffffff);
+ archive_be32enc(p, (uint32_t)(u >> 32));
+ archive_be32enc(p + 4, (uint32_t)(u & 0xffffffff));
}
static inline void
@@ -189,8 +189,8 @@ archive_le64enc(void *pp, uint64_t u)
{
unsigned char *p = (unsigned char *)pp;
- archive_le32enc(p, u & 0xffffffff);
- archive_le32enc(p + 4, u >> 32);
+ archive_le32enc(p, (uint32_t)(u & 0xffffffff));
+ archive_le32enc(p + 4, (uint32_t)(u >> 32));
}
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.3 b/Utilities/cmlibarchive/libarchive/archive_entry.3
index 10e3c34..f77f385 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.3
@@ -23,9 +23,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $
+.\" $FreeBSD$
.\"
-.Dd Feburary 22, 2010
+.Dd Feburary 2, 2012
.Dt ARCHIVE_ENTRY 3
.Os
.Sh NAME
@@ -34,6 +34,8 @@
.Nm archive_entry_free ,
.Nm archive_entry_new ,
.Nd functions for managing archive entry descriptions
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft "struct archive_entry *"
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c
index cbdda8a..386e51d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.c
@@ -375,8 +375,11 @@ archive_entry_fflags_text(struct archive_entry *entry)
char *p;
if (archive_mstring_get_mbs(entry->archive,
- &entry->ae_fflags_text, &f) == 0 && f != NULL)
- return (f);
+ &entry->ae_fflags_text, &f) == 0) {
+ if (f != NULL)
+ return (f);
+ } else if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0)
return (NULL);
@@ -390,6 +393,8 @@ archive_entry_fflags_text(struct archive_entry *entry)
if (archive_mstring_get_mbs(entry->archive,
&entry->ae_fflags_text, &f) == 0)
return (f);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -405,6 +410,8 @@ archive_entry_gname(struct archive_entry *entry)
const char *p;
if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -414,6 +421,8 @@ archive_entry_gname_w(struct archive_entry *entry)
const wchar_t *p;
if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -428,9 +437,13 @@ const char *
archive_entry_hardlink(struct archive_entry *entry)
{
const char *p;
- if ((entry->ae_set & AE_SET_HARDLINK) && archive_mstring_get_mbs(
+ if ((entry->ae_set & AE_SET_HARDLINK) == 0)
+ return (NULL);
+ if (archive_mstring_get_mbs(
entry->archive, &entry->ae_hardlink, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -438,9 +451,13 @@ const wchar_t *
archive_entry_hardlink_w(struct archive_entry *entry)
{
const wchar_t *p;
- if ((entry->ae_set & AE_SET_HARDLINK) && archive_mstring_get_wcs(
+ if ((entry->ae_set & AE_SET_HARDLINK) == 0)
+ return (NULL);
+ if (archive_mstring_get_wcs(
entry->archive, &entry->ae_hardlink, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -511,6 +528,8 @@ archive_entry_pathname(struct archive_entry *entry)
if (archive_mstring_get_mbs(
entry->archive, &entry->ae_pathname, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -521,6 +540,8 @@ archive_entry_pathname_w(struct archive_entry *entry)
if (archive_mstring_get_wcs(
entry->archive, &entry->ae_pathname, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -584,6 +605,8 @@ archive_entry_sourcepath(struct archive_entry *entry)
if (archive_mstring_get_mbs(
entry->archive, &entry->ae_sourcepath, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -601,9 +624,13 @@ const char *
archive_entry_symlink(struct archive_entry *entry)
{
const char *p;
- if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_mbs(
+ if ((entry->ae_set & AE_SET_SYMLINK) == 0)
+ return (NULL);
+ if (archive_mstring_get_mbs(
entry->archive, &entry->ae_symlink, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -611,9 +638,13 @@ const wchar_t *
archive_entry_symlink_w(struct archive_entry *entry)
{
const wchar_t *p;
- if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_wcs(
+ if ((entry->ae_set & AE_SET_SYMLINK) == 0)
+ return (NULL);
+ if (archive_mstring_get_wcs(
entry->archive, &entry->ae_symlink, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -641,6 +672,8 @@ archive_entry_uname(struct archive_entry *entry)
const char *p;
if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -650,6 +683,8 @@ archive_entry_uname_w(struct archive_entry *entry)
const wchar_t *p;
if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0)
return (p);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (NULL);
}
@@ -730,6 +765,8 @@ archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_gname, name) == 0)
return (1);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (0);
}
@@ -796,6 +833,8 @@ archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *targ
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_hardlink, target) == 0)
return (1);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (0);
}
@@ -932,7 +971,11 @@ archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
else
r = archive_mstring_update_utf8(entry->archive,
&entry->ae_hardlink, target);
- return ((r == 0)? 1: 0);
+ if (r == 0)
+ return (1);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
+ return (0);
}
int
@@ -1005,6 +1048,8 @@ archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_pathname, name) == 0)
return (1);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (0);
}
@@ -1115,6 +1160,8 @@ archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkn
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_symlink, linkname) == 0)
return (1);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (0);
}
@@ -1164,6 +1211,8 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_uname, name) == 0)
return (1);
+ if (errno == ENOMEM)
+ __archive_errx(1, "No memory");
return (0);
}
@@ -1269,7 +1318,12 @@ int
archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
int *permset, int *tag, int *id, const char **name)
{
- return archive_acl_next(entry->archive, &entry->acl, want_type, type, permset, tag, id, name);
+ int r;
+ r = archive_acl_next(entry->archive, &entry->acl, want_type, type,
+ permset, tag, id, name);
+ if (r == ARCHIVE_FATAL && errno == ENOMEM)
+ __archive_errx(1, "No memory");
+ return (r);
}
/*
@@ -1279,7 +1333,11 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
const wchar_t *
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
{
- return archive_acl_text_w(entry->archive, &entry->acl, flags);
+ const wchar_t *r;
+ r = archive_acl_text_w(entry->archive, &entry->acl, flags);
+ if (r == NULL && errno == ENOMEM)
+ __archive_errx(1, "No memory");
+ return (r);
}
const char *
@@ -1288,7 +1346,7 @@ archive_entry_acl_text(struct archive_entry *entry, int flags)
const char *p;
if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
&& errno == ENOMEM)
- return (NULL);
+ __archive_errx(1, "No memory");
return (p);
}
@@ -1391,6 +1449,9 @@ static struct flag {
{ "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 },
{ "nouunlink", L"nouunlink", UF_NOUNLINK, 0 },
#endif
+#ifdef UF_COMPRESSED
+ { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
+#endif
#ifdef EXT2_UNRM_FL
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h
index 9c44e25..85ea885 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.h
@@ -29,7 +29,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3000002
+#define ARCHIVE_VERSION_NUMBER 3001002
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -47,21 +47,9 @@
#include <windows.h>
#endif
-/* Get appropriate definitions of standard POSIX-style types. */
-/* These should match the types used in 'struct stat' */
+/* Get a suitable 64-bit integer type. */
#if defined(_WIN32) && !defined(__CYGWIN__)
-#define __LA_INT64_T __int64
-# if defined(__BORLANDC__)
-# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */
-# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */
-# define __LA_DEV_T dev_t
-# define __LA_MODE_T mode_t
-# else
-# define __LA_UID_T short /* Remove in libarchive 3.2 */
-# define __LA_GID_T short /* Remove in libarchive 3.2 */
-# define __LA_DEV_T unsigned int
-# define __LA_MODE_T unsigned short
-# endif
+# define __LA_INT64_T __int64
#else
#include <unistd.h>
# if defined(_SCO_DS) || defined(__osf__)
@@ -69,17 +57,17 @@
# else
# define __LA_INT64_T int64_t
# endif
-# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */
-# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */
-# define __LA_DEV_T dev_t
-# define __LA_MODE_T mode_t
#endif
-/*
- * Remove this for libarchive 3.2, since ino_t is no longer used.
- */
-#define __LA_INO_T ino_t
-
+/* Get a suitable definition for mode_t */
+#if ARCHIVE_VERSION_NUMBER >= 3999000
+/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
+# define __LA_MODE_T int
+#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__)
+# define __LA_MODE_T unsigned short
+#else
+# define __LA_MODE_T mode_t
+#endif
/*
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
@@ -149,6 +137,10 @@ struct archive_entry;
* portable values to platform-native values when entries are read from
* or written to disk.
*/
+/*
+ * In libarchive 4.0, we can drop the casts here.
+ * They're needed to work around Borland C's broken mode_t.
+ */
#define AE_IFMT ((__LA_MODE_T)0170000)
#define AE_IFREG ((__LA_MODE_T)0100000)
#define AE_IFLNK ((__LA_MODE_T)0120000)
@@ -321,7 +313,10 @@ __LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char
* manipulate archives on systems different than the ones they were
* created on.
*
- * TODO: On Linux, provide both stat32 and stat64 versions of these functions.
+ * TODO: On Linux and other LFS systems, provide both stat32 and
+ * stat64 versions of these functions and all of the macro glue so
+ * that archive_entry_stat is magically defined to
+ * archive_entry_stat32 or archive_entry_stat64 as appropriate.
*/
__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *);
__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *);
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
index 93906e7..f5c3377 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 21, 2010
+.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_ACL 3
.Os
.Sh NAME
@@ -35,6 +35,8 @@
.Nm archive_entry_acl_reset ,
.Nm archive_entry_acl_text_w
.Nd functions for manipulating Access Control Lists in archive entry descriptions
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft void
@@ -132,7 +134,7 @@ All files have an access ACL
This specifies the permissions required for access to the file itself.
Directories have an additional ACL
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
-which controlls the initial access ACL for newly created directory entries.
+which controls the initial access ACL for newly created directory entries.
.Pp
.Fn archive_entry_acl_add_entry
and
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c b/Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c
index 7a4bc9c..77bf38e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c
@@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$");
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
__inline static void
-fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
+fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
{
ULARGE_INTEGER utc;
@@ -42,10 +42,10 @@ fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
utc.LowPart = filetime->dwLowDateTime;
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
- *time = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
+ *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
} else {
- *time = 0;
+ *t = 0;
*ns = 0;
}
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c b/Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c
index a18144d..c7d5949 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c
@@ -244,6 +244,9 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
* for future use.
*/
le = insert_entry(res, *e);
+ if (le == NULL)
+ /* XXX We should return an error code XXX */
+ return;
le->entry = *e;
*e = NULL;
}
@@ -362,7 +365,7 @@ insert_entry(struct archive_entry_linkresolver *res,
if (res->number_entries > res->number_buckets * 2)
grow_hash(res);
- hash = archive_entry_dev(entry) ^ archive_entry_ino64(entry);
+ hash = (size_t)(archive_entry_dev(entry) ^ archive_entry_ino64(entry));
bucket = hash & (res->number_buckets - 1);
/* If we could allocate the entry, record it. */
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_linkify.3 b/Utilities/cmlibarchive/libarchive/archive_entry_linkify.3
index a34b095..8c19fdd 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_linkify.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_linkify.3
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 20, 2010
+.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_LINKIFY 3
.Os
.Sh NAME
@@ -33,7 +33,7 @@
.Nm archive_entry_linkify
.Nd hardlink resolver functions
.Sh LIBRARY
-.Lb libarchive
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft struct archive_entry_linkresolver *
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 b/Utilities/cmlibarchive/libarchive/archive_entry_paths.3
index 621f655..51c8b8c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_paths.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_paths.3
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 22, 2010
+.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_PATHS 3
.Os
.Sh NAME
@@ -51,6 +51,8 @@
.Nm archive_entry_copy_symlink_w ,
.Nm archve_entry_update_symlink_utf8
.Nd functions for manipulating path names in archive entry descriptions
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft const char *
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 b/Utilities/cmlibarchive/libarchive/archive_entry_perms.3
index 164af97..5b7b5d9 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_perms.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_perms.3
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd February 22, 2010
+.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_PERMS 3
.Os
.Sh NAME
@@ -52,6 +52,8 @@
.Nm archive_entry_copy_fflags_text ,
.Nm archive_entry_copy_fflags_text_w
.Nd functions for manipulating ownership and permissions in archive entry descriptions
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft gid_t
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_stat.3 b/Utilities/cmlibarchive/libarchive/archive_entry_stat.3
index 36a7efb..84a4ea1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_stat.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_stat.3
@@ -22,8 +22,8 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 12, 2008
-.Dt ARCHIVE_ENTRY 3
+.Dd February 2, 2012
+.Dt ARCHIVE_ENTRY_STAT 3
.Os
.Sh NAME
.Nm archive_entry_stat ,
@@ -56,6 +56,8 @@
.Nm archive_entry_rdevminor ,
.Nm archive_entry_set_rdevminor ,
.Nd accessor functions for manipulating archive entry descriptions
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft const struct stat *
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_stat.c b/Utilities/cmlibarchive/libarchive/archive_entry_stat.c
index d5ed1cb..71a407b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_stat.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_stat.c
@@ -70,12 +70,12 @@ archive_entry_stat(struct archive_entry *entry)
st->st_ctime = archive_entry_ctime(entry);
st->st_mtime = archive_entry_mtime(entry);
st->st_dev = archive_entry_dev(entry);
- st->st_gid = archive_entry_gid(entry);
- st->st_uid = archive_entry_uid(entry);
- st->st_ino = archive_entry_ino64(entry);
+ st->st_gid = (gid_t)archive_entry_gid(entry);
+ st->st_uid = (uid_t)archive_entry_uid(entry);
+ st->st_ino = (ino_t)archive_entry_ino64(entry);
st->st_nlink = archive_entry_nlink(entry);
st->st_rdev = archive_entry_rdev(entry);
- st->st_size = archive_entry_size(entry);
+ st->st_size = (off_t)archive_entry_size(entry);
st->st_mode = archive_entry_mode(entry);
/*
@@ -110,7 +110,7 @@ archive_entry_stat(struct archive_entry *entry)
/*
* TODO: On Linux, store 32 or 64 here depending on whether
* the cached stat structure is a stat32 or a stat64. This
- * will allow us to support both variants interchangably.
+ * will allow us to support both variants interchangeably.
*/
entry->stat_valid = 1;
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_time.3 b/Utilities/cmlibarchive/libarchive/archive_entry_time.3
index 85a8209..17c658a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_time.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_time.3
@@ -23,9 +23,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $
+.\" $FreeBSD$
.\"
-.Dd February 21, 2010
+.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_TIME 3
.Os
.Sh NAME
@@ -50,6 +50,8 @@
.Nm archive_entry_set_mtime ,
.Nm archive_entry_unset_mtime ,
.Nd functions for manipulating times in archive entry descriptions
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft time_t
diff --git a/Utilities/cmlibarchive/libarchive/archive_getdate.c b/Utilities/cmlibarchive/libarchive/archive_getdate.c
new file mode 100644
index 0000000..f8b5a28
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_getdate.c
@@ -0,0 +1,1037 @@
+/*
+ * This code is in the public domain and has no copyright.
+ *
+ * This is a plain C recursive-descent translation of an old
+ * public-domain YACC grammar that has been used for parsing dates in
+ * very many open-source projects.
+ *
+ * Since the original authors were generous enough to donate their
+ * work to the public domain, I feel compelled to match their
+ * generosity.
+ *
+ * Tim Kientzle, February 2009.
+ */
+
+/*
+ * Header comment from original getdate.y:
+ */
+
+/*
+** Originally written by Steven M. Bellovin <smb@research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**
+** This grammar has 10 shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+
+#ifdef __FreeBSD__
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+/* This file defines a single public function. */
+time_t __archive_get_date(time_t now, char *);
+
+/* Basic time units. */
+#define EPOCH 1970
+#define MINUTE (60L)
+#define HOUR (60L * MINUTE)
+#define DAY (24L * HOUR)
+
+/* Daylight-savings mode: on, off, or not yet known. */
+enum DSTMODE { DSTon, DSToff, DSTmaybe };
+/* Meridian: am or pm. */
+enum { tAM, tPM };
+/* Token types returned by nexttoken() */
+enum { tAGO = 260, tDAY, tDAYZONE, tAMPM, tMONTH, tMONTH_UNIT, tSEC_UNIT,
+ tUNUMBER, tZONE, tDST };
+struct token { int token; time_t value; };
+
+/*
+ * Parser state.
+ */
+struct gdstate {
+ struct token *tokenp; /* Pointer to next token. */
+ /* HaveXxxx counts how many of this kind of phrase we've seen;
+ * it's a fatal error to have more than one time, zone, day,
+ * or date phrase. */
+ int HaveYear;
+ int HaveMonth;
+ int HaveDay;
+ int HaveWeekDay; /* Day of week */
+ int HaveTime; /* Hour/minute/second */
+ int HaveZone; /* timezone and/or DST info */
+ int HaveRel; /* time offset; we can have more than one */
+ /* Absolute time values. */
+ time_t Timezone; /* Seconds offset from GMT */
+ time_t Day;
+ time_t Hour;
+ time_t Minutes;
+ time_t Month;
+ time_t Seconds;
+ time_t Year;
+ /* DST selection */
+ enum DSTMODE DSTmode;
+ /* Day of week accounting, e.g., "3rd Tuesday" */
+ time_t DayOrdinal; /* "3" in "3rd Tuesday" */
+ time_t DayNumber; /* "Tuesday" in "3rd Tuesday" */
+ /* Relative time values: hour/day/week offsets are measured in
+ * seconds, month/year are counted in months. */
+ time_t RelMonth;
+ time_t RelSeconds;
+};
+
+/*
+ * A series of functions that recognize certain common time phrases.
+ * Each function returns 1 if it managed to make sense of some of the
+ * tokens, zero otherwise.
+ */
+
+/*
+ * hour:minute or hour:minute:second with optional AM, PM, or numeric
+ * timezone offset
+ */
+static int
+timephrase(struct gdstate *gds)
+{
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == ':'
+ && gds->tokenp[2].token == tUNUMBER
+ && gds->tokenp[3].token == ':'
+ && gds->tokenp[4].token == tUNUMBER) {
+ /* "12:14:18" or "22:08:07" */
+ ++gds->HaveTime;
+ gds->Hour = gds->tokenp[0].value;
+ gds->Minutes = gds->tokenp[2].value;
+ gds->Seconds = gds->tokenp[4].value;
+ gds->tokenp += 5;
+ }
+ else if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == ':'
+ && gds->tokenp[2].token == tUNUMBER) {
+ /* "12:14" or "22:08" */
+ ++gds->HaveTime;
+ gds->Hour = gds->tokenp[0].value;
+ gds->Minutes = gds->tokenp[2].value;
+ gds->Seconds = 0;
+ gds->tokenp += 3;
+ }
+ else if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == tAMPM) {
+ /* "7" is a time if it's followed by "am" or "pm" */
+ ++gds->HaveTime;
+ gds->Hour = gds->tokenp[0].value;
+ gds->Minutes = gds->Seconds = 0;
+ /* We'll handle the AM/PM below. */
+ gds->tokenp += 1;
+ } else {
+ /* We can't handle this. */
+ return 0;
+ }
+
+ if (gds->tokenp[0].token == tAMPM) {
+ /* "7:12pm", "12:20:13am" */
+ if (gds->Hour == 12)
+ gds->Hour = 0;
+ if (gds->tokenp[0].value == tPM)
+ gds->Hour += 12;
+ gds->tokenp += 1;
+ }
+ if (gds->tokenp[0].token == '+'
+ && gds->tokenp[1].token == tUNUMBER) {
+ /* "7:14+0700" */
+ gds->HaveZone++;
+ gds->DSTmode = DSToff;
+ gds->Timezone = - ((gds->tokenp[1].value / 100) * HOUR
+ + (gds->tokenp[1].value % 100) * MINUTE);
+ gds->tokenp += 2;
+ }
+ if (gds->tokenp[0].token == '-'
+ && gds->tokenp[1].token == tUNUMBER) {
+ /* "19:14:12-0530" */
+ gds->HaveZone++;
+ gds->DSTmode = DSToff;
+ gds->Timezone = + ((gds->tokenp[1].value / 100) * HOUR
+ + (gds->tokenp[1].value % 100) * MINUTE);
+ gds->tokenp += 2;
+ }
+ return 1;
+}
+
+/*
+ * Timezone name, possibly including DST.
+ */
+static int
+zonephrase(struct gdstate *gds)
+{
+ if (gds->tokenp[0].token == tZONE
+ && gds->tokenp[1].token == tDST) {
+ gds->HaveZone++;
+ gds->Timezone = gds->tokenp[0].value;
+ gds->DSTmode = DSTon;
+ gds->tokenp += 1;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tZONE) {
+ gds->HaveZone++;
+ gds->Timezone = gds->tokenp[0].value;
+ gds->DSTmode = DSToff;
+ gds->tokenp += 1;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tDAYZONE) {
+ gds->HaveZone++;
+ gds->Timezone = gds->tokenp[0].value;
+ gds->DSTmode = DSTon;
+ gds->tokenp += 1;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Year/month/day in various combinations.
+ */
+static int
+datephrase(struct gdstate *gds)
+{
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == '/'
+ && gds->tokenp[2].token == tUNUMBER
+ && gds->tokenp[3].token == '/'
+ && gds->tokenp[4].token == tUNUMBER) {
+ gds->HaveYear++;
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ if (gds->tokenp[0].value >= 13) {
+ /* First number is big: 2004/01/29, 99/02/17 */
+ gds->Year = gds->tokenp[0].value;
+ gds->Month = gds->tokenp[2].value;
+ gds->Day = gds->tokenp[4].value;
+ } else if ((gds->tokenp[4].value >= 13)
+ || (gds->tokenp[2].value >= 13)) {
+ /* Last number is big: 01/07/98 */
+ /* Middle number is big: 01/29/04 */
+ gds->Month = gds->tokenp[0].value;
+ gds->Day = gds->tokenp[2].value;
+ gds->Year = gds->tokenp[4].value;
+ } else {
+ /* No significant clues: 02/03/04 */
+ gds->Month = gds->tokenp[0].value;
+ gds->Day = gds->tokenp[2].value;
+ gds->Year = gds->tokenp[4].value;
+ }
+ gds->tokenp += 5;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == '/'
+ && gds->tokenp[2].token == tUNUMBER) {
+ /* "1/15" */
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ gds->Month = gds->tokenp[0].value;
+ gds->Day = gds->tokenp[2].value;
+ gds->tokenp += 3;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == '-'
+ && gds->tokenp[2].token == tUNUMBER
+ && gds->tokenp[3].token == '-'
+ && gds->tokenp[4].token == tUNUMBER) {
+ /* ISO 8601 format. yyyy-mm-dd. */
+ gds->HaveYear++;
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ gds->Year = gds->tokenp[0].value;
+ gds->Month = gds->tokenp[2].value;
+ gds->Day = gds->tokenp[4].value;
+ gds->tokenp += 5;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == '-'
+ && gds->tokenp[2].token == tMONTH
+ && gds->tokenp[3].token == '-'
+ && gds->tokenp[4].token == tUNUMBER) {
+ gds->HaveYear++;
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ if (gds->tokenp[0].value > 31) {
+ /* e.g. 1992-Jun-17 */
+ gds->Year = gds->tokenp[0].value;
+ gds->Month = gds->tokenp[2].value;
+ gds->Day = gds->tokenp[4].value;
+ } else {
+ /* e.g. 17-JUN-1992. */
+ gds->Day = gds->tokenp[0].value;
+ gds->Month = gds->tokenp[2].value;
+ gds->Year = gds->tokenp[4].value;
+ }
+ gds->tokenp += 5;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tMONTH
+ && gds->tokenp[1].token == tUNUMBER
+ && gds->tokenp[2].token == ','
+ && gds->tokenp[3].token == tUNUMBER) {
+ /* "June 17, 2001" */
+ gds->HaveYear++;
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ gds->Month = gds->tokenp[0].value;
+ gds->Day = gds->tokenp[1].value;
+ gds->Year = gds->tokenp[3].value;
+ gds->tokenp += 4;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tMONTH
+ && gds->tokenp[1].token == tUNUMBER) {
+ /* "May 3" */
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ gds->Month = gds->tokenp[0].value;
+ gds->Day = gds->tokenp[1].value;
+ gds->tokenp += 2;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == tMONTH
+ && gds->tokenp[2].token == tUNUMBER) {
+ /* "12 Sept 1997" */
+ gds->HaveYear++;
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ gds->Day = gds->tokenp[0].value;
+ gds->Month = gds->tokenp[1].value;
+ gds->Year = gds->tokenp[2].value;
+ gds->tokenp += 3;
+ return 1;
+ }
+
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == tMONTH) {
+ /* "12 Sept" */
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ gds->Day = gds->tokenp[0].value;
+ gds->Month = gds->tokenp[1].value;
+ gds->tokenp += 2;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Relative time phrase: "tomorrow", "yesterday", "+1 hour", etc.
+ */
+static int
+relunitphrase(struct gdstate *gds)
+{
+ if (gds->tokenp[0].token == '-'
+ && gds->tokenp[1].token == tUNUMBER
+ && gds->tokenp[2].token == tSEC_UNIT) {
+ /* "-3 hours" */
+ gds->HaveRel++;
+ gds->RelSeconds -= gds->tokenp[1].value * gds->tokenp[2].value;
+ gds->tokenp += 3;
+ return 1;
+ }
+ if (gds->tokenp[0].token == '+'
+ && gds->tokenp[1].token == tUNUMBER
+ && gds->tokenp[2].token == tSEC_UNIT) {
+ /* "+1 minute" */
+ gds->HaveRel++;
+ gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value;
+ gds->tokenp += 3;
+ return 1;
+ }
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == tSEC_UNIT) {
+ /* "1 day" */
+ gds->HaveRel++;
+ gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value;
+ gds->tokenp += 3;
+ return 1;
+ }
+ if (gds->tokenp[0].token == '-'
+ && gds->tokenp[1].token == tUNUMBER
+ && gds->tokenp[2].token == tMONTH_UNIT) {
+ /* "-3 months" */
+ gds->HaveRel++;
+ gds->RelMonth -= gds->tokenp[1].value * gds->tokenp[2].value;
+ gds->tokenp += 3;
+ return 1;
+ }
+ if (gds->tokenp[0].token == '+'
+ && gds->tokenp[1].token == tUNUMBER
+ && gds->tokenp[2].token == tMONTH_UNIT) {
+ /* "+5 years" */
+ gds->HaveRel++;
+ gds->RelMonth += gds->tokenp[1].value * gds->tokenp[2].value;
+ gds->tokenp += 3;
+ return 1;
+ }
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == tMONTH_UNIT) {
+ /* "2 years" */
+ gds->HaveRel++;
+ gds->RelMonth += gds->tokenp[0].value * gds->tokenp[1].value;
+ gds->tokenp += 2;
+ return 1;
+ }
+ if (gds->tokenp[0].token == tSEC_UNIT) {
+ /* "now", "tomorrow" */
+ gds->HaveRel++;
+ gds->RelSeconds += gds->tokenp[0].value;
+ ++gds->tokenp;
+ return 1;
+ }
+ if (gds->tokenp[0].token == tMONTH_UNIT) {
+ /* "month" */
+ gds->HaveRel++;
+ gds->RelMonth += gds->tokenp[0].value;
+ gds->tokenp += 1;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Day of the week specification.
+ */
+static int
+dayphrase(struct gdstate *gds)
+{
+ if (gds->tokenp[0].token == tDAY) {
+ /* "tues", "wednesday," */
+ gds->HaveWeekDay++;
+ gds->DayOrdinal = 1;
+ gds->DayNumber = gds->tokenp[0].value;
+ gds->tokenp += 1;
+ if (gds->tokenp[0].token == ',')
+ gds->tokenp += 1;
+ return 1;
+ }
+ if (gds->tokenp[0].token == tUNUMBER
+ && gds->tokenp[1].token == tDAY) {
+ /* "second tues" "3 wed" */
+ gds->HaveWeekDay++;
+ gds->DayOrdinal = gds->tokenp[0].value;
+ gds->DayNumber = gds->tokenp[1].value;
+ gds->tokenp += 2;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Try to match a phrase using one of the above functions.
+ * This layer also deals with a couple of generic issues.
+ */
+static int
+phrase(struct gdstate *gds)
+{
+ if (timephrase(gds))
+ return 1;
+ if (zonephrase(gds))
+ return 1;
+ if (datephrase(gds))
+ return 1;
+ if (dayphrase(gds))
+ return 1;
+ if (relunitphrase(gds)) {
+ if (gds->tokenp[0].token == tAGO) {
+ gds->RelSeconds = -gds->RelSeconds;
+ gds->RelMonth = -gds->RelMonth;
+ gds->tokenp += 1;
+ }
+ return 1;
+ }
+
+ /* Bare numbers sometimes have meaning. */
+ if (gds->tokenp[0].token == tUNUMBER) {
+ if (gds->HaveTime && !gds->HaveYear && !gds->HaveRel) {
+ gds->HaveYear++;
+ gds->Year = gds->tokenp[0].value;
+ gds->tokenp += 1;
+ return 1;
+ }
+
+ if(gds->tokenp[0].value > 10000) {
+ /* "20040301" */
+ gds->HaveYear++;
+ gds->HaveMonth++;
+ gds->HaveDay++;
+ gds->Day= (gds->tokenp[0].value)%100;
+ gds->Month= (gds->tokenp[0].value/100)%100;
+ gds->Year = gds->tokenp[0].value/10000;
+ gds->tokenp += 1;
+ return 1;
+ }
+
+ if (gds->tokenp[0].value < 24) {
+ gds->HaveTime++;
+ gds->Hour = gds->tokenp[0].value;
+ gds->Minutes = 0;
+ gds->Seconds = 0;
+ gds->tokenp += 1;
+ return 1;
+ }
+
+ if ((gds->tokenp[0].value / 100 < 24)
+ && (gds->tokenp[0].value % 100 < 60)) {
+ /* "513" is same as "5:13" */
+ gds->Hour = gds->tokenp[0].value / 100;
+ gds->Minutes = gds->tokenp[0].value % 100;
+ gds->Seconds = 0;
+ gds->tokenp += 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * A dictionary of time words.
+ */
+static struct LEXICON {
+ size_t abbrev;
+ const char *name;
+ int type;
+ time_t value;
+} const TimeWords[] = {
+ /* am/pm */
+ { 0, "am", tAMPM, tAM },
+ { 0, "pm", tAMPM, tPM },
+
+ /* Month names. */
+ { 3, "january", tMONTH, 1 },
+ { 3, "february", tMONTH, 2 },
+ { 3, "march", tMONTH, 3 },
+ { 3, "april", tMONTH, 4 },
+ { 3, "may", tMONTH, 5 },
+ { 3, "june", tMONTH, 6 },
+ { 3, "july", tMONTH, 7 },
+ { 3, "august", tMONTH, 8 },
+ { 3, "september", tMONTH, 9 },
+ { 3, "october", tMONTH, 10 },
+ { 3, "november", tMONTH, 11 },
+ { 3, "december", tMONTH, 12 },
+
+ /* Days of the week. */
+ { 2, "sunday", tDAY, 0 },
+ { 3, "monday", tDAY, 1 },
+ { 2, "tuesday", tDAY, 2 },
+ { 3, "wednesday", tDAY, 3 },
+ { 2, "thursday", tDAY, 4 },
+ { 2, "friday", tDAY, 5 },
+ { 2, "saturday", tDAY, 6 },
+
+ /* Timezones: Offsets are in seconds. */
+ { 0, "gmt", tZONE, 0*HOUR }, /* Greenwich Mean */
+ { 0, "ut", tZONE, 0*HOUR }, /* Universal (Coordinated) */
+ { 0, "utc", tZONE, 0*HOUR },
+ { 0, "wet", tZONE, 0*HOUR }, /* Western European */
+ { 0, "bst", tDAYZONE, 0*HOUR }, /* British Summer */
+ { 0, "wat", tZONE, 1*HOUR }, /* West Africa */
+ { 0, "at", tZONE, 2*HOUR }, /* Azores */
+ /* { 0, "bst", tZONE, 3*HOUR }, */ /* Brazil Standard: Conflict */
+ /* { 0, "gst", tZONE, 3*HOUR }, */ /* Greenland Standard: Conflict*/
+ { 0, "nft", tZONE, 3*HOUR+30*MINUTE }, /* Newfoundland */
+ { 0, "nst", tZONE, 3*HOUR+30*MINUTE }, /* Newfoundland Standard */
+ { 0, "ndt", tDAYZONE, 3*HOUR+30*MINUTE }, /* Newfoundland Daylight */
+ { 0, "ast", tZONE, 4*HOUR }, /* Atlantic Standard */
+ { 0, "adt", tDAYZONE, 4*HOUR }, /* Atlantic Daylight */
+ { 0, "est", tZONE, 5*HOUR }, /* Eastern Standard */
+ { 0, "edt", tDAYZONE, 5*HOUR }, /* Eastern Daylight */
+ { 0, "cst", tZONE, 6*HOUR }, /* Central Standard */
+ { 0, "cdt", tDAYZONE, 6*HOUR }, /* Central Daylight */
+ { 0, "mst", tZONE, 7*HOUR }, /* Mountain Standard */
+ { 0, "mdt", tDAYZONE, 7*HOUR }, /* Mountain Daylight */
+ { 0, "pst", tZONE, 8*HOUR }, /* Pacific Standard */
+ { 0, "pdt", tDAYZONE, 8*HOUR }, /* Pacific Daylight */
+ { 0, "yst", tZONE, 9*HOUR }, /* Yukon Standard */
+ { 0, "ydt", tDAYZONE, 9*HOUR }, /* Yukon Daylight */
+ { 0, "hst", tZONE, 10*HOUR }, /* Hawaii Standard */
+ { 0, "hdt", tDAYZONE, 10*HOUR }, /* Hawaii Daylight */
+ { 0, "cat", tZONE, 10*HOUR }, /* Central Alaska */
+ { 0, "ahst", tZONE, 10*HOUR }, /* Alaska-Hawaii Standard */
+ { 0, "nt", tZONE, 11*HOUR }, /* Nome */
+ { 0, "idlw", tZONE, 12*HOUR }, /* Intl Date Line West */
+ { 0, "cet", tZONE, -1*HOUR }, /* Central European */
+ { 0, "met", tZONE, -1*HOUR }, /* Middle European */
+ { 0, "mewt", tZONE, -1*HOUR }, /* Middle European Winter */
+ { 0, "mest", tDAYZONE, -1*HOUR }, /* Middle European Summer */
+ { 0, "swt", tZONE, -1*HOUR }, /* Swedish Winter */
+ { 0, "sst", tDAYZONE, -1*HOUR }, /* Swedish Summer */
+ { 0, "fwt", tZONE, -1*HOUR }, /* French Winter */
+ { 0, "fst", tDAYZONE, -1*HOUR }, /* French Summer */
+ { 0, "eet", tZONE, -2*HOUR }, /* Eastern Eur, USSR Zone 1 */
+ { 0, "bt", tZONE, -3*HOUR }, /* Baghdad, USSR Zone 2 */
+ { 0, "it", tZONE, -3*HOUR-30*MINUTE },/* Iran */
+ { 0, "zp4", tZONE, -4*HOUR }, /* USSR Zone 3 */
+ { 0, "zp5", tZONE, -5*HOUR }, /* USSR Zone 4 */
+ { 0, "ist", tZONE, -5*HOUR-30*MINUTE },/* Indian Standard */
+ { 0, "zp6", tZONE, -6*HOUR }, /* USSR Zone 5 */
+ /* { 0, "nst", tZONE, -6.5*HOUR }, */ /* North Sumatra: Conflict */
+ /* { 0, "sst", tZONE, -7*HOUR }, */ /* So Sumatra, USSR 6: Conflict */
+ { 0, "wast", tZONE, -7*HOUR }, /* West Australian Standard */
+ { 0, "wadt", tDAYZONE, -7*HOUR }, /* West Australian Daylight */
+ { 0, "jt", tZONE, -7*HOUR-30*MINUTE },/* Java (3pm in Cronusland!)*/
+ { 0, "cct", tZONE, -8*HOUR }, /* China Coast, USSR Zone 7 */
+ { 0, "jst", tZONE, -9*HOUR }, /* Japan Std, USSR Zone 8 */
+ { 0, "cast", tZONE, -9*HOUR-30*MINUTE },/* Ctrl Australian Std */
+ { 0, "cadt", tDAYZONE, -9*HOUR-30*MINUTE },/* Ctrl Australian Daylt */
+ { 0, "east", tZONE, -10*HOUR }, /* Eastern Australian Std */
+ { 0, "eadt", tDAYZONE, -10*HOUR }, /* Eastern Australian Daylt */
+ { 0, "gst", tZONE, -10*HOUR }, /* Guam Std, USSR Zone 9 */
+ { 0, "nzt", tZONE, -12*HOUR }, /* New Zealand */
+ { 0, "nzst", tZONE, -12*HOUR }, /* New Zealand Standard */
+ { 0, "nzdt", tDAYZONE, -12*HOUR }, /* New Zealand Daylight */
+ { 0, "idle", tZONE, -12*HOUR }, /* Intl Date Line East */
+
+ { 0, "dst", tDST, 0 },
+
+ /* Time units. */
+ { 4, "years", tMONTH_UNIT, 12 },
+ { 5, "months", tMONTH_UNIT, 1 },
+ { 9, "fortnights", tSEC_UNIT, 14 * DAY },
+ { 4, "weeks", tSEC_UNIT, 7 * DAY },
+ { 3, "days", tSEC_UNIT, DAY },
+ { 4, "hours", tSEC_UNIT, HOUR },
+ { 3, "minutes", tSEC_UNIT, MINUTE },
+ { 3, "seconds", tSEC_UNIT, 1 },
+
+ /* Relative-time words. */
+ { 0, "tomorrow", tSEC_UNIT, DAY },
+ { 0, "yesterday", tSEC_UNIT, -DAY },
+ { 0, "today", tSEC_UNIT, 0 },
+ { 0, "now", tSEC_UNIT, 0 },
+ { 0, "last", tUNUMBER, -1 },
+ { 0, "this", tSEC_UNIT, 0 },
+ { 0, "next", tUNUMBER, 2 },
+ { 0, "first", tUNUMBER, 1 },
+ { 0, "1st", tUNUMBER, 1 },
+/* { 0, "second", tUNUMBER, 2 }, */
+ { 0, "2nd", tUNUMBER, 2 },
+ { 0, "third", tUNUMBER, 3 },
+ { 0, "3rd", tUNUMBER, 3 },
+ { 0, "fourth", tUNUMBER, 4 },
+ { 0, "4th", tUNUMBER, 4 },
+ { 0, "fifth", tUNUMBER, 5 },
+ { 0, "5th", tUNUMBER, 5 },
+ { 0, "sixth", tUNUMBER, 6 },
+ { 0, "seventh", tUNUMBER, 7 },
+ { 0, "eighth", tUNUMBER, 8 },
+ { 0, "ninth", tUNUMBER, 9 },
+ { 0, "tenth", tUNUMBER, 10 },
+ { 0, "eleventh", tUNUMBER, 11 },
+ { 0, "twelfth", tUNUMBER, 12 },
+ { 0, "ago", tAGO, 1 },
+
+ /* Military timezones. */
+ { 0, "a", tZONE, 1*HOUR },
+ { 0, "b", tZONE, 2*HOUR },
+ { 0, "c", tZONE, 3*HOUR },
+ { 0, "d", tZONE, 4*HOUR },
+ { 0, "e", tZONE, 5*HOUR },
+ { 0, "f", tZONE, 6*HOUR },
+ { 0, "g", tZONE, 7*HOUR },
+ { 0, "h", tZONE, 8*HOUR },
+ { 0, "i", tZONE, 9*HOUR },
+ { 0, "k", tZONE, 10*HOUR },
+ { 0, "l", tZONE, 11*HOUR },
+ { 0, "m", tZONE, 12*HOUR },
+ { 0, "n", tZONE, -1*HOUR },
+ { 0, "o", tZONE, -2*HOUR },
+ { 0, "p", tZONE, -3*HOUR },
+ { 0, "q", tZONE, -4*HOUR },
+ { 0, "r", tZONE, -5*HOUR },
+ { 0, "s", tZONE, -6*HOUR },
+ { 0, "t", tZONE, -7*HOUR },
+ { 0, "u", tZONE, -8*HOUR },
+ { 0, "v", tZONE, -9*HOUR },
+ { 0, "w", tZONE, -10*HOUR },
+ { 0, "x", tZONE, -11*HOUR },
+ { 0, "y", tZONE, -12*HOUR },
+ { 0, "z", tZONE, 0*HOUR },
+
+ /* End of table. */
+ { 0, NULL, 0, 0 }
+};
+
+/*
+ * Year is either:
+ * = A number from 0 to 99, which means a year from 1970 to 2069, or
+ * = The actual year (>=100).
+ */
+static time_t
+Convert(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds,
+ time_t Timezone, enum DSTMODE DSTmode)
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ time_t Julian;
+ int i;
+
+ if (Year < 69)
+ Year += 2000;
+ else if (Year < 100)
+ Year += 1900;
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ /* Checking for 2038 bogusly assumes that time_t is 32 bits. But
+ I'm too lazy to try to check for time_t overflow in another way. */
+ if (Year < EPOCH || Year > 2038
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[(int)--Month]
+ || Hours < 0 || Hours > 23
+ || Minutes < 0 || Minutes > 59
+ || Seconds < 0 || Seconds > 59)
+ return -1;
+
+ Julian = Day - 1;
+ for (i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= DAY;
+ Julian += Timezone;
+ Julian += Hours * HOUR + Minutes * MINUTE + Seconds;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ Julian -= HOUR;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(time_t Start, time_t Future)
+{
+ time_t StartDay;
+ time_t FutureDay;
+
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * HOUR;
+}
+
+
+static time_t
+RelativeDate(time_t Start, time_t zone, int dstmode,
+ time_t DayOrdinal, time_t DayNumber)
+{
+ struct tm *tm;
+ time_t t, now;
+
+ t = Start - zone;
+ tm = gmtime(&t);
+ now = Start;
+ now += DAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * DAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ if (dstmode == DSTmaybe)
+ return DSTcorrect(Start, now);
+ return now - Start;
+}
+
+
+static time_t
+RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
+{
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm->tm_mday, Year,
+ (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+ Timezone, DSTmaybe));
+}
+
+/*
+ * Tokenizer.
+ */
+static int
+nexttoken(char **in, time_t *value)
+{
+ char c;
+ char buff[64];
+
+ for ( ; ; ) {
+ while (isspace((unsigned char)**in))
+ ++*in;
+
+ /* Skip parenthesized comments. */
+ if (**in == '(') {
+ int Count = 0;
+ do {
+ c = *(*in)++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ continue;
+ }
+
+ /* Try the next token in the word table first. */
+ /* This allows us to match "2nd", for example. */
+ {
+ char *src = *in;
+ const struct LEXICON *tp;
+ unsigned i = 0;
+
+ /* Force to lowercase and strip '.' characters. */
+ while (*src != '\0'
+ && (isalnum((unsigned char)*src) || *src == '.')
+ && i < sizeof(buff)-1) {
+ if (*src != '.') {
+ if (isupper((unsigned char)*src))
+ buff[i++] = tolower((unsigned char)*src);
+ else
+ buff[i++] = *src;
+ }
+ src++;
+ }
+ buff[i] = '\0';
+
+ /*
+ * Find the first match. If the word can be
+ * abbreviated, make sure we match at least
+ * the minimum abbreviation.
+ */
+ for (tp = TimeWords; tp->name; tp++) {
+ size_t abbrev = tp->abbrev;
+ if (abbrev == 0)
+ abbrev = strlen(tp->name);
+ if (strlen(buff) >= abbrev
+ && strncmp(tp->name, buff, strlen(buff))
+ == 0) {
+ /* Skip over token. */
+ *in = src;
+ /* Return the match. */
+ *value = tp->value;
+ return tp->type;
+ }
+ }
+ }
+
+ /*
+ * Not in the word table, maybe it's a number. Note:
+ * Because '-' and '+' have other special meanings, I
+ * don't deal with signed numbers here.
+ */
+ if (isdigit((unsigned char)(c = **in))) {
+ for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
+ *value = 10 * *value + c - '0';
+ (*in)--;
+ return (tUNUMBER);
+ }
+
+ return *(*in)++;
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm (struct tm *a, struct tm *b)
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (days * DAY + (a->tm_hour - b->tm_hour) * HOUR
+ + (a->tm_min - b->tm_min) * MINUTE
+ + (a->tm_sec - b->tm_sec));
+}
+
+/*
+ *
+ * The public function.
+ *
+ * TODO: tokens[] array should be dynamically sized.
+ */
+time_t
+__archive_get_date(time_t now, char *p)
+{
+ struct token tokens[256];
+ struct gdstate _gds;
+ struct token *lasttoken;
+ struct gdstate *gds;
+ struct tm local, *tm;
+ struct tm gmt, *gmt_ptr;
+ time_t Start;
+ time_t tod;
+ long tzone;
+
+ /* Clear out the parsed token array. */
+ memset(tokens, 0, sizeof(tokens));
+ /* Initialize the parser state. */
+ memset(&_gds, 0, sizeof(_gds));
+ gds = &_gds;
+
+ /* Look up the current time. */
+ memset(&local, 0, sizeof(local));
+ tm = localtime (&now);
+ if (tm == NULL)
+ return -1;
+ local = *tm;
+
+ /* Look up UTC if we can and use that to determine the current
+ * timezone offset. */
+ memset(&gmt, 0, sizeof(gmt));
+ gmt_ptr = gmtime (&now);
+ if (gmt_ptr != NULL) {
+ /* Copy, in case localtime and gmtime use the same buffer. */
+ gmt = *gmt_ptr;
+ }
+ if (gmt_ptr != NULL)
+ tzone = difftm (&gmt, &local);
+ else
+ /* This system doesn't understand timezones; fake it. */
+ tzone = 0;
+ if(local.tm_isdst)
+ tzone += HOUR;
+
+ /* Tokenize the input string. */
+ lasttoken = tokens;
+ while ((lasttoken->token = nexttoken(&p, &lasttoken->value)) != 0) {
+ ++lasttoken;
+ if (lasttoken > tokens + 255)
+ return -1;
+ }
+ gds->tokenp = tokens;
+
+ /* Match phrases until we run out of input tokens. */
+ while (gds->tokenp < lasttoken) {
+ if (!phrase(gds))
+ return -1;
+ }
+
+ /* Use current local timezone if none was specified. */
+ if (!gds->HaveZone) {
+ gds->Timezone = tzone;
+ gds->DSTmode = DSTmaybe;
+ }
+
+ /* If a timezone was specified, use that for generating the default
+ * time components instead of the local timezone. */
+ if (gds->HaveZone && gmt_ptr != NULL) {
+ now -= gds->Timezone;
+ gmt_ptr = gmtime (&now);
+ if (gmt_ptr != NULL)
+ local = *gmt_ptr;
+ now += gds->Timezone;
+ }
+
+ if (!gds->HaveYear)
+ gds->Year = local.tm_year + 1900;
+ if (!gds->HaveMonth)
+ gds->Month = local.tm_mon + 1;
+ if (!gds->HaveDay)
+ gds->Day = local.tm_mday;
+ /* Note: No default for hour/min/sec; a specifier that just
+ * gives date always refers to 00:00 on that date. */
+
+ /* If we saw more than one time, timezone, weekday, year, month,
+ * or day, then give up. */
+ if (gds->HaveTime > 1 || gds->HaveZone > 1 || gds->HaveWeekDay > 1
+ || gds->HaveYear > 1 || gds->HaveMonth > 1 || gds->HaveDay > 1)
+ return -1;
+
+ /* Compute an absolute time based on whatever absolute information
+ * we collected. */
+ if (gds->HaveYear || gds->HaveMonth || gds->HaveDay
+ || gds->HaveTime || gds->HaveWeekDay) {
+ Start = Convert(gds->Month, gds->Day, gds->Year,
+ gds->Hour, gds->Minutes, gds->Seconds,
+ gds->Timezone, gds->DSTmode);
+ if (Start < 0)
+ return -1;
+ } else {
+ Start = now;
+ if (!gds->HaveRel)
+ Start -= local.tm_hour * HOUR + local.tm_min * MINUTE
+ + local.tm_sec;
+ }
+
+ /* Add the relative offset. */
+ Start += gds->RelSeconds;
+ Start += RelativeMonth(Start, gds->Timezone, gds->RelMonth);
+
+ /* Adjust for day-of-week offsets. */
+ if (gds->HaveWeekDay
+ && !(gds->HaveYear || gds->HaveMonth || gds->HaveDay)) {
+ tod = RelativeDate(Start, gds->Timezone,
+ gds->DSTmode, gds->DayOrdinal, gds->DayNumber);
+ Start += tod;
+ }
+
+ /* -1 is an error indicator, so return 0 instead of -1 if
+ * that's the actual time. */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#if defined(TEST)
+
+/* ARGSUSED */
+int
+main(int argc, char **argv)
+{
+ time_t d;
+
+ while (*++argv != NULL) {
+ (void)printf("Input: %s\n", *argv);
+ d = get_date(*argv);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("Output: %s\n", ctime(&d));
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
diff --git a/Utilities/cmlibarchive/libarchive/archive_match.c b/Utilities/cmlibarchive/libarchive/archive_match.c
new file mode 100644
index 0000000..6b6be9c
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_match.c
@@ -0,0 +1,1841 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_entry.h"
+#include "archive_pathmatch.h"
+#include "archive_rb.h"
+#include "archive_string.h"
+
+struct match {
+ struct match *next;
+ int matches;
+ struct archive_mstring pattern;
+};
+
+struct match_list {
+ struct match *first;
+ struct match **last;
+ int count;
+ int unmatched_count;
+ struct match *unmatched_next;
+ int unmatched_eof;
+};
+
+struct match_file {
+ struct archive_rb_node node;
+ struct match_file *next;
+ struct archive_mstring pathname;
+ int flag;
+ time_t mtime_sec;
+ long mtime_nsec;
+ time_t ctime_sec;
+ long ctime_nsec;
+};
+
+struct entry_list {
+ struct match_file *first;
+ struct match_file **last;
+ int count;
+};
+
+struct id_array {
+ size_t size;/* Allocated size */
+ size_t count;
+ int64_t *ids;
+};
+
+#define PATTERN_IS_SET 1
+#define TIME_IS_SET 2
+#define ID_IS_SET 4
+
+struct archive_match {
+ struct archive archive;
+
+ /* exclusion/inclusion set flag. */
+ int setflag;
+
+ /*
+ * Matching filename patterns.
+ */
+ struct match_list exclusions;
+ struct match_list inclusions;
+
+ /*
+ * Matching time stamps.
+ */
+ time_t now;
+ int newer_mtime_filter;
+ time_t newer_mtime_sec;
+ long newer_mtime_nsec;
+ int newer_ctime_filter;
+ time_t newer_ctime_sec;
+ long newer_ctime_nsec;
+ int older_mtime_filter;
+ time_t older_mtime_sec;
+ long older_mtime_nsec;
+ int older_ctime_filter;
+ time_t older_ctime_sec;
+ long older_ctime_nsec;
+ /*
+ * Matching time stamps with its filename.
+ */
+ struct archive_rb_tree exclusion_tree;
+ struct entry_list exclusion_entry_list;
+
+ /*
+ * Matching file owners.
+ */
+ struct id_array inclusion_uids;
+ struct id_array inclusion_gids;
+ struct match_list inclusion_unames;
+ struct match_list inclusion_gnames;
+};
+
+static int add_pattern_from_file(struct archive_match *,
+ struct match_list *, int, const void *, int);
+static int add_entry(struct archive_match *, int,
+ struct archive_entry *);
+static int add_owner_id(struct archive_match *, struct id_array *,
+ int64_t);
+static int add_owner_name(struct archive_match *, struct match_list *,
+ int, const void *);
+static int add_pattern_mbs(struct archive_match *, struct match_list *,
+ const char *);
+static int add_pattern_wcs(struct archive_match *, struct match_list *,
+ const wchar_t *);
+static int cmp_key_mbs(const struct archive_rb_node *, const void *);
+static int cmp_key_wcs(const struct archive_rb_node *, const void *);
+static int cmp_node_mbs(const struct archive_rb_node *,
+ const struct archive_rb_node *);
+static int cmp_node_wcs(const struct archive_rb_node *,
+ const struct archive_rb_node *);
+static void entry_list_add(struct entry_list *, struct match_file *);
+static void entry_list_free(struct entry_list *);
+static void entry_list_init(struct entry_list *);
+static int error_nomem(struct archive_match *);
+static void match_list_add(struct match_list *, struct match *);
+static void match_list_free(struct match_list *);
+static void match_list_init(struct match_list *);
+static int match_list_unmatched_inclusions_next(struct archive_match *,
+ struct match_list *, int, const void **);
+static int match_owner_id(struct id_array *, int64_t);
+#if !defined(_WIN32) || defined(__CYGWIN__)
+static int match_owner_name_mbs(struct archive_match *,
+ struct match_list *, const char *);
+#else
+static int match_owner_name_wcs(struct archive_match *,
+ struct match_list *, const wchar_t *);
+#endif
+static int match_path_exclusion(struct archive_match *,
+ struct match *, int, const void *);
+static int match_path_inclusion(struct archive_match *,
+ struct match *, int, const void *);
+static int owner_excluded(struct archive_match *,
+ struct archive_entry *);
+static int path_excluded(struct archive_match *, int, const void *);
+static int set_timefilter(struct archive_match *, int, time_t, long,
+ time_t, long);
+static int set_timefilter_pathname_mbs(struct archive_match *,
+ int, const char *);
+static int set_timefilter_pathname_wcs(struct archive_match *,
+ int, const wchar_t *);
+static int set_timefilter_date(struct archive_match *, int, const char *);
+static int set_timefilter_date_w(struct archive_match *, int,
+ const wchar_t *);
+static int time_excluded(struct archive_match *,
+ struct archive_entry *);
+static int validate_time_flag(struct archive *, int, const char *);
+
+time_t __archive_get_date(time_t now, const char *);
+#define get_date __archive_get_date
+
+static const struct archive_rb_tree_ops rb_ops_mbs = {
+ cmp_node_mbs, cmp_key_mbs
+};
+
+static const struct archive_rb_tree_ops rb_ops_wcs = {
+ cmp_node_wcs, cmp_key_wcs
+};
+
+/*
+ * The matching logic here needs to be re-thought. I started out to
+ * try to mimic gtar's matching logic, but it's not entirely
+ * consistent. In particular 'tar -t' and 'tar -x' interpret patterns
+ * on the command line as anchored, but --exclude doesn't.
+ */
+
+static int
+error_nomem(struct archive_match *a)
+{
+ archive_set_error(&(a->archive), ENOMEM, "No memory");
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+}
+
+/*
+ * Create an ARCHIVE_MATCH object.
+ */
+struct archive *
+archive_match_new(void)
+{
+ struct archive_match *a;
+
+ a = (struct archive_match *)calloc(1, sizeof(*a));
+ if (a == NULL)
+ return (NULL);
+ a->archive.magic = ARCHIVE_MATCH_MAGIC;
+ a->archive.state = ARCHIVE_STATE_NEW;
+ match_list_init(&(a->inclusions));
+ match_list_init(&(a->exclusions));
+ __archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
+ entry_list_init(&(a->exclusion_entry_list));
+ match_list_init(&(a->inclusion_unames));
+ match_list_init(&(a->inclusion_gnames));
+ time(&a->now);
+ return (&(a->archive));
+}
+
+/*
+ * Free an ARCHIVE_MATCH object.
+ */
+int
+archive_match_free(struct archive *_a)
+{
+ struct archive_match *a;
+
+ if (_a == NULL)
+ return (ARCHIVE_OK);
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_match_free");
+ a = (struct archive_match *)_a;
+ match_list_free(&(a->inclusions));
+ match_list_free(&(a->exclusions));
+ entry_list_free(&(a->exclusion_entry_list));
+ free(a->inclusion_uids.ids);
+ free(a->inclusion_gids.ids);
+ match_list_free(&(a->inclusion_unames));
+ match_list_free(&(a->inclusion_gnames));
+ free(a);
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Convenience function to perform all exclusion tests.
+ *
+ * Returns 1 if archive entry is excluded.
+ * Returns 0 if archive entry is not excluded.
+ * Returns <0 if something error happened.
+ */
+int
+archive_match_excluded(struct archive *_a, struct archive_entry *entry)
+{
+ struct archive_match *a;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_excluded_ae");
+
+ a = (struct archive_match *)_a;
+ if (entry == NULL) {
+ archive_set_error(&(a->archive), EINVAL, "entry is NULL");
+ return (ARCHIVE_FAILED);
+ }
+
+ r = 0;
+ if (a->setflag & PATTERN_IS_SET) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ r = path_excluded(a, 0, archive_entry_pathname_w(entry));
+#else
+ r = path_excluded(a, 1, archive_entry_pathname(entry));
+#endif
+ if (r != 0)
+ return (r);
+ }
+
+ if (a->setflag & TIME_IS_SET) {
+ r = time_excluded(a, entry);
+ if (r != 0)
+ return (r);
+ }
+
+ if (a->setflag & ID_IS_SET)
+ r = owner_excluded(a, entry);
+ return (r);
+}
+
+/*
+ * Utility functions to manage exclusion/inclusion patterns
+ */
+
+int
+archive_match_exclude_pattern(struct archive *_a, const char *pattern)
+{
+ struct archive_match *a;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_exclude_pattern");
+ a = (struct archive_match *)_a;
+
+ if (pattern == NULL || *pattern == '\0') {
+ archive_set_error(&(a->archive), EINVAL, "pattern is empty");
+ return (ARCHIVE_FAILED);
+ }
+ if ((r = add_pattern_mbs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
+ return (r);
+ return (ARCHIVE_OK);
+}
+
+int
+archive_match_exclude_pattern_w(struct archive *_a, const wchar_t *pattern)
+{
+ struct archive_match *a;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_w");
+ a = (struct archive_match *)_a;
+
+ if (pattern == NULL || *pattern == L'\0') {
+ archive_set_error(&(a->archive), EINVAL, "pattern is empty");
+ return (ARCHIVE_FAILED);
+ }
+ if ((r = add_pattern_wcs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
+ return (r);
+ return (ARCHIVE_OK);
+}
+
+int
+archive_match_exclude_pattern_from_file(struct archive *_a,
+ const char *pathname, int nullSeparator)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file");
+ a = (struct archive_match *)_a;
+
+ return add_pattern_from_file(a, &(a->exclusions), 1, pathname,
+ nullSeparator);
+}
+
+int
+archive_match_exclude_pattern_from_file_w(struct archive *_a,
+ const wchar_t *pathname, int nullSeparator)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file_w");
+ a = (struct archive_match *)_a;
+
+ return add_pattern_from_file(a, &(a->exclusions), 0, pathname,
+ nullSeparator);
+}
+
+int
+archive_match_include_pattern(struct archive *_a, const char *pattern)
+{
+ struct archive_match *a;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_pattern");
+ a = (struct archive_match *)_a;
+
+ if (pattern == NULL || *pattern == '\0') {
+ archive_set_error(&(a->archive), EINVAL, "pattern is empty");
+ return (ARCHIVE_FAILED);
+ }
+ if ((r = add_pattern_mbs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
+ return (r);
+ return (ARCHIVE_OK);
+}
+
+int
+archive_match_include_pattern_w(struct archive *_a, const wchar_t *pattern)
+{
+ struct archive_match *a;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_pattern_w");
+ a = (struct archive_match *)_a;
+
+ if (pattern == NULL || *pattern == L'\0') {
+ archive_set_error(&(a->archive), EINVAL, "pattern is empty");
+ return (ARCHIVE_FAILED);
+ }
+ if ((r = add_pattern_wcs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
+ return (r);
+ return (ARCHIVE_OK);
+}
+
+int
+archive_match_include_pattern_from_file(struct archive *_a,
+ const char *pathname, int nullSeparator)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file");
+ a = (struct archive_match *)_a;
+
+ return add_pattern_from_file(a, &(a->inclusions), 1, pathname,
+ nullSeparator);
+}
+
+int
+archive_match_include_pattern_from_file_w(struct archive *_a,
+ const wchar_t *pathname, int nullSeparator)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file_w");
+ a = (struct archive_match *)_a;
+
+ return add_pattern_from_file(a, &(a->inclusions), 0, pathname,
+ nullSeparator);
+}
+
+/*
+ * Test functions for pathname patterns.
+ *
+ * Returns 1 if archive entry is excluded.
+ * Returns 0 if archive entry is not excluded.
+ * Returns <0 if something error happened.
+ */
+int
+archive_match_path_excluded(struct archive *_a,
+ struct archive_entry *entry)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_path_excluded");
+
+ a = (struct archive_match *)_a;
+ if (entry == NULL) {
+ archive_set_error(&(a->archive), EINVAL, "entry is NULL");
+ return (ARCHIVE_FAILED);
+ }
+
+ /* If we don't have exclusion/inclusion pattern set at all,
+ * the entry is always not excluded. */
+ if ((a->setflag & PATTERN_IS_SET) == 0)
+ return (0);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ return (path_excluded(a, 0, archive_entry_pathname_w(entry)));
+#else
+ return (path_excluded(a, 1, archive_entry_pathname(entry)));
+#endif
+}
+
+/*
+ * Utilty functions to get statistic information for inclusion patterns.
+ */
+int
+archive_match_path_unmatched_inclusions(struct archive *_a)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
+ a = (struct archive_match *)_a;
+
+ return (a->inclusions.unmatched_count);
+}
+
+int
+archive_match_path_unmatched_inclusions_next(struct archive *_a,
+ const char **_p)
+{
+ struct archive_match *a;
+ const void *v;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next");
+ a = (struct archive_match *)_a;
+
+ r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 1, &v);
+ *_p = (const char *)v;
+ return (r);
+}
+
+int
+archive_match_path_unmatched_inclusions_next_w(struct archive *_a,
+ const wchar_t **_p)
+{
+ struct archive_match *a;
+ const void *v;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next_w");
+ a = (struct archive_match *)_a;
+
+ r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 0, &v);
+ *_p = (const wchar_t *)v;
+ return (r);
+}
+
+/*
+ * Add inclusion/exclusion patterns.
+ */
+static int
+add_pattern_mbs(struct archive_match *a, struct match_list *list,
+ const char *pattern)
+{
+ struct match *match;
+ size_t len;
+
+ match = calloc(1, sizeof(*match));
+ if (match == NULL)
+ return (error_nomem(a));
+ /* Both "foo/" and "foo" should match "foo/bar". */
+ len = strlen(pattern);
+ if (len && pattern[len - 1] == '/')
+ --len;
+ archive_mstring_copy_mbs_len(&(match->pattern), pattern, len);
+ match_list_add(list, match);
+ a->setflag |= PATTERN_IS_SET;
+ return (ARCHIVE_OK);
+}
+
+static int
+add_pattern_wcs(struct archive_match *a, struct match_list *list,
+ const wchar_t *pattern)
+{
+ struct match *match;
+ size_t len;
+
+ match = calloc(1, sizeof(*match));
+ if (match == NULL)
+ return (error_nomem(a));
+ /* Both "foo/" and "foo" should match "foo/bar". */
+ len = wcslen(pattern);
+ if (len && pattern[len - 1] == L'/')
+ --len;
+ archive_mstring_copy_wcs_len(&(match->pattern), pattern, len);
+ match_list_add(list, match);
+ a->setflag |= PATTERN_IS_SET;
+ return (ARCHIVE_OK);
+}
+
+static int
+add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
+ int mbs, const void *pathname, int nullSeparator)
+{
+ struct archive *ar;
+ struct archive_entry *ae;
+ struct archive_string as;
+ const void *buff;
+ size_t size;
+ int64_t offset;
+ int r;
+
+ ar = archive_read_new();
+ if (ar == NULL) {
+ archive_set_error(&(a->archive), ENOMEM, "No memory");
+ return (ARCHIVE_FATAL);
+ }
+ r = archive_read_support_format_raw(ar);
+ if (r != ARCHIVE_OK) {
+ archive_copy_error(&(a->archive), ar);
+ archive_read_free(ar);
+ return (r);
+ }
+ if (mbs)
+ r = archive_read_open_filename(ar, pathname, 512*20);
+ else
+ r = archive_read_open_filename_w(ar, pathname, 512*20);
+ if (r != ARCHIVE_OK) {
+ archive_copy_error(&(a->archive), ar);
+ archive_read_free(ar);
+ return (r);
+ }
+ r = archive_read_next_header(ar, &ae);
+ if (r != ARCHIVE_OK) {
+ archive_copy_error(&(a->archive), ar);
+ archive_read_free(ar);
+ return (r);
+ }
+
+ archive_string_init(&as);
+
+ while ((r = archive_read_data_block(ar, &buff, &size, &offset))
+ == ARCHIVE_OK) {
+ const char *b = (const char *)buff;
+
+ while (size) {
+ const char *s = (const char *)b;
+ size_t length = 0;
+ int found_separator = 0;
+
+ while (length < size) {
+ if (nullSeparator) {
+ if (*b == '\0') {
+ found_separator = 1;
+ break;
+ }
+ } else {
+ if (*b == 0x0d || *b == 0x0a) {
+ found_separator = 1;
+ break;
+ }
+ }
+ b++;
+ length++;
+ }
+ if (!found_separator) {
+ archive_strncat(&as, s, length);
+ /* Read next data block. */
+ break;
+ }
+ b++;
+ size -= length + 1;
+ archive_strncat(&as, s, length);
+
+ /* If the line is not empty, add the pattern. */
+ if (archive_strlen(&as) > 0) {
+ /* Add pattern. */
+ r = add_pattern_mbs(a, mlist, as.s);
+ if (r != ARCHIVE_OK) {
+ archive_read_free(ar);
+ archive_string_free(&as);
+ return (r);
+ }
+ archive_string_empty(&as);
+ }
+ }
+ }
+
+ /* If something error happend, report it immediately. */
+ if (r < ARCHIVE_OK) {
+ archive_copy_error(&(a->archive), ar);
+ archive_read_free(ar);
+ archive_string_free(&as);
+ return (r);
+ }
+
+ /* If the line is not empty, add the pattern. */
+ if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) {
+ /* Add pattern. */
+ r = add_pattern_mbs(a, mlist, as.s);
+ if (r != ARCHIVE_OK) {
+ archive_read_free(ar);
+ archive_string_free(&as);
+ return (r);
+ }
+ }
+ archive_read_free(ar);
+ archive_string_free(&as);
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Test if pathname is excluded by inclusion/exclusion patterns.
+ */
+static int
+path_excluded(struct archive_match *a, int mbs, const void *pathname)
+{
+ struct match *match;
+ struct match *matched;
+ int r;
+
+ if (a == NULL)
+ return (0);
+
+ /* Mark off any unmatched inclusions. */
+ /* In particular, if a filename does appear in the archive and
+ * is explicitly included and excluded, then we don't report
+ * it as missing even though we don't extract it.
+ */
+ matched = NULL;
+ for (match = a->inclusions.first; match != NULL;
+ match = match->next){
+ if (match->matches == 0 &&
+ (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
+ if (r < 0)
+ return (r);
+ a->inclusions.unmatched_count--;
+ match->matches++;
+ matched = match;
+ }
+ }
+
+ /* Exclusions take priority */
+ for (match = a->exclusions.first; match != NULL;
+ match = match->next){
+ r = match_path_exclusion(a, match, mbs, pathname);
+ if (r)
+ return (r);
+ }
+
+ /* It's not excluded and we found an inclusion above, so it's
+ * included. */
+ if (matched != NULL)
+ return (0);
+
+
+ /* We didn't find an unmatched inclusion, check the remaining ones. */
+ for (match = a->inclusions.first; match != NULL;
+ match = match->next){
+ /* We looked at previously-unmatched inclusions already. */
+ if (match->matches > 0 &&
+ (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
+ if (r < 0)
+ return (r);
+ match->matches++;
+ return (0);
+ }
+ }
+
+ /* If there were inclusions, default is to exclude. */
+ if (a->inclusions.first != NULL)
+ return (1);
+
+ /* No explicit inclusions, default is to match. */
+ return (0);
+}
+
+/*
+ * This is a little odd, but it matches the default behavior of
+ * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
+ *
+ */
+static int
+match_path_exclusion(struct archive_match *a, struct match *m,
+ int mbs, const void *pn)
+{
+ int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END;
+ int r;
+
+ if (mbs) {
+ const char *p;
+ r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
+ if (r == 0)
+ return (archive_pathmatch(p, (const char *)pn, flag));
+ } else {
+ const wchar_t *p;
+ r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
+ if (r == 0)
+ return (archive_pathmatch_w(p, (const wchar_t *)pn,
+ flag));
+ }
+ if (errno == ENOMEM)
+ return (error_nomem(a));
+ return (0);
+}
+
+/*
+ * Again, mimic gtar: inclusions are always anchored (have to match
+ * the beginning of the path) even though exclusions are not anchored.
+ */
+static int
+match_path_inclusion(struct archive_match *a, struct match *m,
+ int mbs, const void *pn)
+{
+ int flag = PATHMATCH_NO_ANCHOR_END;
+ int r;
+
+ if (mbs) {
+ const char *p;
+ r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
+ if (r == 0)
+ return (archive_pathmatch(p, (const char *)pn, flag));
+ } else {
+ const wchar_t *p;
+ r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
+ if (r == 0)
+ return (archive_pathmatch_w(p, (const wchar_t *)pn,
+ flag));
+ }
+ if (errno == ENOMEM)
+ return (error_nomem(a));
+ return (0);
+}
+
+static void
+match_list_init(struct match_list *list)
+{
+ list->first = NULL;
+ list->last = &(list->first);
+ list->count = 0;
+}
+
+static void
+match_list_free(struct match_list *list)
+{
+ struct match *p, *q;
+
+ for (p = list->first; p != NULL; ) {
+ q = p;
+ p = p->next;
+ archive_mstring_clean(&(q->pattern));
+ free(q);
+ }
+}
+
+static void
+match_list_add(struct match_list *list, struct match *m)
+{
+ *list->last = m;
+ list->last = &(m->next);
+ list->count++;
+ list->unmatched_count++;
+}
+
+static int
+match_list_unmatched_inclusions_next(struct archive_match *a,
+ struct match_list *list, int mbs, const void **vp)
+{
+ struct match *m;
+
+ *vp = NULL;
+ if (list->unmatched_eof) {
+ list->unmatched_eof = 0;
+ return (ARCHIVE_EOF);
+ }
+ if (list->unmatched_next == NULL) {
+ if (list->unmatched_count == 0)
+ return (ARCHIVE_EOF);
+ list->unmatched_next = list->first;
+ }
+
+ for (m = list->unmatched_next; m != NULL; m = m->next) {
+ int r;
+
+ if (m->matches)
+ continue;
+ if (mbs) {
+ const char *p;
+ r = archive_mstring_get_mbs(&(a->archive),
+ &(m->pattern), &p);
+ if (r < 0 && errno == ENOMEM)
+ return (error_nomem(a));
+ if (p == NULL)
+ p = "";
+ *vp = p;
+ } else {
+ const wchar_t *p;
+ r = archive_mstring_get_wcs(&(a->archive),
+ &(m->pattern), &p);
+ if (r < 0 && errno == ENOMEM)
+ return (error_nomem(a));
+ if (p == NULL)
+ p = L"";
+ *vp = p;
+ }
+ list->unmatched_next = m->next;
+ if (list->unmatched_next == NULL)
+ /* To return EOF next time. */
+ list->unmatched_eof = 1;
+ return (ARCHIVE_OK);
+ }
+ list->unmatched_next = NULL;
+ return (ARCHIVE_EOF);
+}
+
+/*
+ * Utility functions to manage inclusion timestamps.
+ */
+int
+archive_match_include_time(struct archive *_a, int flag, time_t sec,
+ long nsec)
+{
+ int r;
+
+ r = validate_time_flag(_a, flag, "archive_match_include_time");
+ if (r != ARCHIVE_OK)
+ return (r);
+ return set_timefilter((struct archive_match *)_a, flag,
+ sec, nsec, sec, nsec);
+}
+
+int
+archive_match_include_date(struct archive *_a, int flag,
+ const char *datestr)
+{
+ int r;
+
+ r = validate_time_flag(_a, flag, "archive_match_include_date");
+ if (r != ARCHIVE_OK)
+ return (r);
+ return set_timefilter_date((struct archive_match *)_a, flag, datestr);
+}
+
+int
+archive_match_include_date_w(struct archive *_a, int flag,
+ const wchar_t *datestr)
+{
+ int r;
+
+ r = validate_time_flag(_a, flag, "archive_match_include_date_w");
+ if (r != ARCHIVE_OK)
+ return (r);
+
+ return set_timefilter_date_w((struct archive_match *)_a, flag, datestr);
+}
+
+int
+archive_match_include_file_time(struct archive *_a, int flag,
+ const char *pathname)
+{
+ int r;
+
+ r = validate_time_flag(_a, flag, "archive_match_include_file_time");
+ if (r != ARCHIVE_OK)
+ return (r);
+ return set_timefilter_pathname_mbs((struct archive_match *)_a,
+ flag, pathname);
+}
+
+int
+archive_match_include_file_time_w(struct archive *_a, int flag,
+ const wchar_t *pathname)
+{
+ int r;
+
+ r = validate_time_flag(_a, flag, "archive_match_include_file_time_w");
+ if (r != ARCHIVE_OK)
+ return (r);
+ return set_timefilter_pathname_wcs((struct archive_match *)_a,
+ flag, pathname);
+}
+
+int
+archive_match_exclude_entry(struct archive *_a, int flag,
+ struct archive_entry *entry)
+{
+ struct archive_match *a;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_time_include_entry");
+ a = (struct archive_match *)_a;
+
+ if (entry == NULL) {
+ archive_set_error(&(a->archive), EINVAL, "entry is NULL");
+ return (ARCHIVE_FAILED);
+ }
+ r = validate_time_flag(_a, flag, "archive_match_exclude_entry");
+ if (r != ARCHIVE_OK)
+ return (r);
+ return (add_entry(a, flag, entry));
+}
+
+/*
+ * Test function for time stamps.
+ *
+ * Returns 1 if archive entry is excluded.
+ * Returns 0 if archive entry is not excluded.
+ * Returns <0 if something error happened.
+ */
+int
+archive_match_time_excluded(struct archive *_a,
+ struct archive_entry *entry)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae");
+
+ a = (struct archive_match *)_a;
+ if (entry == NULL) {
+ archive_set_error(&(a->archive), EINVAL, "entry is NULL");
+ return (ARCHIVE_FAILED);
+ }
+
+ /* If we don't have inclusion time set at all, the entry is always
+ * not excluded. */
+ if ((a->setflag & TIME_IS_SET) == 0)
+ return (0);
+ return (time_excluded(a, entry));
+}
+
+static int
+validate_time_flag(struct archive *_a, int flag, const char *_fn)
+{
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, _fn);
+
+ /* Check a type of time. */
+ if (flag &
+ ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) {
+ archive_set_error(_a, EINVAL, "Invalid time flag");
+ return (ARCHIVE_FAILED);
+ }
+ if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) {
+ archive_set_error(_a, EINVAL, "No time flag");
+ return (ARCHIVE_FAILED);
+ }
+
+ /* Check a type of comparison. */
+ if (flag &
+ ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
+ | ARCHIVE_MATCH_EQUAL)) & 0x00ff)) {
+ archive_set_error(_a, EINVAL, "Invalid comparison flag");
+ return (ARCHIVE_FAILED);
+ }
+ if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
+ | ARCHIVE_MATCH_EQUAL)) == 0) {
+ archive_set_error(_a, EINVAL, "No comparison flag");
+ return (ARCHIVE_FAILED);
+ }
+
+ return (ARCHIVE_OK);
+}
+
+#define JUST_EQUAL(t) (((t) & (ARCHIVE_MATCH_EQUAL |\
+ ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL)
+static int
+set_timefilter(struct archive_match *a, int timetype,
+ time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec)
+{
+ if (timetype & ARCHIVE_MATCH_MTIME) {
+ if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
+ a->newer_mtime_filter = timetype;
+ a->newer_mtime_sec = mtime_sec;
+ a->newer_mtime_nsec = mtime_nsec;
+ a->setflag |= TIME_IS_SET;
+ }
+ if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
+ a->older_mtime_filter = timetype;
+ a->older_mtime_sec = mtime_sec;
+ a->older_mtime_nsec = mtime_nsec;
+ a->setflag |= TIME_IS_SET;
+ }
+ }
+ if (timetype & ARCHIVE_MATCH_CTIME) {
+ if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
+ a->newer_ctime_filter = timetype;
+ a->newer_ctime_sec = ctime_sec;
+ a->newer_ctime_nsec = ctime_nsec;
+ a->setflag |= TIME_IS_SET;
+ }
+ if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
+ a->older_ctime_filter = timetype;
+ a->older_ctime_sec = ctime_sec;
+ a->older_ctime_nsec = ctime_nsec;
+ a->setflag |= TIME_IS_SET;
+ }
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+set_timefilter_date(struct archive_match *a, int timetype, const char *datestr)
+{
+ time_t t;
+
+ if (datestr == NULL || *datestr == '\0') {
+ archive_set_error(&(a->archive), EINVAL, "date is empty");
+ return (ARCHIVE_FAILED);
+ }
+ t = get_date(a->now, datestr);
+ if (t == (time_t)-1) {
+ archive_set_error(&(a->archive), EINVAL, "invalid date string");
+ return (ARCHIVE_FAILED);
+ }
+ return set_timefilter(a, timetype, t, 0, t, 0);
+}
+
+static int
+set_timefilter_date_w(struct archive_match *a, int timetype,
+ const wchar_t *datestr)
+{
+ struct archive_string as;
+ time_t t;
+
+ if (datestr == NULL || *datestr == L'\0') {
+ archive_set_error(&(a->archive), EINVAL, "date is empty");
+ return (ARCHIVE_FAILED);
+ }
+
+ archive_string_init(&as);
+ if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) {
+ archive_string_free(&as);
+ if (errno == ENOMEM)
+ return (error_nomem(a));
+ archive_set_error(&(a->archive), -1,
+ "Failed to convert WCS to MBS");
+ return (ARCHIVE_FAILED);
+ }
+ t = get_date(a->now, as.s);
+ archive_string_free(&as);
+ if (t == (time_t)-1) {
+ archive_set_error(&(a->archive), EINVAL, "invalid date string");
+ return (ARCHIVE_FAILED);
+ }
+ return set_timefilter(a, timetype, t, 0, t, 0);
+}
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
+static int
+set_timefilter_find_data(struct archive_match *a, int timetype,
+ DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
+ DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
+{
+ ULARGE_INTEGER utc;
+ time_t ctime_sec, mtime_sec;
+ long ctime_ns, mtime_ns;
+
+ utc.HighPart = ftCreationTime_dwHighDateTime;
+ utc.LowPart = ftCreationTime_dwLowDateTime;
+ if (utc.QuadPart >= EPOC_TIME) {
+ utc.QuadPart -= EPOC_TIME;
+ ctime_sec = (time_t)(utc.QuadPart / 10000000);
+ ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
+ } else {
+ ctime_sec = 0;
+ ctime_ns = 0;
+ }
+ utc.HighPart = ftLastWriteTime_dwHighDateTime;
+ utc.LowPart = ftLastWriteTime_dwLowDateTime;
+ if (utc.QuadPart >= EPOC_TIME) {
+ utc.QuadPart -= EPOC_TIME;
+ mtime_sec = (time_t)(utc.QuadPart / 10000000);
+ mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
+ } else {
+ mtime_sec = 0;
+ mtime_ns = 0;
+ }
+ return set_timefilter(a, timetype,
+ mtime_sec, mtime_ns, ctime_sec, ctime_ns);
+}
+
+static int
+set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
+ const char *path)
+{
+ /* NOTE: stat() on Windows cannot handle nano seconds. */
+ HANDLE h;
+ WIN32_FIND_DATA d;
+
+ if (path == NULL || *path == '\0') {
+ archive_set_error(&(a->archive), EINVAL, "pathname is empty");
+ return (ARCHIVE_FAILED);
+ }
+ h = FindFirstFileA(path, &d);
+ if (h == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
+ archive_set_error(&(a->archive), errno,
+ "Failed to FindFirstFileA");
+ return (ARCHIVE_FAILED);
+ }
+ FindClose(h);
+ return set_timefilter_find_data(a, timetype,
+ d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
+ d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
+}
+
+static int
+set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
+ const wchar_t *path)
+{
+ HANDLE h;
+ WIN32_FIND_DATAW d;
+
+ if (path == NULL || *path == L'\0') {
+ archive_set_error(&(a->archive), EINVAL, "pathname is empty");
+ return (ARCHIVE_FAILED);
+ }
+ h = FindFirstFileW(path, &d);
+ if (h == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
+ archive_set_error(&(a->archive), errno,
+ "Failed to FindFirstFile");
+ return (ARCHIVE_FAILED);
+ }
+ FindClose(h);
+ return set_timefilter_find_data(a, timetype,
+ d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
+ d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
+}
+
+#else /* _WIN32 && !__CYGWIN__ */
+
+static int
+set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st)
+{
+ struct archive_entry *ae;
+ time_t ctime_sec, mtime_sec;
+ long ctime_ns, mtime_ns;
+
+ ae = archive_entry_new();
+ if (ae == NULL)
+ return (error_nomem(a));
+ archive_entry_copy_stat(ae, st);
+ ctime_sec = archive_entry_ctime(ae);
+ ctime_ns = archive_entry_ctime_nsec(ae);
+ mtime_sec = archive_entry_mtime(ae);
+ mtime_ns = archive_entry_mtime_nsec(ae);
+ archive_entry_free(ae);
+ return set_timefilter(a, timetype, mtime_sec, mtime_ns,
+ ctime_sec, ctime_ns);
+}
+
+static int
+set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
+ const char *path)
+{
+ struct stat st;
+
+ if (path == NULL || *path == '\0') {
+ archive_set_error(&(a->archive), EINVAL, "pathname is empty");
+ return (ARCHIVE_FAILED);
+ }
+ if (stat(path, &st) != 0) {
+ archive_set_error(&(a->archive), errno, "Failed to stat()");
+ return (ARCHIVE_FAILED);
+ }
+ return (set_timefilter_stat(a, timetype, &st));
+}
+
+static int
+set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
+ const wchar_t *path)
+{
+ struct archive_string as;
+ int r;
+
+ if (path == NULL || *path == L'\0') {
+ archive_set_error(&(a->archive), EINVAL, "pathname is empty");
+ return (ARCHIVE_FAILED);
+ }
+
+ /* Convert WCS filename to MBS filename. */
+ archive_string_init(&as);
+ if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) {
+ archive_string_free(&as);
+ if (errno == ENOMEM)
+ return (error_nomem(a));
+ archive_set_error(&(a->archive), -1,
+ "Failed to convert WCS to MBS");
+ return (ARCHIVE_FAILED);
+ }
+
+ r = set_timefilter_pathname_mbs(a, timetype, as.s);
+ archive_string_free(&as);
+
+ return (r);
+}
+#endif /* _WIN32 && !__CYGWIN__ */
+
+/*
+ * Call back funtions for archive_rb.
+ */
+static int
+cmp_node_mbs(const struct archive_rb_node *n1,
+ const struct archive_rb_node *n2)
+{
+ struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
+ struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
+ const char *p1, *p2;
+
+ archive_mstring_get_mbs(NULL, &(f1->pathname), &p1);
+ archive_mstring_get_mbs(NULL, &(f2->pathname), &p2);
+ if (p1 == NULL)
+ return (1);
+ if (p2 == NULL)
+ return (-1);
+ return (strcmp(p1, p2));
+}
+
+static int
+cmp_key_mbs(const struct archive_rb_node *n, const void *key)
+{
+ struct match_file *f = (struct match_file *)(uintptr_t)n;
+ const char *p;
+
+ archive_mstring_get_mbs(NULL, &(f->pathname), &p);
+ if (p == NULL)
+ return (-1);
+ return (strcmp(p, (const char *)key));
+}
+
+static int
+cmp_node_wcs(const struct archive_rb_node *n1,
+ const struct archive_rb_node *n2)
+{
+ struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
+ struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
+ const wchar_t *p1, *p2;
+
+ archive_mstring_get_wcs(NULL, &(f1->pathname), &p1);
+ archive_mstring_get_wcs(NULL, &(f2->pathname), &p2);
+ if (p1 == NULL)
+ return (1);
+ if (p2 == NULL)
+ return (-1);
+ return (wcscmp(p1, p2));
+}
+
+static int
+cmp_key_wcs(const struct archive_rb_node *n, const void *key)
+{
+ struct match_file *f = (struct match_file *)(uintptr_t)n;
+ const wchar_t *p;
+
+ archive_mstring_get_wcs(NULL, &(f->pathname), &p);
+ if (p == NULL)
+ return (-1);
+ return (wcscmp(p, (const wchar_t *)key));
+}
+
+static void
+entry_list_init(struct entry_list *list)
+{
+ list->first = NULL;
+ list->last = &(list->first);
+ list->count = 0;
+}
+
+static void
+entry_list_free(struct entry_list *list)
+{
+ struct match_file *p, *q;
+
+ for (p = list->first; p != NULL; ) {
+ q = p;
+ p = p->next;
+ archive_mstring_clean(&(q->pathname));
+ free(q);
+ }
+}
+
+static void
+entry_list_add(struct entry_list *list, struct match_file *file)
+{
+ *list->last = file;
+ list->last = &(file->next);
+ list->count++;
+}
+
+static int
+add_entry(struct archive_match *a, int flag,
+ struct archive_entry *entry)
+{
+ struct match_file *f;
+ const void *pathname;
+ int r;
+
+ f = calloc(1, sizeof(*f));
+ if (f == NULL)
+ return (error_nomem(a));
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ pathname = archive_entry_pathname_w(entry);
+ if (pathname == NULL) {
+ free(f);
+ archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
+ return (ARCHIVE_FAILED);
+ }
+ archive_mstring_copy_wcs(&(f->pathname), pathname);
+ a->exclusion_tree.rbt_ops = &rb_ops_wcs;
+#else
+ (void)rb_ops_wcs;
+ pathname = archive_entry_pathname(entry);
+ if (pathname == NULL) {
+ free(f);
+ archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
+ return (ARCHIVE_FAILED);
+ }
+ archive_mstring_copy_mbs(&(f->pathname), pathname);
+ a->exclusion_tree.rbt_ops = &rb_ops_mbs;
+#endif
+ f->flag = flag;
+ f->mtime_sec = archive_entry_mtime(entry);
+ f->mtime_nsec = archive_entry_mtime_nsec(entry);
+ f->ctime_sec = archive_entry_ctime(entry);
+ f->ctime_nsec = archive_entry_ctime_nsec(entry);
+ r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
+ if (!r) {
+ struct match_file *f2;
+
+ /* Get the duplicated file. */
+ f2 = (struct match_file *)__archive_rb_tree_find_node(
+ &(a->exclusion_tree), pathname);
+
+ /*
+ * We always overwrite comparison condision.
+ * If you do not want to overwrite it, you should not
+ * call archive_match_exclude_entry(). We cannot know
+ * what behavior you really expect since overwriting
+ * condition might be different with the flag.
+ */
+ if (f2 != NULL) {
+ f2->flag = f->flag;
+ f2->mtime_sec = f->mtime_sec;
+ f2->mtime_nsec = f->mtime_nsec;
+ f2->ctime_sec = f->ctime_sec;
+ f2->ctime_nsec = f->ctime_nsec;
+ }
+ /* Release the duplicated file. */
+ archive_mstring_clean(&(f->pathname));
+ free(f);
+ return (ARCHIVE_OK);
+ }
+ entry_list_add(&(a->exclusion_entry_list), f);
+ a->setflag |= TIME_IS_SET;
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Test if entry is excluded by its timestamp.
+ */
+static int
+time_excluded(struct archive_match *a, struct archive_entry *entry)
+{
+ struct match_file *f;
+ const void *pathname;
+ time_t sec;
+ long nsec;
+
+ /*
+ * If this file/dir is excluded by a time comparison, skip it.
+ */
+ if (a->newer_ctime_filter) {
+ /* If ctime is not set, use mtime instead. */
+ if (archive_entry_ctime_is_set(entry))
+ sec = archive_entry_ctime(entry);
+ else
+ sec = archive_entry_mtime(entry);
+ if (sec < a->newer_ctime_sec)
+ return (1); /* Too old, skip it. */
+ if (sec == a->newer_ctime_sec) {
+ if (archive_entry_ctime_is_set(entry))
+ nsec = archive_entry_ctime_nsec(entry);
+ else
+ nsec = archive_entry_mtime_nsec(entry);
+ if (nsec < a->newer_ctime_nsec)
+ return (1); /* Too old, skip it. */
+ if (nsec == a->newer_ctime_nsec &&
+ (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
+ == 0)
+ return (1); /* Equal, skip it. */
+ }
+ }
+ if (a->older_ctime_filter) {
+ /* If ctime is not set, use mtime instead. */
+ if (archive_entry_ctime_is_set(entry))
+ sec = archive_entry_ctime(entry);
+ else
+ sec = archive_entry_mtime(entry);
+ if (sec > a->older_ctime_sec)
+ return (1); /* Too new, skip it. */
+ if (sec == a->older_ctime_sec) {
+ if (archive_entry_ctime_is_set(entry))
+ nsec = archive_entry_ctime_nsec(entry);
+ else
+ nsec = archive_entry_mtime_nsec(entry);
+ if (nsec > a->older_ctime_nsec)
+ return (1); /* Too new, skip it. */
+ if (nsec == a->older_ctime_nsec &&
+ (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
+ == 0)
+ return (1); /* Eeual, skip it. */
+ }
+ }
+ if (a->newer_mtime_filter) {
+ sec = archive_entry_mtime(entry);
+ if (sec < a->newer_mtime_sec)
+ return (1); /* Too old, skip it. */
+ if (sec == a->newer_mtime_sec) {
+ nsec = archive_entry_mtime_nsec(entry);
+ if (nsec < a->newer_mtime_nsec)
+ return (1); /* Too old, skip it. */
+ if (nsec == a->newer_mtime_nsec &&
+ (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
+ == 0)
+ return (1); /* Equal, skip it. */
+ }
+ }
+ if (a->older_mtime_filter) {
+ sec = archive_entry_mtime(entry);
+ if (sec > a->older_mtime_sec)
+ return (1); /* Too new, skip it. */
+ nsec = archive_entry_mtime_nsec(entry);
+ if (sec == a->older_mtime_sec) {
+ if (nsec > a->older_mtime_nsec)
+ return (1); /* Too new, skip it. */
+ if (nsec == a->older_mtime_nsec &&
+ (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
+ == 0)
+ return (1); /* Equal, skip it. */
+ }
+ }
+
+ /* If there is no excluson list, include the file. */
+ if (a->exclusion_entry_list.count == 0)
+ return (0);
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ pathname = archive_entry_pathname_w(entry);
+ a->exclusion_tree.rbt_ops = &rb_ops_wcs;
+#else
+ (void)rb_ops_wcs;
+ pathname = archive_entry_pathname(entry);
+ a->exclusion_tree.rbt_ops = &rb_ops_mbs;
+#endif
+ if (pathname == NULL)
+ return (0);
+
+ f = (struct match_file *)__archive_rb_tree_find_node(
+ &(a->exclusion_tree), pathname);
+ /* If the file wasn't rejected, include it. */
+ if (f == NULL)
+ return (0);
+
+ if (f->flag & ARCHIVE_MATCH_CTIME) {
+ sec = archive_entry_ctime(entry);
+ if (f->ctime_sec > sec) {
+ if (f->flag & ARCHIVE_MATCH_OLDER)
+ return (1);
+ } else if (f->ctime_sec < sec) {
+ if (f->flag & ARCHIVE_MATCH_NEWER)
+ return (1);
+ } else {
+ nsec = archive_entry_ctime_nsec(entry);
+ if (f->ctime_nsec > nsec) {
+ if (f->flag & ARCHIVE_MATCH_OLDER)
+ return (1);
+ } else if (f->ctime_nsec < nsec) {
+ if (f->flag & ARCHIVE_MATCH_NEWER)
+ return (1);
+ } else if (f->flag & ARCHIVE_MATCH_EQUAL)
+ return (1);
+ }
+ }
+ if (f->flag & ARCHIVE_MATCH_MTIME) {
+ sec = archive_entry_mtime(entry);
+ if (f->mtime_sec > sec) {
+ if (f->flag & ARCHIVE_MATCH_OLDER)
+ return (1);
+ } else if (f->mtime_sec < sec) {
+ if (f->flag & ARCHIVE_MATCH_NEWER)
+ return (1);
+ } else {
+ nsec = archive_entry_mtime_nsec(entry);
+ if (f->mtime_nsec > nsec) {
+ if (f->flag & ARCHIVE_MATCH_OLDER)
+ return (1);
+ } else if (f->mtime_nsec < nsec) {
+ if (f->flag & ARCHIVE_MATCH_NEWER)
+ return (1);
+ } else if (f->flag & ARCHIVE_MATCH_EQUAL)
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Utility functions to manage inclusion owners
+ */
+
+int
+archive_match_include_uid(struct archive *_a, int64_t uid)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_uid");
+ a = (struct archive_match *)_a;
+ return (add_owner_id(a, &(a->inclusion_uids), uid));
+}
+
+int
+archive_match_include_gid(struct archive *_a, int64_t gid)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_gid");
+ a = (struct archive_match *)_a;
+ return (add_owner_id(a, &(a->inclusion_gids), gid));
+}
+
+int
+archive_match_include_uname(struct archive *_a, const char *uname)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_uname");
+ a = (struct archive_match *)_a;
+ return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
+}
+
+int
+archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
+ a = (struct archive_match *)_a;
+ return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
+}
+
+int
+archive_match_include_gname(struct archive *_a, const char *gname)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_gname");
+ a = (struct archive_match *)_a;
+ return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
+}
+
+int
+archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
+ a = (struct archive_match *)_a;
+ return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
+}
+
+/*
+ * Test function for owner(uid, gid, uname, gname).
+ *
+ * Returns 1 if archive entry is excluded.
+ * Returns 0 if archive entry is not excluded.
+ * Returns <0 if something error happened.
+ */
+int
+archive_match_owner_excluded(struct archive *_a,
+ struct archive_entry *entry)
+{
+ struct archive_match *a;
+
+ archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
+
+ a = (struct archive_match *)_a;
+ if (entry == NULL) {
+ archive_set_error(&(a->archive), EINVAL, "entry is NULL");
+ return (ARCHIVE_FAILED);
+ }
+
+ /* If we don't have inclusion id set at all, the entry is always
+ * not excluded. */
+ if ((a->setflag & ID_IS_SET) == 0)
+ return (0);
+ return (owner_excluded(a, entry));
+}
+
+static int
+add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
+{
+ unsigned i;
+
+ if (ids->count + 1 >= ids->size) {
+ void *p;
+
+ if (ids->size == 0)
+ ids->size = 8;
+ else
+ ids->size *= 2;
+ p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
+ if (p == NULL)
+ return (error_nomem(a));
+ ids->ids = (int64_t *)p;
+ }
+
+ /* Find an insert point. */
+ for (i = 0; i < ids->count; i++) {
+ if (ids->ids[i] >= id)
+ break;
+ }
+
+ /* Add oowner id. */
+ if (i == ids->count)
+ ids->ids[ids->count++] = id;
+ else if (ids->ids[i] != id) {
+ memmove(&(ids->ids[i+1]), &(ids->ids[i]),
+ (ids->count - i) * sizeof(ids->ids[0]));
+ ids->ids[i] = id;
+ ids->count++;
+ }
+ a->setflag |= ID_IS_SET;
+ return (ARCHIVE_OK);
+}
+
+static int
+match_owner_id(struct id_array *ids, int64_t id)
+{
+ unsigned b, m, t;
+
+ t = 0;
+ b = (unsigned)ids->count;
+ while (t < b) {
+ m = (t + b)>>1;
+ if (ids->ids[m] == id)
+ return (1);
+ if (ids->ids[m] < id)
+ t = m + 1;
+ else
+ b = m;
+ }
+ return (0);
+}
+
+static int
+add_owner_name(struct archive_match *a, struct match_list *list,
+ int mbs, const void *name)
+{
+ struct match *match;
+
+ match = calloc(1, sizeof(*match));
+ if (match == NULL)
+ return (error_nomem(a));
+ if (mbs)
+ archive_mstring_copy_mbs(&(match->pattern), name);
+ else
+ archive_mstring_copy_wcs(&(match->pattern), name);
+ match_list_add(list, match);
+ a->setflag |= ID_IS_SET;
+ return (ARCHIVE_OK);
+}
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+static int
+match_owner_name_mbs(struct archive_match *a, struct match_list *list,
+ const char *name)
+{
+ struct match *m;
+ const char *p;
+
+ if (name == NULL || *name == '\0')
+ return (0);
+ for (m = list->first; m; m = m->next) {
+ if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
+ < 0 && errno == ENOMEM)
+ return (error_nomem(a));
+ if (p != NULL && strcmp(p, name) == 0) {
+ m->matches++;
+ return (1);
+ }
+ }
+ return (0);
+}
+#else
+static int
+match_owner_name_wcs(struct archive_match *a, struct match_list *list,
+ const wchar_t *name)
+{
+ struct match *m;
+ const wchar_t *p;
+
+ if (name == NULL || *name == L'\0')
+ return (0);
+ for (m = list->first; m; m = m->next) {
+ if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
+ < 0 && errno == ENOMEM)
+ return (error_nomem(a));
+ if (p != NULL && wcscmp(p, name) == 0) {
+ m->matches++;
+ return (1);
+ }
+ }
+ return (0);
+}
+#endif
+
+/*
+ * Test if entry is excluded by uid, gid, uname or gname.
+ */
+static int
+owner_excluded(struct archive_match *a, struct archive_entry *entry)
+{
+ int r;
+
+ if (a->inclusion_uids.count) {
+ if (!match_owner_id(&(a->inclusion_uids),
+ archive_entry_uid(entry)))
+ return (1);
+ }
+
+ if (a->inclusion_gids.count) {
+ if (!match_owner_id(&(a->inclusion_gids),
+ archive_entry_gid(entry)))
+ return (1);
+ }
+
+ if (a->inclusion_unames.count) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ r = match_owner_name_wcs(a, &(a->inclusion_unames),
+ archive_entry_uname_w(entry));
+#else
+ r = match_owner_name_mbs(a, &(a->inclusion_unames),
+ archive_entry_uname(entry));
+#endif
+ if (!r)
+ return (1);
+ else if (r < 0)
+ return (r);
+ }
+
+ if (a->inclusion_gnames.count) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ r = match_owner_name_wcs(a, &(a->inclusion_gnames),
+ archive_entry_gname_w(entry));
+#else
+ r = match_owner_name_mbs(a, &(a->inclusion_gnames),
+ archive_entry_gname(entry));
+#endif
+ if (!r)
+ return (1);
+ else if (r < 0)
+ return (r);
+ }
+ return (0);
+}
+
diff --git a/Utilities/cmlibarchive/libarchive/archive_options.c b/Utilities/cmlibarchive/libarchive/archive_options.c
index 79b4ffb..220ebd4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_options.c
+++ b/Utilities/cmlibarchive/libarchive/archive_options.c
@@ -38,6 +38,7 @@ _archive_set_option(struct archive *a,
int magic, const char *fn, option_handler use_option)
{
const char *mp, *op, *vp;
+ int r;
archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
@@ -47,10 +48,24 @@ _archive_set_option(struct archive *a,
if (op == NULL && vp == NULL)
return (ARCHIVE_OK);
- if (op == NULL)
+ if (op == NULL) {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option");
return (ARCHIVE_FAILED);
+ }
- return use_option(a, mp, op, vp);
+ r = use_option(a, mp, op, vp);
+ if (r == ARCHIVE_WARN - 1) {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unknown module name: `%s'", mp);
+ return (ARCHIVE_FAILED);
+ }
+ if (r == ARCHIVE_WARN) {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Undefined option: `%s%s%s%s%s%s'",
+ vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:"");
+ return (ARCHIVE_FAILED);
+ }
+ return (r);
}
int
@@ -72,6 +87,8 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
if (r2 == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
+ if (r2 == ARCHIVE_WARN - 1)
+ return r1;
return r1 > r2 ? r1 : r2;
}
@@ -79,7 +96,7 @@ int
_archive_set_options(struct archive *a, const char *options,
int magic, const char *fn, option_handler use_option)
{
- int allok = 1, anyok = 0, r;
+ int allok = 1, anyok = 0, ignore_mod_err = 0, r;
char *data;
const char *s, *mod, *opt, *val;
@@ -96,12 +113,42 @@ _archive_set_options(struct archive *a, const char *options,
mod = opt = val = NULL;
parse_option(&s, &mod, &opt, &val);
+ if (mod == NULL && opt != NULL &&
+ strcmp("__ignore_wrong_module_name__", opt) == 0) {
+ /* Ignore module name error */
+ if (val != NULL) {
+ ignore_mod_err = 1;
+ anyok = 1;
+ }
+ continue;
+ }
r = use_option(a, mod, opt, val);
if (r == ARCHIVE_FATAL) {
free(data);
return (ARCHIVE_FATAL);
}
+ if (r == ARCHIVE_FAILED && mod != NULL) {
+ free(data);
+ return (ARCHIVE_FAILED);
+ }
+ if (r == ARCHIVE_WARN - 1) {
+ if (ignore_mod_err)
+ continue;
+ /* The module name is wrong. */
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Unknown module name: `%s'", mod);
+ free(data);
+ return (ARCHIVE_FAILED);
+ }
+ if (r == ARCHIVE_WARN) {
+ /* The option name is wrong. No-one used this. */
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Undefined option: `%s%s%s'",
+ mod?mod:"", mod?":":"", opt);
+ free(data);
+ return (ARCHIVE_FAILED);
+ }
if (r == ARCHIVE_OK)
anyok = 1;
else
diff --git a/Utilities/cmlibarchive/libarchive/archive_pathmatch.c b/Utilities/cmlibarchive/libarchive/archive_pathmatch.c
new file mode 100644
index 0000000..505252a
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_pathmatch.c
@@ -0,0 +1,459 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_WCHAR_H
+#include <wchar.h>
+#endif
+
+#include "archive_pathmatch.h"
+
+/*
+ * Check whether a character 'c' is matched by a list specification [...]:
+ * * Leading '!' or '^' negates the class.
+ * * <char>-<char> is a range of characters
+ * * \<char> removes any special meaning for <char>
+ *
+ * Some interesting boundary cases:
+ * a-d-e is one range (a-d) followed by two single characters - and e.
+ * \a-\d is same as a-d
+ * a\-d is three single characters: a, d, -
+ * Trailing - is not special (so [a-] is two characters a and -).
+ * Initial - is not special ([a-] is same as [-a] is same as [\\-a])
+ * This function never sees a trailing \.
+ * [] always fails
+ * [!] always succeeds
+ */
+static int
+pm_list(const char *start, const char *end, const char c, int flags)
+{
+ const char *p = start;
+ char rangeStart = '\0', nextRangeStart;
+ int match = 1, nomatch = 0;
+
+ /* This will be used soon... */
+ (void)flags; /* UNUSED */
+
+ /* If this is a negated class, return success for nomatch. */
+ if ((*p == '!' || *p == '^') && p < end) {
+ match = 0;
+ nomatch = 1;
+ ++p;
+ }
+
+ while (p < end) {
+ nextRangeStart = '\0';
+ switch (*p) {
+ case '-':
+ /* Trailing or initial '-' is not special. */
+ if ((rangeStart == '\0') || (p == end - 1)) {
+ if (*p == c)
+ return (match);
+ } else {
+ char rangeEnd = *++p;
+ if (rangeEnd == '\\')
+ rangeEnd = *++p;
+ if ((rangeStart <= c) && (c <= rangeEnd))
+ return (match);
+ }
+ break;
+ case '\\':
+ ++p;
+ /* Fall through */
+ default:
+ if (*p == c)
+ return (match);
+ nextRangeStart = *p; /* Possible start of range. */
+ }
+ rangeStart = nextRangeStart;
+ ++p;
+ }
+ return (nomatch);
+}
+
+static int
+pm_list_w(const wchar_t *start, const wchar_t *end, const wchar_t c, int flags)
+{
+ const wchar_t *p = start;
+ wchar_t rangeStart = L'\0', nextRangeStart;
+ int match = 1, nomatch = 0;
+
+ /* This will be used soon... */
+ (void)flags; /* UNUSED */
+
+ /* If this is a negated class, return success for nomatch. */
+ if ((*p == L'!' || *p == L'^') && p < end) {
+ match = 0;
+ nomatch = 1;
+ ++p;
+ }
+
+ while (p < end) {
+ nextRangeStart = L'\0';
+ switch (*p) {
+ case L'-':
+ /* Trailing or initial '-' is not special. */
+ if ((rangeStart == L'\0') || (p == end - 1)) {
+ if (*p == c)
+ return (match);
+ } else {
+ wchar_t rangeEnd = *++p;
+ if (rangeEnd == L'\\')
+ rangeEnd = *++p;
+ if ((rangeStart <= c) && (c <= rangeEnd))
+ return (match);
+ }
+ break;
+ case L'\\':
+ ++p;
+ /* Fall through */
+ default:
+ if (*p == c)
+ return (match);
+ nextRangeStart = *p; /* Possible start of range. */
+ }
+ rangeStart = nextRangeStart;
+ ++p;
+ }
+ return (nomatch);
+}
+
+/*
+ * If s is pointing to "./", ".//", "./././" or the like, skip it.
+ */
+static const char *
+pm_slashskip(const char *s) {
+ while ((*s == '/')
+ || (s[0] == '.' && s[1] == '/')
+ || (s[0] == '.' && s[1] == '\0'))
+ ++s;
+ return (s);
+}
+
+static const wchar_t *
+pm_slashskip_w(const wchar_t *s) {
+ while ((*s == L'/')
+ || (s[0] == L'.' && s[1] == L'/')
+ || (s[0] == L'.' && s[1] == L'\0'))
+ ++s;
+ return (s);
+}
+
+static int
+pm(const char *p, const char *s, int flags)
+{
+ const char *end;
+
+ /*
+ * Ignore leading './', './/', '././', etc.
+ */
+ if (s[0] == '.' && s[1] == '/')
+ s = pm_slashskip(s + 1);
+ if (p[0] == '.' && p[1] == '/')
+ p = pm_slashskip(p + 1);
+
+ for (;;) {
+ switch (*p) {
+ case '\0':
+ if (s[0] == '/') {
+ if (flags & PATHMATCH_NO_ANCHOR_END)
+ return (1);
+ /* "dir" == "dir/" == "dir/." */
+ s = pm_slashskip(s);
+ }
+ return (*s == '\0');
+ case '?':
+ /* ? always succeeds, unless we hit end of 's' */
+ if (*s == '\0')
+ return (0);
+ break;
+ case '*':
+ /* "*" == "**" == "***" ... */
+ while (*p == '*')
+ ++p;
+ /* Trailing '*' always succeeds. */
+ if (*p == '\0')
+ return (1);
+ while (*s) {
+ if (archive_pathmatch(p, s, flags))
+ return (1);
+ ++s;
+ }
+ return (0);
+ case '[':
+ /*
+ * Find the end of the [...] character class,
+ * ignoring \] that might occur within the class.
+ */
+ end = p + 1;
+ while (*end != '\0' && *end != ']') {
+ if (*end == '\\' && end[1] != '\0')
+ ++end;
+ ++end;
+ }
+ if (*end == ']') {
+ /* We found [...], try to match it. */
+ if (!pm_list(p + 1, end, *s, flags))
+ return (0);
+ p = end; /* Jump to trailing ']' char. */
+ break;
+ } else
+ /* No final ']', so just match '['. */
+ if (*p != *s)
+ return (0);
+ break;
+ case '\\':
+ /* Trailing '\\' matches itself. */
+ if (p[1] == '\0') {
+ if (*s != '\\')
+ return (0);
+ } else {
+ ++p;
+ if (*p != *s)
+ return (0);
+ }
+ break;
+ case '/':
+ if (*s != '/' && *s != '\0')
+ return (0);
+ /* Note: pattern "/\./" won't match "/";
+ * pm_slashskip() correctly stops at backslash. */
+ p = pm_slashskip(p);
+ s = pm_slashskip(s);
+ if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END))
+ return (1);
+ --p; /* Counteract the increment below. */
+ --s;
+ break;
+ case '$':
+ /* '$' is special only at end of pattern and only
+ * if PATHMATCH_NO_ANCHOR_END is specified. */
+ if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
+ /* "dir" == "dir/" == "dir/." */
+ return (*pm_slashskip(s) == '\0');
+ }
+ /* Otherwise, '$' is not special. */
+ /* FALL THROUGH */
+ default:
+ if (*p != *s)
+ return (0);
+ break;
+ }
+ ++p;
+ ++s;
+ }
+}
+
+static int
+pm_w(const wchar_t *p, const wchar_t *s, int flags)
+{
+ const wchar_t *end;
+
+ /*
+ * Ignore leading './', './/', '././', etc.
+ */
+ if (s[0] == L'.' && s[1] == L'/')
+ s = pm_slashskip_w(s + 1);
+ if (p[0] == L'.' && p[1] == L'/')
+ p = pm_slashskip_w(p + 1);
+
+ for (;;) {
+ switch (*p) {
+ case L'\0':
+ if (s[0] == L'/') {
+ if (flags & PATHMATCH_NO_ANCHOR_END)
+ return (1);
+ /* "dir" == "dir/" == "dir/." */
+ s = pm_slashskip_w(s);
+ }
+ return (*s == L'\0');
+ case L'?':
+ /* ? always succeeds, unless we hit end of 's' */
+ if (*s == L'\0')
+ return (0);
+ break;
+ case L'*':
+ /* "*" == "**" == "***" ... */
+ while (*p == L'*')
+ ++p;
+ /* Trailing '*' always succeeds. */
+ if (*p == L'\0')
+ return (1);
+ while (*s) {
+ if (archive_pathmatch_w(p, s, flags))
+ return (1);
+ ++s;
+ }
+ return (0);
+ case L'[':
+ /*
+ * Find the end of the [...] character class,
+ * ignoring \] that might occur within the class.
+ */
+ end = p + 1;
+ while (*end != L'\0' && *end != L']') {
+ if (*end == L'\\' && end[1] != L'\0')
+ ++end;
+ ++end;
+ }
+ if (*end == L']') {
+ /* We found [...], try to match it. */
+ if (!pm_list_w(p + 1, end, *s, flags))
+ return (0);
+ p = end; /* Jump to trailing ']' char. */
+ break;
+ } else
+ /* No final ']', so just match '['. */
+ if (*p != *s)
+ return (0);
+ break;
+ case L'\\':
+ /* Trailing '\\' matches itself. */
+ if (p[1] == L'\0') {
+ if (*s != L'\\')
+ return (0);
+ } else {
+ ++p;
+ if (*p != *s)
+ return (0);
+ }
+ break;
+ case L'/':
+ if (*s != L'/' && *s != L'\0')
+ return (0);
+ /* Note: pattern "/\./" won't match "/";
+ * pm_slashskip() correctly stops at backslash. */
+ p = pm_slashskip_w(p);
+ s = pm_slashskip_w(s);
+ if (*p == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END))
+ return (1);
+ --p; /* Counteract the increment below. */
+ --s;
+ break;
+ case L'$':
+ /* '$' is special only at end of pattern and only
+ * if PATHMATCH_NO_ANCHOR_END is specified. */
+ if (p[1] == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
+ /* "dir" == "dir/" == "dir/." */
+ return (*pm_slashskip_w(s) == L'\0');
+ }
+ /* Otherwise, '$' is not special. */
+ /* FALL THROUGH */
+ default:
+ if (*p != *s)
+ return (0);
+ break;
+ }
+ ++p;
+ ++s;
+ }
+}
+
+/* Main entry point. */
+int
+__archive_pathmatch(const char *p, const char *s, int flags)
+{
+ /* Empty pattern only matches the empty string. */
+ if (p == NULL || *p == '\0')
+ return (s == NULL || *s == '\0');
+
+ /* Leading '^' anchors the start of the pattern. */
+ if (*p == '^') {
+ ++p;
+ flags &= ~PATHMATCH_NO_ANCHOR_START;
+ }
+
+ if (*p == '/' && *s != '/')
+ return (0);
+
+ /* Certain patterns and file names anchor implicitly. */
+ if (*p == '*' || *p == '/' || *p == '/') {
+ while (*p == '/')
+ ++p;
+ while (*s == '/')
+ ++s;
+ return (pm(p, s, flags));
+ }
+
+ /* If start is unanchored, try to match start of each path element. */
+ if (flags & PATHMATCH_NO_ANCHOR_START) {
+ for ( ; s != NULL; s = strchr(s, '/')) {
+ if (*s == '/')
+ s++;
+ if (pm(p, s, flags))
+ return (1);
+ }
+ return (0);
+ }
+
+ /* Default: Match from beginning. */
+ return (pm(p, s, flags));
+}
+
+int
+__archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags)
+{
+ /* Empty pattern only matches the empty string. */
+ if (p == NULL || *p == L'\0')
+ return (s == NULL || *s == L'\0');
+
+ /* Leading '^' anchors the start of the pattern. */
+ if (*p == L'^') {
+ ++p;
+ flags &= ~PATHMATCH_NO_ANCHOR_START;
+ }
+
+ if (*p == L'/' && *s != L'/')
+ return (0);
+
+ /* Certain patterns and file names anchor implicitly. */
+ if (*p == L'*' || *p == L'/' || *p == L'/') {
+ while (*p == L'/')
+ ++p;
+ while (*s == L'/')
+ ++s;
+ return (pm_w(p, s, flags));
+ }
+
+ /* If start is unanchored, try to match start of each path element. */
+ if (flags & PATHMATCH_NO_ANCHOR_START) {
+ for ( ; s != NULL; s = wcschr(s, L'/')) {
+ if (*s == L'/')
+ s++;
+ if (pm_w(p, s, flags))
+ return (1);
+ }
+ return (0);
+ }
+
+ /* Default: Match from beginning. */
+ return (pm_w(p, s, flags));
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_pathmatch.h b/Utilities/cmlibarchive/libarchive/archive_pathmatch.h
new file mode 100644
index 0000000..e690177
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_pathmatch.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST
+#error This header is only to be used internally to libarchive.
+#endif
+#endif
+
+#ifndef ARCHIVE_PATHMATCH_H
+#define ARCHIVE_PATHMATCH_H
+
+/* Don't anchor at beginning unless the pattern starts with "^" */
+#define PATHMATCH_NO_ANCHOR_START 1
+/* Don't anchor at end unless the pattern ends with "$" */
+#define PATHMATCH_NO_ANCHOR_END 2
+
+/* Note that "^" and "$" are not special unless you set the corresponding
+ * flag above. */
+
+int __archive_pathmatch(const char *p, const char *s, int flags);
+int __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags);
+
+#define archive_pathmatch(p, s, f) __archive_pathmatch(p, s, f)
+#define archive_pathmatch_w(p, s, f) __archive_pathmatch_w(p, s, f)
+
+#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd7.c b/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
index b2e8c3a..fe0b031 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
@@ -415,7 +415,7 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
}
- do
+ while (numPs != 0)
{
/* Create Child */
CTX_PTR c1; /* = AllocContext(p); */
@@ -435,7 +435,6 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
SetSuccessor(ps[--numPs], REF(c1));
c = c1;
}
- while (numPs != 0);
return c;
}
@@ -778,7 +777,7 @@ static void Range_Normalize(CPpmd7z_RangeDec *p)
if(p->Range >= p->Bottom)
break;
else
- p->Range = -p->Low & (p->Bottom - 1);
+ p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1);
}
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
p->Range <<= 8;
@@ -991,7 +990,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
p->Cache = (Byte)((UInt32)p->Low >> 24);
}
p->CacheSize++;
- p->Low = (UInt32)p->Low << 8;
+ p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF;
}
static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h b/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h
index 2666768..e78bde5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd_private.h
@@ -152,7 +152,7 @@ typedef
CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \
- { unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
- p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
+ { unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
+ p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }}
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_private.h b/Utilities/cmlibarchive/libarchive/archive_private.h
index 9941e96..30d472f 100644
--- a/Utilities/cmlibarchive/libarchive/archive_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_private.h
@@ -50,6 +50,7 @@
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
#define ARCHIVE_READ_DISK_MAGIC (0xbadb0c5U)
+#define ARCHIVE_MATCH_MAGIC (0xcad11c9U)
#define ARCHIVE_STATE_NEW 1U
#define ARCHIVE_STATE_HEADER 2U
@@ -133,6 +134,7 @@ int __archive_check_magic(struct archive *, unsigned int magic,
void __archive_errx(int retvalue, const char *msg) __LA_DEAD;
+void __archive_ensure_cloexec_flag(int fd);
int __archive_mktemp(const char *tmpdir);
int __archive_clean(struct archive *);
diff --git a/Utilities/cmlibarchive/libarchive/archive_rb.c b/Utilities/cmlibarchive/libarchive/archive_rb.c
index f8035d9..5b5da20 100644
--- a/Utilities/cmlibarchive/libarchive/archive_rb.c
+++ b/Utilities/cmlibarchive/libarchive/archive_rb.c
@@ -96,7 +96,7 @@ __archive_rb_tree_init(struct archive_rb_tree *rbt,
const struct archive_rb_tree_ops *ops)
{
rbt->rbt_ops = ops;
- *((const struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
+ *((struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
}
struct archive_rb_node *
@@ -237,6 +237,8 @@ __archive_rb_tree_reparent_nodes(
struct archive_rb_node * const new_father = old_child;
struct archive_rb_node * const new_child = old_father;
+ if (new_father == NULL)
+ return;
/*
* Exchange descendant linkages.
*/
@@ -377,13 +379,13 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
if (standin_father == self) {
/*
- * As a child of self, any childen would be opposite of
+ * As a child of self, any children would be opposite of
* our parent.
*/
standin_son = standin->rb_nodes[standin_which];
} else {
/*
- * Since we aren't a child of self, any childen would be
+ * Since we aren't a child of self, any children would be
* on the same side as our parent.
*/
standin_son = standin->rb_nodes[standin_other];
@@ -410,7 +412,7 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
/*
* If we are about to delete the standin's father, then when
* we call rebalance, we need to use ourselves as our father.
- * Otherwise remember our original father. Also, sincef we are
+ * Otherwise remember our original father. Also, since we are
* our standin's father we only need to reparent the standin's
* brother.
*
@@ -466,7 +468,7 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
* __archive_rb_tree_node_swap(rbt, self, which);
* __archive_rb_tree_prune_node(rbt, self, F);
*
- * But it's more efficient to just evalate and recolor the child.
+ * But it's more efficient to just evaluate and recolor the child.
*/
static void
__archive_rb_tree_prune_blackred_branch(
@@ -505,7 +507,7 @@ __archive_rb_tree_remove_node(struct archive_rb_tree *rbt,
* red-black tree. So if we must remove a node, attempt to rearrange
* the tree so we can remove a red node.
*
- * The simpliest case is a childless red node or a childless root node:
+ * The simplest case is a childless red node or a childless root node:
*
* | T --> T | or | R --> * |
* | s --> * |
@@ -517,7 +519,7 @@ __archive_rb_tree_remove_node(struct archive_rb_tree *rbt,
}
if (!RB_TWOCHILDREN_P(self)) {
/*
- * The next simpliest case is the node we are deleting is
+ * The next simplest case is the node we are deleting is
* black and has one red child.
*
* | T --> T --> T |
@@ -552,6 +554,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
unsigned int other = which ^ RB_DIR_OTHER;
struct archive_rb_node *brother = parent->rb_nodes[other];
+ if (brother == NULL)
+ return;/* The tree may be broken. */
/*
* For cases 1, 2a, and 2b, our brother's children must
* be black and our father must be black
@@ -573,6 +577,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
*/
__archive_rb_tree_reparent_nodes(parent, other);
brother = parent->rb_nodes[other];
+ if (brother == NULL)
+ return;/* The tree may be broken. */
} else {
/*
* Both our parent and brother are black.
@@ -656,6 +662,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
* If we had two red nephews, then after the swap,
* our former father would have a red grandson.
*/
+ if (brother->rb_nodes[other] == NULL)
+ return;/* The tree may be broken. */
RB_MARK_BLACK(brother->rb_nodes[other]);
__archive_rb_tree_reparent_nodes(parent, other);
break; /* We're done! */
@@ -683,7 +691,7 @@ __archive_rb_tree_iterate(struct archive_rb_tree *rbt,
*/
if (RB_SENTINEL_P(self->rb_nodes[direction])) {
while (!RB_ROOT_P(rbt, self)) {
- if (other == RB_POSITION(self))
+ if (other == (unsigned int)RB_POSITION(self))
return RB_FATHER(self);
self = RB_FATHER(self);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read.3 b/Utilities/cmlibarchive/libarchive/archive_read.3
index 5285192..a29cc1e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read.3
@@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ 3
.Os
.Sh NAME
.Nm archive_read
.Nd functions for reading streaming archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Sh DESCRIPTION
diff --git a/Utilities/cmlibarchive/libarchive/archive_read.c b/Utilities/cmlibarchive/libarchive/archive_read.c
index baf9dc4..796d37d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read.c
@@ -57,8 +57,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2
static int choose_filters(struct archive_read *);
static int choose_format(struct archive_read *);
-static void free_filters(struct archive_read *);
-static int close_filters(struct archive_read *);
static struct archive_vtable *archive_read_vtable(void);
static int64_t _archive_filter_bytes(struct archive *, int);
static int _archive_filter_code(struct archive *, int);
@@ -194,14 +192,13 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
int64_t get, ask = request;
if (ask > skip_limit)
ask = skip_limit;
- get = (self->archive->client.skipper)(&self->archive->archive,
- self->data, ask);
+ get = (self->archive->client.skipper)
+ (&self->archive->archive, self->data, ask);
if (get == 0)
return (total);
request -= get;
total += get;
}
- return total;
} else if (self->archive->client.seeker != NULL
&& request > 64 * 1024) {
/* If the client provided a seeker but not a skipper,
@@ -216,8 +213,8 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
* only do this for skips of over 64k.
*/
int64_t before = self->position;
- int64_t after = (self->archive->client.seeker)(&self->archive->archive,
- self->data, request, SEEK_CUR);
+ int64_t after = (self->archive->client.seeker)
+ (&self->archive->archive, self->data, request, SEEK_CUR);
if (after != before + request)
return ARCHIVE_FATAL;
return after - before;
@@ -242,14 +239,64 @@ client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
static int
client_close_proxy(struct archive_read_filter *self)
{
- int r = ARCHIVE_OK;
+ int r = ARCHIVE_OK, r2;
+ unsigned int i;
+
+ if (self->archive->client.closer == NULL)
+ return (r);
+ for (i = 0; i < self->archive->client.nodes; i++)
+ {
+ r2 = (self->archive->client.closer)
+ ((struct archive *)self->archive,
+ self->archive->client.dataset[i].data);
+ if (r > r2)
+ r = r2;
+ }
+ return (r);
+}
- if (self->archive->client.closer != NULL)
- r = (self->archive->client.closer)((struct archive *)self->archive,
- self->data);
+static int
+client_open_proxy(struct archive_read_filter *self)
+{
+ int r = ARCHIVE_OK;
+ if (self->archive->client.opener != NULL)
+ r = (self->archive->client.opener)(
+ (struct archive *)self->archive, self->data);
return (r);
}
+static int
+client_switch_proxy(struct archive_read_filter *self, unsigned int iindex)
+{
+ int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK;
+ void *data2 = NULL;
+
+ /* Don't do anything if already in the specified data node */
+ if (self->archive->client.cursor == iindex)
+ return (ARCHIVE_OK);
+
+ self->archive->client.cursor = iindex;
+ data2 = self->archive->client.dataset[self->archive->client.cursor].data;
+ if (self->archive->client.switcher != NULL)
+ {
+ r1 = r2 = (self->archive->client.switcher)
+ ((struct archive *)self->archive, self->data, data2);
+ self->data = data2;
+ }
+ else
+ {
+ /* Attempt to call close and open instead */
+ if (self->archive->client.closer != NULL)
+ r1 = (self->archive->client.closer)
+ ((struct archive *)self->archive, self->data);
+ self->data = data2;
+ if (self->archive->client.opener != NULL)
+ r2 = (self->archive->client.opener)
+ ((struct archive *)self->archive, self->data);
+ }
+ return (r1 < r2) ? r1 : r2;
+}
+
int
archive_read_set_open_callback(struct archive *_a,
archive_open_callback *client_opener)
@@ -306,21 +353,109 @@ archive_read_set_close_callback(struct archive *_a,
}
int
+archive_read_set_switch_callback(struct archive *_a,
+ archive_switch_callback *client_switcher)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+ "archive_read_set_switch_callback");
+ a->client.switcher = client_switcher;
+ return ARCHIVE_OK;
+}
+
+int
archive_read_set_callback_data(struct archive *_a, void *client_data)
{
+ return archive_read_set_callback_data2(_a, client_data, 0);
+}
+
+int
+archive_read_set_callback_data2(struct archive *_a, void *client_data,
+ unsigned int iindex)
+{
struct archive_read *a = (struct archive_read *)_a;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
- "archive_read_set_callback_data");
- a->client.data = client_data;
+ "archive_read_set_callback_data2");
+
+ if (a->client.nodes == 0)
+ {
+ a->client.dataset = (struct archive_read_data_node *)
+ calloc(1, sizeof(*a->client.dataset));
+ if (a->client.dataset == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM,
+ "No memory.");
+ return ARCHIVE_FATAL;
+ }
+ a->client.nodes = 1;
+ }
+
+ if (iindex > a->client.nodes - 1)
+ {
+ archive_set_error(&a->archive, EINVAL,
+ "Invalid index specified.");
+ return ARCHIVE_FATAL;
+ }
+ a->client.dataset[iindex].data = client_data;
+ a->client.dataset[iindex].begin_position = -1;
+ a->client.dataset[iindex].total_size = -1;
+ return ARCHIVE_OK;
+}
+
+int
+archive_read_add_callback_data(struct archive *_a, void *client_data,
+ unsigned int iindex)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ void *p;
+ unsigned int i;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
+ "archive_read_add_callback_data");
+ if (iindex > a->client.nodes) {
+ archive_set_error(&a->archive, EINVAL,
+ "Invalid index specified.");
+ return ARCHIVE_FATAL;
+ }
+ p = realloc(a->client.dataset, sizeof(*a->client.dataset)
+ * (++(a->client.nodes)));
+ if (p == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "No memory.");
+ return ARCHIVE_FATAL;
+ }
+ a->client.dataset = (struct archive_read_data_node *)p;
+ for (i = a->client.nodes - 1; i > iindex && i > 0; i--) {
+ a->client.dataset[i].data = a->client.dataset[i-1].data;
+ a->client.dataset[i].begin_position = -1;
+ a->client.dataset[i].total_size = -1;
+ }
+ a->client.dataset[iindex].data = client_data;
+ a->client.dataset[iindex].begin_position = -1;
+ a->client.dataset[iindex].total_size = -1;
return ARCHIVE_OK;
}
int
+archive_read_append_callback_data(struct archive *_a, void *client_data)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ return archive_read_add_callback_data(_a, client_data, a->client.nodes);
+}
+
+int
+archive_read_prepend_callback_data(struct archive *_a, void *client_data)
+{
+ return archive_read_add_callback_data(_a, client_data, 0);
+}
+
+int
archive_read_open1(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_read_filter *filter;
+ struct archive_read_filter *filter, *tmp;
int slot, e;
+ unsigned int i;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_open");
@@ -335,11 +470,14 @@ archive_read_open1(struct archive *_a)
/* Open data source. */
if (a->client.opener != NULL) {
- e =(a->client.opener)(&a->archive, a->client.data);
+ e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
if (e != 0) {
/* If the open failed, call the closer to clean up. */
- if (a->client.closer)
- (a->client.closer)(&a->archive, a->client.data);
+ if (a->client.closer) {
+ for (i = 0; i < a->client.nodes; i++)
+ (a->client.closer)(&a->archive,
+ a->client.dataset[i].data);
+ }
return (e);
}
}
@@ -350,31 +488,51 @@ archive_read_open1(struct archive *_a)
filter->bidder = NULL;
filter->upstream = NULL;
filter->archive = a;
- filter->data = a->client.data;
+ filter->data = a->client.dataset[0].data;
+ filter->open = client_open_proxy;
filter->read = client_read_proxy;
filter->skip = client_skip_proxy;
filter->seek = client_seek_proxy;
filter->close = client_close_proxy;
+ filter->sswitch = client_switch_proxy;
filter->name = "none";
- filter->code = ARCHIVE_COMPRESSION_NONE;
- a->filter = filter;
+ filter->code = ARCHIVE_FILTER_NONE;
- /* Build out the input pipeline. */
- e = choose_filters(a);
- if (e < ARCHIVE_WARN) {
- a->archive.state = ARCHIVE_STATE_FATAL;
- return (ARCHIVE_FATAL);
+ a->client.dataset[0].begin_position = 0;
+ if (!a->filter || !a->bypass_filter_bidding)
+ {
+ a->filter = filter;
+ /* Build out the input pipeline. */
+ e = choose_filters(a);
+ if (e < ARCHIVE_WARN) {
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
+ }
+ else
+ {
+ /* Need to add "NONE" type filter at the end of the filter chain */
+ tmp = a->filter;
+ while (tmp->upstream)
+ tmp = tmp->upstream;
+ tmp->upstream = filter;
}
- slot = choose_format(a);
- if (slot < 0) {
- close_filters(a);
- a->archive.state = ARCHIVE_STATE_FATAL;
- return (ARCHIVE_FATAL);
+ if (!a->format)
+ {
+ slot = choose_format(a);
+ if (slot < 0) {
+ __archive_read_close_filters(a);
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
+ a->format = &(a->formats[slot]);
}
- a->format = &(a->formats[slot]);
a->archive.state = ARCHIVE_STATE_HEADER;
+
+ /* Ensure libarchive starts from the first node in a multivolume set */
+ client_switch_proxy(a->filter, 0);
return (e);
}
@@ -414,8 +572,8 @@ choose_filters(struct archive_read *a)
/* Verify the filter by asking it for some data. */
__archive_read_filter_ahead(a->filter, 1, &avail);
if (avail < 0) {
- close_filters(a);
- free_filters(a);
+ __archive_read_close_filters(a);
+ __archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
a->archive.compression_name = a->filter->name;
@@ -433,8 +591,8 @@ choose_filters(struct archive_read *a)
a->filter = filter;
r = (best_bidder->init)(a->filter);
if (r != ARCHIVE_OK) {
- close_filters(a);
- free_filters(a);
+ __archive_read_close_filters(a);
+ __archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
}
@@ -502,6 +660,9 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
a->read_data_output_offset = 0;
a->read_data_remaining = 0;
+ a->read_data_is_posix_read = 0;
+ a->read_data_requested = 0;
+ a->data_start_node = a->client.cursor;
/* EOF always wins; otherwise return the worst error. */
return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
}
@@ -612,6 +773,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
while (s > 0) {
if (a->read_data_remaining == 0) {
read_buf = a->read_data_block;
+ a->read_data_is_posix_read = 1;
+ a->read_data_requested = s;
r = _archive_read_data_block(&a->archive, &read_buf,
&a->read_data_remaining, &a->read_data_offset);
a->read_data_block = read_buf;
@@ -633,13 +796,13 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
}
/* Compute the amount of zero padding needed. */
- if (a->read_data_output_offset + s <
+ if (a->read_data_output_offset + (int64_t)s <
a->read_data_offset) {
len = s;
} else if (a->read_data_output_offset <
a->read_data_offset) {
- len = a->read_data_offset -
- a->read_data_output_offset;
+ len = (size_t)(a->read_data_offset -
+ a->read_data_output_offset);
} else
len = 0;
@@ -665,6 +828,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
bytes_read += len;
}
}
+ a->read_data_is_posix_read = 0;
+ a->read_data_requested = 0;
return (bytes_read);
}
@@ -699,6 +864,23 @@ archive_read_data_skip(struct archive *_a)
return (r);
}
+int64_t
+archive_seek_data(struct archive *_a, int64_t offset, int whence)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
+ "archive_seek_data_block");
+
+ if (a->format->seek_data == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: "
+ "No format_seek_data_block function registered");
+ return (ARCHIVE_FATAL);
+ }
+
+ return (a->format->seek_data)(a, offset, whence);
+}
+
/*
* Read the next block of entry data from the archive.
* This is a zero-copy interface; the client receives a pointer,
@@ -725,8 +907,8 @@ _archive_read_data_block(struct archive *_a,
return (a->format->read_data)(a, buff, size, offset);
}
-static int
-close_filters(struct archive_read *a)
+int
+__archive_read_close_filters(struct archive_read *a)
{
struct archive_read_filter *f = a->filter;
int r = ARCHIVE_OK;
@@ -746,8 +928,8 @@ close_filters(struct archive_read *a)
return r;
}
-static void
-free_filters(struct archive_read *a)
+void
+__archive_read_free_filters(struct archive_read *a)
{
while (a->filter != NULL) {
struct archive_read_filter *t = a->filter->upstream;
@@ -791,7 +973,7 @@ _archive_read_close(struct archive *_a)
/* TODO: Clean up the formatters. */
/* Release the filter objects. */
- r1 = close_filters(a);
+ r1 = __archive_read_close_filters(a);
if (r1 < r)
r = r1;
@@ -830,7 +1012,7 @@ _archive_read_free(struct archive *_a)
}
/* Free the filters */
- free_filters(a);
+ __archive_read_free_filters(a);
/* Release the bidder objects. */
n = sizeof(a->bidders)/sizeof(a->bidders[0]);
@@ -847,6 +1029,7 @@ _archive_read_free(struct archive *_a)
archive_entry_free(a->entry);
a->archive.magic = 0;
__archive_clean(&a->archive);
+ free(a->client.dataset);
free(a);
return (r);
}
@@ -856,7 +1039,8 @@ get_filter(struct archive *_a, int n)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *f = a->filter;
- /* We use n == -1 for 'the last filter', which is always the client proxy. */
+ /* We use n == -1 for 'the last filter', which is always the
+ * client proxy. */
if (n == -1 && f != NULL) {
struct archive_read_filter *last = f;
f = f->upstream;
@@ -909,6 +1093,7 @@ __archive_read_register_format(struct archive_read *a,
int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
+ int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *))
{
int i, number_slots;
@@ -928,6 +1113,7 @@ __archive_read_register_format(struct archive_read *a,
a->formats[i].read_header = read_header;
a->formats[i].read_data = read_data;
a->formats[i].read_data_skip = read_data_skip;
+ a->formats[i].seek_data = seek_data;
a->formats[i].cleanup = cleanup;
a->formats[i].data = format_data;
a->formats[i].name = name;
@@ -1074,7 +1260,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
if (filter->next > filter->buffer &&
filter->next + min > filter->buffer + filter->buffer_size) {
if (filter->avail > 0)
- memmove(filter->buffer, filter->next, filter->avail);
+ memmove(filter->buffer, filter->next,
+ filter->avail);
filter->next = filter->buffer;
}
@@ -1089,15 +1276,26 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
&filter->client_buff);
if (bytes_read < 0) { /* Read error. */
filter->client_total = filter->client_avail = 0;
- filter->client_next = filter->client_buff = NULL;
+ filter->client_next =
+ filter->client_buff = NULL;
filter->fatal = 1;
if (avail != NULL)
*avail = ARCHIVE_FATAL;
return (NULL);
}
- if (bytes_read == 0) { /* Premature end-of-file. */
+ if (bytes_read == 0) {
+ /* Check for another client object first */
+ if (filter->archive->client.cursor !=
+ filter->archive->client.nodes - 1) {
+ if (client_switch_proxy(filter,
+ filter->archive->client.cursor + 1)
+ == ARCHIVE_OK)
+ continue;
+ }
+ /* Premature end-of-file. */
filter->client_total = filter->client_avail = 0;
- filter->client_next = filter->client_buff = NULL;
+ filter->client_next =
+ filter->client_buff = NULL;
filter->end_of_file = 1;
/* Return whatever we do have. */
if (avail != NULL)
@@ -1107,9 +1305,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
filter->client_total = bytes_read;
filter->client_avail = filter->client_total;
filter->client_next = filter->client_buff;
- }
- else
- {
+ } else {
/*
* We can't satisfy the request from the copy
* buffer or the existing client data, so we
@@ -1130,9 +1326,10 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
t *= 2;
if (t <= s) { /* Integer overflow! */
archive_set_error(
- &filter->archive->archive,
- ENOMEM,
- "Unable to allocate copy buffer");
+ &filter->archive->archive,
+ ENOMEM,
+ "Unable to allocate copy"
+ " buffer");
filter->fatal = 1;
if (avail != NULL)
*avail = ARCHIVE_FATAL;
@@ -1171,8 +1368,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
if (tocopy > filter->client_avail)
tocopy = filter->client_avail;
- memcpy(filter->next + filter->avail, filter->client_next,
- tocopy);
+ memcpy(filter->next + filter->avail,
+ filter->client_next, tocopy);
/* Remove this data from client buffer. */
filter->client_next += tocopy;
filter->client_avail -= tocopy;
@@ -1231,7 +1428,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
/* Use up the copy buffer first. */
if (filter->avail > 0) {
- min = minimum(request, (int64_t)filter->avail);
+ min = (size_t)minimum(request, (int64_t)filter->avail);
filter->next += min;
filter->avail -= min;
request -= min;
@@ -1241,7 +1438,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
/* Then use up the client buffer. */
if (filter->client_avail > 0) {
- min = minimum(request, (int64_t)filter->client_avail);
+ min = (size_t)minimum(request, (int64_t)filter->client_avail);
filter->client_next += min;
filter->client_avail -= min;
request -= min;
@@ -1275,6 +1472,13 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
}
if (bytes_read == 0) {
+ if (filter->archive->client.cursor !=
+ filter->archive->client.nodes - 1) {
+ if (client_switch_proxy(filter,
+ filter->archive->client.cursor + 1)
+ == ARCHIVE_OK)
+ continue;
+ }
filter->client_buff = NULL;
filter->end_of_file = 1;
return (total_bytes_skipped);
@@ -1283,7 +1487,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
if (bytes_read >= request) {
filter->client_next =
((const char *)filter->client_buff) + request;
- filter->client_avail = bytes_read - request;
+ filter->client_avail = (size_t)(bytes_read - request);
filter->client_total = bytes_read;
total_bytes_skipped += request;
filter->position += request;
@@ -1306,15 +1510,109 @@ __archive_read_seek(struct archive_read *a, int64_t offset, int whence)
}
int64_t
-__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, int whence)
+__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
+ int whence)
{
+ struct archive_read_client *client;
int64_t r;
+ unsigned int cursor;
if (filter->closed || filter->fatal)
return (ARCHIVE_FATAL);
if (filter->seek == NULL)
return (ARCHIVE_FAILED);
- r = filter->seek(filter, offset, whence);
+
+ client = &(filter->archive->client);
+ switch (whence) {
+ case SEEK_CUR:
+ /* Adjust the offset and use SEEK_SET instead */
+ offset += filter->position;
+ case SEEK_SET:
+ cursor = 0;
+ while (1)
+ {
+ if (client->dataset[cursor].begin_position < 0 ||
+ client->dataset[cursor].total_size < 0 ||
+ client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size - 1 > offset ||
+ cursor + 1 >= client->nodes)
+ break;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ client->dataset[++cursor].begin_position = r;
+ }
+ while (1) {
+ r = client_switch_proxy(filter, cursor);
+ if (r != ARCHIVE_OK)
+ return r;
+ if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
+ return r;
+ client->dataset[cursor].total_size = r;
+ if (client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size - 1 > offset ||
+ cursor + 1 >= client->nodes)
+ break;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ client->dataset[++cursor].begin_position = r;
+ }
+ offset -= client->dataset[cursor].begin_position;
+ if (offset < 0)
+ offset = 0;
+ else if (offset > client->dataset[cursor].total_size - 1)
+ offset = client->dataset[cursor].total_size - 1;
+ if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
+ return r;
+ break;
+
+ case SEEK_END:
+ cursor = 0;
+ while (1) {
+ if (client->dataset[cursor].begin_position < 0 ||
+ client->dataset[cursor].total_size < 0 ||
+ cursor + 1 >= client->nodes)
+ break;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ client->dataset[++cursor].begin_position = r;
+ }
+ while (1) {
+ r = client_switch_proxy(filter, cursor);
+ if (r != ARCHIVE_OK)
+ return r;
+ if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
+ return r;
+ client->dataset[cursor].total_size = r;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ if (cursor + 1 >= client->nodes)
+ break;
+ client->dataset[++cursor].begin_position = r;
+ }
+ while (1) {
+ if (r + offset >=
+ client->dataset[cursor].begin_position)
+ break;
+ offset += client->dataset[cursor].total_size;
+ if (cursor == 0)
+ break;
+ cursor--;
+ r = client->dataset[cursor].begin_position +
+ client->dataset[cursor].total_size;
+ }
+ offset = (r + offset) - client->dataset[cursor].begin_position;
+ if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK)
+ return r;
+ r = client_seek_proxy(filter, offset, SEEK_SET);
+ if (r < ARCHIVE_OK)
+ return r;
+ break;
+
+ default:
+ return (ARCHIVE_FATAL);
+ }
+ r += client->dataset[cursor].begin_position;
+
if (r >= 0) {
/*
* Ouch. Clearing the buffer like this hurts, especially
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
new file mode 100644
index 0000000..017d7c6
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_read_append_filter.c
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2003-2012 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+int
+archive_read_append_filter(struct archive *_a, int code)
+{
+ int r1, r2, number_bidders, i;
+ char str[20];
+ struct archive_read_filter_bidder *bidder;
+ struct archive_read_filter *filter;
+ struct archive_read *a = (struct archive_read *)_a;
+
+ r1 = r2 = (ARCHIVE_OK);
+ switch (code)
+ {
+ case ARCHIVE_FILTER_NONE:
+ /* No filter to add, so do nothing.
+ * NOTE: An initial "NONE" type filter is always set at the end of the
+ * filter chain.
+ */
+ r1 = (ARCHIVE_OK);
+ break;
+ case ARCHIVE_FILTER_GZIP:
+ strcpy(str, "gzip");
+ r1 = archive_read_support_filter_gzip(_a);
+ break;
+ case ARCHIVE_FILTER_BZIP2:
+ strcpy(str, "bzip2");
+ r1 = archive_read_support_filter_bzip2(_a);
+ break;
+ case ARCHIVE_FILTER_COMPRESS:
+ strcpy(str, "compress (.Z)");
+ r1 = archive_read_support_filter_compress(_a);
+ break;
+ case ARCHIVE_FILTER_PROGRAM:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Cannot append program filter using archive_read_append_filter");
+ return (ARCHIVE_FATAL);
+ case ARCHIVE_FILTER_LZMA:
+ strcpy(str, "lzma");
+ r1 = archive_read_support_filter_lzma(_a);
+ break;
+ case ARCHIVE_FILTER_XZ:
+ strcpy(str, "xz");
+ r1 = archive_read_support_filter_xz(_a);
+ break;
+ case ARCHIVE_FILTER_UU:
+ strcpy(str, "uu");
+ r1 = archive_read_support_filter_uu(_a);
+ break;
+ case ARCHIVE_FILTER_RPM:
+ strcpy(str, "rpm");
+ r1 = archive_read_support_filter_rpm(_a);
+ break;
+ case ARCHIVE_FILTER_LZIP:
+ strcpy(str, "lzip");
+ r1 = archive_read_support_filter_lzip(_a);
+ break;
+ case ARCHIVE_FILTER_LRZIP:
+ strcpy(str, "lrzip");
+ r1 = archive_read_support_filter_lrzip(_a);
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Invalid filter code specified");
+ return (ARCHIVE_FATAL);
+ }
+
+ if (code != ARCHIVE_FILTER_NONE)
+ {
+ number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
+
+ bidder = a->bidders;
+ for (i = 0; i < number_bidders; i++, bidder++)
+ {
+ if (!bidder->name || !strcmp(bidder->name, str))
+ break;
+ }
+ if (!bidder->name || strcmp(bidder->name, str))
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: Unable to append filter");
+ return (ARCHIVE_FATAL);
+ }
+
+ filter
+ = (struct archive_read_filter *)calloc(1, sizeof(*filter));
+ if (filter == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ filter->bidder = bidder;
+ filter->archive = a;
+ filter->upstream = a->filter;
+ a->filter = filter;
+ r2 = (bidder->init)(a->filter);
+ if (r2 != ARCHIVE_OK) {
+ __archive_read_close_filters(a);
+ __archive_read_free_filters(a);
+ return (ARCHIVE_FATAL);
+ }
+ }
+
+ a->bypass_filter_bidding = 1;
+ return (r1 < r2) ? r1 : r2;
+}
+
+int
+archive_read_append_filter_program(struct archive *_a, const char *cmd)
+{
+ return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0));
+}
+
+int
+archive_read_append_filter_program_signature(struct archive *_a,
+ const char *cmd, const void *signature, size_t signature_len)
+{
+ int r, number_bidders, i;
+ struct archive_read_filter_bidder *bidder;
+ struct archive_read_filter *filter;
+ struct archive_read *a = (struct archive_read *)_a;
+
+ if (archive_read_support_filter_program_signature(_a, cmd, signature,
+ signature_len) != (ARCHIVE_OK))
+ return (ARCHIVE_FATAL);
+
+ number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
+
+ bidder = a->bidders;
+ for (i = 0; i < number_bidders; i++, bidder++)
+ {
+ /* Program bidder name set to filter name after initialization */
+ if (bidder->data && !bidder->name)
+ break;
+ }
+ if (!bidder->data)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: Unable to append program filter");
+ return (ARCHIVE_FATAL);
+ }
+
+ filter
+ = (struct archive_read_filter *)calloc(1, sizeof(*filter));
+ if (filter == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ filter->bidder = bidder;
+ filter->archive = a;
+ filter->upstream = a->filter;
+ a->filter = filter;
+ r = (bidder->init)(a->filter);
+ if (r != ARCHIVE_OK) {
+ __archive_read_close_filters(a);
+ __archive_read_free_filters(a);
+ return (ARCHIVE_FATAL);
+ }
+ bidder->name = a->filter->name;
+
+ a->bypass_filter_bidding = 1;
+ return r;
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_data.3 b/Utilities/cmlibarchive/libarchive/archive_read_data.3
index 78d0497..bf0578c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_data.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_data.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 22, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ_DATA 3
.Os
.Sh NAME
@@ -33,6 +33,8 @@
.Nm archive_read_data_skip ,
.Nm archive_read_data_into_fd
.Nd functions for reading streaming archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft ssize_t
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c b/Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c
index 14f9410..b4398f1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c
@@ -64,7 +64,7 @@ pad_to(struct archive *a, int fd, int can_lseek,
}
while (target_offset > actual_offset) {
to_write = nulls_size;
- if (target_offset < actual_offset + nulls_size)
+ if (target_offset < actual_offset + (int64_t)nulls_size)
to_write = (size_t)(target_offset - actual_offset);
bytes_written = write(fd, nulls, to_write);
if (bytes_written < 0) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 b/Utilities/cmlibarchive/libarchive/archive_read_disk.3
index 3c49bff..525dc59 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk.3
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_read_disk.3 190957 2009-04-12 05:04:02Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 10, 2009
+.Dd February 2, 2012
.Dt ARCHIVE_READ_DISK 3
.Os
.Sh NAME
@@ -42,6 +42,8 @@
.Nm archive_read_finish ,
.Nm archive_read_free
.Nd functions for reading objects from disk
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
index fdeb516..e984aaa 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
- * Copyright (c) 2010 Michihiro NAKAJIMA
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,8 +49,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#ifdef HAVE_SYS_XATTR_H
+#if defined(HAVE_SYS_XATTR_H)
#include <sys/xattr.h>
+#elif defined(HAVE_ATTR_XATTR_H)
+#include <attr/xattr.h>
#endif
#ifdef HAVE_SYS_EA_H
#include <sys/ea.h>
@@ -58,9 +60,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
-#ifdef HAVE_ATTR_XATTR_H
-#include <attr/xattr.h>
-#endif
#ifdef HAVE_COPYFILE_H
#include <copyfile.h>
#endif
@@ -104,6 +103,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#include "archive_private.h"
#include "archive_read_disk_private.h"
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
/*
* Linux and FreeBSD plug this obvious hole in POSIX.1e in
* different ways.
@@ -114,14 +117,14 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#define ACL_GET_PERM acl_get_perm_np
#endif
-static int setup_acls_posix1e(struct archive_read_disk *,
- struct archive_entry *, int fd);
+static int setup_acls(struct archive_read_disk *,
+ struct archive_entry *, int *fd);
static int setup_mac_metadata(struct archive_read_disk *,
- struct archive_entry *, int fd);
+ struct archive_entry *, int *fd);
static int setup_xattrs(struct archive_read_disk *,
- struct archive_entry *, int fd);
+ struct archive_entry *, int *fd);
static int setup_sparse(struct archive_read_disk *,
- struct archive_entry *, int fd);
+ struct archive_entry *, int *fd);
int
archive_read_disk_entry_from_file(struct archive *_a,
@@ -190,11 +193,18 @@ archive_read_disk_entry_from_file(struct archive *_a,
* this is an extra step, it has a nice side-effect: We get an
* open file descriptor which we can use in the subsequent lookups. */
if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
- if (fd < 0)
- fd = open(path, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) {
+ if (a->tree != NULL)
+ fd = a->open_on_current_dir(a->tree, path,
+ O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ else
+ fd = open(path, O_RDONLY | O_NONBLOCK |
+ O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
+ }
if (fd >= 0) {
- unsigned long stflags;
- int r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
+ int stflags;
+ r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
if (r == 0 && stflags != 0)
archive_entry_set_fflags(entry, stflags, 0);
}
@@ -213,13 +223,21 @@ archive_read_disk_entry_from_file(struct archive *_a,
"Couldn't read link data");
return (ARCHIVE_FAILED);
}
+ if (a->tree != NULL) {
#ifdef HAVE_READLINKAT
- if (a->entry_wd_fd >= 0)
- lnklen = readlinkat(a->entry_wd_fd, path,
- linkbuffer, linkbuffer_len);
- else
+ lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
+ path, linkbuffer, linkbuffer_len);
+#else
+ if (a->tree_enter_working_dir(a->tree) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't read link data");
+ free(linkbuffer);
+ return (ARCHIVE_FAILED);
+ }
+ lnklen = readlink(path, linkbuffer, linkbuffer_len);
#endif /* HAVE_READLINKAT */
- lnklen = readlink(path, linkbuffer, linkbuffer_len);
+ } else
+ lnklen = readlink(path, linkbuffer, linkbuffer_len);
if (lnklen < 0) {
archive_set_error(&a->archive, errno,
"Couldn't read link data");
@@ -232,14 +250,16 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
#endif /* HAVE_READLINK || HAVE_READLINKAT */
- r = setup_acls_posix1e(a, entry, fd);
- r1 = setup_xattrs(a, entry, fd);
- if (r1 < r)
- r = r1;
- r1 = setup_mac_metadata(a, entry, fd);
+ r = setup_acls(a, entry, &fd);
+ r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
- r1 = setup_sparse(a, entry, fd);
+ if (a->enable_copyfile) {
+ r1 = setup_mac_metadata(a, entry, &fd);
+ if (r1 < r)
+ r = r1;
+ }
+ r1 = setup_sparse(a, entry, &fd);
if (r1 < r)
r = r1;
@@ -265,16 +285,18 @@ archive_read_disk_entry_from_file(struct archive *_a,
*/
static int
setup_mac_metadata(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+ struct archive_entry *entry, int *fd)
{
int tempfd = -1;
int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
struct stat copyfile_stat;
int ret = ARCHIVE_OK;
- void *buff;
+ void *buff = NULL;
int have_attrs;
- const char *name, *tempdir, *tempfile = NULL;
+ const char *name, *tempdir;
+ struct archive_string tempfile;
+ (void)fd; /* UNUSED */
name = archive_entry_sourcepath(entry);
if (name == NULL)
name = archive_entry_pathname(entry);
@@ -284,6 +306,14 @@ setup_mac_metadata(struct archive_read_disk *a,
return (ARCHIVE_WARN);
}
+ if (a->tree != NULL) {
+ if (a->tree_enter_working_dir(a->tree) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't change dir");
+ return (ARCHIVE_FAILED);
+ }
+ }
+
/* Short-circuit if there's nothing to do. */
have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
if (have_attrs == -1) {
@@ -299,25 +329,28 @@ setup_mac_metadata(struct archive_read_disk *a,
tempdir = getenv("TMPDIR");
if (tempdir == NULL)
tempdir = _PATH_TMP;
- tempfile = tempnam(tempdir, "tar.md.");
+ archive_string_init(&tempfile);
+ archive_strcpy(&tempfile, tempdir);
+ archive_strcat(&tempfile, "tar.md.XXXXXX");
+ tempfd = mkstemp(tempfile.s);
+ if (tempfd < 0) {
+ archive_set_error(&a->archive, errno,
+ "Could not open extended attribute file");
+ ret = ARCHIVE_WARN;
+ goto cleanup;
+ }
+ __archive_ensure_cloexec_flag(tempfd);
/* XXX I wish copyfile() could pack directly to a memory
* buffer; that would avoid the temp file here. For that
* matter, it would be nice if fcopyfile() actually worked,
* that would reduce the many open/close races here. */
- if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) {
+ if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
archive_set_error(&a->archive, errno,
"Could not pack extended attributes");
ret = ARCHIVE_WARN;
goto cleanup;
}
- tempfd = open(tempfile, O_RDONLY);
- if (tempfd < 0) {
- archive_set_error(&a->archive, errno,
- "Could not open extended attribute file");
- ret = ARCHIVE_WARN;
- goto cleanup;
- }
if (fstat(tempfd, &copyfile_stat)) {
archive_set_error(&a->archive, errno,
"Could not check size of extended attributes");
@@ -340,10 +373,12 @@ setup_mac_metadata(struct archive_read_disk *a,
archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
cleanup:
- if (tempfd >= 0)
+ if (tempfd >= 0) {
close(tempfd);
- if (tempfile != NULL)
- unlink(tempfile);
+ unlink(tempfile.s);
+ }
+ archive_string_free(&tempfile);
+ free(buff);
return (ret);
}
@@ -354,7 +389,7 @@ cleanup:
*/
static int
setup_mac_metadata(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+ struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
(void)entry; /* UNUSED */
@@ -364,16 +399,19 @@ setup_mac_metadata(struct archive_read_disk *a,
#endif
-#ifdef HAVE_POSIX_ACL
-static void setup_acl_posix1e(struct archive_read_disk *a,
+#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4)
+static int translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
static int
-setup_acls_posix1e(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+setup_acls(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
{
const char *accpath;
acl_t acl;
+#if HAVE_ACL_IS_TRIVIAL_NP
+ int r;
+#endif
accpath = archive_entry_sourcepath(entry);
if (accpath == NULL)
@@ -381,9 +419,38 @@ setup_acls_posix1e(struct archive_read_disk *a,
archive_entry_acl_clear(entry);
+ /* Try NFS4 ACL first. */
+ if (*fd >= 0)
+ acl = acl_get_fd(*fd);
+#if HAVE_ACL_GET_LINK_NP
+ else if (!a->follow_symlinks)
+ acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
+#else
+ else if ((!a->follow_symlinks)
+ && (archive_entry_filetype(entry) == AE_IFLNK))
+ /* We can't get the ACL of a symlink, so we assume it can't
+ have one. */
+ acl = NULL;
+#endif
+ else
+ acl = acl_get_file(accpath, ACL_TYPE_NFS4);
+#if HAVE_ACL_IS_TRIVIAL_NP
+ /* Ignore "trivial" ACLs that just mirror the file mode. */
+ acl_is_trivial_np(acl, &r);
+ if (r) {
+ acl_free(acl);
+ acl = NULL;
+ }
+#endif
+ if (acl != NULL) {
+ translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ acl_free(acl);
+ return (ARCHIVE_OK);
+ }
+
/* Retrieve access ACL from file. */
- if (fd >= 0)
- acl = acl_get_fd(fd);
+ if (*fd >= 0)
+ acl = acl_get_fd(*fd);
#if HAVE_ACL_GET_LINK_NP
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
@@ -397,7 +464,7 @@ setup_acls_posix1e(struct archive_read_disk *a,
else
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
if (acl != NULL) {
- setup_acl_posix1e(a, entry, acl,
+ translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
acl_free(acl);
}
@@ -406,7 +473,7 @@ setup_acls_posix1e(struct archive_read_disk *a,
if (S_ISDIR(archive_entry_mode(entry))) {
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
if (acl != NULL) {
- setup_acl_posix1e(a, entry, acl,
+ translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
acl_free(acl);
}
@@ -415,69 +482,181 @@ setup_acls_posix1e(struct archive_read_disk *a,
}
/*
- * Translate POSIX.1e ACL into libarchive internal structure.
+ * Translate system ACL into libarchive internal structure.
*/
-static void
-setup_acl_posix1e(struct archive_read_disk *a,
- struct archive_entry *entry, acl_t acl, int archive_entry_acl_type)
+
+static struct {
+ int archive_perm;
+ int platform_perm;
+} acl_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+ {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+};
+
+static struct {
+ int archive_inherit;
+ int platform_inherit;
+} acl_inherit_map[] = {
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
+};
+
+static int
+translate_acl(struct archive_read_disk *a,
+ struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
acl_tag_t acl_tag;
+ acl_entry_type_t acl_type;
+ acl_flagset_t acl_flagset;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
+ int brand, i, r, entry_acl_type;
int s, ae_id, ae_tag, ae_perm;
const char *ae_name;
+
+ // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
+ // Make sure the "brand" on this ACL is consistent
+ // with the default_entry_acl_type bits provided.
+ acl_get_brand_np(acl, &brand);
+ switch (brand) {
+ case ACL_BRAND_POSIX:
+ switch (default_entry_acl_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ break;
+ default:
+ // XXX set warning message?
+ return ARCHIVE_FAILED;
+ }
+ break;
+ case ACL_BRAND_NFS4:
+ if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+ // XXX set warning message?
+ return ARCHIVE_FAILED;
+ }
+ break;
+ default:
+ // XXX set warning message?
+ return ARCHIVE_FAILED;
+ break;
+ }
+
+
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
while (s == 1) {
ae_id = -1;
ae_name = NULL;
+ ae_perm = 0;
acl_get_tag_type(acl_entry, &acl_tag);
- if (acl_tag == ACL_USER) {
+ switch (acl_tag) {
+ case ACL_USER:
ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
ae_name = archive_read_disk_uname(&a->archive, ae_id);
ae_tag = ARCHIVE_ENTRY_ACL_USER;
- } else if (acl_tag == ACL_GROUP) {
+ break;
+ case ACL_GROUP:
ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
ae_name = archive_read_disk_gname(&a->archive, ae_id);
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
- } else if (acl_tag == ACL_MASK) {
+ break;
+ case ACL_MASK:
ae_tag = ARCHIVE_ENTRY_ACL_MASK;
- } else if (acl_tag == ACL_USER_OBJ) {
+ break;
+ case ACL_USER_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
- } else if (acl_tag == ACL_GROUP_OBJ) {
+ break;
+ case ACL_GROUP_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
- } else if (acl_tag == ACL_OTHER) {
+ break;
+ case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
- } else {
+ break;
+ case ACL_EVERYONE:
+ ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
+ break;
+ default:
/* Skip types that libarchive can't support. */
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
- acl_get_permset(acl_entry, &acl_permset);
- ae_perm = 0;
+ // XXX acl type maps to allow/deny/audit/YYYY bits
+ // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
+ // non-NFSv4 ACLs
+ entry_acl_type = default_entry_acl_type;
+ r = acl_get_entry_type_np(acl_entry, &acl_type);
+ if (r == 0) {
+ switch (acl_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+ break;
+ case ACL_ENTRY_TYPE_DENY:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
+ break;
+ case ACL_ENTRY_TYPE_AUDIT:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
+ break;
+ case ACL_ENTRY_TYPE_ALARM:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ break;
+ }
+ }
+
/*
- * acl_get_perm() is spelled differently on different
- * platforms; see above.
+ * Libarchive stores "flag" (NFSv4 inheritance bits)
+ * in the ae_perm bitmap.
*/
- if (ACL_GET_PERM(acl_permset, ACL_EXECUTE))
- ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
- if (ACL_GET_PERM(acl_permset, ACL_READ))
- ae_perm |= ARCHIVE_ENTRY_ACL_READ;
- if (ACL_GET_PERM(acl_permset, ACL_WRITE))
- ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
+ acl_get_flagset_np(acl_entry, &acl_flagset);
+ for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
+ if (acl_get_flag_np(acl_flagset,
+ acl_inherit_map[i].platform_inherit))
+ ae_perm |= acl_inherit_map[i].archive_inherit;
- archive_entry_acl_add_entry(entry,
- archive_entry_acl_type, ae_perm, ae_tag,
- ae_id, ae_name);
+ }
+
+ acl_get_permset(acl_entry, &acl_permset);
+ for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
+ /*
+ * acl_get_perm() is spelled differently on different
+ * platforms; see above.
+ */
+ if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
+ ae_perm |= acl_perm_map[i].archive_perm;
+ }
+
+ archive_entry_acl_add_entry(entry, entry_acl_type,
+ ae_perm, ae_tag,
+ ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
}
+ return (ARCHIVE_OK);
}
#else
static int
-setup_acls_posix1e(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+setup_acls(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
(void)entry; /* UNUSED */
@@ -571,7 +750,7 @@ setup_xattr(struct archive_read_disk *a,
static int
setup_xattrs(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+ struct archive_entry *entry, int *fd)
{
char *list, *p;
const char *path;
@@ -581,16 +760,30 @@ setup_xattrs(struct archive_read_disk *a,
if (path == NULL)
path = archive_entry_pathname(entry);
+ if (*fd < 0 && a->tree != NULL) {
+ if (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)
+ *fd = a->open_on_current_dir(a->tree, path,
+ O_RDONLY | O_NONBLOCK);
+ if (*fd < 0) {
+ if (a->tree_enter_working_dir(a->tree) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't access %s", path);
+ return (ARCHIVE_FAILED);
+ }
+ }
+ }
+
#if HAVE_FLISTXATTR
- if (fd >= 0)
- list_size = flistxattr(fd, NULL, 0);
+ if (*fd >= 0)
+ list_size = flistxattr(*fd, NULL, 0);
else if (!a->follow_symlinks)
list_size = llistxattr(path, NULL, 0);
else
list_size = listxattr(path, NULL, 0);
#elif HAVE_FLISTEA
- if (fd >= 0)
- list_size = flistea(fd, NULL, 0);
+ if (*fd >= 0)
+ list_size = flistea(*fd, NULL, 0);
else if (!a->follow_symlinks)
list_size = llistea(path, NULL, 0);
else
@@ -614,15 +807,15 @@ setup_xattrs(struct archive_read_disk *a,
}
#if HAVE_FLISTXATTR
- if (fd >= 0)
- list_size = flistxattr(fd, list, list_size);
+ if (*fd >= 0)
+ list_size = flistxattr(*fd, list, list_size);
else if (!a->follow_symlinks)
list_size = llistxattr(path, list, list_size);
else
list_size = listxattr(path, list, list_size);
#elif HAVE_FLISTEA
- if (fd >= 0)
- list_size = flistea(fd, list, list_size);
+ if (*fd >= 0)
+ list_size = flistea(*fd, list, list_size);
else if (!a->follow_symlinks)
list_size = llistea(path, list, list_size);
else
@@ -640,7 +833,7 @@ setup_xattrs(struct archive_read_disk *a,
if (strncmp(p, "system.", 7) == 0 ||
strncmp(p, "xfsroot.", 8) == 0)
continue;
- setup_xattr(a, entry, p, fd);
+ setup_xattr(a, entry, p, *fd);
}
free(list);
@@ -701,6 +894,7 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
size = extattr_get_file(accpath, namespace, name, value, size);
if (size == -1) {
+ free(value);
archive_set_error(&a->archive, errno,
"Couldn't read extended attribute");
return (ARCHIVE_WARN);
@@ -714,7 +908,7 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
static int
setup_xattrs(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+ struct archive_entry *entry, int *fd)
{
char buff[512];
char *list, *p;
@@ -726,8 +920,22 @@ setup_xattrs(struct archive_read_disk *a,
if (path == NULL)
path = archive_entry_pathname(entry);
- if (fd >= 0)
- list_size = extattr_list_fd(fd, namespace, NULL, 0);
+ if (*fd < 0 && a->tree != NULL) {
+ if (a->follow_symlinks ||
+ archive_entry_filetype(entry) != AE_IFLNK)
+ *fd = a->open_on_current_dir(a->tree, path,
+ O_RDONLY | O_NONBLOCK);
+ if (*fd < 0) {
+ if (a->tree_enter_working_dir(a->tree) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Couldn't access %s", path);
+ return (ARCHIVE_FAILED);
+ }
+ }
+ }
+
+ if (*fd >= 0)
+ list_size = extattr_list_fd(*fd, namespace, NULL, 0);
else if (!a->follow_symlinks)
list_size = extattr_list_link(path, namespace, NULL, 0);
else
@@ -749,8 +957,8 @@ setup_xattrs(struct archive_read_disk *a,
return (ARCHIVE_FATAL);
}
- if (fd >= 0)
- list_size = extattr_list_fd(fd, namespace, list, list_size);
+ if (*fd >= 0)
+ list_size = extattr_list_fd(*fd, namespace, list, list_size);
else if (!a->follow_symlinks)
list_size = extattr_list_link(path, namespace, list, list_size);
else
@@ -772,7 +980,7 @@ setup_xattrs(struct archive_read_disk *a,
name = buff + strlen(buff);
memcpy(name, p + 1, len);
name[len] = '\0';
- setup_xattr(a, entry, namespace, name, buff, fd);
+ setup_xattr(a, entry, namespace, name, buff, *fd);
p += 1 + len;
}
@@ -787,7 +995,7 @@ setup_xattrs(struct archive_read_disk *a,
*/
static int
setup_xattrs(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+ struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
(void)entry; /* UNUSED */
@@ -816,14 +1024,13 @@ setup_xattrs(struct archive_read_disk *a,
static int
setup_sparse(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+ struct archive_entry *entry, int *fd)
{
char buff[4096];
struct fiemap *fm;
struct fiemap_extent *fe;
int64_t size;
int count, do_fiemap;
- int initial_fd = fd;
int exit_sts = ARCHIVE_OK;
if (archive_entry_filetype(entry) != AE_IFREG
@@ -831,20 +1038,27 @@ setup_sparse(struct archive_read_disk *a,
|| archive_entry_hardlink(entry) != NULL)
return (ARCHIVE_OK);
- if (fd < 0) {
+ if (*fd < 0) {
const char *path;
path = archive_entry_sourcepath(entry);
if (path == NULL)
path = archive_entry_pathname(entry);
- fd = open(path, O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
+ if (a->tree != NULL)
+ *fd = a->open_on_current_dir(a->tree, path,
+ O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ else
+ *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (*fd < 0) {
archive_set_error(&a->archive, errno,
"Can't open `%s'", path);
return (ARCHIVE_FAILED);
}
+ __archive_ensure_cloexec_flag(*fd);
}
+ /* Initialize buffer to avoid the error valgrind complains about. */
+ memset(buff, 0, sizeof(buff));
count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
fm = (struct fiemap *)buff;
fm->fm_start = 0;
@@ -856,29 +1070,22 @@ setup_sparse(struct archive_read_disk *a,
for (;;) {
int i, r;
- r = ioctl(fd, FS_IOC_FIEMAP, fm);
+ r = ioctl(*fd, FS_IOC_FIEMAP, fm);
if (r < 0) {
- /* When errno is ENOTTY, it is better we should
- * return ARCHIVE_OK because an earlier version
- *(<2.6.28) cannot perfom FS_IOC_FIEMAP.
- * We should also check if errno is EOPNOTSUPP,
- * it means "Operation not supported". */
- if (errno != ENOTTY && errno != EOPNOTSUPP) {
- archive_set_error(&a->archive, errno,
- "FIEMAP failed");
- exit_sts = ARCHIVE_FAILED;
- }
+ /* When something error happens, it is better we
+ * should return ARCHIVE_OK because an earlier
+ * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
goto exit_setup_sparse;
}
if (fm->fm_mapped_extents == 0)
break;
fe = fm->fm_extents;
- for (i = 0; i < fm->fm_mapped_extents; i++, fe++) {
+ for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
/* The fe_length of the last block does not
* adjust itself to its size files. */
int64_t length = fe->fe_length;
- if (fe->fe_logical + length > size)
+ if (fe->fe_logical + length > (uint64_t)size)
length -= fe->fe_logical + length - size;
if (fe->fe_logical == 0 && length == size) {
/* This is not sparse. */
@@ -899,8 +1106,6 @@ setup_sparse(struct archive_read_disk *a,
break;
}
exit_setup_sparse:
- if (initial_fd != fd)
- close(fd);
return (exit_sts);
}
@@ -912,10 +1117,9 @@ exit_setup_sparse:
static int
setup_sparse(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+ struct archive_entry *entry, int *fd)
{
int64_t size;
- int initial_fd = fd;
off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
int exit_sts = ARCHIVE_OK;
@@ -926,33 +1130,50 @@ setup_sparse(struct archive_read_disk *a,
return (ARCHIVE_OK);
/* Does filesystem support the reporting of hole ? */
- if (fd >= 0) {
- if (fpathconf(fd, _PC_MIN_HOLE_SIZE) <= 0)
+ if (*fd < 0 && a->tree != NULL) {
+ const char *path;
+
+ path = archive_entry_sourcepath(entry);
+ if (path == NULL)
+ path = archive_entry_pathname(entry);
+ *fd = a->open_on_current_dir(a->tree, path,
+ O_RDONLY | O_NONBLOCK);
+ if (*fd < 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't open `%s'", path);
+ return (ARCHIVE_FAILED);
+ }
+ }
+
+ if (*fd >= 0) {
+ if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
- initial_off = lseek(fd, 0, SEEK_CUR);
+ initial_off = lseek(*fd, 0, SEEK_CUR);
if (initial_off != 0)
- lseek(fd, 0, SEEK_SET);
+ lseek(*fd, 0, SEEK_SET);
} else {
const char *path;
path = archive_entry_sourcepath(entry);
if (path == NULL)
path = archive_entry_pathname(entry);
+
if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
- fd = open(path, O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
+ *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (*fd < 0) {
archive_set_error(&a->archive, errno,
"Can't open `%s'", path);
return (ARCHIVE_FAILED);
}
+ __archive_ensure_cloexec_flag(*fd);
initial_off = 0;
}
off_s = 0;
size = archive_entry_size(entry);
while (off_s < size) {
- off_s = lseek(fd, off_s, SEEK_DATA);
+ off_s = lseek(*fd, off_s, SEEK_DATA);
if (off_s == (off_t)-1) {
if (errno == ENXIO)
break;/* no more hole */
@@ -961,10 +1182,10 @@ setup_sparse(struct archive_read_disk *a,
exit_sts = ARCHIVE_FAILED;
goto exit_setup_sparse;
}
- off_e = lseek(fd, off_s, SEEK_HOLE);
- if (off_s == (off_t)-1) {
+ off_e = lseek(*fd, off_s, SEEK_HOLE);
+ if (off_e == (off_t)-1) {
if (errno == ENXIO) {
- off_e = lseek(fd, 0, SEEK_END);
+ off_e = lseek(*fd, 0, SEEK_END);
if (off_e != (off_t)-1)
break;/* no more data */
}
@@ -980,10 +1201,7 @@ setup_sparse(struct archive_read_disk *a,
off_s = off_e;
}
exit_setup_sparse:
- if (initial_fd != fd)
- close(fd);
- else
- lseek(fd, initial_off, SEEK_SET);
+ lseek(*fd, initial_off, SEEK_SET);
return (exit_sts);
}
@@ -994,7 +1212,7 @@ exit_setup_sparse:
*/
static int
setup_sparse(struct archive_read_disk *a,
- struct archive_entry *entry, int fd)
+ struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
(void)entry; /* UNUSED */
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
index 365a874..a13dbbf 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
- * Copyright (c) 2010,2011 Michihiro NAKAJIMA
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -52,6 +52,19 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_LINUX_MAGIC_H
#include <linux/magic.h>
#endif
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h>
+#endif
+/*
+ * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
+ * As the include guards don't agree, the order of include is important.
+ */
+#ifdef HAVE_LINUX_EXT2_FS_H
+#include <linux/ext2_fs.h> /* for Linux file flags */
+#endif
+#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
+#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
+#endif
#ifdef HAVE_DIRECT_H
#include <direct.h>
#endif
@@ -76,6 +89,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
#include "archive.h"
#include "archive_string.h"
@@ -89,6 +105,9 @@ __FBSDID("$FreeBSD$");
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
/*-
* This is a new directory-walking system that addresses a number
@@ -222,6 +241,7 @@ struct tree {
char symlink_mode;
struct filesystem *current_filesystem;
struct filesystem *filesystem_table;
+ int initial_filesystem_id;
int current_filesystem_id;
int max_filesystem_id;
int allocated_filesytem;
@@ -240,6 +260,7 @@ struct tree {
#define onWorkingDir 64 /* We are on the working dir where we are
* reading directory entry at this time. */
#define needsRestoreTimes 128
+#define onInitialDir 256 /* We are on the initial dir. */
static int
tree_dir_next_posix(struct tree *t);
@@ -342,6 +363,8 @@ static const char *trivial_lookup_uname(void *, int64_t uid);
static int setup_sparse(struct archive_read_disk *, struct archive_entry *);
static int close_and_restore_time(int fd, struct tree *,
struct restore_time *);
+static int open_on_current_dir(struct tree *, const char *, int);
+static int tree_dup(int);
static struct archive_vtable *
@@ -430,16 +453,19 @@ archive_read_disk_new(void)
{
struct archive_read_disk *a;
- a = (struct archive_read_disk *)malloc(sizeof(*a));
+ a = (struct archive_read_disk *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
- memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->archive.vtable = archive_read_disk_vtable();
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->entry_wd_fd = -1;
+ a->enable_copyfile = 1;
+ a->traverse_mount_points = 1;
+ a->open_on_current_dir = open_on_current_dir;
+ a->tree_current_dir_fd = tree_current_dir_fd;
+ a->tree_enter_working_dir = tree_enter_working_dir;
return (&a->archive);
}
@@ -555,6 +581,37 @@ archive_read_disk_set_atime_restored(struct archive *_a)
#endif
}
+int
+archive_read_disk_set_behavior(struct archive *_a, int flags)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ int r = ARCHIVE_OK;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+
+ if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
+ r = archive_read_disk_set_atime_restored(_a);
+ else {
+ a->restore_time = 0;
+ if (a->tree != NULL)
+ a->tree->flags &= ~needsRestoreTimes;
+ }
+ if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
+ a->honor_nodump = 1;
+ else
+ a->honor_nodump = 0;
+ if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
+ a->enable_copyfile = 1;
+ else
+ a->enable_copyfile = 0;
+ if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
+ a->traverse_mount_points = 0;
+ else
+ a->traverse_mount_points = 1;
+ return (r);
+}
+
/*
* Trivial implementations of gname/uname lookup functions.
* These are normally overridden by the client, but these stub
@@ -664,7 +721,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
* Open the current file.
*/
if (t->entry_fd < 0) {
- int flags = O_RDONLY | O_BINARY;
+ int flags = O_RDONLY | O_BINARY | O_CLOEXEC;
/*
* Eliminate or reduce cache effects if we can.
@@ -685,13 +742,9 @@ _archive_read_data_block(struct archive *_a, const void **buff,
flags |= O_NOATIME;
do {
#endif
-#ifdef HAVE_OPENAT
- t->entry_fd = openat(tree_current_dir_fd(t),
+ t->entry_fd = open_on_current_dir(t,
tree_current_access_path(t), flags);
-#else
- tree_enter_working_dir(t);
- t->entry_fd = open(tree_current_access_path(t), flags);
-#endif
+ __archive_ensure_cloexec_flag(t->entry_fd);
#if defined(O_NOATIME)
/*
* When we did open the file with O_NOATIME flag,
@@ -733,7 +786,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
t->entry_buff_size = t->current_filesystem->buff_size;
buffbytes = t->entry_buff_size;
- if (buffbytes > t->current_sparse->length)
+ if ((int64_t)buffbytes > t->current_sparse->length)
buffbytes = t->current_sparse->length;
/*
@@ -802,29 +855,17 @@ abort_read_data:
}
static int
-_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
+next_entry(struct archive_read_disk *a, struct tree *t,
+ struct archive_entry *entry)
{
- struct archive_read_disk *a = (struct archive_read_disk *)_a;
- struct tree *t;
const struct stat *st; /* info to use for this entry */
const struct stat *lst;/* lstat() information */
- int descend, fd = -1, r;
-
- archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
- ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
- "archive_read_next_header2");
+ const char *name;
+ int descend, r;
- t = a->tree;
- if (t->entry_fd >= 0) {
- close_and_restore_time(t->entry_fd, t, &t->restore_time);
- t->entry_fd = -1;
- }
-#if !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR))
- /* Restore working directory. */
- tree_enter_working_dir(t);
-#endif
st = NULL;
lst = NULL;
+ t->descend = 0;
do {
switch (tree_next(t)) {
case TREE_ERROR_FATAL:
@@ -859,6 +900,38 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
}
} while (lst == NULL);
+#ifdef __APPLE__
+ if (a->enable_copyfile) {
+ /* If we're using copyfile(), ignore "._XXX" files. */
+ const char *bname = strrchr(tree_current_path(t), '/');
+ if (bname == NULL)
+ bname = tree_current_path(t);
+ else
+ ++bname;
+ if (bname[0] == '.' && bname[1] == '_')
+ return (ARCHIVE_RETRY);
+ }
+#endif
+
+ archive_entry_copy_pathname(entry, tree_current_path(t));
+ /*
+ * Perform path matching.
+ */
+ if (a->matching) {
+ r = archive_match_path_excluded(a->matching, entry);
+ if (r < 0) {
+ archive_set_error(&(a->archive), errno,
+ "Faild : %s", archive_error_string(a->matching));
+ return (r);
+ }
+ if (r) {
+ if (a->excluded_cb_func)
+ a->excluded_cb_func(&(a->archive),
+ a->excluded_cb_data, entry);
+ return (ARCHIVE_RETRY);
+ }
+ }
+
/*
* Distinguish 'L'/'P'/'H' symlink following.
*/
@@ -897,13 +970,46 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
tree_enter_initial_dir(t);
return (ARCHIVE_FATAL);
}
+ if (t->initial_filesystem_id == -1)
+ t->initial_filesystem_id = t->current_filesystem_id;
+ if (!a->traverse_mount_points) {
+ if (t->initial_filesystem_id != t->current_filesystem_id)
+ return (ARCHIVE_RETRY);
+ }
t->descend = descend;
- archive_entry_set_pathname(entry, tree_current_path(t));
- archive_entry_copy_sourcepath(entry, tree_current_access_path(t));
+ /*
+ * Honor nodump flag.
+ * If the file is marked with nodump flag, do not return this entry.
+ */
+ if (a->honor_nodump) {
+#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
+ if (st->st_flags & UF_NODUMP)
+ return (ARCHIVE_RETRY);
+#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+ if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
+ int stflags;
+
+ t->entry_fd = open_on_current_dir(t,
+ tree_current_access_path(t),
+ O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(t->entry_fd);
+ if (t->entry_fd >= 0) {
+ r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
+ &stflags);
+ if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
+ return (ARCHIVE_RETRY);
+ }
+ }
+#endif
+ }
+
archive_entry_copy_stat(entry, st);
- /* Save the times to be restored. */
+ /* Save the times to be restored. This must be in before
+ * calling archive_read_disk_descend() or any chance of it,
+ * especially, invokng a callback. */
t->restore_time.mtime = archive_entry_mtime(entry);
t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry);
t->restore_time.atime = archive_entry_atime(entry);
@@ -911,39 +1017,102 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
t->restore_time.filetype = archive_entry_filetype(entry);
t->restore_time.noatime = t->current_filesystem->noatime;
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
/*
- * Open the current file to freely gather its metadata anywhere in
- * working directory.
- * Note: A symbolic link file cannot be opened with O_NOFOLLOW.
+ * Perform time matching.
*/
- if (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)
- fd = openat(tree_current_dir_fd(t), tree_current_access_path(t),
- O_RDONLY | O_NONBLOCK);
- /* Restore working directory if openat() operation failed or
- * the file is a symbolic link. */
- if (fd < 0)
- tree_enter_working_dir(t);
+ if (a->matching) {
+ r = archive_match_time_excluded(a->matching, entry);
+ if (r < 0) {
+ archive_set_error(&(a->archive), errno,
+ "Faild : %s", archive_error_string(a->matching));
+ return (r);
+ }
+ if (r) {
+ if (a->excluded_cb_func)
+ a->excluded_cb_func(&(a->archive),
+ a->excluded_cb_data, entry);
+ return (ARCHIVE_RETRY);
+ }
+ }
- /* The current directory fd is needed at
- * archive_read_disk_entry_from_file() function to read link data
- * with readlinkat(). */
- a->entry_wd_fd = tree_current_dir_fd(t);
-#endif
+ /* Lookup uname/gname */
+ name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry));
+ if (name != NULL)
+ archive_entry_copy_uname(entry, name);
+ name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry));
+ if (name != NULL)
+ archive_entry_copy_gname(entry, name);
+
+ /*
+ * Perform owner matching.
+ */
+ if (a->matching) {
+ r = archive_match_owner_excluded(a->matching, entry);
+ if (r < 0) {
+ archive_set_error(&(a->archive), errno,
+ "Faild : %s", archive_error_string(a->matching));
+ return (r);
+ }
+ if (r) {
+ if (a->excluded_cb_func)
+ a->excluded_cb_func(&(a->archive),
+ a->excluded_cb_data, entry);
+ return (ARCHIVE_RETRY);
+ }
+ }
+
+ /*
+ * Invoke a meta data filter callback.
+ */
+ if (a->metadata_filter_func) {
+ if (!a->metadata_filter_func(&(a->archive),
+ a->metadata_filter_data, entry))
+ return (ARCHIVE_RETRY);
+ }
/*
* Populate the archive_entry with metadata from the disk.
*/
- r = archive_read_disk_entry_from_file(&(a->archive), entry, fd, st);
+ archive_entry_copy_sourcepath(entry, tree_current_access_path(t));
+ r = archive_read_disk_entry_from_file(&(a->archive), entry,
+ t->entry_fd, st);
- /* Close the file descriptor used for reding the current file
- * metadata at archive_read_disk_entry_from_file(). */
- if (fd >= 0)
- close(fd);
+ return (r);
+}
+
+static int
+_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ struct tree *t;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+ "archive_read_next_header2");
+
+ t = a->tree;
+ if (t->entry_fd >= 0) {
+ close_and_restore_time(t->entry_fd, t, &t->restore_time);
+ t->entry_fd = -1;
+ }
+
+ for (;;) {
+ r = next_entry(a, t, entry);
+ if (t->entry_fd >= 0) {
+ close(t->entry_fd);
+ t->entry_fd = -1;
+ }
+
+ if (r == ARCHIVE_RETRY) {
+ archive_entry_clear(entry);
+ continue;
+ }
+ break;
+ }
/* Return to the initial directory. */
tree_enter_initial_dir(t);
- archive_entry_copy_sourcepath(entry, tree_current_path(t));
/*
* EOF and FATAL are persistent at this layer. By
@@ -956,6 +1125,8 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
break;
case ARCHIVE_OK:
case ARCHIVE_WARN:
+ /* Overwrite the sourcepath based on the initial directory. */
+ archive_entry_copy_sourcepath(entry, tree_current_path(t));
t->entry_total = 0;
if (archive_entry_filetype(entry) == AE_IFREG) {
t->nlink = archive_entry_nlink(entry);
@@ -1018,6 +1189,48 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
return (ARCHIVE_OK);
}
+int
+archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
+ void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
+ void *_client_data)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
+ a->matching = _ma;
+ a->excluded_cb_func = _excluded_func;
+ a->excluded_cb_data = _client_data;
+ return (ARCHIVE_OK);
+}
+
+int
+archive_read_disk_set_metadata_filter_callback(struct archive *_a,
+ int (*_metadata_filter_func)(struct archive *, void *,
+ struct archive_entry *), void *_client_data)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
+ "archive_read_disk_set_metadata_filter_callback");
+
+ a->metadata_filter_func = _metadata_filter_func;
+ a->metadata_filter_data = _client_data;
+ return (ARCHIVE_OK);
+}
+
+int
+archive_read_disk_can_descend(struct archive *_a)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ struct tree *t = a->tree;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+ "archive_read_disk_can_descend");
+
+ return (t->visit_type == TREE_REGULAR && t->descend);
+}
+
/*
* Called by the client to mark the directory just returned from
* tree_next() as needing to be visited.
@@ -1028,14 +1241,12 @@ archive_read_disk_descend(struct archive *_a)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
struct tree *t = a->tree;
- archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_read_disk_descend");
- if (t->visit_type != TREE_REGULAR || !t->descend) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Ignored the request descending the current object");
- return (ARCHIVE_WARN);
- }
+ if (t->visit_type != TREE_REGULAR || !t->descend)
+ return (ARCHIVE_OK);
if (tree_current_is_physical_dir(t)) {
tree_push(t, t->basename, t->current_filesystem_id,
@@ -1079,8 +1290,12 @@ archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
archive_string_init(&path);
if (archive_string_append_from_wcs(&path, pathname,
wcslen(pathname)) != 0) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Can't convert a path to a char string");
+ if (errno == ENOMEM)
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory");
+ else
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Can't convert a path to a char string");
a->archive.state = ARCHIVE_STATE_FATAL;
ret = ARCHIVE_FATAL;
} else
@@ -1151,15 +1366,17 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
fid = t->max_filesystem_id++;
if (t->max_filesystem_id > t->allocated_filesytem) {
size_t s;
+ void *p;
s = t->max_filesystem_id * 2;
- t->filesystem_table = realloc(t->filesystem_table,
- s * sizeof(*t->filesystem_table));
- if (t->filesystem_table == NULL) {
+ p = realloc(t->filesystem_table,
+ s * sizeof(*t->filesystem_table));
+ if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
return (ARCHIVE_FATAL);
}
+ t->filesystem_table = (struct filesystem *)p;
t->allocated_filesytem = s;
}
t->current_filesystem_id = fid;
@@ -1268,13 +1485,14 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->synthetic = -1;
t->current_filesystem->remote = -1;
if (tree_current_is_symblic_link_target(t)) {
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
+#if defined(HAVE_OPENAT)
/*
* Get file system statistics on any directory
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
- tree_current_access_path(t), O_RDONLY);
+ tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@@ -1285,6 +1503,10 @@ setup_current_filesystem(struct archive_read_disk *a)
xr = get_xfer_size(t, fd, NULL);
close(fd);
#else
+ if (tree_enter_working_dir(t) != 0) {
+ archive_set_error(&a->archive, errno, "fchdir failed");
+ return (ARCHIVE_FAILED);
+ }
r = statfs(tree_current_access_path(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, -1, tree_current_access_path(t));
@@ -1334,9 +1556,13 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->name_max = sfs.f_namemax;
#else
/* Mac OS X does not have f_namemax in struct statfs. */
- if (tree_current_is_symblic_link_target(t))
+ if (tree_current_is_symblic_link_target(t)) {
+ if (tree_enter_working_dir(t) != 0) {
+ archive_set_error(&a->archive, errno, "fchdir failed");
+ return (ARCHIVE_FAILED);
+ }
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
- else
+ } else
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
if (nm == -1)
t->current_filesystem->name_max = NAME_MAX;
@@ -1360,6 +1586,10 @@ setup_current_filesystem(struct archive_read_disk *a)
int r, xr = 0;
t->current_filesystem->synthetic = -1;
+ if (tree_enter_working_dir(t) != 0) {
+ archive_set_error(&a->archive, errno, "fchdir failed");
+ return (ARCHIVE_FAILED);
+ }
if (tree_current_is_symblic_link_target(t)) {
r = statvfs(tree_current_access_path(t), &sfs);
if (r == 0)
@@ -1434,13 +1664,14 @@ setup_current_filesystem(struct archive_read_disk *a)
int r, vr = 0, xr = 0;
if (tree_current_is_symblic_link_target(t)) {
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
+#if defined(HAVE_OPENAT)
/*
* Get file system statistics on any directory
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
- tree_current_access_path(t), O_RDONLY);
+ tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@@ -1452,6 +1683,10 @@ setup_current_filesystem(struct archive_read_disk *a)
xr = get_xfer_size(t, fd, NULL);
close(fd);
#else
+ if (tree_enter_working_dir(t) != 0) {
+ archive_set_error(&a->archive, errno, "fchdir failed");
+ return (ARCHIVE_FAILED);
+ }
vr = statvfs(tree_current_access_path(t), &svfs);
r = statfs(tree_current_access_path(t), &sfs);
if (r == 0)
@@ -1463,9 +1698,11 @@ setup_current_filesystem(struct archive_read_disk *a)
r = fstatfs(tree_current_dir_fd(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
-#elif defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
-#error "Unexpected case. Please tell us about this error."
#else
+ if (tree_enter_working_dir(t) != 0) {
+ archive_set_error(&a->archive, errno, "fchdir failed");
+ return (ARCHIVE_FAILED);
+ }
vr = statvfs(".", &svfs);
r = statfs(".", &sfs);
if (r == 0)
@@ -1536,13 +1773,14 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->synthetic = -1;/* Not supported */
t->current_filesystem->remote = -1;/* Not supported */
if (tree_current_is_symblic_link_target(t)) {
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
+#if defined(HAVE_OPENAT)
/*
* Get file system statistics on any directory
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
- tree_current_access_path(t), O_RDONLY);
+ tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@@ -1553,6 +1791,10 @@ setup_current_filesystem(struct archive_read_disk *a)
xr = get_xfer_size(t, fd, NULL);
close(fd);
#else
+ if (tree_enter_working_dir(t) != 0) {
+ archive_set_error(&a->archive, errno, "fchdir failed");
+ return (ARCHIVE_FAILED);
+ }
r = statvfs(tree_current_access_path(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, -1, tree_current_access_path(t));
@@ -1562,9 +1804,11 @@ setup_current_filesystem(struct archive_read_disk *a)
r = fstatvfs(tree_current_dir_fd(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
-#elif defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
-#error "Unexpected case. Please tell us about this error."
#else
+ if (tree_enter_working_dir(t) != 0) {
+ archive_set_error(&a->archive, errno, "fchdir failed");
+ return (ARCHIVE_FAILED);
+ }
r = statvfs(".", &sfs);
if (r == 0)
xr = get_xfer_size(t, -1, ".");
@@ -1622,9 +1866,13 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(HAVE_READDIR_R)
/* Set maximum filename length. */
# if defined(_PC_NAME_MAX)
- if (tree_current_is_symblic_link_target(t))
+ if (tree_current_is_symblic_link_target(t)) {
+ if (tree_enter_working_dir(t) != 0) {
+ archive_set_error(&a->archive, errno, "fchdir failed");
+ return (ARCHIVE_FAILED);
+ }
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
- else
+ } else
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
if (nm == -1)
# endif /* _PC_NAME_MAX */
@@ -1653,7 +1901,8 @@ static int
close_and_restore_time(int fd, struct tree *t, struct restore_time *rt)
{
#ifndef HAVE_UTIMES
- (void)a; /* UNUSED */
+ (void)t; /* UNUSED */
+ (void)rt; /* UNUSED */
return (close(fd));
#else
#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__)
@@ -1704,6 +1953,40 @@ close_and_restore_time(int fd, struct tree *t, struct restore_time *rt)
return (0);
}
+static int
+open_on_current_dir(struct tree *t, const char *path, int flags)
+{
+#ifdef HAVE_OPENAT
+ return (openat(tree_current_dir_fd(t), path, flags));
+#else
+ if (tree_enter_working_dir(t) != 0)
+ return (-1);
+ return (open(path, flags));
+#endif
+}
+
+static int
+tree_dup(int fd)
+{
+ int new_fd;
+#ifdef F_DUPFD_CLOEXEC
+ static volatile int can_dupfd_cloexec = 1;
+
+ if (can_dupfd_cloexec) {
+ new_fd = fcntl(fd, F_DUPFD_CLOEXEC);
+ if (new_fd != -1)
+ return (new_fd);
+ /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,
+ * but it cannot be used. So we have to try dup(). */
+ /* We won't try F_DUPFD_CLOEXEC. */
+ can_dupfd_cloexec = 0;
+ }
+#endif /* F_DUPFD_CLOEXEC */
+ new_fd = dup(fd);
+ __archive_ensure_cloexec_flag(new_fd);
+ return (new_fd);
+}
+
/*
* Add a directory path to the current stack.
*/
@@ -1785,6 +2068,7 @@ static struct tree *
tree_reopen(struct tree *t, const char *path, int restore_time)
{
t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags |= onInitialDir;
t->visit_type = 0;
t->tree_errno = 0;
t->dirname_length = 0;
@@ -1797,25 +2081,30 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
t->entry_fd = -1;
t->entry_eof = 0;
t->entry_remaining_bytes = 0;
+ t->initial_filesystem_id = -1;
/* First item is set up a lot like a symlink traversal. */
tree_push(t, path, 0, 0, 0, NULL);
t->stack->flags = needsFirstVisit;
t->maxOpenCount = t->openCount = 1;
- t->initial_dir_fd = open(".", O_RDONLY);
- t->working_dir_fd = dup(t->initial_dir_fd);
+ t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(t->initial_dir_fd);
+ t->working_dir_fd = tree_dup(t->initial_dir_fd);
return (t);
}
static int
tree_descent(struct tree *t)
{
- int r = 0;
+ int flag, new_fd, r = 0;
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
- int new_fd;
t->dirname_length = archive_strlen(&t->path);
- new_fd = openat(t->working_dir_fd, t->stack->name.s, O_RDONLY);
+ flag = O_RDONLY | O_CLOEXEC;
+#if defined(O_DIRECTORY)
+ flag |= O_DIRECTORY;
+#endif
+ new_fd = open_on_current_dir(t, t->stack->name.s, flag);
+ __archive_ensure_cloexec_flag(new_fd);
if (new_fd < 0) {
t->tree_errno = errno;
r = TREE_ERROR_DIR;
@@ -1829,30 +2118,10 @@ tree_descent(struct tree *t)
t->maxOpenCount = t->openCount;
} else
close(t->working_dir_fd);
+ /* Renew the current working directory. */
t->working_dir_fd = new_fd;
+ t->flags &= ~onWorkingDir;
}
-#else
- /* If it is a link, set up fd for the ascent. */
- if (t->stack->flags & isDirLink)
- t->stack->symlink_parent_fd = t->working_dir_fd;
- else {
- close(t->working_dir_fd);
- t->openCount--;
- }
- t->working_dir_fd = -1;
- t->dirname_length = archive_strlen(&t->path);
- if (chdir(t->stack->name.s) != 0)
- {
- t->tree_errno = errno;
- r = TREE_ERROR_DIR;
- } else {
- t->depth++;
- t->working_dir_fd = open(".", O_RDONLY);
- t->openCount++;
- if (t->openCount > t->maxOpenCount)
- t->maxOpenCount = t->openCount;
- }
-#endif
return (r);
}
@@ -1863,37 +2132,23 @@ static int
tree_ascend(struct tree *t)
{
struct tree_entry *te;
- int r = 0, prev_dir_fd;
+ int new_fd, r = 0, prev_dir_fd;
te = t->stack;
prev_dir_fd = t->working_dir_fd;
-#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
if (te->flags & isDirLink)
- t->working_dir_fd = te->symlink_parent_fd;
+ new_fd = te->symlink_parent_fd;
else {
- int new_fd = openat(t->working_dir_fd, "..", O_RDONLY);
- if (new_fd < 0) {
- t->tree_errno = errno;
- r = TREE_ERROR_FATAL;
- } else
- t->working_dir_fd = new_fd;
+ new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(new_fd);
}
-#else
- if (te->flags & isDirLink) {
- if (fchdir(te->symlink_parent_fd) != 0) {
- t->tree_errno = errno;
- r = TREE_ERROR_FATAL;
- } else
- t->working_dir_fd = te->symlink_parent_fd;
+ if (new_fd < 0) {
+ t->tree_errno = errno;
+ r = TREE_ERROR_FATAL;
} else {
- if (chdir("..") != 0) {
- t->tree_errno = errno;
- r = TREE_ERROR_FATAL;
- } else
- t->working_dir_fd = open(".", O_RDONLY);
- }
-#endif
- if (r == 0) {
+ /* Renew the current working directory. */
+ t->working_dir_fd = new_fd;
+ t->flags &= ~onWorkingDir;
/* Current directory has been changed, we should
* close an fd of previous working directory. */
close_and_restore_time(prev_dir_fd, t, &te->restore_time);
@@ -1914,10 +2169,12 @@ tree_enter_initial_dir(struct tree *t)
{
int r = 0;
- if (t->flags & onWorkingDir) {
+ if ((t->flags & onInitialDir) == 0) {
r = fchdir(t->initial_dir_fd);
- if (r == 0)
+ if (r == 0) {
t->flags &= ~onWorkingDir;
+ t->flags |= onInitialDir;
+ }
}
return (r);
}
@@ -1937,8 +2194,10 @@ tree_enter_working_dir(struct tree *t)
*/
if (t->depth > 0 && (t->flags & onWorkingDir) == 0) {
r = fchdir(t->working_dir_fd);
- if (r == 0)
+ if (r == 0) {
+ t->flags &= ~onInitialDir;
t->flags |= onWorkingDir;
+ }
}
return (r);
}
@@ -2045,10 +2304,16 @@ tree_dir_next_posix(struct tree *t)
#endif
#if defined(HAVE_FDOPENDIR)
- if ((t->d = fdopendir(dup(t->working_dir_fd))) == NULL) {
-#else
- if ((t->d = opendir(".")) == NULL) {
+ t->d = fdopendir(tree_dup(t->working_dir_fd));
+#else /* HAVE_FDOPENDIR */
+ if (tree_enter_working_dir(t) == 0) {
+ t->d = opendir(".");
+#if HAVE_DIRFD || defined(dirfd)
+ __archive_ensure_cloexec_flag(dirfd(t->d));
#endif
+ }
+#endif /* HAVE_FDOPENDIR */
+ if (t->d == NULL) {
r = tree_ascend(t); /* Undo "chdir" */
tree_pop(t);
t->tree_errno = errno;
@@ -2075,11 +2340,21 @@ tree_dir_next_posix(struct tree *t)
#endif /* HAVE_READDIR_R */
}
for (;;) {
+ errno = 0;
#if defined(HAVE_READDIR_R)
r = readdir_r(t->d, t->dirent, &t->de);
+#ifdef _AIX
+ /* Note: According to the man page, return value 9 indicates
+ * that the readdir_r was not successful and the error code
+ * is set to the global errno variable. And then if the end
+ * of directory entries was reached, the return value is 9
+ * and the third parameter is set to NULL and errno is
+ * unchanged. */
+ if (r == 9)
+ r = errno;
+#endif /* _AIX */
if (r != 0 || t->de == NULL) {
#else
- errno = 0;
t->de = readdir(t->d);
if (t->de == NULL) {
r = errno;
@@ -2118,6 +2393,8 @@ tree_current_stat(struct tree *t)
if (fstatat(tree_current_dir_fd(t),
tree_current_access_path(t), &t->st, 0) != 0)
#else
+ if (tree_enter_working_dir(t) != 0)
+ return NULL;
if (stat(tree_current_access_path(t), &t->st) != 0)
#endif
return NULL;
@@ -2138,6 +2415,8 @@ tree_current_lstat(struct tree *t)
tree_current_access_path(t), &t->lst,
AT_SYMLINK_NOFOLLOW) != 0)
#else
+ if (tree_enter_working_dir(t) != 0)
+ return NULL;
if (lstat(tree_current_access_path(t), &t->lst) != 0)
#endif
return NULL;
@@ -2159,11 +2438,14 @@ tree_current_is_dir(struct tree *t)
*/
if (t->flags & hasLstat) {
/* If lstat() says it's a dir, it must be a dir. */
- if (S_ISDIR(tree_current_lstat(t)->st_mode))
+ st = tree_current_lstat(t);
+ if (st == NULL)
+ return 0;
+ if (S_ISDIR(st->st_mode))
return 1;
/* Not a dir; might be a link to a dir. */
/* If it's not a link, then it's not a link to a dir. */
- if (!S_ISLNK(tree_current_lstat(t)->st_mode))
+ if (!S_ISLNK(st->st_mode))
return 0;
/*
* It's a link, but we don't know what it's a link to,
@@ -2193,9 +2475,13 @@ tree_current_is_physical_dir(struct tree *t)
* If stat() says it isn't a dir, then it's not a dir.
* If stat() data is cached, this check is free, so do it first.
*/
- if ((t->flags & hasStat)
- && (!S_ISDIR(tree_current_stat(t)->st_mode)))
- return 0;
+ if (t->flags & hasStat) {
+ st = tree_current_stat(t);
+ if (st == NULL)
+ return (0);
+ if (!S_ISDIR(st->st_mode))
+ return (0);
+ }
/*
* Either stat() said it was a dir (in which case, we have
@@ -2221,7 +2507,8 @@ tree_target_is_same_as_parent(struct tree *t, const struct stat *st)
struct tree_entry *te;
for (te = t->current->parent; te != NULL; te = te->parent) {
- if (te->dev == st->st_dev && te->ino == st->st_ino)
+ if (te->dev == (int64_t)st->st_dev &&
+ te->ino == (int64_t)st->st_ino)
return (1);
}
return (0);
@@ -2238,7 +2525,8 @@ tree_current_is_symblic_link_target(struct tree *t)
lst = tree_current_lstat(t);
st = tree_current_stat(t);
- return (st != NULL && st->st_dev == t->current_filesystem->dev &&
+ return (st != NULL && lst != NULL &&
+ (int64_t)st->st_dev == t->current_filesystem->dev &&
st->st_dev != lst->st_dev);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
index 4446474..e5af16b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
@@ -34,6 +34,7 @@
#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
struct tree;
+struct archive_entry;
struct archive_read_disk {
struct archive archive;
@@ -55,10 +56,18 @@ struct archive_read_disk {
/* Directory traversals. */
struct tree *tree;
+ int (*open_on_current_dir)(struct tree*, const char *, int);
+ int (*tree_current_dir_fd)(struct tree*);
+ int (*tree_enter_working_dir)(struct tree*);
/* Set 1 if users request to restore atime . */
int restore_time;
- int entry_wd_fd;
+ /* Set 1 if users request to honor nodump flag . */
+ int honor_nodump;
+ /* Set 1 if users request to enable mac copyfile. */
+ int enable_copyfile;
+ /* Set 1 if users request to traverse mount points. */
+ int traverse_mount_points;
const char * (*lookup_gname)(void *private, int64_t gid);
void (*cleanup_gname)(void *private);
@@ -66,6 +75,18 @@ struct archive_read_disk {
const char * (*lookup_uname)(void *private, int64_t uid);
void (*cleanup_uname)(void *private);
void *lookup_uname_data;
+
+ int (*metadata_filter_func)(struct archive *, void *,
+ struct archive_entry *);
+ void *metadata_filter_data;
+
+ /* ARCHIVE_MATCH object. */
+ struct archive *matching;
+ /* Callback function, this will be invoked when ARCHIVE_MATCH
+ * archive_match_*_excluded_ae return true. */
+ void (*excluded_cb_func)(struct archive *, void *,
+ struct archive_entry *);
+ void *excluded_cb_data;
};
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
index 217a91a..9c5420d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
- * Copyright (c) 2010-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,48 +29,13 @@ __FBSDID("$FreeBSD$");
#if defined(_WIN32) && !defined(__CYGWIN__)
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-#ifdef HAVE_SYS_VFS_H
-#include <sys/vfs.h>
-#endif
-#ifdef HAVE_LINUX_MAGIC_H
-#include <linux/magic.h>
-#endif
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if defined(HAVE_WINIOCTL_H) && !defined(__CYGWIN__)
#include <winioctl.h>
-#endif
#include "archive.h"
#include "archive_string.h"
@@ -86,21 +51,6 @@ __FBSDID("$FreeBSD$");
#define IO_REPARSE_TAG_SYMLINK 0xA000000CL
#endif
-static BOOL SetFilePointerEx_perso(HANDLE hFile,
- LARGE_INTEGER liDistanceToMove,
- PLARGE_INTEGER lpNewFilePointer,
- DWORD dwMoveMethod)
-{
- LARGE_INTEGER li;
- li.QuadPart = liDistanceToMove.QuadPart;
- li.LowPart = SetFilePointer(
- hFile, li.LowPart, &li.HighPart, dwMoveMethod);
- if(lpNewFilePointer) {
- lpNewFilePointer->QuadPart = li.QuadPart;
- }
- return li.LowPart != -1 || GetLastError() == NO_ERROR;
-}
-
/*-
* This is a new directory-walking system that addresses a number
* of problems I've had with fts(3). In particular, it has no
@@ -120,11 +70,6 @@ static BOOL SetFilePointerEx_perso(HANDLE hFile,
* indicating how to get back to the parent (via chdir("..") for a
* regular dir or via fchdir(2) for a symlink).
*/
-/*
- * TODO:
- * 1) Loop checking.
- * 3) Arbitrary logical traversals by closing/reopening intermediate fds.
- */
struct restore_time {
const wchar_t *full_path;
@@ -153,6 +98,7 @@ struct filesystem {
int64_t dev;
int synthetic;
int remote;
+ DWORD bytesPerSector;
};
/* Definitions for tree_entry.flags bitmap. */
@@ -170,6 +116,11 @@ struct filesystem {
* "first visit" is just returned to the client.
*/
+#define MAX_OVERLAPPED 8
+#define BUFFER_SIZE (1024 * 8)
+#define DIRECT_IO 0/* Disabled */
+#define ASYNC_IO 1/* Enabled */
+
/*
* Local data for this package.
*/
@@ -177,7 +128,6 @@ struct tree {
struct tree_entry *stack;
struct tree_entry *current;
HANDLE d;
-#define INVALID_DIR_HANDLE INVALID_HANDLE_VALUE
WIN32_FIND_DATAW _findData;
WIN32_FIND_DATAW *findData;
int flags;
@@ -215,6 +165,7 @@ struct tree {
char symlink_mode;
struct filesystem *current_filesystem;
struct filesystem *filesystem_table;
+ int initial_filesystem_id;
int current_filesystem_id;
int max_filesystem_id;
int allocated_filesytem;
@@ -223,8 +174,24 @@ struct tree {
int entry_eof;
int64_t entry_remaining_bytes;
int64_t entry_total;
- unsigned char *entry_buff;
- size_t entry_buff_size;
+
+ int ol_idx_doing;
+ int ol_idx_done;
+ int ol_num_doing;
+ int ol_num_done;
+ int64_t ol_remaining_bytes;
+ int64_t ol_total;
+ struct la_overlapped {
+ OVERLAPPED ol;
+ struct archive * _a;
+ unsigned char *buff;
+ size_t buff_size;
+ int64_t offset;
+ size_t bytes_expected;
+ size_t bytes_transferred;
+ } ol[MAX_OVERLAPPED];
+ int direct_io;
+ int async_io;
};
#define bhfi_dev(bhfi) ((bhfi)->dwVolumeSerialNumber)
@@ -242,13 +209,6 @@ struct tree {
static int
tree_dir_next_windows(struct tree *t, const wchar_t *pattern);
-#ifdef HAVE_DIRENT_D_NAMLEN
-/* BSD extension; avoids need for a strlen() call. */
-#define D_NAMELEN(dp) (dp)->d_namlen
-#else
-#define D_NAMELEN(dp) (strlen((dp)->d_name))
-#endif
-
/* Initiate/terminate a tree traversal. */
static struct tree *tree_open(const wchar_t *, int, int);
static struct tree *tree_reopen(struct tree *, const wchar_t *, int);
@@ -435,7 +395,8 @@ archive_read_disk_new(void)
a->archive.vtable = archive_read_disk_vtable();
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->entry_wd_fd = -1;
+ a->enable_copyfile = 1;
+ a->traverse_mount_points = 1;
return (&a->archive);
}
@@ -536,6 +497,37 @@ archive_read_disk_set_atime_restored(struct archive *_a)
return (ARCHIVE_OK);
}
+int
+archive_read_disk_set_behavior(struct archive *_a, int flags)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ int r = ARCHIVE_OK;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+
+ if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
+ r = archive_read_disk_set_atime_restored(_a);
+ else {
+ a->restore_time = 0;
+ if (a->tree != NULL)
+ a->tree->flags &= ~needsRestoreTimes;
+ }
+ if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
+ a->honor_nodump = 1;
+ else
+ a->honor_nodump = 0;
+ if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
+ a->enable_copyfile = 1;
+ else
+ a->enable_copyfile = 0;
+ if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
+ a->traverse_mount_points = 0;
+ else
+ a->traverse_mount_points = 1;
+ return (r);
+}
+
/*
* Trivial implementations of gname/uname lookup functions.
* These are normally overridden by the client, but these stub
@@ -557,71 +549,92 @@ trivial_lookup_uname(void *private_data, int64_t uid)
return (NULL);
}
+static int64_t
+align_num_per_sector(struct tree *t, int64_t size)
+{
+ int64_t surplus;
+
+ size += t->current_filesystem->bytesPerSector -1;
+ surplus = size % t->current_filesystem->bytesPerSector;
+ size -= surplus;
+ return (size);
+}
+
static int
-_archive_read_data_block(struct archive *_a, const void **buff,
- size_t *size, int64_t *offset)
+start_next_async_read(struct archive_read_disk *a, struct tree *t)
{
- struct archive_read_disk *a = (struct archive_read_disk *)_a;
- struct tree *t = a->tree;
- int r;
- int64_t bytes;
- size_t buffbytes;
+ struct la_overlapped *olp;
+ DWORD buffbytes, rbytes;
- archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
- "archive_read_data_block");
+ if (t->ol_remaining_bytes == 0)
+ return (ARCHIVE_EOF);
- if (t->entry_eof || t->entry_remaining_bytes <= 0) {
- r = ARCHIVE_EOF;
- goto abort_read_data;
- }
+ olp = &(t->ol[t->ol_idx_doing]);
+ t->ol_idx_doing = (t->ol_idx_doing + 1) % MAX_OVERLAPPED;
/* Allocate read buffer. */
- if (t->entry_buff == NULL) {
- t->entry_buff = malloc(1024 * 64);
- if (t->entry_buff == NULL) {
+ if (olp->buff == NULL) {
+ void *p;
+ size_t s = (size_t)align_num_per_sector(t, BUFFER_SIZE);
+ p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE);
+ if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Couldn't allocate memory");
- r = ARCHIVE_FATAL;
a->archive.state = ARCHIVE_STATE_FATAL;
- goto abort_read_data;
+ return (ARCHIVE_FATAL);
}
- t->entry_buff_size = 1024 * 64;
- }
+ olp->buff = p;
+ olp->buff_size = s;
+ olp->_a = &a->archive;
+ olp->ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+ if (olp->ol.hEvent == NULL) {
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
+ "CreateEvent failed");
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
+ } else
+ ResetEvent(olp->ol.hEvent);
- buffbytes = t->entry_buff_size;
+ buffbytes = (DWORD)olp->buff_size;
if (buffbytes > t->current_sparse->length)
- buffbytes = t->current_sparse->length;
+ buffbytes = (DWORD)t->current_sparse->length;
- /*
- * Skip hole.
- */
- if (t->current_sparse->offset > t->entry_total) {
- LARGE_INTEGER distance;
- distance.QuadPart = t->current_sparse->offset;
- if (!SetFilePointerEx_perso(t->entry_fh, distance, NULL, FILE_BEGIN)) {
- DWORD lasterr;
-
- lasterr = GetLastError();
- if (lasterr == ERROR_ACCESS_DENIED)
- errno = EBADF;
- else
- la_dosmaperr(lasterr);
- archive_set_error(&a->archive, errno, "Seek error");
- r = ARCHIVE_FATAL;
- a->archive.state = ARCHIVE_STATE_FATAL;
- goto abort_read_data;
- }
- bytes = t->current_sparse->offset - t->entry_total;
- t->entry_remaining_bytes -= bytes;
- t->entry_total += bytes;
+ /* Skip hole. */
+ if (t->current_sparse->offset > t->ol_total) {
+ t->ol_remaining_bytes -=
+ t->current_sparse->offset - t->ol_total;
+ }
+
+ olp->offset = t->current_sparse->offset;
+ olp->ol.Offset = (DWORD)(olp->offset & 0xffffffff);
+ olp->ol.OffsetHigh = (DWORD)(olp->offset >> 32);
+
+ if (t->ol_remaining_bytes > buffbytes) {
+ olp->bytes_expected = buffbytes;
+ t->ol_remaining_bytes -= buffbytes;
+ } else {
+ olp->bytes_expected = (size_t)t->ol_remaining_bytes;
+ t->ol_remaining_bytes = 0;
}
- if (buffbytes > 0) {
- DWORD bytes_read;
- if (!ReadFile(t->entry_fh, t->entry_buff,
- (uint32_t)buffbytes, &bytes_read, NULL)) {
- DWORD lasterr;
+ olp->bytes_transferred = 0;
+ t->current_sparse->offset += buffbytes;
+ t->current_sparse->length -= buffbytes;
+ t->ol_total = t->current_sparse->offset;
+ if (t->current_sparse->length == 0 && t->ol_remaining_bytes > 0)
+ t->current_sparse++;
- lasterr = GetLastError();
+ if (!ReadFile(t->entry_fh, olp->buff, buffbytes, &rbytes, &(olp->ol))) {
+ DWORD lasterr;
+
+ lasterr = GetLastError();
+ if (lasterr == ERROR_HANDLE_EOF) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Reading file truncated");
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ } else if (lasterr != ERROR_IO_PENDING) {
if (lasterr == ERROR_NO_DATA)
errno = EAGAIN;
else if (lasterr == ERROR_ACCESS_DENIED)
@@ -629,34 +642,96 @@ _archive_read_data_block(struct archive *_a, const void **buff,
else
la_dosmaperr(lasterr);
archive_set_error(&a->archive, errno, "Read error");
- r = ARCHIVE_FATAL;
a->archive.state = ARCHIVE_STATE_FATAL;
- goto abort_read_data;
+ return (ARCHIVE_FATAL);
}
- bytes = bytes_read;
} else
- bytes = 0;
- if (bytes == 0) {
- /* Get EOF */
- t->entry_eof = 1;
+ olp->bytes_transferred = rbytes;
+ t->ol_num_doing++;
+
+ return (t->ol_remaining_bytes == 0)? ARCHIVE_EOF: ARCHIVE_OK;
+}
+
+static void
+cancel_async(struct tree *t)
+{
+ if (t->ol_num_doing != t->ol_num_done) {
+ CancelIo(t->entry_fh);
+ t->ol_num_doing = t->ol_num_done = 0;
+ }
+}
+
+static int
+_archive_read_data_block(struct archive *_a, const void **buff,
+ size_t *size, int64_t *offset)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ struct tree *t = a->tree;
+ struct la_overlapped *olp;
+ DWORD bytes_transferred;
+ int r = ARCHIVE_FATAL;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
+ "archive_read_data_block");
+
+ if (t->entry_eof || t->entry_remaining_bytes <= 0) {
r = ARCHIVE_EOF;
goto abort_read_data;
}
- *buff = t->entry_buff;
- *size = bytes;
- *offset = t->entry_total;
- t->entry_total += bytes;
- t->entry_remaining_bytes -= bytes;
+
+ /*
+ * Make a request to read the file in asynchronous.
+ */
+ if (t->ol_num_doing == 0) {
+ do {
+ r = start_next_async_read(a, t);
+ if (r == ARCHIVE_FATAL)
+ goto abort_read_data;
+ if (!t->async_io)
+ break;
+ } while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED);
+ } else {
+ if (start_next_async_read(a, t) == ARCHIVE_FATAL)
+ goto abort_read_data;
+ }
+
+ olp = &(t->ol[t->ol_idx_done]);
+ t->ol_idx_done = (t->ol_idx_done + 1) % MAX_OVERLAPPED;
+ if (olp->bytes_transferred)
+ bytes_transferred = (DWORD)olp->bytes_transferred;
+ else if (!GetOverlappedResult(t->entry_fh, &(olp->ol),
+ &bytes_transferred, TRUE)) {
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
+ "GetOverlappedResult failed");
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ r = ARCHIVE_FATAL;
+ goto abort_read_data;
+ }
+ t->ol_num_done++;
+
+ if (bytes_transferred == 0 ||
+ olp->bytes_expected != bytes_transferred) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Reading file truncated");
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ r = ARCHIVE_FATAL;
+ goto abort_read_data;
+ }
+
+ *buff = olp->buff;
+ *size = bytes_transferred;
+ *offset = olp->offset;
+ if (olp->offset > t->entry_total)
+ t->entry_remaining_bytes -= olp->offset - t->entry_total;
+ t->entry_total = olp->offset + *size;
+ t->entry_remaining_bytes -= *size;
if (t->entry_remaining_bytes == 0) {
/* Close the current file descriptor */
close_and_restore_time(t->entry_fh, t, &t->restore_time);
t->entry_fh = INVALID_HANDLE_VALUE;
t->entry_eof = 1;
}
- t->current_sparse->offset += bytes;
- t->current_sparse->length -= bytes;
- if (t->current_sparse->length == 0 && !t->entry_eof)
- t->current_sparse++;
return (ARCHIVE_OK);
abort_read_data:
@@ -664,6 +739,7 @@ abort_read_data:
*size = 0;
*offset = t->entry_total;
if (t->entry_fh != INVALID_HANDLE_VALUE) {
+ cancel_async(t);
/* Close the current file descriptor */
close_and_restore_time(t->entry_fh, t, &t->restore_time);
t->entry_fh = INVALID_HANDLE_VALUE;
@@ -672,26 +748,17 @@ abort_read_data:
}
static int
-_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
+next_entry(struct archive_read_disk *a, struct tree *t,
+ struct archive_entry *entry)
{
- struct archive_read_disk *a = (struct archive_read_disk *)_a;
- struct tree *t;
const BY_HANDLE_FILE_INFORMATION *st;
const BY_HANDLE_FILE_INFORMATION *lst;
const char*name;
int descend, r;
- archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
- ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
- "archive_read_next_header2");
-
- t = a->tree;
- if (t->entry_fh != INVALID_HANDLE_VALUE) {
- close_and_restore_time(t->entry_fh, t, &t->restore_time);
- t->entry_fh = INVALID_HANDLE_VALUE;
- }
st = NULL;
lst = NULL;
+ t->descend = 0;
do {
switch (tree_next(t)) {
case TREE_ERROR_FATAL:
@@ -701,7 +768,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
case TREE_ERROR_DIR:
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ archive_set_error(&a->archive, t->tree_errno,
"%ls: Couldn't visit directory",
tree_current_path(t));
return (ARCHIVE_FAILED);
@@ -713,7 +780,7 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
case TREE_REGULAR:
lst = tree_current_lstat(t);
if (lst == NULL) {
- archive_set_error(&a->archive, errno,
+ archive_set_error(&a->archive, t->tree_errno,
"%ls: Cannot stat",
tree_current_path(t));
return (ARCHIVE_FAILED);
@@ -722,6 +789,26 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
}
} while (lst == NULL);
+ archive_entry_copy_pathname_w(entry, tree_current_path(t));
+
+ /*
+ * Perform path matching.
+ */
+ if (a->matching) {
+ r = archive_match_path_excluded(a->matching, entry);
+ if (r < 0) {
+ archive_set_error(&(a->archive), errno,
+ "Faild : %s", archive_error_string(a->matching));
+ return (r);
+ }
+ if (r) {
+ if (a->excluded_cb_func)
+ a->excluded_cb_func(&(a->archive),
+ a->excluded_cb_data, entry);
+ return (ARCHIVE_RETRY);
+ }
+ }
+
/*
* Distinguish 'L'/'P'/'H' symlink following.
*/
@@ -759,31 +846,90 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
+ if (t->initial_filesystem_id == -1)
+ t->initial_filesystem_id = t->current_filesystem_id;
+ if (!a->traverse_mount_points) {
+ if (t->initial_filesystem_id != t->current_filesystem_id)
+ return (ARCHIVE_RETRY);
+ }
t->descend = descend;
- archive_entry_copy_pathname_w(entry, tree_current_path(t));
- archive_entry_copy_sourcepath_w(entry, tree_current_access_path(t));
tree_archive_entry_copy_bhfi(entry, t, st);
- /* Save the times to be restored. */
+ /* Save the times to be restored. This must be in before
+ * calling archive_read_disk_descend() or any chance of it,
+ * especially, invokng a callback. */
t->restore_time.lastWriteTime = st->ftLastWriteTime;
t->restore_time.lastAccessTime = st->ftLastAccessTime;
t->restore_time.filetype = archive_entry_filetype(entry);
+ /*
+ * Perform time matching.
+ */
+ if (a->matching) {
+ r = archive_match_time_excluded(a->matching, entry);
+ if (r < 0) {
+ archive_set_error(&(a->archive), errno,
+ "Faild : %s", archive_error_string(a->matching));
+ return (r);
+ }
+ if (r) {
+ if (a->excluded_cb_func)
+ a->excluded_cb_func(&(a->archive),
+ a->excluded_cb_data, entry);
+ return (ARCHIVE_RETRY);
+ }
+ }
+
/* Lookup uname/gname */
- name = archive_read_disk_uname(_a, archive_entry_uid(entry));
+ name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry));
if (name != NULL)
archive_entry_copy_uname(entry, name);
- name = archive_read_disk_gname(_a, archive_entry_gid(entry));
+ name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry));
if (name != NULL)
archive_entry_copy_gname(entry, name);
+ /*
+ * Perform owner matching.
+ */
+ if (a->matching) {
+ r = archive_match_owner_excluded(a->matching, entry);
+ if (r < 0) {
+ archive_set_error(&(a->archive), errno,
+ "Faild : %s", archive_error_string(a->matching));
+ return (r);
+ }
+ if (r) {
+ if (a->excluded_cb_func)
+ a->excluded_cb_func(&(a->archive),
+ a->excluded_cb_data, entry);
+ return (ARCHIVE_RETRY);
+ }
+ }
+
+ /*
+ * Invoke a meta data filter callback.
+ */
+ if (a->metadata_filter_func) {
+ if (!a->metadata_filter_func(&(a->archive),
+ a->metadata_filter_data, entry))
+ return (ARCHIVE_RETRY);
+ }
+
+ archive_entry_copy_sourcepath_w(entry, tree_current_access_path(t));
+
r = ARCHIVE_OK;
if (archive_entry_filetype(entry) == AE_IFREG &&
archive_entry_size(entry) > 0) {
+ DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
+ if (t->async_io)
+ flags |= FILE_FLAG_OVERLAPPED;
+ if (t->direct_io)
+ flags |= FILE_FLAG_NO_BUFFERING;
+ else
+ flags |= FILE_FLAG_SEQUENTIAL_SCAN;
t->entry_fh = CreateFileW(tree_current_access_path(t),
- GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+ GENERIC_READ, 0, NULL, OPEN_EXISTING, flags, NULL);
if (t->entry_fh == INVALID_HANDLE_VALUE) {
archive_set_error(&a->archive, errno,
"Couldn't open %ls", tree_current_path(a->tree));
@@ -795,6 +941,29 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
(st->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0)
r = setup_sparse_from_disk(a, entry, t->entry_fh);
}
+ return (r);
+}
+
+static int
+_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ struct tree *t;
+ int r;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+ "archive_read_next_header2");
+
+ t = a->tree;
+ if (t->entry_fh != INVALID_HANDLE_VALUE) {
+ cancel_async(t);
+ close_and_restore_time(t->entry_fh, t, &t->restore_time);
+ t->entry_fh = INVALID_HANDLE_VALUE;
+ }
+
+ while ((r = next_entry(a, t, entry)) == ARCHIVE_RETRY)
+ archive_entry_clear(entry);
/*
* EOF and FATAL are persistent at this layer. By
@@ -818,6 +987,10 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
t->entry_remaining_bytes = 0;
t->entry_eof = 1;
}
+ t->ol_idx_doing = t->ol_idx_done = 0;
+ t->ol_num_doing = t->ol_num_done = 0;
+ t->ol_remaining_bytes = t->entry_remaining_bytes;
+ t->ol_total = 0;
a->archive.state = ARCHIVE_STATE_DATA;
break;
case ARCHIVE_RETRY:
@@ -834,7 +1007,7 @@ static int
setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
{
struct tree *t = a->tree;
- int64_t length, offset;
+ int64_t aligned, length, offset;
int i;
t->sparse_count = archive_entry_sparse_reset(entry);
@@ -851,23 +1024,101 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
return (ARCHIVE_FATAL);
}
}
+ /*
+ * Get sparse list and make sure those offsets and lengths are
+ * aligned by a sector size.
+ */
for (i = 0; i < t->sparse_count; i++) {
archive_entry_sparse_next(entry, &offset, &length);
- t->sparse_list[i].offset = offset;
- t->sparse_list[i].length = length;
+ aligned = align_num_per_sector(t, offset);
+ if (aligned != offset) {
+ aligned -= t->current_filesystem->bytesPerSector;
+ length += offset - aligned;
+ }
+ t->sparse_list[i].offset = aligned;
+ aligned = align_num_per_sector(t, length);
+ t->sparse_list[i].length = aligned;
}
+
+ aligned = align_num_per_sector(t, archive_entry_size(entry));
if (i == 0) {
t->sparse_list[i].offset = 0;
- t->sparse_list[i].length = archive_entry_size(entry);
+ t->sparse_list[i].length = aligned;
} else {
- t->sparse_list[i].offset = archive_entry_size(entry);
+ int j, last = i;
+
+ t->sparse_list[i].offset = aligned;
t->sparse_list[i].length = 0;
+ for (i = 0; i < last; i++) {
+ if ((t->sparse_list[i].offset +
+ t->sparse_list[i].length) <=
+ t->sparse_list[i+1].offset)
+ continue;
+ /*
+ * Now sparse_list[i+1] is overlapped by sparse_list[i].
+ * Merge those two.
+ */
+ length = t->sparse_list[i+1].offset -
+ t->sparse_list[i].offset;
+ t->sparse_list[i+1].offset = t->sparse_list[i].offset;
+ t->sparse_list[i+1].length += length;
+ /* Remove sparse_list[i]. */
+ for (j = i; j < last; j++) {
+ t->sparse_list[j].offset =
+ t->sparse_list[j+1].offset;
+ t->sparse_list[j].length =
+ t->sparse_list[j+1].length;
+ }
+ last--;
+ }
}
t->current_sparse = t->sparse_list;
return (ARCHIVE_OK);
}
+int
+archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
+ void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
+ void *_client_data)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
+ a->matching = _ma;
+ a->excluded_cb_func = _excluded_func;
+ a->excluded_cb_data = _client_data;
+ return (ARCHIVE_OK);
+}
+
+int
+archive_read_disk_set_metadata_filter_callback(struct archive *_a,
+ int (*_metadata_filter_func)(struct archive *, void *,
+ struct archive_entry *), void *_client_data)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
+ "archive_read_disk_set_metadata_filter_callback");
+
+ a->metadata_filter_func = _metadata_filter_func;
+ a->metadata_filter_data = _client_data;
+ return (ARCHIVE_OK);
+}
+
+int
+archive_read_disk_can_descend(struct archive *_a)
+{
+ struct archive_read_disk *a = (struct archive_read_disk *)_a;
+ struct tree *t = a->tree;
+
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+ "archive_read_disk_can_descend");
+
+ return (t->visit_type == TREE_REGULAR && t->descend);
+}
+
/*
* Called by the client to mark the directory just returned from
* tree_next() as needing to be visited.
@@ -878,14 +1129,12 @@ archive_read_disk_descend(struct archive *_a)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
struct tree *t = a->tree;
- archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
+ archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_read_disk_descend");
- if (t->visit_type != TREE_REGULAR || !t->descend) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Ignored the request descending the current object");
- return (ARCHIVE_WARN);
- }
+ if (t->visit_type != TREE_REGULAR || !t->descend)
+ return (ARCHIVE_OK);
if (tree_current_is_physical_dir(t)) {
tree_push(t, t->basename, t->full_path.s,
@@ -920,8 +1169,12 @@ archive_read_disk_open(struct archive *_a, const char *pathname)
archive_string_init(&wpath);
if (archive_wstring_append_from_mbs(&wpath, pathname,
strlen(pathname)) != 0) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Can't convert a path to a wchar_t string");
+ if (errno == ENOMEM)
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory");
+ else
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Can't convert a path to a wchar_t string");
a->archive.state = ARCHIVE_STATE_FATAL;
ret = ARCHIVE_FATAL;
} else
@@ -1004,16 +1257,18 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
fid = t->max_filesystem_id++;
if (t->max_filesystem_id > t->allocated_filesytem) {
size_t s;
+ void *p;
s = t->max_filesystem_id * 2;
- t->filesystem_table = realloc(t->filesystem_table,
- s * sizeof(*t->filesystem_table));
- if (t->filesystem_table == NULL) {
+ p = realloc(t->filesystem_table,
+ s * sizeof(*t->filesystem_table));
+ if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
return (ARCHIVE_FATAL);
}
- t->allocated_filesytem = s;
+ t->filesystem_table = (struct filesystem *)p;
+ t->allocated_filesytem = (int)s;
}
t->current_filesystem_id = fid;
t->current_filesystem = &(t->filesystem_table[fid]);
@@ -1091,6 +1346,7 @@ setup_current_filesystem(struct archive_read_disk *a)
if (!GetVolumePathNameW(path, vol, sizeof(vol)/sizeof(vol[0]))) {
free(path);
t->current_filesystem->remote = -1;
+ t->current_filesystem->bytesPerSector = 0;
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"GetVolumePathName failed: %d", (int)GetLastError());
return (ARCHIVE_FAILED);
@@ -1109,6 +1365,14 @@ setup_current_filesystem(struct archive_read_disk *a)
break;
}
+ if (!GetDiskFreeSpaceW(vol, NULL,
+ &(t->current_filesystem->bytesPerSector), NULL, NULL)) {
+ t->current_filesystem->bytesPerSector = 0;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "GetDiskFreeSpace failed: %d", (int)GetLastError());
+ return (ARCHIVE_FAILED);
+ }
+
return (ARCHIVE_OK);
}
@@ -1249,13 +1513,14 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
t->depth = 0;
t->descend = 0;
t->current = NULL;
- t->d = INVALID_DIR_HANDLE;
+ t->d = INVALID_HANDLE_VALUE;
t->symlink_mode = t->initial_symlink_mode;
archive_string_empty(&(t->full_path));
archive_string_empty(&t->path);
t->entry_fh = INVALID_HANDLE_VALUE;
t->entry_eof = 0;
t->entry_remaining_bytes = 0;
+ t->initial_filesystem_id = -1;
/* Get wchar_t strings from char strings. */
archive_string_init(&ws);
@@ -1277,8 +1542,12 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
/* First item is set up a lot like a symlink traversal. */
/* printf("Looking for wildcard in %s\n", path); */
- /* TODO: wildcard detection here screws up on \\?\c:\ UNC names */
- if (wcschr(base, L'*') || wcschr(base, L'?')) {
+ if ((base[0] == L'/' && base[1] == L'/' &&
+ base[2] == L'?' && base[3] == L'/' &&
+ (wcschr(base+4, L'*') || wcschr(base+4, L'?'))) ||
+ (!(base[0] == L'/' && base[1] == L'/' &&
+ base[2] == L'?' && base[3] == L'/') &&
+ (wcschr(base, L'*') || wcschr(base, L'?')))) {
// It has a wildcard in it...
// Separate the last element.
p = wcsrchr(base, L'/');
@@ -1298,6 +1567,32 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
tree_push(t, base, t->full_path.s, 0, 0, 0, NULL);
archive_wstring_free(&ws);
t->stack->flags = needsFirstVisit;
+ /*
+ * Debug flag for Direct IO(No buffering) or Async IO.
+ * Those dependant on environment variable switches
+ * will be removed until next release.
+ */
+ {
+ const char *e;
+ if ((e = getenv("LIBARCHIVE_DIRECT_IO")) != NULL) {
+ if (e[0] == '0')
+ t->direct_io = 0;
+ else
+ t->direct_io = 1;
+ fprintf(stderr, "LIBARCHIVE_DIRECT_IO=%s\n",
+ (t->direct_io)?"Enabled":"Disabled");
+ } else
+ t->direct_io = DIRECT_IO;
+ if ((e = getenv("LIBARCHIVE_ASYNC_IO")) != NULL) {
+ if (e[0] == '0')
+ t->async_io = 0;
+ else
+ t->async_io = 1;
+ fprintf(stderr, "LIBARCHIVE_ASYNC_IO=%s\n",
+ (t->async_io)?"Enabled":"Disabled");
+ } else
+ t->async_io = ASYNC_IO;
+ }
return (t);
failed:
archive_wstring_free(&ws);
@@ -1324,7 +1619,7 @@ tree_ascend(struct tree *t)
te = t->stack;
t->depth--;
- close_and_restore_time(INVALID_DIR_HANDLE, t, &te->restore_time);
+ close_and_restore_time(INVALID_HANDLE_VALUE, t, &te->restore_time);
return (0);
}
@@ -1364,7 +1659,7 @@ tree_next(struct tree *t)
while (t->stack != NULL) {
/* If there's an open dir, get the next entry from there. */
- if (t->d != INVALID_DIR_HANDLE) {
+ if (t->d != INVALID_HANDLE_VALUE) {
r = tree_dir_next_windows(t, NULL);
if (r == 0)
continue;
@@ -1374,14 +1669,17 @@ tree_next(struct tree *t)
if (t->stack->flags & needsFirstVisit) {
wchar_t *d = t->stack->name.s;
t->stack->flags &= ~needsFirstVisit;
- if (wcschr(d, L'*') || wcschr(d, L'?')) {
+ if (!(d[0] == L'/' && d[1] == L'/' &&
+ d[2] == L'?' && d[3] == L'/') &&
+ (wcschr(d, L'*') || wcschr(d, L'?'))) {
r = tree_dir_next_windows(t, d);
if (r == 0)
continue;
return (r);
} else {
HANDLE h = FindFirstFileW(d, &t->_findData);
- if (h == INVALID_DIR_HANDLE) {
+ if (h == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
t->tree_errno = errno;
t->visit_type = TREE_ERROR_DIR;
return (t->visit_type);
@@ -1452,10 +1750,11 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
archive_wstrcat(&pt, pattern);
t->d = FindFirstFileW(pt.s, &t->_findData);
archive_wstring_free(&pt);
- if (t->d == INVALID_DIR_HANDLE) {
+ if (t->d == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
+ t->tree_errno = errno;
r = tree_ascend(t); /* Undo "chdir" */
tree_pop(t);
- t->tree_errno = errno;
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
return (t->visit_type);
}
@@ -1463,7 +1762,7 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
pattern = NULL;
} else if (!FindNextFileW(t->d, &t->_findData)) {
FindClose(t->d);
- t->d = INVALID_DIR_HANDLE;
+ t->d = INVALID_HANDLE_VALUE;
t->findData = NULL;
return (0);
}
@@ -1482,7 +1781,7 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
static void
-fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
+fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
{
ULARGE_INTEGER utc;
@@ -1491,11 +1790,11 @@ fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
/* milli seconds base */
- *time = (time_t)(utc.QuadPart / 10000000);
+ *t = (time_t)(utc.QuadPart / 10000000);
/* nano seconds base */
*ns = (long)(utc.QuadPart % 10000000) * 100;
} else {
- *time = 0;
+ *t = 0;
*ns = 0;
}
}
@@ -1589,8 +1888,11 @@ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st,
flag |= FILE_FLAG_OPEN_REPARSE_POINT;
h = CreateFileW(tree_current_access_path(t), 0, 0, NULL,
OPEN_EXISTING, flag, NULL);
- if (h == INVALID_HANDLE_VALUE)
+ if (h == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
+ t->tree_errno = errno;
return (0);
+ }
r = GetFileInformationByHandle(h, st);
CloseHandle(h);
return (r);
@@ -1709,13 +2011,14 @@ tree_close(struct tree *t)
if (t == NULL)
return;
if (t->entry_fh != INVALID_HANDLE_VALUE) {
+ cancel_async(t);
close_and_restore_time(t->entry_fh, t, &t->restore_time);
t->entry_fh = INVALID_HANDLE_VALUE;
}
/* Close the handle of FindFirstFileW */
- if (t->d != INVALID_DIR_HANDLE) {
+ if (t->d != INVALID_HANDLE_VALUE) {
FindClose(t->d);
- t->d = INVALID_DIR_HANDLE;
+ t->d = INVALID_HANDLE_VALUE;
t->findData = NULL;
}
/* Release anything remaining in the stack. */
@@ -1729,13 +2032,19 @@ tree_close(struct tree *t)
static void
tree_free(struct tree *t)
{
+ int i;
+
if (t == NULL)
return;
archive_wstring_free(&t->path);
archive_wstring_free(&t->full_path);
free(t->sparse_list);
free(t->filesystem_table);
- free(t->entry_buff);
+ for (i = 0; i < MAX_OVERLAPPED; i++) {
+ if (t->ol[i].buff)
+ VirtualFree(t->ol[i].buff, 0, MEM_RELEASE);
+ CloseHandle(t->ol[i].ol.hEvent);
+ }
free(t);
}
@@ -1775,7 +2084,8 @@ archive_read_disk_entry_from_file(struct archive *_a,
h = (HANDLE)_get_osfhandle(fd);
r = GetFileInformationByHandle(h, &bhfi);
if (r == 0) {
- archive_set_error(&a->archive, GetLastError(),
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
"Can't GetFileInformationByHandle");
return (ARCHIVE_FAILED);
}
@@ -1785,8 +2095,9 @@ archive_read_disk_entry_from_file(struct archive *_a,
DWORD flag, desiredAccess;
h = FindFirstFileW(path, &findData);
- if (h == INVALID_DIR_HANDLE) {
- archive_set_error(&a->archive, GetLastError(),
+ if (h == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
"Can't FindFirstFileW");
return (ARCHIVE_FAILED);
}
@@ -1807,15 +2118,15 @@ archive_read_disk_entry_from_file(struct archive *_a,
h = CreateFileW(path, desiredAccess, 0, NULL,
OPEN_EXISTING, flag, NULL);
if (h == INVALID_HANDLE_VALUE) {
- archive_set_error(&a->archive,
- GetLastError(),
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
"Can't CreateFileW");
return (ARCHIVE_FAILED);
}
r = GetFileInformationByHandle(h, &bhfi);
if (r == 0) {
- archive_set_error(&a->archive,
- GetLastError(),
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
"Can't GetFileInformationByHandle");
CloseHandle(h);
return (ARCHIVE_FAILED);
@@ -1825,7 +2136,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
fileAttributes = bhfi.dwFileAttributes;
} else {
archive_entry_copy_stat(entry, st);
- h = INVALID_DIR_HANDLE;
+ h = INVALID_HANDLE_VALUE;
}
/* Lookup uname/gname */
@@ -1854,14 +2165,16 @@ archive_read_disk_entry_from_file(struct archive *_a,
h = CreateFileW(path, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
- archive_set_error(&a->archive, GetLastError(),
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
"Can't CreateFileW");
return (ARCHIVE_FAILED);
}
}
r = GetFileInformationByHandle(h, &bhfi);
if (r == 0) {
- archive_set_error(&a->archive, GetLastError(),
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
"Can't GetFileInformationByHandle");
if (h != INVALID_HANDLE_VALUE && fd < 0)
CloseHandle(h);
@@ -1909,7 +2222,7 @@ setup_sparse_from_disk(struct archive_read_disk *a,
outranges_size = 2048;
outranges = (FILE_ALLOCATED_RANGE_BUFFER *)malloc(outranges_size);
if (outranges == NULL) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ archive_set_error(&a->archive, ENOMEM,
"Couldn't allocate memory");
exit_sts = ARCHIVE_FATAL;
goto exit_setup_sparse;
@@ -1923,15 +2236,14 @@ setup_sparse_from_disk(struct archive_read_disk *a,
ret = DeviceIoControl(handle,
FSCTL_QUERY_ALLOCATED_RANGES,
&range, sizeof(range), outranges,
- outranges_size, &retbytes, NULL);
+ (DWORD)outranges_size, &retbytes, NULL);
if (ret == 0 && GetLastError() == ERROR_MORE_DATA) {
free(outranges);
outranges_size *= 2;
outranges = (FILE_ALLOCATED_RANGE_BUFFER *)
malloc(outranges_size);
if (outranges == NULL) {
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
+ archive_set_error(&a->archive, ENOMEM,
"Couldn't allocate memory");
exit_sts = ARCHIVE_FATAL;
goto exit_setup_sparse;
@@ -1968,7 +2280,8 @@ setup_sparse_from_disk(struct archive_read_disk *a,
}
break;
} else {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
"DeviceIoControl Failed: %lu", GetLastError());
exit_sts = ARCHIVE_FAILED;
goto exit_setup_sparse;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_extract.3 b/Utilities/cmlibarchive/libarchive/archive_read_extract.3
index 882c6e1..6ec0ced 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_extract.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_extract.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 22, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ_EXTRACT 3
.Os
.Sh NAME
@@ -32,6 +32,8 @@
.Nm archive_read_extract2 ,
.Nm archive_read_extract_set_progress_callback
.Nd functions for reading streaming archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_extract.c b/Utilities/cmlibarchive/libarchive/archive_read_extract.c
index aad8ac5..795f2ab 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_extract.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_extract.c
@@ -154,7 +154,7 @@ copy_data(struct archive *ar, struct archive *aw)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
- r = archive_write_data_block(aw, buff, size, offset);
+ r = (int)archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_WARN)
r = ARCHIVE_WARN;
if (r != ARCHIVE_OK) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_filter.3 b/Utilities/cmlibarchive/libarchive/archive_read_filter.3
index 1cfa215..8761127 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_filter.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_filter.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 19, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ_FILTER 3
.Os
.Sh NAME
@@ -39,6 +39,8 @@
.Nm archive_read_support_filter_program_signature
.Nd functions for reading streaming archives
.\"
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_format.3 b/Utilities/cmlibarchive/libarchive/archive_read_format.3
index e707e05..53b9a7e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_format.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_format.3
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 19, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ_FORMAT 3
.Os
.Sh NAME
@@ -45,6 +45,8 @@
.Nm archive_read_support_format_zip
.Nd functions for reading streaming archives
.\"
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_free.3 b/Utilities/cmlibarchive/libarchive/archive_read_free.3
index f5f2515..5b21822 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_free.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_free.3
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 20, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ_FREE 3
.Os
.Sh NAME
@@ -32,6 +32,8 @@
.Nm archive_read_finish ,
.Nm archive_read_free
.Nd functions for reading streaming archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_header.3 b/Utilities/cmlibarchive/libarchive/archive_read_header.3
index 999e963..480a666 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_header.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_header.3
@@ -24,13 +24,15 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 22, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ_HEADER 3
.Os
.Sh NAME
.Nm archive_read_next_header ,
.Nm archive_read_next_header2
.Nd functions for reading streaming archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_new.3 b/Utilities/cmlibarchive/libarchive/archive_read_new.3
index e04406a..0c9d1a7 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_new.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_new.3
@@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 20, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ_NEW 3
.Os
.Sh NAME
.Nm archive_read_new
.Nd functions for reading streaming archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open.3 b/Utilities/cmlibarchive/libarchive/archive_read_open.3
index 09c0575..30a740b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open.3
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 19, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_READ_OPEN 3
.Os
.Sh NAME
@@ -35,6 +35,8 @@
.Nm archive_read_open_filename ,
.Nm archive_read_open_memory ,
.Nd functions for reading streaming archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_fd.c b/Utilities/cmlibarchive/libarchive/archive_read_open_fd.c
index d8f6572..e0f95bf 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_fd.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_fd.c
@@ -119,7 +119,8 @@ file_read(struct archive *a, void *client_data, const void **buff)
if (bytes_read < 0) {
if (errno == EINTR)
continue;
- archive_set_error(a, errno, "Error reading fd %d", mine->fd);
+ archive_set_error(a, errno, "Error reading fd %d",
+ mine->fd);
}
return (bytes_read);
}
@@ -129,8 +130,8 @@ static int64_t
file_skip(struct archive *a, void *client_data, int64_t request)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
- off_t skip = (off_t)request;
- off_t old_offset, new_offset;
+ int64_t skip = request;
+ int64_t old_offset, new_offset;
int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
if (!mine->use_lseek)
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_file.c b/Utilities/cmlibarchive/libarchive/archive_read_open_file.c
index b1aac0a..3a33c25 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_file.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_file.c
@@ -108,11 +108,11 @@ static ssize_t
file_read(struct archive *a, void *client_data, const void **buff)
{
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
- ssize_t bytes_read;
+ size_t bytes_read;
*buff = mine->buffer;
bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f);
- if (bytes_read < 0) {
+ if (bytes_read < mine->block_size && ferror(mine->f)) {
archive_set_error(a, errno, "Error reading file");
}
return (bytes_read);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
index bf52697..622c960 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
@@ -60,11 +60,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_filename.c 201093 2009
#endif
#include "archive.h"
+#include "archive_private.h"
#include "archive_string.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
struct read_file_data {
int fd;
@@ -79,9 +83,10 @@ struct read_file_data {
} filename; /* Must be last! */
};
+static int file_open(struct archive *, void *);
static int file_close(struct archive *, void *);
-static int file_open_filename(struct archive *, enum fnt_e, const void *,
- size_t);
+static int file_close2(struct archive *, void *);
+static int file_switch(struct archive *, void *, void *);
static ssize_t file_read(struct archive *, void *, const void **buff);
static int64_t file_seek(struct archive *, void *, int64_t request, int);
static int64_t file_skip(struct archive *, void *, int64_t request);
@@ -98,26 +103,78 @@ int
archive_read_open_filename(struct archive *a, const char *filename,
size_t block_size)
{
- enum fnt_e filename_type;
+ const char *filenames[2];
+ filenames[0] = filename;
+ filenames[1] = NULL;
+ return archive_read_open_filenames(a, filenames, block_size);
+}
+
+int
+archive_read_open_filenames(struct archive *a, const char **filenames,
+ size_t block_size)
+{
+ struct read_file_data *mine;
+ const char *filename = NULL;
+ if (filenames)
+ filename = *(filenames++);
+
+ archive_clear_error(a);
+ do
+ {
+ if (filename == NULL)
+ filename = "";
+ mine = (struct read_file_data *)calloc(1,
+ sizeof(*mine) + strlen(filename));
+ if (mine == NULL)
+ goto no_memory;
+ strcpy(mine->filename.m, filename);
+ mine->block_size = block_size;
+ mine->fd = -1;
+ mine->buffer = NULL;
+ mine->st_mode = mine->use_lseek = 0;
+ if (filename == NULL || filename[0] == '\0') {
+ mine->filename_type = FNT_STDIN;
+ } else
+ mine->filename_type = FNT_MBS;
+ if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
+ return (ARCHIVE_FATAL);
+ if (filenames == NULL)
+ break;
+ filename = *(filenames++);
+ } while (filename != NULL && filename[0] != '\0');
+ archive_read_set_open_callback(a, file_open);
+ archive_read_set_read_callback(a, file_read);
+ archive_read_set_skip_callback(a, file_skip);
+ archive_read_set_close_callback(a, file_close);
+ archive_read_set_switch_callback(a, file_switch);
+ archive_read_set_seek_callback(a, file_seek);
- if (filename == NULL || filename[0] == '\0') {
- filename_type = FNT_STDIN;
- } else
- filename_type = FNT_MBS;
- return (file_open_filename(a, filename_type, filename, block_size));
+ return (archive_read_open1(a));
+no_memory:
+ archive_set_error(a, ENOMEM, "No memory");
+ return (ARCHIVE_FATAL);
}
int
archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
size_t block_size)
{
- enum fnt_e filename_type;
+ struct read_file_data *mine = (struct read_file_data *)calloc(1,
+ sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
+ if (!mine)
+ {
+ archive_set_error(a, ENOMEM, "No memory");
+ return (ARCHIVE_FATAL);
+ }
+ mine->fd = -1;
+ mine->block_size = block_size;
if (wfilename == NULL || wfilename[0] == L'\0') {
- filename_type = FNT_STDIN;
+ mine->filename_type = FNT_STDIN;
} else {
#if defined(_WIN32) && !defined(__CYGWIN__)
- filename_type = FNT_WCS;
+ mine->filename_type = FNT_WCS;
+ wcscpy(mine->filename.w, wfilename);
#else
/*
* POSIX system does not support a wchar_t interface for
@@ -125,31 +182,43 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
* filename to multi-byte one and use it.
*/
struct archive_string fn;
- int r;
archive_string_init(&fn);
if (archive_string_append_from_wcs(&fn, wfilename,
wcslen(wfilename)) != 0) {
- archive_set_error(a, EINVAL,
- "Failed to convert a wide-character filename to"
- " a multi-byte filename");
+ if (errno == ENOMEM)
+ archive_set_error(a, errno,
+ "Can't allocate memory");
+ else
+ archive_set_error(a, EINVAL,
+ "Failed to convert a wide-character"
+ " filename to a multi-byte filename");
archive_string_free(&fn);
+ free(mine);
return (ARCHIVE_FATAL);
}
- r = file_open_filename(a, FNT_MBS, fn.s, block_size);
+ mine->filename_type = FNT_MBS;
+ strcpy(mine->filename.m, fn.s);
archive_string_free(&fn);
- return (r);
#endif
}
- return (file_open_filename(a, filename_type, wfilename, block_size));
+ if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
+ return (ARCHIVE_FATAL);
+ archive_read_set_open_callback(a, file_open);
+ archive_read_set_read_callback(a, file_read);
+ archive_read_set_skip_callback(a, file_skip);
+ archive_read_set_close_callback(a, file_close);
+ archive_read_set_switch_callback(a, file_switch);
+ archive_read_set_seek_callback(a, file_seek);
+
+ return (archive_read_open1(a));
}
static int
-file_open_filename(struct archive *a, enum fnt_e filename_type,
- const void *_filename, size_t block_size)
+file_open(struct archive *a, void *client_data)
{
struct stat st;
- struct read_file_data *mine;
+ struct read_file_data *mine = (struct read_file_data *)client_data;
void *buffer;
const char *filename = NULL;
const wchar_t *wfilename = NULL;
@@ -164,7 +233,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
archive_clear_error(a);
- if (filename_type == FNT_STDIN) {
+ if (mine->filename_type == FNT_STDIN) {
/* We used to delegate stdin support by
* directly calling archive_read_open_fd(a,0,block_size)
* here, but that doesn't (and shouldn't) handle the
@@ -179,9 +248,10 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
setmode(0, O_BINARY);
#endif
filename = "";
- } else if (filename_type == FNT_MBS) {
- filename = (const char *)_filename;
- fd = open(filename, O_RDONLY | O_BINARY);
+ } else if (mine->filename_type == FNT_MBS) {
+ filename = mine->filename.m;
+ fd = open(filename, O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(a, errno,
"Failed to open '%s'", filename);
@@ -189,7 +259,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
}
} else {
#if defined(_WIN32) && !defined(__CYGWIN__)
- wfilename = (const wchar_t *)_filename;
+ wfilename = mine->filename.w;
fd = _wopen(wfilename, O_RDONLY | O_BINARY);
if (fd < 0 && errno == ENOENT) {
wchar_t *fullpath;
@@ -211,7 +281,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
}
if (fstat(fd, &st) != 0) {
- if (filename_type == FNT_WCS)
+ if (mine->filename_type == FNT_WCS)
archive_set_error(a, errno, "Can't stat '%S'",
wfilename);
else
@@ -276,50 +346,32 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
/* TODO: Add an "is_tape_like" variable and appropriate tests. */
- if (filename_type == FNT_WCS)
- mine = (struct read_file_data *)calloc(1,
- sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
- else
- mine = (struct read_file_data *)calloc(1,
- sizeof(*mine) + strlen(filename));
/* Disk-like devices prefer power-of-two block sizes. */
/* Use provided block_size as a guide so users have some control. */
if (is_disk_like) {
size_t new_block_size = 64 * 1024;
- while (new_block_size < block_size
+ while (new_block_size < mine->block_size
&& new_block_size < 64 * 1024 * 1024)
new_block_size *= 2;
- block_size = new_block_size;
+ mine->block_size = new_block_size;
}
- buffer = malloc(block_size);
+ buffer = malloc(mine->block_size);
if (mine == NULL || buffer == NULL) {
archive_set_error(a, ENOMEM, "No memory");
free(mine);
free(buffer);
return (ARCHIVE_FATAL);
}
- if (filename_type == FNT_WCS)
- wcscpy(mine->filename.w, wfilename);
- else
- strcpy(mine->filename.m, filename);
- mine->filename_type = filename_type;
- mine->block_size = block_size;
mine->buffer = buffer;
mine->fd = fd;
/* Remember mode so close can decide whether to flush. */
mine->st_mode = st.st_mode;
/* Disk-like inputs can use lseek(). */
- if (is_disk_like) {
- archive_read_set_seek_callback(a, file_seek);
+ if (is_disk_like)
mine->use_lseek = 1;
- }
- archive_read_set_read_callback(a, file_read);
- archive_read_set_skip_callback(a, file_skip);
- archive_read_set_close_callback(a, file_close);
- archive_read_set_callback_data(a, mine);
- return (archive_read_open1(a));
+ return (ARCHIVE_OK);
}
static ssize_t
@@ -397,9 +449,7 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
/* TODO: Deal with case where off_t isn't 64 bits.
* This shouldn't be a problem on Linux or other POSIX
* systems, since the configuration logic for libarchive
- * tries to obtain a 64-bit off_t. It's still an issue
- * on Windows, though, so it might suffice to just use
- * _lseeki64() on Windows.
+ * tries to obtain a 64-bit off_t.
*/
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
(new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
@@ -450,7 +500,7 @@ static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
- off_t r;
+ int64_t r;
/* We use off_t here because lseek() is declared that way. */
/* See above for notes about when off_t is less than 64 bits. */
@@ -471,7 +521,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
}
static int
-file_close(struct archive *a, void *client_data)
+file_close2(struct archive *a, void *client_data)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
@@ -504,6 +554,23 @@ file_close(struct archive *a, void *client_data)
close(mine->fd);
}
free(mine->buffer);
+ mine->buffer = NULL;
+ mine->fd = -1;
+ return (ARCHIVE_OK);
+}
+
+static int
+file_close(struct archive *a, void *client_data)
+{
+ struct read_file_data *mine = (struct read_file_data *)client_data;
+ file_close2(a, client_data);
free(mine);
return (ARCHIVE_OK);
}
+
+static int
+file_switch(struct archive *a, void *client_data1, void *client_data2)
+{
+ file_close2(a, client_data1);
+ return file_open(a, client_data2);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
index 07940a2..bcc7d6f 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
@@ -149,6 +149,7 @@ memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whenc
{
struct read_memory_data *mine = (struct read_memory_data *)client_data;
+ (void)a; /* UNUSED */
switch (whence) {
case SEEK_SET:
mine->p = mine->start + offset;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_private.h b/Utilities/cmlibarchive/libarchive/archive_read_private.h
index 76d0b91..8a6c859 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_read_private.h
@@ -58,6 +58,8 @@ struct archive_read_filter;
struct archive_read_filter_bidder {
/* Configuration data for the bidder. */
void *data;
+ /* Name of the filter */
+ const char *name;
/* Taste the upstream filter to see if we handle this. */
int (*bid)(struct archive_read_filter_bidder *,
struct archive_read_filter *);
@@ -82,6 +84,8 @@ struct archive_read_filter {
struct archive_read_filter_bidder *bidder; /* My bidder. */
struct archive_read_filter *upstream; /* Who I read from. */
struct archive_read *archive; /* Associated archive. */
+ /* Open a block for reading */
+ int (*open)(struct archive_read_filter *self);
/* Return next block. */
ssize_t (*read)(struct archive_read_filter *, const void **);
/* Skip forward this many bytes. */
@@ -90,6 +94,8 @@ struct archive_read_filter {
int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence);
/* Close (just this filter) and free(self). */
int (*close)(struct archive_read_filter *self);
+ /* Function that handles switching from reading one block to the next/prev */
+ int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
/* My private data. */
void *data;
@@ -118,13 +124,22 @@ struct archive_read_filter {
* transformation filters. This will probably break the API/ABI and
* so should be deferred at least until libarchive 3.0.
*/
+struct archive_read_data_node {
+ int64_t begin_position;
+ int64_t total_size;
+ void *data;
+};
struct archive_read_client {
archive_open_callback *opener;
archive_read_callback *reader;
archive_skip_callback *skipper;
archive_seek_callback *seeker;
archive_close_callback *closer;
- void *data;
+ archive_switch_callback *switcher;
+ unsigned int nodes;
+ unsigned int cursor;
+ int64_t position;
+ struct archive_read_data_node *dataset;
};
struct archive_read {
@@ -134,8 +149,8 @@ struct archive_read {
/* Dev/ino of the archive being read/written. */
int skip_file_set;
- dev_t skip_file_dev;
- ino_t skip_file_ino;
+ int64_t skip_file_dev;
+ int64_t skip_file_ino;
/*
* Used by archive_read_data() to track blocks and copy
@@ -146,18 +161,33 @@ struct archive_read {
int64_t read_data_output_offset;
size_t read_data_remaining;
- /* Callbacks to open/read/write/close client archive stream. */
+ /*
+ * Used by formats/filters to determine the amount of data
+ * requested from a call to archive_read_data(). This is only
+ * useful when the format/filter has seek support.
+ */
+ char read_data_is_posix_read;
+ size_t read_data_requested;
+
+ /* Callbacks to open/read/write/close client archive streams. */
struct archive_read_client client;
/* Registered filter bidders. */
- struct archive_read_filter_bidder bidders[9];
+ struct archive_read_filter_bidder bidders[14];
/* Last filter in chain */
struct archive_read_filter *filter;
+ /* Whether to bypass filter bidding process */
+ int bypass_filter_bidding;
+
/* File offset of beginning of most recently-read header. */
int64_t header_position;
+ /* Nodes and offsets of compressed data block */
+ unsigned int data_start_node;
+ unsigned int data_end_node;
+
/*
* Format detection is mostly the same as compression
* detection, with one significant difference: The bidders
@@ -175,6 +205,7 @@ struct archive_read {
int (*read_header)(struct archive_read *, struct archive_entry *);
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *);
int (*read_data_skip)(struct archive_read *);
+ int64_t (*seek_data)(struct archive_read *, int64_t, int);
int (*cleanup)(struct archive_read *);
} formats[16];
struct archive_format_descriptor *format; /* Active format. */
@@ -194,6 +225,7 @@ int __archive_read_register_format(struct archive_read *a,
int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
+ int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *));
int __archive_read_get_bidder(struct archive_read *a,
@@ -207,4 +239,6 @@ int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
int64_t __archive_read_consume(struct archive_read *, int64_t);
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
int __archive_read_program(struct archive_read_filter *, const char *);
+void __archive_read_free_filters(struct archive_read *);
+int __archive_read_close_filters(struct archive_read *);
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_set_format.c b/Utilities/cmlibarchive/libarchive/archive_read_set_format.c
new file mode 100644
index 0000000..190f436
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_read_set_format.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2003-2012 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+int
+archive_read_set_format(struct archive *_a, int code)
+{
+ int r1, r2, slots, i;
+ char str[10];
+ struct archive_read *a = (struct archive_read *)_a;
+
+ if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK))
+ return r1;
+
+ r1 = r2 = (ARCHIVE_OK);
+ if (a->format)
+ r2 = (ARCHIVE_WARN);
+ switch (code & ARCHIVE_FORMAT_BASE_MASK)
+ {
+ case ARCHIVE_FORMAT_7ZIP:
+ strcpy(str, "7zip");
+ break;
+ case ARCHIVE_FORMAT_AR:
+ strcpy(str, "ar");
+ break;
+ case ARCHIVE_FORMAT_CAB:
+ strcpy(str, "cab");
+ break;
+ case ARCHIVE_FORMAT_CPIO:
+ strcpy(str, "cpio");
+ break;
+ case ARCHIVE_FORMAT_ISO9660:
+ strcpy(str, "iso9660");
+ break;
+ case ARCHIVE_FORMAT_LHA:
+ strcpy(str, "lha");
+ break;
+ case ARCHIVE_FORMAT_MTREE:
+ strcpy(str, "mtree");
+ break;
+ case ARCHIVE_FORMAT_RAR:
+ strcpy(str, "rar");
+ break;
+ case ARCHIVE_FORMAT_TAR:
+ strcpy(str, "tar");
+ break;
+ case ARCHIVE_FORMAT_XAR:
+ strcpy(str, "xar");
+ break;
+ case ARCHIVE_FORMAT_ZIP:
+ strcpy(str, "zip");
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Invalid format code specified");
+ return (ARCHIVE_FATAL);
+ }
+
+ slots = sizeof(a->formats) / sizeof(a->formats[0]);
+ a->format = &(a->formats[0]);
+ for (i = 0; i < slots; i++, a->format++) {
+ if (!a->format->name || !strcmp(a->format->name, str))
+ break;
+ }
+ if (!a->format->name || strcmp(a->format->name, str))
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: Unable to set format");
+ r1 = (ARCHIVE_FATAL);
+ }
+
+ return (r1 < r2) ? r1 : r2;
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_set_options.3 b/Utilities/cmlibarchive/libarchive/archive_read_set_options.3
index 81efb08..6fe9f90 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_set_options.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_set_options.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 13, 2009
+.Dd February 2, 2012
.Dt ARCHIVE_READ_OPTIONS 3
.Os
.Sh NAME
@@ -34,6 +34,8 @@
.Nm archive_read_set_options
.Nd functions controlling options for reading archives
.\"
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.Ft int
.Fo archive_read_set_filter_option
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_set_options.c b/Utilities/cmlibarchive/libarchive/archive_read_set_options.c
index d6a5f45..793f8f7 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_set_options.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_set_options.c
@@ -78,7 +78,7 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
struct archive_read *a = (struct archive_read *)_a;
struct archive_format_descriptor *format;
size_t i;
- int r, rv = ARCHIVE_FAILED;
+ int r, rv = ARCHIVE_WARN;
for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) {
format = &a->formats[i];
@@ -102,6 +102,10 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
if (r == ARCHIVE_OK)
rv = ARCHIVE_OK;
}
+ /* If the format name didn't match, return a special code for
+ * _archive_set_option[s]. */
+ if (rv == ARCHIVE_WARN && m != NULL)
+ rv = ARCHIVE_WARN - 1;
return (rv);
}
@@ -112,7 +116,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *filter;
struct archive_read_filter_bidder *bidder;
- int r, rv = ARCHIVE_FAILED;
+ int r, rv = ARCHIVE_WARN;
for (filter = a->filter; filter != NULL; filter = filter->upstream) {
bidder = filter->bidder;
@@ -135,6 +139,10 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
if (r == ARCHIVE_OK)
rv = ARCHIVE_OK;
}
+ /* If the filter name didn't match, return a special code for
+ * _archive_set_option[s]. */
+ if (rv == ARCHIVE_WARN && m != NULL)
+ rv = ARCHIVE_WARN - 1;
return (rv);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c
index 733d862..b778cfb 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_all.c
@@ -48,7 +48,7 @@ archive_read_support_filter_all(struct archive *a)
archive_read_support_filter_bzip2(a);
/* The decompress code doesn't use an outside library. */
archive_read_support_filter_compress(a);
- /* Gzip decompress falls back to "gunzip" command-line. */
+ /* Gzip decompress falls back to "gzip -d" command-line. */
archive_read_support_filter_gzip(a);
/* Lzip falls back to "unlzip" command-line program. */
archive_read_support_filter_lzip(a);
@@ -63,6 +63,12 @@ archive_read_support_filter_all(struct archive *a)
archive_read_support_filter_uu(a);
/* The decode code doesn't use an outside library. */
archive_read_support_filter_rpm(a);
+ /* The decode code always uses "lrzip -q -d" command-line. */
+ archive_read_support_filter_lrzip(a);
+ /* Lzop decompress falls back to "lzop -d" command-line. */
+ archive_read_support_filter_lzop(a);
+ /* The decode code always uses "grzip -d" command-line. */
+ archive_read_support_filter_grzip(a);
/* Note: We always return ARCHIVE_OK here, even if some of the
* above return ARCHIVE_WARN. The intent here is to enable
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c
index af618b0..2b1a5e2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_bzip2.c
@@ -94,6 +94,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
return (ARCHIVE_FATAL);
reader->data = NULL;
+ reader->name = "bzip2";
reader->bid = bzip2_reader_bid;
reader->init = bzip2_reader_init;
reader->options = NULL;
@@ -102,7 +103,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
- "Using external bunzip2 program");
+ "Using external bzip2 program");
return (ARCHIVE_WARN);
#endif
}
@@ -170,11 +171,11 @@ bzip2_reader_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "bunzip2");
+ r = __archive_read_program(self, "bzip2 -d");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_BZIP2;
+ self->code = ARCHIVE_FILTER_BZIP2;
self->name = "bzip2";
return (r);
}
@@ -192,7 +193,7 @@ bzip2_reader_init(struct archive_read_filter *self)
void *out_block;
struct private_data *state;
- self->code = ARCHIVE_COMPRESSION_BZIP2;
+ self->code = ARCHIVE_FILTER_BZIP2;
self->name = "bzip2";
state = (struct private_data *)calloc(sizeof(*state), 1);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c
index 1b85300..3f5d1f3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c
@@ -163,6 +163,7 @@ archive_read_support_filter_compress(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "compress (.Z)";
bidder->bid = compress_bidder_bid;
bidder->init = compress_bidder_init;
bidder->options = NULL;
@@ -212,7 +213,7 @@ compress_bidder_init(struct archive_read_filter *self)
void *out_block;
int code;
- self->code = ARCHIVE_COMPRESSION_COMPRESS;
+ self->code = ARCHIVE_FILTER_COMPRESS;
self->name = "compress (.Z)";
state = (struct private_data *)calloc(sizeof(*state), 1);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_grzip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_grzip.c
new file mode 100644
index 0000000..84c86ae
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_grzip.c
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+static const unsigned char grzip_magic[] = {
+ 0x47, 0x52, 0x5a, 0x69, 0x70, 0x49, 0x49, 0x00,
+ 0x02, 0x04, 0x3a, 0x29 };
+
+static int grzip_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int grzip_bidder_init(struct archive_read_filter *);
+
+
+static int
+grzip_reader_free(struct archive_read_filter_bidder *self)
+{
+ (void)self; /* UNUSED */
+ return (ARCHIVE_OK);
+}
+
+int
+archive_read_support_filter_grzip(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *reader;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_grzip");
+
+ if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ reader->data = NULL;
+ reader->bid = grzip_bidder_bid;
+ reader->init = grzip_bidder_init;
+ reader->options = NULL;
+ reader->free = grzip_reader_free;
+ /* This filter always uses an external program. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external grzip program for grzip decompression");
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Bidder just verifies the header and returns the number of verified bits.
+ */
+static int
+grzip_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *p;
+ ssize_t avail;
+
+ (void)self; /* UNUSED */
+
+ p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail);
+ if (p == NULL || avail == 0)
+ return (0);
+
+ if (memcmp(p, grzip_magic, sizeof(grzip_magic)))
+ return (0);
+
+ return (sizeof(grzip_magic) * 8);
+}
+
+static int
+grzip_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "grzip -d");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_GRZIP;
+ self->name = "grzip";
+ return (r);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c
index 9d03b2b..e9f59f1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_gzip.c
@@ -72,7 +72,7 @@ static int gzip_filter_close(struct archive_read_filter *);
*
* TODO: If zlib is unavailable, gzip_bidder_init() should
* use the compress_program framework to try to fire up an external
- * gunzip program.
+ * gzip program.
*/
static int gzip_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *);
@@ -100,6 +100,7 @@ archive_read_support_filter_gzip(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "gzip";
bidder->bid = gzip_bidder_bid;
bidder->init = gzip_bidder_init;
bidder->options = NULL;
@@ -109,7 +110,7 @@ archive_read_support_filter_gzip(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
- "Using external gunzip program");
+ "Using external gzip program");
return (ARCHIVE_WARN);
#endif
}
@@ -121,7 +122,7 @@ archive_read_support_filter_gzip(struct archive *_a)
* number of bytes in header. If pbits is non-NULL, it receives a
* count of bits verified, suitable for use by bidder.
*/
-static int
+static ssize_t
peek_at_header(struct archive_read_filter *filter, int *pbits)
{
const unsigned char *p;
@@ -223,7 +224,7 @@ gzip_bidder_bid(struct archive_read_filter_bidder *self,
/*
* If we don't have the library on this system, we can't do the
- * decompression directly. We can, however, try to run gunzip
+ * decompression directly. We can, however, try to run "gzip -d"
* in case that's available.
*/
static int
@@ -231,11 +232,11 @@ gzip_bidder_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "gunzip");
+ r = __archive_read_program(self, "gzip -d");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_GZIP;
+ self->code = ARCHIVE_FILTER_GZIP;
self->name = "gzip";
return (r);
}
@@ -252,7 +253,7 @@ gzip_bidder_init(struct archive_read_filter *self)
static const size_t out_block_size = 64 * 1024;
void *out_block;
- self->code = ARCHIVE_COMPRESSION_GZIP;
+ self->code = ARCHIVE_FILTER_GZIP;
self->name = "gzip";
state = (struct private_data *)calloc(sizeof(*state), 1);
@@ -299,7 +300,7 @@ consume_header(struct archive_read_filter *self)
/* Initialize compression library. */
state->stream.next_in = (unsigned char *)(uintptr_t)
__archive_read_filter_ahead(self->upstream, 1, &avail);
- state->stream.avail_in = avail;
+ state->stream.avail_in = (uInt)avail;
ret = inflateInit2(&(state->stream),
-15 /* Don't check for zlib header */);
@@ -380,7 +381,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
/* Empty our output buffer. */
state->stream.next_out = state->out_block;
- state->stream.avail_out = state->out_block_size;
+ state->stream.avail_out = (uInt)state->out_block_size;
/* Try to fill the output buffer. */
while (state->stream.avail_out > 0 && !state->eof) {
@@ -407,7 +408,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
"truncated gzip input");
return (ARCHIVE_FATAL);
}
- state->stream.avail_in = avail_in;
+ state->stream.avail_in = (uInt)avail_in;
/* Decompress and consume some of that data. */
ret = inflate(&(state->stream), 0);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lrzip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lrzip.c
new file mode 100644
index 0000000..c82a8e2
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lrzip.c
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+#define LRZIP_HEADER_MAGIC "LRZI"
+#define LRZIP_HEADER_MAGIC_LEN 4
+
+static int lrzip_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int lrzip_bidder_init(struct archive_read_filter *);
+
+
+static int
+lrzip_reader_free(struct archive_read_filter_bidder *self)
+{
+ (void)self; /* UNUSED */
+ return (ARCHIVE_OK);
+}
+
+int
+archive_read_support_filter_lrzip(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *reader;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_lrzip");
+
+ if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ reader->data = NULL;
+ reader->name = "lrzip";
+ reader->bid = lrzip_bidder_bid;
+ reader->init = lrzip_bidder_init;
+ reader->options = NULL;
+ reader->free = lrzip_reader_free;
+ /* This filter always uses an external program. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external lrzip program for lrzip decompression");
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Bidder just verifies the header and returns the number of verified bits.
+ */
+static int
+lrzip_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *p;
+ ssize_t avail, len;
+ int i;
+
+ (void)self; /* UNUSED */
+ /* Start by looking at the first six bytes of the header, which
+ * is all fixed layout. */
+ len = 6;
+ p = __archive_read_filter_ahead(filter, len, &avail);
+ if (p == NULL || avail == 0)
+ return (0);
+
+ if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN))
+ return (0);
+
+ /* current major version is always 0, verify this */
+ if (p[LRZIP_HEADER_MAGIC_LEN])
+ return 0;
+ /* support only v0.6+ lrzip for sanity */
+ i = p[LRZIP_HEADER_MAGIC_LEN + 1];
+ if ((i < 6) || (i > 10))
+ return 0;
+
+ return (int)len;
+}
+
+static int
+lrzip_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "lrzip -d -q");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_LRZIP;
+ self->name = "lrzip";
+ return (r);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c
new file mode 100644
index 0000000..7958fa5
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c
@@ -0,0 +1,486 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_LZO_LZOCONF_H
+#include <lzo/lzoconf.h>
+#endif
+#ifdef HAVE_LZO_LZO1X_H
+#include <lzo/lzo1x.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <cm_zlib.h> /* for crc32 and adler32 */
+#endif
+
+#include "archive.h"
+#if !defined(HAVE_ZLIB_H) &&\
+ defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+#include "archive_crc32.h"
+#endif
+#include "archive_endian.h"
+#include "archive_private.h"
+#include "archive_read_private.h"
+
+#ifndef HAVE_ZLIB_H
+#define adler32 lzo_adler32
+#endif
+
+#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a"
+#define LZOP_HEADER_MAGIC_LEN 9
+
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+struct read_lzop {
+ unsigned char *out_block;
+ size_t out_block_size;
+ int64_t total_out;
+ int flags;
+ uint32_t compressed_cksum;
+ uint32_t uncompressed_cksum;
+ size_t compressed_size;
+ size_t uncompressed_size;
+ size_t unconsumed_bytes;
+ char in_stream;
+ char eof; /* True = found end of compressed data. */
+};
+
+#define FILTER 0x0800
+#define CRC32_HEADER 0x1000
+#define EXTRA_FIELD 0x0040
+#define ADLER32_UNCOMPRESSED 0x0001
+#define ADLER32_COMPRESSED 0x0002
+#define CRC32_UNCOMPRESSED 0x0100
+#define CRC32_COMPRESSED 0x0200
+#define MAX_BLOCK_SIZE (64 * 1024 * 1024)
+
+static ssize_t lzop_filter_read(struct archive_read_filter *, const void **);
+static int lzop_filter_close(struct archive_read_filter *);
+#endif
+
+static int lzop_bidder_bid(struct archive_read_filter_bidder *,
+ struct archive_read_filter *);
+static int lzop_bidder_init(struct archive_read_filter *);
+
+int
+archive_read_support_filter_lzop(struct archive *_a)
+{
+ struct archive_read *a = (struct archive_read *)_a;
+ struct archive_read_filter_bidder *reader;
+
+ archive_check_magic(_a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop");
+
+ if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ reader->data = NULL;
+ reader->bid = lzop_bidder_bid;
+ reader->init = lzop_bidder_init;
+ reader->options = NULL;
+ reader->free = NULL;
+ /* Signal the extent of lzop support with the return value here. */
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+ return (ARCHIVE_OK);
+#else
+ /* Return ARCHIVE_WARN since this always uses an external program. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external lzop program for lzop decompression");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+/*
+ * Bidder just verifies the header and returns the number of verified bits.
+ */
+static int
+lzop_bidder_bid(struct archive_read_filter_bidder *self,
+ struct archive_read_filter *filter)
+{
+ const unsigned char *p;
+ ssize_t avail;
+
+ (void)self; /* UNUSED */
+
+ p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail);
+ if (p == NULL || avail == 0)
+ return (0);
+
+ if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
+ return (0);
+
+ return (LZOP_HEADER_MAGIC_LEN * 8);
+}
+
+#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H)
+/*
+ * If we don't have the library on this system, we can't do the
+ * decompression directly. We can, however, try to run "lzop -d"
+ * in case that's available.
+ */
+static int
+lzop_bidder_init(struct archive_read_filter *self)
+{
+ int r;
+
+ r = __archive_read_program(self, "lzop -d");
+ /* Note: We set the format here even if __archive_read_program()
+ * above fails. We do, after all, know what the format is
+ * even if we weren't able to read it. */
+ self->code = ARCHIVE_FILTER_LZOP;
+ self->name = "lzop";
+ return (r);
+}
+#else
+/*
+ * Initialize the filter object.
+ */
+static int
+lzop_bidder_init(struct archive_read_filter *self)
+{
+ struct read_lzop *state;
+
+ self->code = ARCHIVE_FILTER_LZOP;
+ self->name = "lzop";
+
+ state = (struct read_lzop *)calloc(sizeof(*state), 1);
+ if (state == NULL) {
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate data for lzop decompression");
+ return (ARCHIVE_FATAL);
+ }
+
+ self->data = state;
+ self->read = lzop_filter_read;
+ self->skip = NULL; /* not supported */
+ self->close = lzop_filter_close;
+
+ return (ARCHIVE_OK);
+}
+
+static int
+consume_header(struct archive_read_filter *self)
+{
+ struct read_lzop *state = (struct read_lzop *)self->data;
+ const unsigned char *p, *_p;
+ unsigned checksum, flags, len, method, version;
+
+ /*
+ * Check LZOP magic code.
+ */
+ p = __archive_read_filter_ahead(self->upstream,
+ LZOP_HEADER_MAGIC_LEN, NULL);
+ if (p == NULL)
+ return (ARCHIVE_EOF);
+
+ if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
+ return (ARCHIVE_EOF);
+ __archive_read_filter_consume(self->upstream,
+ LZOP_HEADER_MAGIC_LEN);
+
+ p = __archive_read_filter_ahead(self->upstream, 29, NULL);
+ if (p == NULL)
+ goto truncated;
+ _p = p;
+ version = archive_be16dec(p);
+ p += 4;/* version(2 bytes) + library version(2 bytes) */
+
+ if (version >= 0x940) {
+ unsigned reqversion = archive_be16dec(p); p += 2;
+ if (reqversion < 0x900) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Invalid required version");
+ return (ARCHIVE_FAILED);
+ }
+ }
+
+ method = *p++;
+ if (method < 1 || method > 3) {
+ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
+ "Unsupported method");
+ return (ARCHIVE_FAILED);
+ }
+
+ if (version >= 0x940) {
+ unsigned level = *p++;
+ if (method == 1 && level == 0) level = 3;
+ if (method == 2 && level == 0) level = 1;
+ if (method == 3 && level == 0) level = 9;
+ if (level < 1 && level > 9) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Invalid level");
+ return (ARCHIVE_FAILED);
+ }
+ }
+
+ flags = archive_be32dec(p); p += 4;
+
+ if (flags & FILTER)
+ p += 4; /* Skip filter */
+ p += 4; /* Skip mode */
+ if (version >= 0x940)
+ p += 8; /* Skip mtime */
+ else
+ p += 4; /* Skip mtime */
+ len = *p++; /* Read filename length */
+ len += p - _p;
+ /* Make sure we have all bytes we need to calculate checksum. */
+ p = __archive_read_filter_ahead(self->upstream, len + 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ if (flags & CRC32_HEADER)
+ checksum = crc32(crc32(0, NULL, 0), p, len);
+ else
+ checksum = adler32(adler32(0, NULL, 0), p, len);
+ if (archive_be32dec(p + len) != checksum)
+ goto corrupted;
+ __archive_read_filter_consume(self->upstream, len + 4);
+ if (flags & EXTRA_FIELD) {
+ /* Skip extra field */
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ len = archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, len + 4 + 4);
+ }
+ state->flags = flags;
+ state->in_stream = 1;
+ return (ARCHIVE_OK);
+truncated:
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
+ return (ARCHIVE_FAILED);
+corrupted:
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
+ return (ARCHIVE_FAILED);
+}
+
+static int
+consume_block_info(struct archive_read_filter *self)
+{
+ struct read_lzop *state = (struct read_lzop *)self->data;
+ const unsigned char *p;
+ unsigned flags = state->flags;
+
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ state->uncompressed_size = archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, 4);
+ if (state->uncompressed_size == 0)
+ return (ARCHIVE_EOF);
+ if (state->uncompressed_size > MAX_BLOCK_SIZE)
+ goto corrupted;
+
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ state->compressed_size = archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, 4);
+ if (state->compressed_size > state->uncompressed_size)
+ goto corrupted;
+
+ if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) {
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ state->compressed_cksum = state->uncompressed_cksum =
+ archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, 4);
+ }
+ if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) &&
+ state->compressed_size < state->uncompressed_size) {
+ p = __archive_read_filter_ahead(self->upstream, 4, NULL);
+ if (p == NULL)
+ goto truncated;
+ state->compressed_cksum = archive_be32dec(p);
+ __archive_read_filter_consume(self->upstream, 4);
+ }
+ return (ARCHIVE_OK);
+truncated:
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
+ return (ARCHIVE_FAILED);
+corrupted:
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
+ return (ARCHIVE_FAILED);
+}
+
+static ssize_t
+lzop_filter_read(struct archive_read_filter *self, const void **p)
+{
+ struct read_lzop *state = (struct read_lzop *)self->data;
+ const void *b;
+ lzo_uint out_size;
+ uint32_t cksum;
+ int ret, r;
+
+ if (state->unconsumed_bytes) {
+ __archive_read_filter_consume(self->upstream,
+ state->unconsumed_bytes);
+ state->unconsumed_bytes = 0;
+ }
+ if (state->eof)
+ return (0);
+
+ for (;;) {
+ if (!state->in_stream) {
+ ret = consume_header(self);
+ if (ret < ARCHIVE_OK)
+ return (ret);
+ if (ret == ARCHIVE_EOF) {
+ state->eof = 1;
+ return (0);
+ }
+ }
+ ret = consume_block_info(self);
+ if (ret < ARCHIVE_OK)
+ return (ret);
+ if (ret == ARCHIVE_EOF)
+ state->in_stream = 0;
+ else
+ break;
+ }
+
+ if (state->out_block == NULL ||
+ state->out_block_size < state->uncompressed_size) {
+ void *new_block;
+
+ new_block = realloc(state->out_block, state->uncompressed_size);
+ if (new_block == NULL) {
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate data for lzop decompression");
+ return (ARCHIVE_FATAL);
+ }
+ state->out_block = new_block;
+ state->out_block_size = state->uncompressed_size;
+ }
+
+ b = __archive_read_filter_ahead(self->upstream,
+ state->compressed_size, NULL);
+ if (b == NULL) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
+ return (ARCHIVE_FATAL);
+ }
+ if (state->flags & CRC32_COMPRESSED)
+ cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size);
+ else if (state->flags & ADLER32_COMPRESSED)
+ cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size);
+ else
+ cksum = state->compressed_cksum;
+ if (cksum != state->compressed_cksum) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Corrupted data");
+ return (ARCHIVE_FATAL);
+ }
+
+ /*
+ * If the both uncompressed size and compressed size are the same,
+ * we do not decompress this block.
+ */
+ if (state->uncompressed_size == state->compressed_size) {
+ *p = b;
+ state->total_out += state->compressed_size;
+ state->unconsumed_bytes = state->compressed_size;
+ return ((ssize_t)state->uncompressed_size);
+ }
+
+ /*
+ * Drive lzo uncompresison.
+ */
+ out_size = (lzo_uint)state->uncompressed_size;
+ r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
+ state->out_block, &out_size, NULL);
+ switch (r) {
+ case LZO_E_OK:
+ if (out_size == state->uncompressed_size)
+ break;
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Corrupted data");
+ return (ARCHIVE_FATAL);
+ case LZO_E_OUT_OF_MEMORY:
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "lzop decompression failed: out of memory");
+ return (ARCHIVE_FATAL);
+ default:
+ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
+ "lzop decompression failed: %d", r);
+ return (ARCHIVE_FATAL);
+ }
+
+ if (state->flags & CRC32_UNCOMPRESSED)
+ cksum = crc32(crc32(0, NULL, 0), state->out_block,
+ state->uncompressed_size);
+ else if (state->flags & ADLER32_UNCOMPRESSED)
+ cksum = adler32(adler32(0, NULL, 0), state->out_block,
+ state->uncompressed_size);
+ else
+ cksum = state->uncompressed_cksum;
+ if (cksum != state->uncompressed_cksum) {
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC, "Corrupted data");
+ return (ARCHIVE_FATAL);
+ }
+
+ __archive_read_filter_consume(self->upstream, state->compressed_size);
+ *p = state->out_block;
+ state->total_out += out_size;
+ return ((ssize_t)out_size);
+}
+
+/*
+ * Clean up the decompressor.
+ */
+static int
+lzop_filter_close(struct archive_read_filter *self)
+{
+ struct read_lzop *state = (struct read_lzop *)self->data;
+
+ free(state->out_block);
+ free(state);
+ return (ARCHIVE_OK);
+}
+
+#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
index b05eb03..66dc2f4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Joerg Sonnenberger
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,7 +54,9 @@ __FBSDID("$FreeBSD$");
#include "archive.h"
#include "archive_private.h"
+#include "archive_string.h"
#include "archive_read_private.h"
+#include "filter_fork.h"
#if ARCHIVE_VERSION_NUMBER < 4000000
@@ -79,50 +82,13 @@ archive_read_support_filter_program(struct archive *a, const char *cmd)
return (archive_read_support_filter_program_signature(a, cmd, NULL, 0));
}
-
-/* This capability is only available on POSIX systems. */
-#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
- !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
-
-/*
- * On non-Posix systems, allow the program to build, but choke if
- * this function is actually invoked.
- */
-int
-archive_read_support_filter_program_signature(struct archive *_a,
- const char *cmd, const void *signature, size_t signature_len)
-{
- (void)_a; /* UNUSED */
- (void)cmd; /* UNUSED */
- (void)signature; /* UNUSED */
- (void)signature_len; /* UNUSED */
-
- archive_set_error(_a, -1,
- "External compression programs not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-
-int
-__archive_read_program(struct archive_read_filter *self, const char *cmd)
-{
- (void)self; /* UNUSED */
- (void)cmd; /* UNUSED */
-
- archive_set_error(&self->archive->archive, -1,
- "External compression programs not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-
-#else
-
-#include "filter_fork.h"
-
/*
* The bidder object stores the command and the signature to watch for.
* The 'inhibit' entry here is used to ensure that unchecked filters never
* bid twice in the same pipeline.
*/
struct program_bidder {
+ char *description;
char *cmd;
void *signature;
size_t signature_len;
@@ -138,8 +104,12 @@ static int program_bidder_free(struct archive_read_filter_bidder *);
* The actual filter needs to track input and output data.
*/
struct program_filter {
- char *description;
+ struct archive_string description;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ HANDLE child;
+#else
pid_t child;
+#endif
int exit_status;
int waitpid_return;
int child_stdin, child_stdout;
@@ -151,6 +121,29 @@ struct program_filter {
static ssize_t program_filter_read(struct archive_read_filter *,
const void **);
static int program_filter_close(struct archive_read_filter *);
+static void free_state(struct program_bidder *);
+
+static int
+set_bidder_signature(struct archive_read_filter_bidder *bidder,
+ struct program_bidder *state, const void *signature, size_t signature_len)
+{
+
+ if (signature != NULL && signature_len > 0) {
+ state->signature_len = signature_len;
+ state->signature = malloc(signature_len);
+ memcpy(state->signature, signature, signature_len);
+ }
+
+ /*
+ * Fill in the bidder object.
+ */
+ bidder->data = state;
+ bidder->bid = program_bidder_bid;
+ bidder->init = program_bidder_init;
+ bidder->options = NULL;
+ bidder->free = program_bidder_free;
+ return (ARCHIVE_OK);
+}
int
archive_read_support_filter_program_signature(struct archive *_a,
@@ -169,37 +162,40 @@ archive_read_support_filter_program_signature(struct archive *_a,
/*
* Allocate our private state.
*/
- state = (struct program_bidder *)calloc(sizeof (*state), 1);
+ state = (struct program_bidder *)calloc(1, sizeof (*state));
if (state == NULL)
- return (ARCHIVE_FATAL);
+ goto memerr;
state->cmd = strdup(cmd);
- if (signature != NULL && signature_len > 0) {
- state->signature_len = signature_len;
- state->signature = malloc(signature_len);
- memcpy(state->signature, signature, signature_len);
- }
+ if (state->cmd == NULL)
+ goto memerr;
- /*
- * Fill in the bidder object.
- */
- bidder->data = state;
- bidder->bid = program_bidder_bid;
- bidder->init = program_bidder_init;
- bidder->options = NULL;
- bidder->free = program_bidder_free;
- return (ARCHIVE_OK);
+ return set_bidder_signature(bidder, state, signature, signature_len);
+memerr:
+ free_state(state);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
}
static int
program_bidder_free(struct archive_read_filter_bidder *self)
{
struct program_bidder *state = (struct program_bidder *)self->data;
- free(state->cmd);
- free(state->signature);
- free(self->data);
+
+ free_state(state);
return (ARCHIVE_OK);
}
+static void
+free_state(struct program_bidder *state)
+{
+
+ if (state) {
+ free(state->cmd);
+ free(state->signature);
+ free(state);
+ }
+}
+
/*
* If we do have a signature, bid only if that matches.
*
@@ -258,6 +254,9 @@ child_stop(struct archive_read_filter *self, struct program_filter *state)
state->waitpid_return
= waitpid(state->child, &state->exit_status, 0);
} while (state->waitpid_return == -1 && errno == EINTR);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ CloseHandle(state->child);
+#endif
state->child = 0;
}
@@ -310,11 +309,35 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
struct program_filter *state = self->data;
ssize_t ret, requested, avail;
const char *p;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ HANDLE handle = (HANDLE)_get_osfhandle(state->child_stdout);
+#endif
requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
for (;;) {
do {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Avoid infinity wait.
+ * Note: If there is no data in the pipe, ReadFile()
+ * called in read() never returns and so we won't
+ * write remaining encoded data to the pipe.
+ * Note: This way may cause performance problem.
+ * we are looking forward to great code to resolve
+ * this. */
+ DWORD pipe_avail = -1;
+ int cnt = 2;
+
+ while (PeekNamedPipe(handle, NULL, 0, NULL,
+ &pipe_avail, NULL) != 0 && pipe_avail == 0 &&
+ cnt--)
+ Sleep(5);
+ if (pipe_avail == 0) {
+ ret = -1;
+ errno = EAGAIN;
+ break;
+ }
+#endif
ret = read(state->child_stdout, buf, requested);
} while (ret == -1 && errno == EINTR);
@@ -376,38 +399,57 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
struct program_filter *state;
static const size_t out_buf_len = 65536;
char *out_buf;
- char *description;
const char *prefix = "Program: ";
+ pid_t child;
+ size_t l;
+ l = strlen(prefix) + strlen(cmd) + 1;
state = (struct program_filter *)calloc(1, sizeof(*state));
out_buf = (char *)malloc(out_buf_len);
- description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
- if (state == NULL || out_buf == NULL || description == NULL) {
+ if (state == NULL || out_buf == NULL ||
+ archive_string_ensure(&state->description, l) == NULL) {
archive_set_error(&self->archive->archive, ENOMEM,
"Can't allocate input data");
- free(state);
+ if (state != NULL) {
+ archive_string_free(&state->description);
+ free(state);
+ }
free(out_buf);
- free(description);
return (ARCHIVE_FATAL);
}
+ archive_strcpy(&state->description, prefix);
+ archive_strcat(&state->description, cmd);
- self->code = ARCHIVE_COMPRESSION_PROGRAM;
- state->description = description;
- strcpy(state->description, prefix);
- strcat(state->description, cmd);
- self->name = state->description;
+ self->code = ARCHIVE_FILTER_PROGRAM;
+ self->name = state->description.s;
state->out_buf = out_buf;
state->out_buf_len = out_buf_len;
- if ((state->child = __archive_create_child(cmd,
- &state->child_stdin, &state->child_stdout)) == -1) {
+ child = __archive_create_child(cmd, &state->child_stdin,
+ &state->child_stdout);
+ if (child == -1) {
+ free(state->out_buf);
+ free(state);
+ archive_set_error(&self->archive->archive, EINVAL,
+ "Can't initialize filter; unable to run program \"%s\"",
+ cmd);
+ return (ARCHIVE_FATAL);
+ }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ state->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child);
+ if (state->child == NULL) {
+ child_stop(self, state);
free(state->out_buf);
free(state);
archive_set_error(&self->archive->archive, EINVAL,
- "Can't initialize filter; unable to run program \"%s\"", cmd);
+ "Can't initialize filter; unable to run program \"%s\"",
+ cmd);
return (ARCHIVE_FATAL);
}
+#else
+ state->child = child;
+#endif
self->data = state;
self->read = program_filter_read;
@@ -467,10 +509,8 @@ program_filter_close(struct archive_read_filter *self)
/* Release our private data. */
free(state->out_buf);
- free(state->description);
+ archive_string_free(&state->description);
free(state);
return (e);
}
-
-#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c
index 7dbfc0e..e7e58e5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_rpm.c
@@ -85,6 +85,7 @@ archive_read_support_filter_rpm(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "rpm";
bidder->bid = rpm_bidder_bid;
bidder->init = rpm_bidder_init;
bidder->options = NULL;
@@ -137,7 +138,7 @@ rpm_bidder_init(struct archive_read_filter *self)
{
struct rpm *rpm;
- self->code = ARCHIVE_COMPRESSION_RPM;
+ self->code = ARCHIVE_FILTER_RPM;
self->name = "rpm";
self->read = rpm_filter_read;
self->skip = NULL; /* not supported */
@@ -188,7 +189,7 @@ rpm_filter_read(struct archive_read_filter *self, const void **buff)
if (rpm->total_in + avail_in < RPM_LEAD_SIZE)
used += avail_in;
else {
- n = RPM_LEAD_SIZE - rpm->total_in;
+ n = (size_t)(RPM_LEAD_SIZE - rpm->total_in);
used += n;
b += n;
rpm->state = ST_HEADER;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
index a75ef75..471771b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_uu.c
@@ -56,6 +56,7 @@ struct uudecode {
#define ST_READ_UU 1
#define ST_UUEND 2
#define ST_READ_BASE64 3
+#define ST_IGNORE 4
};
static int uudecode_bidder_bid(struct archive_read_filter_bidder *,
@@ -88,6 +89,7 @@ archive_read_support_filter_uu(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "uu";
bidder->bid = uudecode_bidder_bid;
bidder->init = uudecode_bidder_init;
bidder->options = NULL;
@@ -377,7 +379,7 @@ uudecode_bidder_init(struct archive_read_filter *self)
void *out_buff;
void *in_buff;
- self->code = ARCHIVE_COMPRESSION_UU;
+ self->code = ARCHIVE_FILTER_UU;
self->name = "uu";
self->read = uudecode_filter_read;
self->skip = NULL; /* not supported */
@@ -470,6 +472,10 @@ read_more:
total = 0;
out = uudecode->out_buff;
ravail = avail_in;
+ if (uudecode->state == ST_IGNORE) {
+ used = avail_in;
+ goto finish;
+ }
if (uudecode->in_cnt) {
/*
* If there is remaining data which is saved by
@@ -485,12 +491,18 @@ read_more:
uudecode->in_cnt = 0;
}
for (;used < avail_in; d += llen, used += llen) {
- int l, body;
+ int64_t l, body;
b = d;
len = get_line(b, avail_in - used, &nl);
if (len < 0) {
/* Non-ascii character is found. */
+ if (uudecode->state == ST_FIND_HEAD &&
+ (uudecode->total > 0 || total > 0)) {
+ uudecode->state = ST_IGNORE;
+ used = avail_in;
+ goto finish;
+ }
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC,
"Insufficient compressed data");
@@ -507,7 +519,7 @@ read_more:
return (ARCHIVE_FATAL);
if (uudecode->in_buff != b)
memmove(uudecode->in_buff, b, len);
- uudecode->in_cnt = len;
+ uudecode->in_cnt = (int)len;
if (total == 0) {
/* Do not return 0; it means end-of-file.
* We should try to read bytes more. */
@@ -545,7 +557,7 @@ read_more:
break;
case ST_READ_UU:
if (total + len * 2 > OUT_BUFF_SIZE)
- break;
+ goto finish;
body = len - nl;
if (!uuchar[*b] || body <= 0) {
archive_set_error(&self->archive->archive,
@@ -611,7 +623,7 @@ read_more:
break;
case ST_READ_BASE64:
if (total + len * 2 > OUT_BUFF_SIZE)
- break;
+ goto finish;
l = len - nl;
if (l >= 3 && b[0] == '=' && b[1] == '=' &&
b[2] == '=') {
@@ -657,8 +669,10 @@ read_more:
break;
}
}
-
- __archive_read_filter_consume(self->upstream, ravail);
+finish:
+ if (ravail < avail_in)
+ used -= avail_in - ravail;
+ __archive_read_filter_consume(self->upstream, used);
*buff = uudecode->out_buff;
uudecode->total += total;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
index cf762a4..15824b1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c
@@ -136,6 +136,7 @@ archive_read_support_filter_xz(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "xz";
bidder->bid = xz_bidder_bid;
bidder->init = xz_bidder_init;
bidder->options = NULL;
@@ -144,7 +145,7 @@ archive_read_support_filter_xz(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
- "Using external unxz program for xz decompression");
+ "Using external xz program for xz decompression");
return (ARCHIVE_WARN);
#endif
}
@@ -170,6 +171,7 @@ archive_read_support_filter_lzma(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "lzma";
bidder->bid = lzma_bidder_bid;
bidder->init = lzma_bidder_init;
bidder->options = NULL;
@@ -180,7 +182,7 @@ archive_read_support_filter_lzma(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
- "Using external unlzma program for lzma decompression");
+ "Using external lzma program for lzma decompression");
return (ARCHIVE_WARN);
#endif
}
@@ -207,6 +209,7 @@ archive_read_support_filter_lzip(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
+ bidder->name = "lzip";
bidder->bid = lzip_bidder_bid;
bidder->init = lzip_bidder_init;
bidder->options = NULL;
@@ -415,7 +418,7 @@ lzip_bidder_bid(struct archive_read_filter_bidder *self,
static int
xz_bidder_init(struct archive_read_filter *self)
{
- self->code = ARCHIVE_COMPRESSION_XZ;
+ self->code = ARCHIVE_FILTER_XZ;
self->name = "xz";
return (xz_lzma_bidder_init(self));
}
@@ -423,7 +426,7 @@ xz_bidder_init(struct archive_read_filter *self)
static int
lzma_bidder_init(struct archive_read_filter *self)
{
- self->code = ARCHIVE_COMPRESSION_LZMA;
+ self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
return (xz_lzma_bidder_init(self));
}
@@ -431,7 +434,7 @@ lzma_bidder_init(struct archive_read_filter *self)
static int
lzip_bidder_init(struct archive_read_filter *self)
{
- self->code = ARCHIVE_COMPRESSION_LZIP;
+ self->code = ARCHIVE_FILTER_LZIP;
self->name = "lzip";
return (xz_lzma_bidder_init(self));
}
@@ -518,7 +521,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
state->stream.avail_out = state->out_block_size;
state->crc32 = 0;
- if (self->code == ARCHIVE_COMPRESSION_LZIP) {
+ if (self->code == ARCHIVE_FILTER_LZIP) {
/*
* We have to read a lzip header and use it to initialize
* compression library, thus we cannot initialize the
@@ -530,7 +533,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
state->in_stream = 1;
/* Initialize compression library. */
- if (self->code == ARCHIVE_COMPRESSION_XZ)
+ if (self->code == ARCHIVE_FILTER_XZ)
ret = lzma_stream_decoder(&(state->stream),
LZMA_MEMLIMIT,/* memlimit */
LZMA_CONCATENATED);
@@ -730,7 +733,7 @@ xz_filter_read(struct archive_read_filter *self, const void **p)
*p = NULL;
else {
*p = state->out_block;
- if (self->code == ARCHIVE_COMPRESSION_LZIP) {
+ if (self->code == ARCHIVE_FILTER_LZIP) {
state->crc32 = lzma_crc32(state->out_block,
decompressed, state->crc32);
if (state->eof) {
@@ -778,7 +781,7 @@ lzma_bidder_init(struct archive_read_filter *self)
struct private_data *state;
ssize_t ret, avail_in;
- self->code = ARCHIVE_COMPRESSION_LZMA;
+ self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
state = (struct private_data *)calloc(sizeof(*state), 1);
@@ -941,11 +944,11 @@ lzma_bidder_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "unlzma");
+ r = __archive_read_program(self, "lzma -d -qq");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_LZMA;
+ self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
return (r);
}
@@ -958,11 +961,11 @@ xz_bidder_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "unxz");
+ r = __archive_read_program(self, "xz -d -qq");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_XZ;
+ self->code = ARCHIVE_FILTER_XZ;
self->name = "xz";
return (r);
}
@@ -972,11 +975,11 @@ lzip_bidder_init(struct archive_read_filter *self)
{
int r;
- r = __archive_read_program(self, "unlzip");
+ r = __archive_read_program(self, "lzip -d -q");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
- self->code = ARCHIVE_COMPRESSION_LZIP;
+ self->code = ARCHIVE_FILTER_LZIP;
self->name = "lzip";
return (r);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
index 2be2267..54ea245 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
@@ -318,7 +318,7 @@ struct _7zip {
uint32_t bcj2_code;
uint64_t bcj2_outPos;
- /* Filename character-set convertion data. */
+ /* Filename character-set conversion data. */
struct archive_string_conv *sconv;
char format_name[64];
@@ -409,6 +409,7 @@ archive_read_support_format_7zip(struct archive *_a)
archive_read_format_7zip_read_header,
archive_read_format_7zip_read_data,
archive_read_format_7zip_read_data_skip,
+ NULL,
archive_read_format_7zip_cleanup);
if (r != ARCHIVE_OK)
@@ -481,7 +482,7 @@ check_7zip_header_in_sfx(const char *p)
* Magic Code, so we should do this in order not to
* make a mis-detection.
*/
- if (crc32(0, (unsigned char *)p + 12, 20)
+ if (crc32(0, (const unsigned char *)p + 12, 20)
!= archive_le32dec(p + 8))
return (6);
/* Hit the header! */
@@ -580,7 +581,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
free_Header(&header);
if (r != ARCHIVE_OK)
return (r);
- zip->entries_remaining = zip->numFiles;
+ zip->entries_remaining = (size_t)zip->numFiles;
zip->entry = zip->entries;
} else {
++zip->entry;
@@ -630,7 +631,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
if (zip_entry->flg & ATIME_IS_SET)
archive_entry_set_atime(entry, zip_entry->atime,
zip_entry->atime_ns);
- if (zip_entry->ssIndex != -1) {
+ if (zip_entry->ssIndex != (uint32_t)-1) {
zip->entry_bytes_remaining =
zip->si.ss.unpackSizes[zip_entry->ssIndex];
archive_entry_set_size(entry, zip->entry_bytes_remaining);
@@ -646,7 +647,6 @@ archive_read_format_7zip_read_header(struct archive_read *a,
if ((zip_entry->mode & AE_IFMT) == AE_IFLNK) {
unsigned char *symname = NULL;
size_t symsize = 0;
- int r;
/*
* Symbolic-name is recorded as its contents. We have to
@@ -654,19 +654,24 @@ archive_read_format_7zip_read_header(struct archive_read *a,
*/
while (zip->entry_bytes_remaining > 0) {
const void *buff;
+ unsigned char *mem;
size_t size;
int64_t offset;
r = archive_read_format_7zip_read_data(a, &buff,
&size, &offset);
- if (r < ARCHIVE_WARN)
+ if (r < ARCHIVE_WARN) {
+ free(symname);
return (r);
- symname = realloc(symname, symsize + size + 1);
- if (symname == NULL) {
+ }
+ mem = realloc(symname, symsize + size + 1);
+ if (mem == NULL) {
+ free(symname);
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Symname");
return (ARCHIVE_FATAL);
}
+ symname = mem;
memcpy(symname+symsize, buff, size);
symsize += size;
}
@@ -680,8 +685,8 @@ archive_read_format_7zip_read_header(struct archive_read *a,
symname[symsize] = '\0';
archive_entry_copy_symlink(entry,
(const char *)symname);
- free(symname);
}
+ free(symname);
archive_entry_set_size(entry, 0);
}
@@ -705,18 +710,18 @@ archive_read_format_7zip_read_data(struct archive_read *a,
if (zip->pack_stream_bytes_unconsumed)
read_consume(a);
+ *offset = zip->entry_offset;
+ *size = 0;
+ *buff = NULL;
/*
* If we hit end-of-entry last time, clean up and return
* ARCHIVE_EOF this time.
*/
- if (zip->end_of_entry) {
- *offset = zip->entry_offset;
- *size = 0;
- *buff = NULL;
+ if (zip->end_of_entry)
return (ARCHIVE_EOF);
- }
- bytes = read_stream(a, buff, zip->entry_bytes_remaining, 0);
+ bytes = read_stream(a, buff,
+ (size_t)zip->entry_bytes_remaining, 0);
if (bytes < 0)
return ((int)bytes);
if (bytes == 0) {
@@ -731,7 +736,8 @@ archive_read_format_7zip_read_data(struct archive_read *a,
/* Update checksum */
if ((zip->entry->flg & CRC32_IS_SET) && bytes)
- zip->entry_crc32 = crc32(zip->entry_crc32, *buff, bytes);
+ zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
+ (unsigned)bytes);
/* If we hit the end, swallow any end-of-data marker. */
if (zip->end_of_entry) {
@@ -774,7 +780,7 @@ archive_read_format_7zip_read_data_skip(struct archive_read *a)
* If the length is at the beginning, we can skip the
* compressed data much more quickly.
*/
- bytes_skipped = skip_stream(a, zip->entry_bytes_remaining);
+ bytes_skipped = skip_stream(a, (size_t)zip->entry_bytes_remaining);
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
zip->entry_bytes_remaining = 0;
@@ -1054,7 +1060,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
ff = &filters[fi];
#endif
r = lzma_properties_decode(&filters[fi], NULL,
- coder1->properties, coder1->propertiesSize);
+ coder1->properties, (size_t)coder1->propertiesSize);
if (r != LZMA_OK) {
set_error(a, r);
return (ARCHIVE_FAILED);
@@ -1358,9 +1364,9 @@ decompress(struct archive_read *a, struct _7zip *zip,
#ifdef HAVE_ZLIB_H
case _7Z_DEFLATE:
zip->stream.next_in = (Bytef *)(uintptr_t)t_next_in;
- zip->stream.avail_in = t_avail_in;
+ zip->stream.avail_in = (uInt)t_avail_in;
zip->stream.next_out = t_next_out;
- zip->stream.avail_out = t_avail_out;
+ zip->stream.avail_out = (uInt)t_avail_out;
r = inflate(&(zip->stream), 0);
switch (r) {
case Z_STREAM_END: /* Found end of stream. */
@@ -1382,7 +1388,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
uint64_t flush_bytes;
if (!zip->ppmd7_valid || zip->ppmd7_stat < 0 ||
- t_avail_in < 0 || t_avail_out <= 0) {
+ t_avail_out <= 0) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"Decompression internal error");
@@ -1442,8 +1448,8 @@ decompress(struct archive_read *a, struct _7zip *zip,
} while (zip->ppstream.avail_out &&
(zip->ppstream.avail_in || flush_bytes));
- t_avail_in = zip->ppstream.avail_in;
- t_avail_out = zip->ppstream.avail_out;
+ t_avail_in = (size_t)zip->ppstream.avail_in;
+ t_avail_out = (size_t)zip->ppstream.avail_out;
break;
}
default:
@@ -1506,6 +1512,10 @@ free_decompression(struct archive_read *a, struct _7zip *zip)
{
int r = ARCHIVE_OK;
+#if !defined(HAVE_ZLIB_H) &&\
+ !(defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR))
+ (void)a;/* UNUSED */
+#endif
#ifdef HAVE_LZMA_H
if (zip->lzstream_valid)
lzma_end(&(zip->lzstream));
@@ -1598,9 +1608,10 @@ read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num)
const unsigned char *p;
unsigned i;
+ if (num == 0)
+ return (-1);
memset(d, 0, sizeof(*d));
-
d->defineds = malloc(num);
if (d->defineds == NULL)
return (-1);
@@ -1672,8 +1683,8 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi)
return (0);
if (*p != kSize)
return (-1);
- pi->sizes = calloc(pi->numPackStreams, sizeof(uint64_t));
- pi->positions = calloc(pi->numPackStreams, sizeof(uint64_t));
+ pi->sizes = calloc((size_t)pi->numPackStreams, sizeof(uint64_t));
+ pi->positions = calloc((size_t)pi->numPackStreams, sizeof(uint64_t));
if (pi->sizes == NULL || pi->positions == NULL)
return (-1);
@@ -1690,9 +1701,9 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi)
if (*p == kEnd) {
/* PackStreamDigests[num] are not present. */
pi->digest.defineds =
- calloc(pi->numPackStreams, sizeof(*pi->digest.defineds));
+ calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.defineds));
pi->digest.digests =
- calloc(pi->numPackStreams, sizeof(*pi->digest.digests));
+ calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.digests));
if (pi->digest.defineds == NULL || pi->digest.digests == NULL)
return (-1);
return (0);
@@ -1701,7 +1712,7 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi)
if (*p != kSize)
return (-1);
- if (read_Digests(a, &(pi->digest), pi->numPackStreams) < 0)
+ if (read_Digests(a, &(pi->digest), (size_t)pi->numPackStreams) < 0)
return (-1);
/*
@@ -1750,7 +1761,7 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
/* Too many coders. */
return (-1);
- f->coders = calloc(f->numCoders, sizeof(*f->coders));
+ f->coders = calloc((size_t)f->numCoders, sizeof(*f->coders));
if (f->coders == NULL)
return (-1);
for (i = 0; i< f->numCoders; i++) {
@@ -1802,14 +1813,14 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
a, &(f->coders[i].propertiesSize)) < 0)
return (-1);
if ((p = header_bytes(
- a, f->coders[i].propertiesSize)) == NULL)
+ a, (size_t)f->coders[i].propertiesSize)) == NULL)
return (-1);
f->coders[i].properties =
- malloc(f->coders[i].propertiesSize);
+ malloc((size_t)f->coders[i].propertiesSize);
if (f->coders[i].properties == NULL)
return (-1);
memcpy(f->coders[i].properties, p,
- f->coders[i].propertiesSize);
+ (size_t)f->coders[i].propertiesSize);
}
numInStreamsTotal += f->coders[i].numInStreams;
@@ -1823,9 +1834,13 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
f->numBindPairs = numOutStreamsTotal - 1;
if (zip->header_bytes_remaining < f->numBindPairs)
return (-1);
- f->bindPairs = calloc(f->numBindPairs, sizeof(*f->bindPairs));
- if (f->bindPairs == NULL)
- return (-1);
+ if (f->numBindPairs > 0) {
+ f->bindPairs =
+ calloc((size_t)f->numBindPairs, sizeof(*f->bindPairs));
+ if (f->bindPairs == NULL)
+ return (-1);
+ } else
+ f->bindPairs = NULL;
for (i = 0; i < f->numBindPairs; i++) {
if (parse_7zip_uint64(a, &(f->bindPairs[i].inIndex)) < 0)
return (-1);
@@ -1839,7 +1854,7 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
f->numPackedStreams = numInStreamsTotal - f->numBindPairs;
f->packedStreams =
- calloc(f->numPackedStreams, sizeof(*f->packedStreams));
+ calloc((size_t)f->numPackedStreams, sizeof(*f->packedStreams));
if (f->packedStreams == NULL)
return (-1);
if (f->numPackedStreams == 1) {
@@ -1911,7 +1926,8 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci)
goto failed;
switch (*p) {
case 0:
- ci->folders = calloc(ci->numFolders, sizeof(*ci->folders));
+ ci->folders =
+ calloc((size_t)ci->numFolders, sizeof(*ci->folders));
if (ci->folders == NULL)
return (-1);
for (i = 0; i < ci->numFolders; i++) {
@@ -1937,7 +1953,7 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci)
unsigned j;
folder->unPackSize =
- calloc(folder->numOutStreams, sizeof(*folder->unPackSize));
+ calloc((size_t)folder->numOutStreams, sizeof(*folder->unPackSize));
if (folder->unPackSize == NULL)
goto failed;
for (j = 0; j < folder->numOutStreams; j++) {
@@ -1955,7 +1971,7 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci)
return (0);
if (*p != kCRC)
goto failed;
- if (read_Digests(a, &digest, ci->numFolders) < 0)
+ if (read_Digests(a, &digest, (size_t)ci->numFolders) < 0)
goto failed;
for (i = 0; i < ci->numFolders; i++) {
ci->folders[i].digest_defined = digest.defineds[i];
@@ -1979,13 +1995,13 @@ failed:
static uint64_t
folder_uncompressed_size(struct _7z_folder *f)
{
- int n = f->numOutStreams;
- unsigned pairs = f->numBindPairs;
+ int n = (int)f->numOutStreams;
+ unsigned pairs = (unsigned)f->numBindPairs;
while (--n >= 0) {
unsigned i;
for (i = 0; i < pairs; i++) {
- if (f->bindPairs[i].outIndex == n)
+ if (f->bindPairs[i].outIndex == (uint64_t)n)
break;
}
if (i >= pairs)
@@ -2029,7 +2045,7 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss,
return (-1);
if (1000000 < f[i].numUnpackStreams)
return (-1);
- unpack_streams += f[i].numUnpackStreams;
+ unpack_streams += (size_t)f[i].numUnpackStreams;
}
if ((p = header_bytes(a, 1)) == NULL)
return (-1);
@@ -2083,7 +2099,7 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss,
numDigests = 0;
for (i = 0; i < numFolders; i++) {
if (f[i].numUnpackStreams != 1 || !f[i].digest_defined)
- numDigests += f[i].numUnpackStreams;
+ numDigests += (uint32_t)f[i].numUnpackStreams;
}
if (type == kCRC) {
@@ -2181,7 +2197,7 @@ read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si)
f = si->ci.folders;
for (i = 0; i < si->ci.numFolders; i++) {
f[i].packIndex = packIndex;
- packIndex += f[i].numPackedStreams;
+ packIndex += (uint32_t)f[i].numPackedStreams;
if (packIndex > si->pi.numPackStreams)
return (-1);
}
@@ -2191,7 +2207,7 @@ read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si)
if (*p == kSubStreamsInfo) {
if (read_SubStreamsInfo(a, &(si->ss),
- si->ci.folders, si->ci.numFolders) < 0)
+ si->ci.folders, (size_t)si->ci.numFolders) < 0)
return (-1);
if ((p = header_bytes(a, 1)) == NULL)
return (-1);
@@ -2279,7 +2295,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if (1000000 < zip->numFiles)
return (-1);
- zip->entries = calloc(zip->numFiles, sizeof(*zip->entries));
+ zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries));
if (zip->entries == NULL)
return (-1);
entries = zip->entries;
@@ -2304,12 +2320,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
switch (type) {
case kEmptyStream:
- h->emptyStreamBools = calloc(zip->numFiles,
+ h->emptyStreamBools = calloc((size_t)zip->numFiles,
sizeof(*h->emptyStreamBools));
if (h->emptyStreamBools == NULL)
return (-1);
if (read_Bools(
- a, h->emptyStreamBools, zip->numFiles) < 0)
+ a, h->emptyStreamBools, (size_t)zip->numFiles) < 0)
return (-1);
empty_streams = 0;
for (i = 0; i < zip->numFiles; i++) {
@@ -2318,6 +2334,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
}
break;
case kEmptyFile:
+ if (empty_streams <= 0) {
+ /* Unexcepted sequence. Skip this. */
+ if (header_bytes(a, ll) == NULL)
+ return (-1);
+ break;
+ }
h->emptyFileBools = calloc(empty_streams,
sizeof(*h->emptyFileBools));
if (h->emptyFileBools == NULL)
@@ -2326,6 +2348,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
return (-1);
break;
case kAnti:
+ if (empty_streams <= 0) {
+ /* Unexcepted sequence. Skip this. */
+ if (header_bytes(a, ll) == NULL)
+ return (-1);
+ break;
+ }
h->antiBools = calloc(empty_streams,
sizeof(*h->antiBools));
if (h->antiBools == NULL)
@@ -2404,15 +2432,15 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((p = header_bytes(a, 2)) == NULL)
return (-1);
allAreDefined = *p;
- h->attrBools = calloc(zip->numFiles,
+ h->attrBools = calloc((size_t)zip->numFiles,
sizeof(*h->attrBools));
if (h->attrBools == NULL)
return (-1);
if (allAreDefined)
- memset(h->attrBools, 1, zip->numFiles);
+ memset(h->attrBools, 1, (size_t)zip->numFiles);
else {
if (read_Bools(a, h->attrBools,
- zip->numFiles) < 0)
+ (size_t)zip->numFiles) < 0)
return (-1);
}
for (i = 0; i < zip->numFiles; i++) {
@@ -2446,7 +2474,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((size_t)sindex >= si->ss.unpack_streams)
return (-1);
if (entries[i].mode == 0)
- entries[i].mode = AE_IFREG | 0777;
+ entries[i].mode = AE_IFREG | 0666;
if (si->ss.digestsDefined[sindex])
entries[i].flg |= CRC32_IS_SET;
entries[i].ssIndex = sindex;
@@ -2466,7 +2494,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if (dir)
entries[i].mode = AE_IFDIR | 0777;
else
- entries[i].mode = AE_IFREG | 0777;
+ entries[i].mode = AE_IFREG | 0666;
} else if (dir &&
(entries[i].mode & AE_IFMT) != AE_IFDIR) {
entries[i].mode &= ~AE_IFMT;
@@ -2517,17 +2545,17 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
static void
-fileTimeToUtc(uint64_t fileTime, time_t *time, long *ns)
+fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns)
{
if (fileTime >= EPOC_TIME) {
fileTime -= EPOC_TIME;
/* milli seconds base */
- *time = (time_t)(fileTime / 10000000);
+ *timep = (time_t)(fileTime / 10000000);
/* nano seconds base */
*ns = (long)(fileTime % 10000000) * 100;
} else {
- *time = 0;
+ *timep = 0;
*ns = 0;
}
}
@@ -2542,7 +2570,7 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
int allAreDefined;
unsigned i;
- timeBools = calloc(zip->numFiles, sizeof(*timeBools));
+ timeBools = calloc((size_t)zip->numFiles, sizeof(*timeBools));
if (timeBools == NULL)
return (-1);
@@ -2551,9 +2579,9 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
goto failed;
allAreDefined = *p;
if (allAreDefined)
- memset(timeBools, 1, zip->numFiles);
+ memset(timeBools, 1, (size_t)zip->numFiles);
else {
- if (read_Bools(a, timeBools, zip->numFiles) < 0)
+ if (read_Bools(a, timeBools, (size_t)zip->numFiles) < 0)
goto failed;
}
@@ -2564,7 +2592,7 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
if (parse_7zip_uint64(a, &(h->dataIndex)) < 0)
goto failed;
if (1000000 < h->dataIndex)
- return (-1);
+ goto failed;
}
for (i = 0; i < zip->numFiles; i++) {
@@ -2661,7 +2689,7 @@ header_bytes(struct archive_read *a, size_t rbytes)
}
/* Update checksum */
- zip->header_crc32 = crc32(zip->header_crc32, p, rbytes);
+ zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes);
return (p);
}
@@ -2695,7 +2723,8 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
}
/* CRC check. */
- if (crc32(0, (unsigned char *)p + 12, 20) != archive_le32dec(p + 8)) {
+ if (crc32(0, (const unsigned char *)p + 12, 20)
+ != archive_le32dec(p + 8)) {
archive_set_error(&a->archive, -1, "Header CRC error");
return (ARCHIVE_FATAL);
}
@@ -2714,7 +2743,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
}
__archive_read_consume(a, 32);
if (next_header_offset != 0) {
- if (bytes_avail >= next_header_offset)
+ if (bytes_avail >= (ssize_t)next_header_offset)
__archive_read_consume(a, next_header_offset);
else if (__archive_read_seek(a,
next_header_offset + zip->seek_base, SEEK_SET) < 0)
@@ -2827,7 +2856,7 @@ get_uncompressed_data(struct archive_read *a, const void **buff, size_t size,
struct _7zip *zip = (struct _7zip *)a->format->data;
ssize_t bytes_avail;
- if (zip->codec == _7Z_COPY && zip->codec2 == -1) {
+ if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) {
/* Copy mode. */
/*
@@ -2886,7 +2915,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
ssize_t bytes_avail;
int r;
- if (zip->codec == _7Z_COPY && zip->codec2 == -1) {
+ if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) {
if (minimum == 0)
minimum = 1;
if (__archive_read_ahead(a, minimum, &bytes_avail) == NULL
@@ -2896,11 +2925,11 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
"Truncated 7-Zip file body");
return (ARCHIVE_FATAL);
}
- if (bytes_avail > zip->pack_stream_inbytes_remaining)
- bytes_avail = zip->pack_stream_inbytes_remaining;
+ if (bytes_avail > (ssize_t)zip->pack_stream_inbytes_remaining)
+ bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining;
zip->pack_stream_inbytes_remaining -= bytes_avail;
- if (bytes_avail > zip->folder_outbytes_remaining)
- bytes_avail = zip->folder_outbytes_remaining;
+ if (bytes_avail > (ssize_t)zip->folder_outbytes_remaining)
+ bytes_avail = (ssize_t)zip->folder_outbytes_remaining;
zip->folder_outbytes_remaining -= bytes_avail;
zip->uncompressed_buffer_bytes_remaining = bytes_avail;
return (ARCHIVE_OK);
@@ -2939,16 +2968,19 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
* Expand the uncompressed buffer up to
* the minimum size.
*/
- zip->uncompressed_buffer_size = minimum + 1023;
- zip->uncompressed_buffer_size &= ~0x3ff;
- zip->uncompressed_buffer =
- realloc(zip->uncompressed_buffer,
- zip->uncompressed_buffer_size);
- if (zip->uncompressed_buffer == NULL) {
+ void *p;
+ size_t new_size;
+
+ new_size = minimum + 1023;
+ new_size &= ~0x3ff;
+ p = realloc(zip->uncompressed_buffer, new_size);
+ if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory for 7-Zip decompression");
return (ARCHIVE_FATAL);
}
+ zip->uncompressed_buffer = (unsigned char *)p;
+ zip->uncompressed_buffer_size = new_size;
}
/*
* Move unconsumed bytes to the head.
@@ -2965,7 +2997,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
size_t bytes_in, bytes_out;
const void *buff_in;
unsigned char *buff_out;
- int eof;
+ int end_of_data;
/*
* Note: '1' here is a performance optimization.
@@ -2987,23 +3019,23 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
- zip->uncompressed_buffer_bytes_remaining;
bytes_in = bytes_avail;
if (bytes_in > zip->pack_stream_inbytes_remaining)
- bytes_in = zip->pack_stream_inbytes_remaining;
+ bytes_in = (size_t)zip->pack_stream_inbytes_remaining;
/* Drive decompression. */
r = decompress(a, zip, buff_out, &bytes_out,
buff_in, &bytes_in);
switch (r) {
case ARCHIVE_OK:
- eof = 0;
+ end_of_data = 0;
break;
case ARCHIVE_EOF:
- eof = 1;
+ end_of_data = 1;
break;
default:
return (ARCHIVE_FATAL);
}
zip->pack_stream_inbytes_remaining -= bytes_in;
if (bytes_out > zip->folder_outbytes_remaining)
- bytes_out = zip->folder_outbytes_remaining;
+ bytes_out = (size_t)zip->folder_outbytes_remaining;
zip->folder_outbytes_remaining -= bytes_out;
zip->uncompressed_buffer_bytes_remaining += bytes_out;
zip->pack_stream_bytes_unconsumed = bytes_in;
@@ -3021,7 +3053,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
if (zip->pack_stream_inbytes_remaining == 0 &&
zip->folder_outbytes_remaining == 0)
break;
- if (eof || (bytes_in == 0 && bytes_out == 0)) {
+ if (end_of_data || (bytes_in == 0 && bytes_out == 0)) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive");
return (ARCHIVE_FATAL);
@@ -3041,7 +3073,7 @@ static int
seek_pack(struct archive_read *a)
{
struct _7zip *zip = (struct _7zip *)a->format->data;
- uint64_t pack_offset;
+ int64_t pack_offset;
if (zip->pack_stream_remaining <= 0) {
archive_set_error(&(a->archive),
@@ -3068,7 +3100,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
{
struct _7zip *zip = (struct _7zip *)a->format->data;
uint64_t skip_bytes = 0;
- int r;
+ ssize_t r;
if (zip->uncompressed_buffer_bytes_remaining == 0) {
if (zip->pack_stream_inbytes_remaining > 0) {
@@ -3160,7 +3192,8 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
return (ARCHIVE_FATAL);
}
}
- skipped = get_uncompressed_data(a, buff, skip_bytes, 0);
+ skipped = get_uncompressed_data(
+ a, buff, (size_t)skip_bytes, 0);
if (skipped < 0)
return (skipped);
skip_bytes -= skipped;
@@ -3292,13 +3325,13 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
}
coder2 = &(fc[3]);
zip->main_stream_bytes_remaining =
- folder->unPackSize[2];
+ (size_t)folder->unPackSize[2];
} else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 &&
zip->pack_stream_remaining == 4 &&
folder->numInStreams == 5 && folder->numOutStreams == 2) {
/* Source type 0 made by 7z */
zip->main_stream_bytes_remaining =
- folder->unPackSize[0];
+ (size_t)folder->unPackSize[0];
} else {
/* We got an unexpected form. */
archive_set_error(&(a->archive),
@@ -3311,30 +3344,35 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
if ((r = seek_pack(a)) < 0)
return (r);
zip->pack_stream_bytes_unconsumed =
- zip->pack_stream_inbytes_remaining;
+ (size_t)zip->pack_stream_inbytes_remaining;
read_consume(a);
/* Read following three sub streams. */
for (i = 0; i < 3; i++) {
const struct _7z_coder *coder = scoder[i];
- if ((r = seek_pack(a)) < 0)
+ if ((r = seek_pack(a)) < 0) {
+ free(b[0]); free(b[1]); free(b[2]);
return (r);
+ }
- if (sunpack[i] == -1)
+ if (sunpack[i] == (uint64_t)-1)
zip->folder_outbytes_remaining =
zip->pack_stream_inbytes_remaining;
else
zip->folder_outbytes_remaining = sunpack[i];
r = init_decompression(a, zip, coder, NULL);
- if (r != ARCHIVE_OK)
+ if (r != ARCHIVE_OK) {
+ free(b[0]); free(b[1]); free(b[2]);
return (ARCHIVE_FATAL);
+ }
/* Allocate memory for the decorded data of a sub
* stream. */
- b[i] = malloc(zip->folder_outbytes_remaining);
+ b[i] = malloc((size_t)zip->folder_outbytes_remaining);
if (b[i] == NULL) {
+ free(b[0]); free(b[1]); free(b[2]);
archive_set_error(&a->archive, ENOMEM,
"No memory for 7-Zip decompression");
return (ARCHIVE_FATAL);
@@ -3342,14 +3380,18 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
/* Extract a sub stream. */
while (zip->pack_stream_inbytes_remaining > 0) {
- r = extract_pack_stream(a, 0);
- if (r < 0)
+ r = (int)extract_pack_stream(a, 0);
+ if (r < 0) {
+ free(b[0]); free(b[1]); free(b[2]);
return (r);
+ }
bytes = get_uncompressed_data(a, &buff,
zip->uncompressed_buffer_bytes_remaining,
0);
- if (bytes < 0)
+ if (bytes < 0) {
+ free(b[0]); free(b[1]); free(b[2]);
return ((int)bytes);
+ }
memcpy(b[i]+s[i], buff, bytes);
s[i] += bytes;
if (zip->pack_stream_bytes_unconsumed)
@@ -3428,7 +3470,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes)
"Truncated 7-Zip file body");
return (ARCHIVE_FATAL);
}
- bytes -= skipped_bytes;
+ bytes -= (size_t)skipped_bytes;
if (zip->pack_stream_bytes_unconsumed)
read_consume(a);
}
@@ -3506,16 +3548,16 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
uint32_t dest;
for (;;) {
uint8_t b;
- int index;
+ int b_index;
dest = src - (ip + (uint32_t)bufferPos);
if (prevMask == 0)
break;
- index = kMaskToBitNumber[prevMask] * 8;
- b = (uint8_t)(dest >> (24 - index));
+ b_index = kMaskToBitNumber[prevMask] * 8;
+ b = (uint8_t)(dest >> (24 - b_index));
if (!Test86MSByte(b))
break;
- src = dest ^ ((1 << (32 - index)) - 1);
+ src = dest ^ ((1 << (32 - b_index)) - 1);
}
p[4] = (uint8_t)(~(((dest >> 24) & 1) - 1));
p[3] = (uint8_t)(dest >> 16);
@@ -3529,7 +3571,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
}
zip->bcj_prevPosT = prevPosT;
zip->bcj_prevMask = prevMask;
- zip->bcj_ip += bufferPos;
+ zip->bcj_ip += (uint32_t)bufferPos;
return (bufferPos);
}
@@ -3556,7 +3598,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
#define RC_READ_BYTE (*buffer++)
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
#define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \
- { int i; for (i = 0; i < 5; i++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }}
+ { int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }}
#define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }
@@ -3622,14 +3664,14 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
if (zip->bcj_state == 1) {
while (limit != 0) {
- uint8_t b = buf0[inPos];
- outBuf[outPos++] = b;
- if (IsJ(zip->bcj2_prevByte, b)) {
+ uint8_t bb = buf0[inPos];
+ outBuf[outPos++] = bb;
+ if (IsJ(zip->bcj2_prevByte, bb)) {
zip->bcj_state = 2;
break;
}
inPos++;
- zip->bcj2_prevByte = b;
+ zip->bcj2_prevByte = bb;
limit--;
}
}
@@ -3673,7 +3715,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
((uint32_t)v[1] << 16) |
((uint32_t)v[2] << 8) |
((uint32_t)v[3])) -
- ((uint32_t)zip->bcj2_outPos + outPos + 4);
+ ((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4);
out[0] = (uint8_t)dest;
out[1] = (uint8_t)(dest >> 8);
out[2] = (uint8_t)(dest >> 16);
@@ -3688,7 +3730,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
*/
zip->odd_bcj_size = 4 -i;
for (; i < 4; i++) {
- j = i - 4 + zip->odd_bcj_size;
+ j = i - 4 + (unsigned)zip->odd_bcj_size;
zip->odd_bcj[j] = out[i];
}
break;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
index 9feb547..40be18c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_ar.c
@@ -121,6 +121,7 @@ archive_read_support_format_ar(struct archive *_a)
archive_read_format_ar_read_header,
archive_read_format_ar_read_data,
archive_read_format_ar_skip,
+ NULL,
archive_read_format_ar_cleanup);
if (r != ARCHIVE_OK) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
index e65010e..4dd38db 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2010-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -292,6 +292,8 @@ struct cab {
char end_of_archive;
char end_of_entry;
char end_of_entry_cleanup;
+ char read_data_invoked;
+ int64_t bytes_skipped;
unsigned char *uncompressed_buffer;
size_t uncompressed_buffer_size;
@@ -349,7 +351,7 @@ static int lzx_read_bitlen(struct lzx_stream *, struct huffman *, int);
static int lzx_huffman_init(struct huffman *, size_t, int);
static void lzx_huffman_free(struct huffman *);
static int lzx_make_huffman_table(struct huffman *);
-static int inline lzx_decode_huffman(struct huffman *, unsigned);
+static inline int lzx_decode_huffman(struct huffman *, unsigned);
static int lzx_decode_huffman_tree(struct huffman *, unsigned, int);
@@ -380,6 +382,7 @@ archive_read_support_format_cab(struct archive *_a)
archive_read_format_cab_read_header,
archive_read_format_cab_read_data,
archive_read_format_cab_read_data_skip,
+ NULL,
archive_read_format_cab_cleanup);
if (r != ARCHIVE_OK)
@@ -478,11 +481,13 @@ archive_read_format_cab_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "cab: unknown keyword ``%s''", key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -535,7 +540,7 @@ truncated_error(struct archive_read *a)
return (ARCHIVE_FATAL);
}
-static int
+static ssize_t
cab_strnlen(const unsigned char *p, size_t maxlen)
{
size_t i;
@@ -546,7 +551,7 @@ cab_strnlen(const unsigned char *p, size_t maxlen)
}
if (i > maxlen)
return (-1);/* invalid */
- return (i);
+ return ((ssize_t)i);
}
/* Read bytes as much as remaining. */
@@ -622,8 +627,9 @@ cab_read_header(struct archive_read *a)
struct cab *cab;
struct cfheader *hd;
size_t bytes, used;
+ ssize_t len;
int64_t skip;
- int err, i, len;
+ int err, i;
int cur_folder, prev_folder;
uint32_t offset32;
@@ -796,7 +802,7 @@ cab_read_header(struct archive_read *a)
file->offset = archive_le32dec(p + CFFILE_uoffFolderStart);
file->folder = archive_le16dec(p + CFFILE_iFolder);
file->mtime = cab_dos_time(p + CFFILE_date_time);
- file->attr = archive_le16dec(p + CFFILE_attribs);
+ file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs);
__archive_read_consume(a, 16);
cab->cab_offset += 16;
@@ -986,7 +992,7 @@ archive_read_format_cab_read_header(struct archive_read *a,
if (file->attr & ATTR_RDONLY)
archive_entry_set_mode(entry, AE_IFREG | 0555);
else
- archive_entry_set_mode(entry, AE_IFREG | 0777);
+ archive_entry_set_mode(entry, AE_IFREG | 0666);
archive_entry_set_mtime(entry, file->mtime, 0);
cab->entry_bytes_remaining = file->uncompressed_size;
@@ -1024,9 +1030,22 @@ archive_read_format_cab_read_data(struct archive_read *a,
default:
break;
}
+ if (cab->read_data_invoked == 0) {
+ if (cab->bytes_skipped) {
+ if (cab->entry_cfdata == NULL) {
+ r = cab_next_cfdata(a);
+ if (r < 0)
+ return (r);
+ }
+ if (cab_consume_cfdata(a, cab->bytes_skipped) < 0)
+ return (ARCHIVE_FATAL);
+ cab->bytes_skipped = 0;
+ }
+ cab->read_data_invoked = 1;
+ }
if (cab->entry_unconsumed) {
/* Consume as much as the compressor actually used. */
- r = cab_consume_cfdata(a, cab->entry_unconsumed);
+ r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
cab->entry_unconsumed = 0;
if (r < 0)
return (r);
@@ -1049,13 +1068,13 @@ static uint32_t
cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed)
{
const unsigned char *b;
- int u32num;
+ unsigned u32num;
uint32_t sum;
- u32num = bytes / 4;
+ u32num = (unsigned)bytes / 4;
sum = seed;
b = p;
- while (--u32num >= 0) {
+ for (;u32num > 0; --u32num) {
sum ^= archive_le32dec(b);
b += 4;
}
@@ -1356,46 +1375,25 @@ cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail)
struct cab *cab = (struct cab *)(a->format->data);
struct cfdata *cfdata;
const void *d;
- int64_t skipped_bytes;
cfdata = cab->entry_cfdata;
- if (cfdata->uncompressed_avail == 0 &&
- cfdata->read_offset > 0) {
- /* we've already skipped some bytes before really read. */
- skipped_bytes = cfdata->read_offset;
- cfdata->read_offset = 0;
- cfdata->uncompressed_bytes_remaining += skipped_bytes;
- } else
- skipped_bytes = 0;
- do {
- /*
- * Note: '1' here is a performance optimization.
- * Recall that the decompression layer returns a count of
- * available bytes; asking for more than that forces the
- * decompressor to combine reads by copying data.
- */
- d = __archive_read_ahead(a, 1, avail);
- if (*avail <= 0) {
- *avail = truncated_error(a);
- return (NULL);
- }
- if (*avail > cfdata->uncompressed_bytes_remaining)
- *avail = cfdata->uncompressed_bytes_remaining;
- cfdata->uncompressed_avail = cfdata->uncompressed_size;
- cfdata->unconsumed = *avail;
- cfdata->sum_ptr = d;
- if (skipped_bytes > 0) {
- skipped_bytes =
- cab_minimum_consume_cfdata(a, skipped_bytes);
- if (skipped_bytes < 0) {
- *avail = ARCHIVE_FATAL;
- return (NULL);
- }
- continue;
- }
- } while (0);
-
+ /*
+ * Note: '1' here is a performance optimization.
+ * Recall that the decompression layer returns a count of
+ * available bytes; asking for more than that forces the
+ * decompressor to combine reads by copying data.
+ */
+ d = __archive_read_ahead(a, 1, avail);
+ if (*avail <= 0) {
+ *avail = truncated_error(a);
+ return (NULL);
+ }
+ if (*avail > cfdata->uncompressed_bytes_remaining)
+ *avail = cfdata->uncompressed_bytes_remaining;
+ cfdata->uncompressed_avail = cfdata->uncompressed_size;
+ cfdata->unconsumed = *avail;
+ cfdata->sum_ptr = d;
return (d);
}
@@ -1489,7 +1487,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
* cast to remove 'const'.
*/
cab->stream.next_in = (Bytef *)(uintptr_t)d;
- cab->stream.avail_in = bytes_avail;
+ cab->stream.avail_in = (uInt)bytes_avail;
cab->stream.total_in = 0;
/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
@@ -1510,7 +1508,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
*avail = ARCHIVE_FATAL;
return (NULL);
}
- mszip -= bytes_avail;
+ mszip -= (int)bytes_avail;
continue;
}
if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
@@ -1541,7 +1539,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
return (NULL);
}
}
- uavail = cab->stream.total_out;
+ uavail = (uint16_t)cab->stream.total_out;
if (uavail < cfdata->uncompressed_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -1719,7 +1717,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
}
}
- uavail = cab->xstrm.total_out;
+ uavail = (uint16_t)cab->xstrm.total_out;
/*
* Make sure a read pointer advances to next CFDATA.
*/
@@ -1791,9 +1789,8 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
rbytes -= cbytes;
if (cfdata->uncompressed_avail == 0 &&
- (cab->entry_cffolder->comptype == COMPTYPE_NONE ||
- cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT ||
- cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) {
+ (cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT ||
+ cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) {
/* We have not read any data yet. */
if (cbytes == cfdata->uncompressed_bytes_remaining) {
/* Skip whole current CFDATA. */
@@ -1819,8 +1816,8 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
}
continue;
}
- cfdata->read_offset += cbytes;
- cfdata->uncompressed_bytes_remaining -= cbytes;
+ cfdata->read_offset += (uint16_t)cbytes;
+ cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
break;
} else if (cbytes == 0) {
err = cab_next_cfdata(a);
@@ -1844,7 +1841,7 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
if (avail <= 0)
return (ARCHIVE_FATAL);
if (avail > cbytes)
- avail = cbytes;
+ avail = (ssize_t)cbytes;
if (cab_minimum_consume_cfdata(a, avail) < 0)
return (ARCHIVE_FATAL);
cbytes -= avail;
@@ -1873,8 +1870,8 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
else
cbytes = cfdata->unconsumed;
rbytes -= cbytes;
- cfdata->read_offset += cbytes;
- cfdata->uncompressed_bytes_remaining -= cbytes;
+ cfdata->read_offset += (uint16_t)cbytes;
+ cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
cfdata->unconsumed -= cbytes;
} else {
cbytes = cfdata->uncompressed_avail - cfdata->read_offset;
@@ -1882,8 +1879,8 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
if (consumed_bytes < cbytes)
cbytes = consumed_bytes;
rbytes -= cbytes;
- cfdata->read_offset += cbytes;
- cfdata->uncompressed_bytes_remaining -= cbytes;
+ cfdata->read_offset += (uint16_t)cbytes;
+ cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
}
if (cfdata->unconsumed) {
@@ -1894,12 +1891,12 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
}
if (cbytes) {
/* Compute the sum. */
- cab_checksum_update(a, cbytes);
+ cab_checksum_update(a, (size_t)cbytes);
/* Consume as much as the compressor actually used. */
__archive_read_consume(a, cbytes);
cab->cab_offset += cbytes;
- cfdata->compressed_bytes_remaining -= cbytes;
+ cfdata->compressed_bytes_remaining -= (uint16_t)cbytes;
if (cfdata->compressed_bytes_remaining == 0) {
err = cab_checksum_finish(a);
if (err < 0)
@@ -1940,10 +1937,10 @@ cab_read_data(struct archive_read *a, const void **buff,
ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA");
return (ARCHIVE_FATAL);
} else
- return (bytes_avail);
+ return ((int)bytes_avail);
}
if (bytes_avail > cab->entry_bytes_remaining)
- bytes_avail = cab->entry_bytes_remaining;
+ bytes_avail = (ssize_t)cab->entry_bytes_remaining;
*size = bytes_avail;
*offset = cab->entry_offset;
@@ -1952,6 +1949,11 @@ cab_read_data(struct archive_read *a, const void **buff,
if (cab->entry_bytes_remaining == 0)
cab->end_of_entry = 1;
cab->entry_unconsumed = bytes_avail;
+ if (cab->entry_cffolder->comptype == COMPTYPE_NONE) {
+ /* Don't consume more than current entry used. */
+ if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed)
+ cab->entry_cfdata->unconsumed = cab->entry_unconsumed;
+ }
return (ARCHIVE_OK);
}
@@ -1967,9 +1969,17 @@ archive_read_format_cab_read_data_skip(struct archive_read *a)
if (cab->end_of_archive)
return (ARCHIVE_EOF);
+ if (!cab->read_data_invoked) {
+ cab->bytes_skipped += cab->entry_bytes_remaining;
+ cab->entry_bytes_remaining = 0;
+ /* This entry is finished and done. */
+ cab->end_of_entry_cleanup = cab->end_of_entry = 1;
+ return (ARCHIVE_OK);
+ }
+
if (cab->entry_unconsumed) {
/* Consume as much as the compressor actually used. */
- r = cab_consume_cfdata(a, cab->entry_unconsumed);
+ r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
cab->entry_unconsumed = 0;
if (r < 0)
return (r);
@@ -1991,6 +2001,12 @@ archive_read_format_cab_read_data_skip(struct archive_read *a)
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
+ /* If the compression type is none(uncompressed), we've already
+ * consumed data as much as the current entry size. */
+ if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
+ cab->entry_cfdata != NULL)
+ cab->entry_cfdata->unconsumed = 0;
+
/* This entry is finished and done. */
cab->end_of_entry_cleanup = cab->end_of_entry = 1;
return (ARCHIVE_OK);
@@ -2066,6 +2082,7 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits)
struct lzx_dec *ds;
int slot, w_size, w_slot;
int base, footer;
+ int base_inc[18];
if (strm->ds == NULL) {
strm->ds = calloc(1, sizeof(*strm->ds));
@@ -2100,13 +2117,15 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits)
lzx_huffman_free(&(ds->mt));
}
+ for (footer = 0; footer < 18; footer++)
+ base_inc[footer] = 1 << footer;
base = footer = 0;
for (slot = 0; slot < w_slot; slot++) {
int n;
if (footer == 0)
base = slot;
else
- base += 1 << footer;
+ base += base_inc[footer];
if (footer < 17) {
footer = -2;
for (n = base; n; n >>= 1)
@@ -2180,11 +2199,11 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
end = b + size - 10;
while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) {
size_t i = b - (unsigned char *)p;
- long cp, displacement, value;
+ int32_t cp, displacement, value;
- cp = offset + i;
+ cp = (int32_t)(offset + (uint32_t)i);
value = archive_le32dec(&b[1]);
- if (value >= -cp && value < (long)ds->translation_size) {
+ if (value >= -cp && value < (int32_t)ds->translation_size) {
if (value >= 0)
displacement = value - cp;
else
@@ -2222,7 +2241,9 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
/* Notify how many bits we consumed. */
#define lzx_br_consume(br, n) ((br)->cache_avail -= (n))
-#define lzx_br_consume_unalined_bits(br) ((br)->cache_avail &= ~0x0f)
+#define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f)
+
+#define lzx_br_is_unaligned(br) ((br)->cache_avail & 0x0f)
static const uint32_t cache_masks[] = {
0x00000000, 0x00000001, 0x00000003, 0x00000007,
@@ -2349,24 +2370,25 @@ lzx_cleanup_bitstream(struct lzx_stream *strm)
#define ST_RD_TRANSLATION_SIZE 1
#define ST_RD_BLOCK_TYPE 2
#define ST_RD_BLOCK_SIZE 3
-#define ST_RD_R0 4
-#define ST_RD_R1 5
-#define ST_RD_R2 6
-#define ST_COPY_UNCOMP1 7
-#define ST_COPY_UNCOMP2 8
-#define ST_RD_ALIGNED_OFFSET 9
-#define ST_RD_VERBATIM 10
-#define ST_RD_PRE_MAIN_TREE_256 11
-#define ST_MAIN_TREE_256 12
-#define ST_RD_PRE_MAIN_TREE_REM 13
-#define ST_MAIN_TREE_REM 14
-#define ST_RD_PRE_LENGTH_TREE 15
-#define ST_LENGTH_TREE 16
-#define ST_MAIN 17
-#define ST_LENGTH 18
-#define ST_OFFSET 19
-#define ST_REAL_POS 20
-#define ST_COPY 21
+#define ST_RD_ALIGNMENT 4
+#define ST_RD_R0 5
+#define ST_RD_R1 6
+#define ST_RD_R2 7
+#define ST_COPY_UNCOMP1 8
+#define ST_COPY_UNCOMP2 9
+#define ST_RD_ALIGNED_OFFSET 10
+#define ST_RD_VERBATIM 11
+#define ST_RD_PRE_MAIN_TREE_256 12
+#define ST_MAIN_TREE_256 13
+#define ST_RD_PRE_MAIN_TREE_REM 14
+#define ST_MAIN_TREE_REM 15
+#define ST_RD_PRE_LENGTH_TREE 16
+#define ST_LENGTH_TREE 17
+#define ST_MAIN 18
+#define ST_LENGTH 19
+#define ST_OFFSET 20
+#define ST_REAL_POS 21
+#define ST_COPY 22
static int
lzx_decode(struct lzx_stream *strm, int last)
@@ -2470,12 +2492,25 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
ds->state = ST_RD_ALIGNED_OFFSET;
break;
}
+ /* FALL THROUGH */
+ case ST_RD_ALIGNMENT:
/*
* Handle an Uncompressed Block.
*/
/* Skip padding to align following field on
* 16-bit boundary. */
- lzx_br_consume_unalined_bits(br);
+ if (lzx_br_is_unaligned(br))
+ lzx_br_consume_unaligned_bits(br);
+ else {
+ if (lzx_br_read_ahead(strm, br, 16))
+ lzx_br_consume(br, 16);
+ else {
+ ds->state = ST_RD_ALIGNMENT;
+ if (last)
+ goto failed;
+ return (ARCHIVE_OK);
+ }
+ }
/* Preparation to read repeated offsets R0,R1 and R2. */
ds->rbytes_avail = 0;
ds->state = ST_RD_R0;
@@ -2500,8 +2535,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
lzx_br_consume(br, 16);
archive_le16enc(ds->rbytes, u16);
ds->rbytes_avail = 2;
- } else
- ds->rbytes_avail = 0;
+ }
if (ds->rbytes_avail < 4 && ds->br.have_odd) {
ds->rbytes[ds->rbytes_avail++] =
ds->br.odd;
@@ -2517,6 +2551,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
*strm->next_in++;
strm->avail_in--;
}
+ ds->rbytes_avail = 0;
if (ds->state == ST_RD_R0) {
ds->r0 = archive_le32dec(ds->rbytes);
if (ds->r0 < 0)
@@ -2541,8 +2576,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
* Copy bytes form next_in to next_out directly.
*/
while (ds->block_bytes_avail) {
- unsigned char *d;
- int l,ll;
+ int l;
if (strm->avail_out <= 0)
/* Output buffer is empty. */
@@ -2553,24 +2587,23 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
goto failed;
return (ARCHIVE_OK);
}
- l = ds->block_bytes_avail;
+ l = (int)ds->block_bytes_avail;
if (l > ds->w_size - ds->w_pos)
l = ds->w_size - ds->w_pos;
if (l > strm->avail_out)
l = (int)strm->avail_out;
if (l > strm->avail_in)
l = (int)strm->avail_in;
- ll = l;
- d = &(ds->w_buff[ds->w_pos]);
- while (--l >= 0) {
- *strm->next_out++ = *strm->next_in;
- *d++ = *strm->next_in++;
- }
- strm->avail_out -= ll;
- strm->total_out += ll;
- strm->avail_in -= ll;
- ds->w_pos = (ds->w_pos + ll) & ds->w_mask;
- ds->block_bytes_avail -= ll;
+ memcpy(strm->next_out, strm->next_in, l);
+ memcpy(&(ds->w_buff[ds->w_pos]),
+ strm->next_in, l);
+ strm->next_in += l;
+ strm->avail_in -= l;
+ strm->next_out += l;
+ strm->avail_out -= l;
+ strm->total_out += l;
+ ds->w_pos = (ds->w_pos + l) & ds->w_mask;
+ ds->block_bytes_avail -= l;
}
/* FALL THROUGH */
case ST_COPY_UNCOMP2:
@@ -2716,8 +2749,8 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
struct lzx_br bre = ds->br;
struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt);
const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl;
- unsigned char *outp = strm->next_out;
- unsigned char *endp = outp + strm->avail_out;
+ unsigned char *noutp = strm->next_out;
+ unsigned char *endp = noutp + strm->avail_out;
unsigned char *w_buff = ds->w_buff;
unsigned char *at_bitlen = at->bitlen;
unsigned char *lt_bitlen = lt->bitlen;
@@ -2751,10 +2784,10 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
ds->position_slot = position_slot;
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
ds->w_pos = w_pos;
- strm->avail_out = endp - outp;
+ strm->avail_out = endp - noutp;
return (ARCHIVE_EOF);
}
- if (outp >= endp)
+ if (noutp >= endp)
/* Output buffer is empty. */
goto next_data;
@@ -2788,7 +2821,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
w_buff[w_pos] = c;
w_pos = (w_pos + 1) & w_mask;
/* Store the decoded code to output buffer. */
- *outp++ = c;
+ *noutp++ = c;
block_bytes_avail--;
}
/*
@@ -2933,22 +2966,22 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
if (l > w_size - w_pos)
l = w_size - w_pos;
}
- if (outp + l >= endp)
- l = endp - outp;
+ if (noutp + l >= endp)
+ l = (int)(endp - noutp);
s = w_buff + copy_pos;
if (l >= 8 && ((copy_pos + l < w_pos)
|| (w_pos + l < copy_pos))) {
memcpy(w_buff + w_pos, s, l);
- memcpy(outp, s, l);
+ memcpy(noutp, s, l);
} else {
unsigned char *d;
int li;
d = w_buff + w_pos;
for (li = 0; li < l; li++)
- outp[li] = d[li] = s[li];
+ noutp[li] = d[li] = s[li];
}
- outp += l;
+ noutp += l;
copy_pos = (copy_pos + l) & w_mask;
w_pos = (w_pos + l) & w_mask;
block_bytes_avail -= l;
@@ -2956,7 +2989,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
/* A copy of current pattern ended. */
break;
copy_len -= l;
- if (outp >= endp) {
+ if (noutp >= endp) {
/* Output buffer is empty. */
state = ST_COPY;
goto next_data;
@@ -2979,7 +3012,7 @@ next_data:
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
ds->state = state;
ds->w_pos = w_pos;
- strm->avail_out = endp - outp;
+ strm->avail_out = endp - noutp;
return (ARCHIVE_OK);
}
@@ -3096,7 +3129,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0]));
if (hf->bitlen == NULL)
return (ARCHIVE_FATAL);
- hf->len_size = len_size;
+ hf->len_size = (int)len_size;
} else
memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0]));
if (hf->tbl == NULL) {
@@ -3104,7 +3137,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
bits = tbl_bits;
else
bits = HTBL_BITS;
- hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0]));
+ hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
if (hf->tbl == NULL)
return (ARCHIVE_FATAL);
hf->tbl_bits = tbl_bits;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
index 5ae73d7..819f4a4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2010-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -242,6 +242,7 @@ archive_read_support_format_cpio(struct archive *_a)
archive_read_format_cpio_read_header,
archive_read_format_cpio_read_data,
archive_read_format_cpio_skip,
+ NULL,
archive_read_format_cpio_cleanup);
if (r != ARCHIVE_OK)
@@ -325,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a,
if (strcmp(key, "compat-2x") == 0) {
/* Handle filnames as libarchive 2.x */
cpio->init_default_conversion = (val != NULL)?1:0;
- ret = ARCHIVE_OK;
+ return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -339,11 +340,13 @@ archive_read_format_cpio_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "cpio: unknown keyword ``%s''", key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -396,11 +399,12 @@ archive_read_format_cpio_read_header(struct archive_read *a,
/* If this is a symlink, read the link contents. */
if (archive_entry_filetype(entry) == AE_IFLNK) {
- h = __archive_read_ahead(a, cpio->entry_bytes_remaining, NULL);
+ h = __archive_read_ahead(a,
+ (size_t)cpio->entry_bytes_remaining, NULL);
if (h == NULL)
return (ARCHIVE_FATAL);
if (archive_entry_copy_symlink_l(entry, (const char *)h,
- cpio->entry_bytes_remaining, sconv) != 0) {
+ (size_t)cpio->entry_bytes_remaining, sconv) != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Linkname");
@@ -456,7 +460,7 @@ archive_read_format_cpio_read_data(struct archive_read *a,
if (bytes_read <= 0)
return (ARCHIVE_FATAL);
if (bytes_read > cpio->entry_bytes_remaining)
- bytes_read = cpio->entry_bytes_remaining;
+ bytes_read = (ssize_t)cpio->entry_bytes_remaining;
*size = bytes_read;
cpio->entry_bytes_unconsumed = bytes_read;
*offset = cpio->entry_offset;
@@ -601,17 +605,23 @@ header_newc(struct archive_read *a, struct cpio *cpio,
/* TODO: Abort here? */
}
- archive_entry_set_devmajor(entry, atol16(header + newc_devmajor_offset, newc_devmajor_size));
- archive_entry_set_devminor(entry, atol16(header + newc_devminor_offset, newc_devminor_size));
+ archive_entry_set_devmajor(entry,
+ (dev_t)atol16(header + newc_devmajor_offset, newc_devmajor_size));
+ archive_entry_set_devminor(entry,
+ (dev_t)atol16(header + newc_devminor_offset, newc_devminor_size));
archive_entry_set_ino(entry, atol16(header + newc_ino_offset, newc_ino_size));
- archive_entry_set_mode(entry, atol16(header + newc_mode_offset, newc_mode_size));
+ archive_entry_set_mode(entry,
+ (mode_t)atol16(header + newc_mode_offset, newc_mode_size));
archive_entry_set_uid(entry, atol16(header + newc_uid_offset, newc_uid_size));
archive_entry_set_gid(entry, atol16(header + newc_gid_offset, newc_gid_size));
- archive_entry_set_nlink(entry, atol16(header + newc_nlink_offset, newc_nlink_size));
- archive_entry_set_rdevmajor(entry, atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size));
- archive_entry_set_rdevminor(entry, atol16(header + newc_rdevminor_offset, newc_rdevminor_size));
+ archive_entry_set_nlink(entry,
+ (unsigned int)atol16(header + newc_nlink_offset, newc_nlink_size));
+ archive_entry_set_rdevmajor(entry,
+ (dev_t)atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size));
+ archive_entry_set_rdevminor(entry,
+ (dev_t)atol16(header + newc_rdevminor_offset, newc_rdevminor_size));
archive_entry_set_mtime(entry, atol16(header + newc_mtime_offset, newc_mtime_size), 0);
- *namelength = atol16(header + newc_namesize_offset, newc_namesize_size);
+ *namelength = (size_t)atol16(header + newc_namesize_offset, newc_namesize_size);
/* Pad name to 2 more than a multiple of 4. */
*name_pad = (2 - *namelength) & 3;
@@ -765,15 +775,19 @@ header_odc(struct archive_read *a, struct cpio *cpio,
/* Parse out octal fields. */
header = (const char *)h;
- archive_entry_set_dev(entry, atol8(header + odc_dev_offset, odc_dev_size));
+ archive_entry_set_dev(entry,
+ (dev_t)atol8(header + odc_dev_offset, odc_dev_size));
archive_entry_set_ino(entry, atol8(header + odc_ino_offset, odc_ino_size));
- archive_entry_set_mode(entry, atol8(header + odc_mode_offset, odc_mode_size));
+ archive_entry_set_mode(entry,
+ (mode_t)atol8(header + odc_mode_offset, odc_mode_size));
archive_entry_set_uid(entry, atol8(header + odc_uid_offset, odc_uid_size));
archive_entry_set_gid(entry, atol8(header + odc_gid_offset, odc_gid_size));
- archive_entry_set_nlink(entry, atol8(header + odc_nlink_offset, odc_nlink_size));
- archive_entry_set_rdev(entry, atol8(header + odc_rdev_offset, odc_rdev_size));
+ archive_entry_set_nlink(entry,
+ (unsigned int)atol8(header + odc_nlink_offset, odc_nlink_size));
+ archive_entry_set_rdev(entry,
+ (dev_t)atol8(header + odc_rdev_offset, odc_rdev_size));
archive_entry_set_mtime(entry, atol8(header + odc_mtime_offset, odc_mtime_size), 0);
- *namelength = atol8(header + odc_namesize_offset, odc_namesize_size);
+ *namelength = (size_t)atol8(header + odc_namesize_offset, odc_namesize_size);
*name_pad = 0; /* No padding of filename. */
/*
@@ -814,15 +828,19 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
/* Parse out octal fields. */
header = (const char *)h;
- archive_entry_set_dev(entry, atol16(header + afiol_dev_offset, afiol_dev_size));
+ archive_entry_set_dev(entry,
+ (dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size));
- archive_entry_set_mode(entry, atol8(header + afiol_mode_offset, afiol_mode_size));
+ archive_entry_set_mode(entry,
+ (mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
archive_entry_set_gid(entry, atol16(header + afiol_gid_offset, afiol_gid_size));
- archive_entry_set_nlink(entry, atol16(header + afiol_nlink_offset, afiol_nlink_size));
- archive_entry_set_rdev(entry, atol16(header + afiol_rdev_offset, afiol_rdev_size));
+ archive_entry_set_nlink(entry,
+ (unsigned int)atol16(header + afiol_nlink_offset, afiol_nlink_size));
+ archive_entry_set_rdev(entry,
+ (dev_t)atol16(header + afiol_rdev_offset, afiol_rdev_size));
archive_entry_set_mtime(entry, atol16(header + afiol_mtime_offset, afiol_mtime_size), 0);
- *namelength = atol16(header + afiol_namesize_offset, afiol_namesize_size);
+ *namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size);
*name_pad = 0; /* No padding of filename. */
cpio->entry_bytes_remaining =
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c
index 3dc2196..3660738 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c
@@ -53,6 +53,7 @@ archive_read_support_format_empty(struct archive *_a)
archive_read_format_empty_read_header,
archive_read_format_empty_read_data,
NULL,
+ NULL,
NULL);
return (r);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
index db7aa9d..8147461 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2009 Andreas Henriksson <andreas@fatal.se>
- * Copyright (c) 2009-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2009-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -374,6 +374,8 @@ struct iso9660 {
size_t utf16be_path_len;
unsigned char *utf16be_previous_path;
size_t utf16be_previous_path_len;
+ /* Null buufer used in bidder to improve its performance. */
+ unsigned char null[2048];
};
static int archive_read_format_iso9660_bid(struct archive_read *, int);
@@ -475,6 +477,7 @@ archive_read_support_format_iso9660(struct archive *_a)
archive_read_format_iso9660_read_header,
archive_read_format_iso9660_read_data,
archive_read_format_iso9660_read_data_skip,
+ NULL,
archive_read_format_iso9660_cleanup);
if (r != ARCHIVE_OK) {
@@ -588,6 +591,23 @@ archive_read_format_iso9660_options(struct archive_read *a,
}
static int
+isNull(struct iso9660 *iso9660, const unsigned char *h, unsigned offset,
+unsigned bytes)
+{
+
+ while (bytes >= sizeof(iso9660->null)) {
+ if (!memcmp(iso9660->null, h + offset, sizeof(iso9660->null)))
+ return (0);
+ offset += sizeof(iso9660->null);
+ bytes -= sizeof(iso9660->null);
+ }
+ if (bytes)
+ return memcmp(iso9660->null, h + offset, bytes) == 0;
+ else
+ return (1);
+}
+
+static int
isBootRecord(struct iso9660 *iso9660, const unsigned char *h)
{
(void)iso9660; /* UNUSED */
@@ -632,8 +652,6 @@ isVolumePartition(struct iso9660 *iso9660, const unsigned char *h)
static int
isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
{
- int i;
-
(void)iso9660; /* UNUSED */
/* Type of the Volume Descriptor Set Terminator must be 255. */
@@ -645,9 +663,8 @@ isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 7; i < 2048; ++i)
- if (h[i] != 0)
- return (0);
+ if (!isNull(iso9660, h, 7, 2048-7))
+ return (0);
return (1);
}
@@ -708,7 +725,6 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
ssize_t logical_block_size;
int32_t volume_block;
int32_t location;
- int i;
(void)iso9660; /* UNUSED */
@@ -717,15 +733,12 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < SVD_reserved1_size; ++i)
- if (h[SVD_reserved1_offset + i] != 0)
- return (0);
- for (i = 0; i < SVD_reserved2_size; ++i)
- if (h[SVD_reserved2_offset + i] != 0)
- return (0);
- for (i = 0; i < SVD_reserved3_size; ++i)
- if (h[SVD_reserved3_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, SVD_reserved1_offset, SVD_reserved1_size))
+ return (0);
+ if (!isNull(iso9660, h, SVD_reserved2_offset, SVD_reserved2_size))
+ return (0);
+ if (!isNull(iso9660, h, SVD_reserved3_offset, SVD_reserved3_size))
+ return (0);
/* File structure version must be 1 for ISO9660/ECMA119. */
if (h[SVD_file_structure_version_offset] != 1)
@@ -771,7 +784,6 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
ssize_t logical_block_size;
int32_t volume_block;
int32_t location;
- int i;
(void)iso9660; /* UNUSED */
@@ -788,14 +800,12 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved2_size; ++i)
- if (h[PVD_reserved2_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
+ return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved3_size; ++i)
- if (h[PVD_reserved3_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
+ return (0);
/* Logical block size must be > 0. */
/* I've looked at Ecma 119 and can't find any stronger
@@ -830,14 +840,12 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved4_size; ++i)
- if (h[PVD_reserved4_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved4_offset, PVD_reserved4_size))
+ return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved5_size; ++i)
- if (h[PVD_reserved5_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
+ return (0);
/* Read Root Directory Record in Volume Descriptor. */
p = h + PVD_root_directory_record_offset;
@@ -869,14 +877,12 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved2_size; ++i)
- if (h[PVD_reserved2_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
+ return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved3_size; ++i)
- if (h[PVD_reserved3_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
+ return (0);
/* Logical block size must be > 0. */
/* I've looked at Ecma 119 and can't find any stronger
@@ -919,9 +925,8 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
- for (i = 0; i < PVD_reserved5_size; ++i)
- if (h[PVD_reserved5_offset + i] != 0)
- return (0);
+ if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
+ return (0);
/* XXX TODO: Check other values for sanity; reject more
* malformed PVDs. XXX */
@@ -934,8 +939,10 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
if (!iso9660->primary.location) {
iso9660->logical_block_size = logical_block_size;
iso9660->volume_block = volume_block;
- iso9660->volume_size = logical_block_size * (uint64_t)volume_block;
- iso9660->primary.location = archive_le32dec(p + DR_extent_offset);
+ iso9660->volume_size =
+ logical_block_size * (uint64_t)volume_block;
+ iso9660->primary.location =
+ archive_le32dec(p + DR_extent_offset);
iso9660->primary.size = archive_le32dec(p + DR_size_offset);
}
@@ -951,6 +958,12 @@ read_children(struct archive_read *a, struct file_info *parent)
size_t step, skip_size;
iso9660 = (struct iso9660 *)(a->format->data);
+ /* flush any remaining bytes from the last round to ensure
+ * we're positioned */
+ if (iso9660->entry_bytes_unconsumed) {
+ __archive_read_consume(a, iso9660->entry_bytes_unconsumed);
+ iso9660->entry_bytes_unconsumed = 0;
+ }
if (iso9660->current_position > parent->offset) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignoring out-of-order directory (%s) %jd > %jd",
@@ -975,8 +988,8 @@ read_children(struct archive_read *a, struct file_info *parent)
iso9660->current_position = parent->offset;
}
- step = ((parent->size + iso9660->logical_block_size -1) /
- iso9660->logical_block_size) * iso9660->logical_block_size;
+ step = (size_t)(((parent->size + iso9660->logical_block_size -1) /
+ iso9660->logical_block_size) * iso9660->logical_block_size);
b = __archive_read_ahead(a, step, NULL);
if (b == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -1060,101 +1073,112 @@ read_children(struct archive_read *a, struct file_info *parent)
}
static int
-archive_read_format_iso9660_read_header(struct archive_read *a,
- struct archive_entry *entry)
+choose_volume(struct archive_read *a, struct iso9660 *iso9660)
{
- struct iso9660 *iso9660;
struct file_info *file;
- int r, rd_r = ARCHIVE_OK;
-
- iso9660 = (struct iso9660 *)(a->format->data);
+ int64_t skipsize;
+ struct vd *vd;
+ const void *block;
+ char seenJoliet;
- if (!a->archive.archive_format) {
- a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
- a->archive.archive_format_name = "ISO9660";
+ vd = &(iso9660->primary);
+ if (!iso9660->opt_support_joliet)
+ iso9660->seenJoliet = 0;
+ if (iso9660->seenJoliet &&
+ vd->location > iso9660->joliet.location)
+ /* This condition is unlikely; by way of caution. */
+ vd = &(iso9660->joliet);
+
+ skipsize = LOGICAL_BLOCK_SIZE * vd->location;
+ skipsize = __archive_read_consume(a, skipsize);
+ if (skipsize < 0)
+ return ((int)skipsize);
+ iso9660->current_position = skipsize;
+
+ block = __archive_read_ahead(a, vd->size, NULL);
+ if (block == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Failed to read full block when scanning "
+ "ISO9660 directory list");
+ return (ARCHIVE_FATAL);
}
- if (iso9660->current_position == 0) {
- int64_t skipsize;
- struct vd *vd;
- const void *block;
- char seenJoliet;
-
- vd = &(iso9660->primary);
- if (!iso9660->opt_support_joliet)
- iso9660->seenJoliet = 0;
- if (iso9660->seenJoliet &&
- vd->location > iso9660->joliet.location)
- /* This condition is unlikely; by way of caution. */
- vd = &(iso9660->joliet);
+ /*
+ * While reading Root Directory, flag seenJoliet must be zero to
+ * avoid converting special name 0x00(Current Directory) and
+ * next byte to UCS2.
+ */
+ seenJoliet = iso9660->seenJoliet;/* Save flag. */
+ iso9660->seenJoliet = 0;
+ file = parse_file_info(a, NULL, block);
+ if (file == NULL)
+ return (ARCHIVE_FATAL);
+ iso9660->seenJoliet = seenJoliet;
+ /*
+ * If the iso image has both RockRidge and Joliet, we preferentially
+ * use RockRidge Extensions rather than Joliet ones.
+ */
+ if (vd == &(iso9660->primary) && iso9660->seenRockridge
+ && iso9660->seenJoliet)
+ iso9660->seenJoliet = 0;
+
+ if (vd == &(iso9660->primary) && !iso9660->seenRockridge
+ && iso9660->seenJoliet) {
+ /* Switch reading data from primary to joliet. */
+ vd = &(iso9660->joliet);
skipsize = LOGICAL_BLOCK_SIZE * vd->location;
+ skipsize -= iso9660->current_position;
skipsize = __archive_read_consume(a, skipsize);
if (skipsize < 0)
return ((int)skipsize);
- iso9660->current_position = skipsize;
+ iso9660->current_position += skipsize;
block = __archive_read_ahead(a, vd->size, NULL);
if (block == NULL) {
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Failed to read full block when scanning "
"ISO9660 directory list");
return (ARCHIVE_FATAL);
}
-
- /*
- * While reading Root Directory, flag seenJoliet
- * must be zero to avoid converting special name
- * 0x00(Current Directory) and next byte to UCS2.
- */
- seenJoliet = iso9660->seenJoliet;/* Save flag. */
iso9660->seenJoliet = 0;
file = parse_file_info(a, NULL, block);
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
- if (vd == &(iso9660->primary) && iso9660->seenRockridge
- && iso9660->seenJoliet)
- /*
- * If iso image has RockRidge and Joliet,
- * we use RockRidge Extensions.
- */
- iso9660->seenJoliet = 0;
- if (vd == &(iso9660->primary) && !iso9660->seenRockridge
- && iso9660->seenJoliet) {
- /* Switch reading data from primary to joliet. */
- vd = &(iso9660->joliet);
- skipsize = LOGICAL_BLOCK_SIZE * vd->location;
- skipsize -= iso9660->current_position;
- skipsize = __archive_read_consume(a, skipsize);
- if (skipsize < 0)
- return ((int)skipsize);
- iso9660->current_position += skipsize;
-
- block = __archive_read_ahead(a, vd->size, NULL);
- if (block == NULL) {
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_MISC,
- "Failed to read full block when scanning "
- "ISO9660 directory list");
- return (ARCHIVE_FATAL);
- }
- iso9660->seenJoliet = 0;
- file = parse_file_info(a, NULL, block);
- if (file == NULL)
- return (ARCHIVE_FATAL);
- iso9660->seenJoliet = seenJoliet;
- }
- /* Store the root directory in the pending list. */
- if (add_entry(a, iso9660, file) != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
- if (iso9660->seenRockridge) {
- a->archive.archive_format =
- ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
- a->archive.archive_format_name =
- "ISO9660 with Rockridge extensions";
- }
+ }
+
+ /* Store the root directory in the pending list. */
+ if (add_entry(a, iso9660, file) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ if (iso9660->seenRockridge) {
+ a->archive.archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
+ a->archive.archive_format_name =
+ "ISO9660 with Rockridge extensions";
+ }
+
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_read_format_iso9660_read_header(struct archive_read *a,
+ struct archive_entry *entry)
+{
+ struct iso9660 *iso9660;
+ struct file_info *file;
+ int r, rd_r = ARCHIVE_OK;
+
+ iso9660 = (struct iso9660 *)(a->format->data);
+
+ if (!a->archive.archive_format) {
+ a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
+ a->archive.archive_format_name = "ISO9660";
+ }
+
+ if (iso9660->current_position == 0) {
+ r = choose_volume(a, iso9660);
+ if (r != ARCHIVE_OK)
+ return (r);
}
file = NULL;/* Eliminate a warning. */
@@ -1227,14 +1251,14 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
}
iso9660->entry_bytes_remaining = file->size;
- iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */
+ /* Offset for sparse-file-aware clients. */
+ iso9660->entry_sparse_offset = 0;
if (file->offset + file->size > iso9660->volume_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"File is beyond end-of-media: %s",
archive_entry_pathname(entry));
iso9660->entry_bytes_remaining = 0;
- iso9660->entry_sparse_offset = 0;
return (ARCHIVE_WARN);
}
@@ -1286,36 +1310,33 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
iso9660->previous_pathname.s);
archive_entry_unset_size(entry);
iso9660->entry_bytes_remaining = 0;
- iso9660->entry_sparse_offset = 0;
return (rd_r);
}
- /* Except for the hardlink case above, if the offset of the
- * next entry is before our current position, we can't seek
- * backwards to extract it, so issue a warning. Note that
- * this can only happen if this entry was added to the heap
- * after we passed this offset, that is, only if the directory
- * mentioning this entry is later than the body of the entry.
- * Such layouts are very unusual; most ISO9660 writers lay out
- * and record all directory information first, then store
- * all file bodies. */
- /* TODO: Someday, libarchive's I/O core will support optional
- * seeking. When that day comes, this code should attempt to
- * seek and only return the error if the seek fails. That
- * will give us support for whacky ISO images that require
- * seeking while retaining the ability to read almost all ISO
- * images in a streaming fashion. */
if ((file->mode & AE_IFMT) != AE_IFDIR &&
file->offset < iso9660->current_position) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Ignoring out-of-order file @%jx (%s) %jd < %jd",
- (intmax_t)file->number,
- iso9660->pathname.s,
- (intmax_t)file->offset,
- (intmax_t)iso9660->current_position);
- iso9660->entry_bytes_remaining = 0;
- iso9660->entry_sparse_offset = 0;
- return (ARCHIVE_WARN);
+ int64_t r64;
+
+ r64 = __archive_read_seek(a, file->offset, SEEK_SET);
+ if (r64 != (int64_t)file->offset) {
+ /* We can't seek backwards to extract it, so issue
+ * a warning. Note that this can only happen if
+ * this entry was added to the heap after we passed
+ * this offset, that is, only if the directory
+ * mentioning this entry is later than the body of
+ * the entry. Such layouts are very unusual; most
+ * ISO9660 writers lay out and record all directory
+ * information first, then store all file bodies. */
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Ignoring out-of-order file @%jx (%s) %jd < %jd",
+ (intmax_t)file->number,
+ iso9660->pathname.s,
+ (intmax_t)file->offset,
+ (intmax_t)iso9660->current_position);
+ iso9660->entry_bytes_remaining = 0;
+ return (ARCHIVE_WARN);
+ }
+ iso9660->current_position = (uint64_t)r64;
}
/* Initialize zisofs variables. */
@@ -1356,7 +1377,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
archive_entry_set_nlink(entry, 2 + file->subdirs);
/* Directory data has been read completely. */
iso9660->entry_bytes_remaining = 0;
- iso9660->entry_sparse_offset = 0;
}
if (rd_r != ARCHIVE_OK)
@@ -1397,7 +1417,7 @@ zisofs_read_data(struct archive_read *a,
return (ARCHIVE_FATAL);
}
if (bytes_read > iso9660->entry_bytes_remaining)
- bytes_read = iso9660->entry_bytes_remaining;
+ bytes_read = (ssize_t)iso9660->entry_bytes_remaining;
avail = bytes_read;
uncompressed_size = 0;
@@ -1405,9 +1425,9 @@ zisofs_read_data(struct archive_read *a,
size_t ceil, xsize;
/* Allocate block pointers buffer. */
- ceil = (zisofs->pz_uncompressed_size +
+ ceil = (size_t)((zisofs->pz_uncompressed_size +
(((int64_t)1) << zisofs->pz_log2_bs) - 1)
- >> zisofs->pz_log2_bs;
+ >> zisofs->pz_log2_bs);
xsize = (ceil + 1) * 4;
if (zisofs->block_pointers_alloc < xsize) {
size_t alloc;
@@ -1426,7 +1446,7 @@ zisofs_read_data(struct archive_read *a,
zisofs->block_pointers_size = xsize;
/* Allocate uncompressed data buffer. */
- xsize = 1UL << zisofs->pz_log2_bs;
+ xsize = (size_t)1UL << zisofs->pz_log2_bs;
if (zisofs->uncompressed_buffer_size < xsize) {
if (zisofs->uncompressed_buffer != NULL)
free(zisofs->uncompressed_buffer);
@@ -1563,9 +1583,10 @@ zisofs_read_data(struct archive_read *a,
if (avail > zisofs->block_avail)
zisofs->stream.avail_in = zisofs->block_avail;
else
- zisofs->stream.avail_in = avail;
+ zisofs->stream.avail_in = (uInt)avail;
zisofs->stream.next_out = zisofs->uncompressed_buffer;
- zisofs->stream.avail_out = zisofs->uncompressed_buffer_size;
+ zisofs->stream.avail_out =
+ (uInt)zisofs->uncompressed_buffer_size;
r = inflate(&zisofs->stream, 0);
switch (r) {
@@ -1580,7 +1601,7 @@ zisofs_read_data(struct archive_read *a,
uncompressed_size =
zisofs->uncompressed_buffer_size - zisofs->stream.avail_out;
avail -= zisofs->stream.next_in - p;
- zisofs->block_avail -= zisofs->stream.next_in - p;
+ zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
}
next_data:
bytes_read -= avail;
@@ -1590,7 +1611,7 @@ next_data:
iso9660->entry_sparse_offset += uncompressed_size;
iso9660->entry_bytes_remaining -= bytes_read;
iso9660->current_position += bytes_read;
- zisofs->pz_offset += bytes_read;
+ zisofs->pz_offset += (uint32_t)bytes_read;
iso9660->entry_bytes_unconsumed += bytes_read;
return (ARCHIVE_OK);
@@ -1671,7 +1692,7 @@ archive_read_format_iso9660_read_data(struct archive_read *a,
if (*buff == NULL)
return (ARCHIVE_FATAL);
if (bytes_read > iso9660->entry_bytes_remaining)
- bytes_read = iso9660->entry_bytes_remaining;
+ bytes_read = (ssize_t)iso9660->entry_bytes_remaining;
*size = bytes_read;
*offset = iso9660->entry_sparse_offset;
iso9660->entry_sparse_offset += bytes_read;
@@ -1756,7 +1777,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
*/
if (location > 0 &&
(location + ((fsize + iso9660->logical_block_size -1)
- / iso9660->logical_block_size)) > iso9660->volume_block) {
+ / iso9660->logical_block_size))
+ > (uint32_t)iso9660->volume_block) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid location of extent of file");
return (NULL);
@@ -1872,9 +1894,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if (iso9660->opt_support_rockridge) {
if (parent == NULL && rr_end - rr_start >= 7) {
p = rr_start;
- if (p[0] == 'S' && p[1] == 'P'
- && p[2] == 7 && p[3] == 1
- && p[4] == 0xBE && p[5] == 0xEF) {
+ if (memcmp(p, "SP\x07\x01\xbe\xef", 6) == 0) {
/*
* SP extension stores the suspOffset
* (Number of bytes to skip between
@@ -1907,6 +1927,19 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
free(file);
return (NULL);
}
+ /*
+ * A file size of symbolic link files in ISO images
+ * made by makefs is not zero and its location is
+ * the same as those of next regular file. That is
+ * the same as hard like file and it causes unexpected
+ * error.
+ */
+ if (file->size > 0 &&
+ (file->mode & AE_IFMT) == AE_IFLNK) {
+ file->size = 0;
+ file->number = -1;
+ file->offset = -1;
+ }
} else
/* If there isn't SUSP, disable parsing
* rock ridge extensions. */
@@ -1921,6 +1954,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if (iso9660->seenRockridge) {
if (parent != NULL && parent->parent == NULL &&
(flags & 0x02) && iso9660->rr_moved == NULL &&
+ file->name.s &&
(strcmp(file->name.s, "rr_moved") == 0 ||
strcmp(file->name.s, ".rr_moved") == 0)) {
iso9660->rr_moved = file;
@@ -2053,14 +2087,9 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
int data_length = p[2] - 4;
int version = p[3];
- /*
- * Yes, each 'if' here does test p[0] again.
- * Otherwise, the fall-through handling to catch
- * unsupported extensions doesn't work.
- */
switch(p[0]) {
case 'C':
- if (p[0] == 'C' && p[1] == 'E') {
+ if (p[1] == 'E') {
if (version == 1 && data_length == 24) {
/*
* CE extension comprises:
@@ -2078,53 +2107,42 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
!= ARCHIVE_OK)
return (ARCHIVE_FATAL);
}
- break;
}
- if (p[0] == 'C' && p[1] == 'L') {
+ else if (p[1] == 'L') {
if (version == 1 && data_length == 8) {
file->cl_offset = (uint64_t)
iso9660->logical_block_size *
(uint64_t)archive_le32dec(data);
iso9660->seenRockridge = 1;
}
- break;
}
- /* FALLTHROUGH */
+ break;
case 'N':
- if (p[0] == 'N' && p[1] == 'M') {
+ if (p[1] == 'M') {
if (version == 1) {
parse_rockridge_NM1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
- break;
}
- /* FALLTHROUGH */
+ break;
case 'P':
- if (p[0] == 'P' && p[1] == 'D') {
- /*
- * PD extension is padding;
- * contents are always ignored.
- */
- break;
- }
- if (p[0] == 'P' && p[1] == 'L') {
- /*
- * PL extension won't appear;
- * contents are always ignored.
- */
- break;
- }
- if (p[0] == 'P' && p[1] == 'N') {
+ /*
+ * PD extension is padding;
+ * contents are always ignored.
+ *
+ * PL extension won't appear;
+ * contents are always ignored.
+ */
+ if (p[1] == 'N') {
if (version == 1 && data_length == 16) {
file->rdev = toi(data,4);
file->rdev <<= 32;
file->rdev |= toi(data + 8, 4);
iso9660->seenRockridge = 1;
}
- break;
}
- if (p[0] == 'P' && p[1] == 'X') {
+ else if (p[1] == 'X') {
/*
* PX extension comprises:
* 8 bytes for mode,
@@ -2151,35 +2169,31 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
= toi(data + 32, 4);
iso9660->seenRockridge = 1;
}
- break;
}
- /* FALLTHROUGH */
+ break;
case 'R':
- if (p[0] == 'R' && p[1] == 'E' && version == 1) {
+ if (p[1] == 'E' && version == 1) {
file->re = 1;
iso9660->seenRockridge = 1;
- break;
}
- if (p[0] == 'R' && p[1] == 'R' && version == 1) {
+ else if (p[1] == 'R' && version == 1) {
/*
* RR extension comprises:
* one byte flag value
* This extension is obsolete,
* so contents are always ignored.
*/
- break;
}
- /* FALLTHROUGH */
+ break;
case 'S':
- if (p[0] == 'S' && p[1] == 'L') {
+ if (p[1] == 'L') {
if (version == 1) {
parse_rockridge_SL1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
- break;
}
- if (p[0] == 'S' && p[1] == 'T'
+ else if (p[1] == 'T'
&& data_length == 0 && version == 1) {
/*
* ST extension marks end of this
@@ -2194,32 +2208,27 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
iso9660->seenRockridge = 0;
return (ARCHIVE_OK);
}
+ break;
case 'T':
- if (p[0] == 'T' && p[1] == 'F') {
+ if (p[1] == 'F') {
if (version == 1) {
parse_rockridge_TF1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
- break;
}
- /* FALLTHROUGH */
+ break;
case 'Z':
- if (p[0] == 'Z' && p[1] == 'F') {
+ if (p[1] == 'F') {
if (version == 1)
parse_rockridge_ZF1(file,
data, data_length);
- break;
}
- /* FALLTHROUGH */
+ break;
default:
- /* The FALLTHROUGHs above leave us here for
- * any unsupported extension. */
break;
}
-
-
p += p[2];
}
return (ARCHIVE_OK);
@@ -2241,7 +2250,7 @@ register_CE(struct archive_read *a, int32_t location,
offset >= file->offset) ||
offset < iso9660->current_position ||
(((uint64_t)file->ce_offset) + file->ce_size)
- > iso9660->logical_block_size ||
+ > (uint64_t)iso9660->logical_block_size ||
offset + file->ce_offset + file->ce_size
> iso9660->volume_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -2263,7 +2272,7 @@ register_CE(struct archive_read *a, int32_t location,
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
- p = malloc(new_size * sizeof(p[0]));
+ p = calloc(new_size, sizeof(p[0]));
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
@@ -2513,9 +2522,6 @@ parse_rockridge_SL1(struct file_info *file, const unsigned char *data,
if (!file->symlink_continues || file->symlink.length < 1)
archive_string_empty(&file->symlink);
- else if (!file->symlink_continues &&
- file->symlink.s[file->symlink.length - 1] != '/')
- separator = "/";
file->symlink_continues = 0;
/*
@@ -2882,8 +2888,9 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
fatal_rr:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of"
- "Rockridge extensions");
+ "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of "
+ "Rockridge extensions: current position = %jd, CL offset = %jd",
+ (intmax_t)iso9660->current_position, (intmax_t)file->cl_offset);
return (ARCHIVE_FATAL);
}
@@ -3085,6 +3092,8 @@ isodate7(const unsigned char *v)
{
struct tm tm;
int offset;
+ time_t t;
+
memset(&tm, 0, sizeof(tm));
tm.tm_year = v[0];
tm.tm_mon = v[1] - 1;
@@ -3098,7 +3107,10 @@ isodate7(const unsigned char *v)
tm.tm_hour -= offset / 4;
tm.tm_min -= (offset % 4) * 15;
}
- return (time_from_tm(&tm));
+ t = time_from_tm(&tm);
+ if (t == (time_t)-1)
+ return ((time_t)0);
+ return (t);
}
static time_t
@@ -3106,6 +3118,8 @@ isodate17(const unsigned char *v)
{
struct tm tm;
int offset;
+ time_t t;
+
memset(&tm, 0, sizeof(tm));
tm.tm_year = (v[0] - '0') * 1000 + (v[1] - '0') * 100
+ (v[2] - '0') * 10 + (v[3] - '0')
@@ -3121,7 +3135,10 @@ isodate17(const unsigned char *v)
tm.tm_hour -= offset / 4;
tm.tm_min -= (offset % 4) * 15;
}
- return (time_from_tm(&tm));
+ t = time_from_tm(&tm);
+ if (t == (time_t)-1)
+ return ((time_t)0);
+ return (t);
}
static time_t
@@ -3135,7 +3152,8 @@ time_from_tm(struct tm *t)
#else
/* Else use direct calculation using POSIX assumptions. */
/* First, fix up tm_yday based on the year/month/day. */
- mktime(t);
+ if (mktime(t) == (time_t)-1)
+ return ((time_t)-1);
/* Then we can compute timegm() from first principles. */
return (t->tm_sec + t->tm_min * 60 + t->tm_hour * 3600
+ t->tm_yday * 86400 + (t->tm_year - 70) * 31536000
@@ -3204,10 +3222,12 @@ dump_isodirrec(FILE *out, const unsigned char *isodirrec)
fprintf(out, " ilv %d,",
toi(isodirrec + DR_interleave_offset, DR_interleave_size));
fprintf(out, " seq %d,",
- toi(isodirrec + DR_volume_sequence_number_offset, DR_volume_sequence_number_size));
+ toi(isodirrec + DR_volume_sequence_number_offset,
+ DR_volume_sequence_number_size));
fprintf(out, " nl %d:",
toi(isodirrec + DR_name_len_offset, DR_name_len_size));
fprintf(out, " `%.*s'",
- toi(isodirrec + DR_name_len_offset, DR_name_len_size), isodirrec + DR_name_offset);
+ toi(isodirrec + DR_name_len_offset, DR_name_len_size),
+ isodirrec + DR_name_offset);
}
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
index 50256b1..f702949 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2008-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2008-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -272,7 +272,7 @@ static int lha_skip_sfx(struct archive_read *);
static time_t lha_dos_time(const unsigned char *);
static time_t lha_win_time(uint64_t, long *);
static unsigned char lha_calcsum(unsigned char, const void *,
- int, int);
+ int, size_t);
static int lha_parse_linkname(struct archive_string *,
struct archive_string *);
static int lha_read_data_none(struct archive_read *, const void **,
@@ -289,7 +289,7 @@ static void lzh_huffman_free(struct huffman *);
static int lzh_read_pt_bitlen(struct lzh_stream *, int start, int end);
static int lzh_make_fake_table(struct huffman *, uint16_t);
static int lzh_make_huffman_table(struct huffman *);
-static int inline lzh_decode_huffman(struct huffman *, unsigned);
+static inline int lzh_decode_huffman(struct huffman *, unsigned);
static int lzh_decode_huffman_tree(struct huffman *, unsigned, int);
@@ -319,6 +319,7 @@ archive_read_support_format_lha(struct archive *_a)
archive_read_format_lha_read_header,
archive_read_format_lha_read_data,
archive_read_format_lha_read_data_skip,
+ NULL,
archive_read_format_lha_cleanup);
if (r != ARCHIVE_OK)
@@ -445,11 +446,13 @@ archive_read_format_lha_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "lha: unknown keyword ``%s''", key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -696,7 +699,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
archive_entry_set_symlink(entry, NULL);
archive_string_free(&linkname);
/*
- * When a header level is 0, there is a possibilty that
+ * When a header level is 0, there is a possibility that
* a pathname and a symlink has '\' character, a directory
* separator in DOS/Windows. So we should convert it to '/'.
*/
@@ -949,7 +952,7 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
/* Read extended headers */
err2 = lha_read_file_extended_header(a, lha, NULL, 2,
- lha->compsize + 2, &extdsize);
+ (size_t)(lha->compsize + 2), &extdsize);
if (err2 < ARCHIVE_WARN)
return (err2);
if (err2 < err)
@@ -1444,7 +1447,7 @@ lha_read_data_none(struct archive_read *a, const void **buff,
return (ARCHIVE_FATAL);
}
if (bytes_avail > lha->entry_bytes_remaining)
- bytes_avail = lha->entry_bytes_remaining;
+ bytes_avail = (ssize_t)lha->entry_bytes_remaining;
lha->entry_crc_calculated =
lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail);
*size = bytes_avail;
@@ -1527,7 +1530,7 @@ lha_read_data_lzh(struct archive_read *a, const void **buff,
return (ARCHIVE_FATAL);
}
if (bytes_avail > lha->entry_bytes_remaining)
- bytes_avail = lha->entry_bytes_remaining;
+ bytes_avail = (ssize_t)lha->entry_bytes_remaining;
lha->strm.avail_in = bytes_avail;
lha->strm.total_in = 0;
@@ -1573,7 +1576,7 @@ static int
archive_read_format_lha_read_data_skip(struct archive_read *a)
{
struct lha *lha;
- off_t bytes_skipped;
+ int64_t bytes_skipped;
lha = (struct lha *)(a->format->data);
@@ -1632,7 +1635,7 @@ lha_parse_linkname(struct archive_string *linkname,
struct archive_string *pathname)
{
char * linkptr;
- int symlen;
+ size_t symlen;
linkptr = strchr(pathname->s, '|');
if (linkptr != NULL) {
@@ -1687,12 +1690,12 @@ lha_win_time(uint64_t wintime, long *ns)
}
static unsigned char
-lha_calcsum(unsigned char sum, const void *pp, int offset, int size)
+lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
{
unsigned char const *p = (unsigned char const *)pp;
p += offset;
- while (--size >= 0)
+ for (;size > 0; --size)
sum += *p++;
return (sum);
}
@@ -2014,18 +2017,18 @@ lzh_copy_from_window(struct lzh_stream *strm, struct lzh_dec *ds)
if (ds->w_pos - ds->copy_pos <= strm->avail_out)
copy_bytes = ds->w_pos - ds->copy_pos;
else
- copy_bytes = strm->avail_out;
+ copy_bytes = (size_t)strm->avail_out;
memcpy(strm->next_out,
ds->w_buff + ds->copy_pos, copy_bytes);
- ds->copy_pos += copy_bytes;
+ ds->copy_pos += (int)copy_bytes;
} else {
if (ds->w_remaining <= strm->avail_out)
copy_bytes = ds->w_remaining;
else
- copy_bytes = strm->avail_out;
+ copy_bytes = (size_t)strm->avail_out;
memcpy(strm->next_out,
ds->w_buff + ds->w_size - ds->w_remaining, copy_bytes);
- ds->w_remaining -= copy_bytes;
+ ds->w_remaining -= (int)copy_bytes;
}
strm->next_out += copy_bytes;
strm->avail_out -= copy_bytes;
@@ -2479,7 +2482,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
bits = tbl_bits;
else
bits = HTBL_BITS;
- hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0]));
+ hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
if (hf->tbl == NULL)
return (ARCHIVE_FATAL);
}
@@ -2489,7 +2492,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
if (hf->tree == NULL)
return (ARCHIVE_FATAL);
}
- hf->len_size = len_size;
+ hf->len_size = (int)len_size;
hf->tbl_bits = tbl_bits;
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
index 3ba4be0..c4e7021 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2008 Joerg Sonnenberger
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
#define MTREE_HAS_DEVICE 0x0001
#define MTREE_HAS_FFLAGS 0x0002
@@ -69,6 +72,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#define MTREE_HAS_UNAME 0x0400
#define MTREE_HAS_OPTIONAL 0x0800
+#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
struct mtree_option {
struct mtree_option *next;
@@ -101,7 +105,9 @@ struct mtree {
int64_t cur_size;
};
+static int bid_keycmp(const char *, const char *, ssize_t);
static int cleanup(struct archive_read *);
+static int detect_form(struct archive_read *, int *);
static int mtree_bid(struct archive_read *, int);
static int parse_file(struct archive_read *, struct archive_entry *,
struct mtree *, struct mtree_entry *, int *);
@@ -199,7 +205,7 @@ archive_read_support_format_mtree(struct archive *_a)
mtree->fd = -1;
r = __archive_read_register_format(a, mtree, "mtree",
- mtree_bid, NULL, read_header, read_data, skip, cleanup);
+ mtree_bid, NULL, read_header, read_data, skip, NULL, cleanup);
if (r != ARCHIVE_OK)
free(mtree);
@@ -317,7 +323,7 @@ next_line(struct archive_read *a,
* Returns the length of a mtree keyword if matched.
* Returns 0 if not matched.
*/
-int
+static int
bid_keycmp(const char *p, const char *key, ssize_t len)
{
int match_len = 0;
@@ -348,7 +354,7 @@ bid_keycmp(const char *p, const char *key, ssize_t len)
* Returns the length of a detected keyword.
* Returns 0 if any keywords were not found.
*/
-static ssize_t
+static int
bid_keyword(const char *p, ssize_t len)
{
static const char *keys_c[] = {
@@ -367,7 +373,7 @@ bid_keyword(const char *p, ssize_t len)
"md5", "md5digest", "mode", NULL
};
static const char *keys_no[] = {
- "nlink", "optional", NULL
+ "nlink", "nochange", "optional", NULL
};
static const char *keys_r[] = {
"rmd160", "rmd160digest", NULL
@@ -418,7 +424,7 @@ bid_keyword(const char *p, ssize_t len)
* When "unset" is specified, expects a set of "<space characters>keyword".
*/
static int
-bid_keyword_list(const char *p, ssize_t len, int unset)
+bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path)
{
int l;
int keycnt = 0;
@@ -436,8 +442,10 @@ bid_keyword_list(const char *p, ssize_t len, int unset)
break;
if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r'))
break;
- if (!blank) /* No blank character. */
+ if (!blank && !last_is_path) /* No blank character. */
return (-1);
+ if (last_is_path && len == 0)
+ return (keycnt);
if (unset) {
l = bid_keycmp(p, "all", len);
@@ -472,7 +480,7 @@ bid_keyword_list(const char *p, ssize_t len, int unset)
}
static int
-bid_entry(const char *p, ssize_t len)
+bid_entry(const char *p, ssize_t len, ssize_t nl, int *last_is_path)
{
int f = 0;
static const unsigned char safe_char[256] = {
@@ -499,22 +507,60 @@ bid_entry(const char *p, ssize_t len)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
};
+ ssize_t ll = len;
+ const char *pp = p;
+ *last_is_path = 0;
/*
* Skip the path-name which is quoted.
*/
- while (len > 0 && *p != ' ' && *p != '\t') {
- if (!safe_char[*(const unsigned char *)p])
- return (-1);
- ++p;
- --len;
+ while (ll > 0 && *pp != ' ' &&*pp != '\t' && *pp != '\r' &&
+ *pp != '\n') {
+ if (!safe_char[*(const unsigned char *)pp]) {
+ f = 0;
+ break;
+ }
+ ++pp;
+ --ll;
++f;
}
- /* If a path-name was not found, returns error. */
- if (f == 0)
- return (-1);
+ /* If a path-name was not found at the first, try to check
+ * a mtree format ``NetBSD's mtree -D'' creates, which
+ * places the path-name at the last. */
+ if (f == 0) {
+ const char *pb = p + len - nl;
+ int name_len = 0;
+ int slash;
+
+ /* Do not accept multi lines for form D. */
+ if (pb-2 >= p &&
+ pb[-1] == '\\' && (pb[-2] == ' ' || pb[-2] == '\t'))
+ return (-1);
+ if (pb-1 >= p && pb[-1] == '\\')
+ return (-1);
+
+ slash = 0;
+ while (p <= --pb && *pb != ' ' && *pb != '\t') {
+ if (!safe_char[*(const unsigned char *)pb])
+ return (-1);
+ name_len++;
+ /* The pathname should have a slash in this
+ * format. */
+ if (*pb == '/')
+ slash = 1;
+ }
+ if (name_len == 0 || slash == 0)
+ return (-1);
+ /* If '/' is placed at the first in this field, this is not
+ * a valid filename. */
+ if (pb[1] == '/')
+ return (-1);
+ ll = len - nl - name_len;
+ pp = p;
+ *last_is_path = 1;
+ }
- return (bid_keyword_list(p, len, 0));
+ return (bid_keyword_list(pp, ll, 0, *last_is_path));
}
#define MAX_BID_ENTRY 3
@@ -524,14 +570,11 @@ mtree_bid(struct archive_read *a, int best_bid)
{
const char *signature = "#mtree";
const char *p;
- ssize_t avail, ravail;
- ssize_t len, nl;
- int detected_bytes = 0, entry_cnt = 0, multiline = 0;
(void)best_bid; /* UNUSED */
/* Now let's look at the actual header and see if it matches. */
- p = __archive_read_ahead(a, strlen(signature), &avail);
+ p = __archive_read_ahead(a, strlen(signature), NULL);
if (p == NULL)
return (-1);
@@ -541,6 +584,24 @@ mtree_bid(struct archive_read *a, int best_bid)
/*
* There is not a mtree signature. Let's try to detect mtree format.
*/
+ return (detect_form(a, NULL));
+}
+
+static int
+detect_form(struct archive_read *a, int *is_form_d)
+{
+ const char *p;
+ ssize_t avail, ravail;
+ ssize_t detected_bytes = 0, len, nl;
+ int entry_cnt = 0, multiline = 0;
+ int form_D = 0;/* The archive is generated by `NetBSD mtree -D'
+ * (In this source we call it `form D') . */
+
+ if (is_form_d != NULL)
+ *is_form_d = 0;
+ p = __archive_read_ahead(a, 1, &avail);
+ if (p == NULL)
+ return (-1);
ravail = avail;
for (;;) {
len = next_line(a, &p, &avail, &ravail, &nl);
@@ -565,7 +626,7 @@ mtree_bid(struct archive_read *a, int best_bid)
} else {
/* A continuance line; the terminal
* character of previous line was '\' character. */
- if (bid_keyword_list(p, len, 0) <= 0)
+ if (bid_keyword_list(p, len, 0, 0) <= 0)
break;
if (multiline == 1)
detected_bytes += len;
@@ -580,9 +641,25 @@ mtree_bid(struct archive_read *a, int best_bid)
continue;
}
if (p[0] != '/') {
- if (bid_entry(p, len) >= 0) {
+ int last_is_path, keywords;
+
+ keywords = bid_entry(p, len, nl, &last_is_path);
+ if (keywords >= 0) {
detected_bytes += len;
- if (p[len-nl-1] == '\\')
+ if (form_D == 0) {
+ if (last_is_path)
+ form_D = 1;
+ else if (keywords > 0)
+ /* This line is not `form D'. */
+ form_D = -1;
+ } else if (form_D == 1) {
+ if (!last_is_path && keywords > 0)
+ /* This this is not `form D'
+ * and We cannot accept mixed
+ * format. */
+ break;
+ }
+ if (!last_is_path && p[len-nl-1] == '\\')
/* This line continues. */
multiline = 1;
else {
@@ -595,13 +672,13 @@ mtree_bid(struct archive_read *a, int best_bid)
} else
break;
} else if (strncmp(p, "/set", 4) == 0) {
- if (bid_keyword_list(p+4, len-4, 0) <= 0)
+ if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
break;
/* This line continues. */
if (p[len-nl-1] == '\\')
multiline = 2;
} else if (strncmp(p, "/unset", 6) == 0) {
- if (bid_keyword_list(p+6, len-6, 1) <= 0)
+ if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
break;
/* This line continues. */
if (p[len-nl-1] == '\\')
@@ -613,8 +690,13 @@ mtree_bid(struct archive_read *a, int best_bid)
p += len;
avail -= len;
}
- if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0))
+ if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) {
+ if (is_form_d != NULL) {
+ if (form_D == 1)
+ *is_form_d = 1;
+ }
return (32);
+ }
return (0);
}
@@ -738,12 +820,12 @@ process_global_unset(struct archive_read *a,
static int
process_add_entry(struct archive_read *a, struct mtree *mtree,
- struct mtree_option **global, const char *line,
- struct mtree_entry **last_entry)
+ struct mtree_option **global, const char *line, ssize_t line_len,
+ struct mtree_entry **last_entry, int is_form_d)
{
struct mtree_entry *entry;
struct mtree_option *iter;
- const char *next, *eq;
+ const char *next, *eq, *name, *end;
size_t len;
int r;
@@ -764,17 +846,46 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
(*last_entry)->next = entry;
*last_entry = entry;
- len = strcspn(line, " \t\r\n");
+ if (is_form_d) {
+ /*
+ * This form places the file name as last parameter.
+ */
+ name = line + line_len -1;
+ while (line_len > 0) {
+ if (*name != '\r' && *name != '\n' &&
+ *name != '\t' && *name != ' ')
+ break;
+ name--;
+ line_len--;
+ }
+ len = 0;
+ while (line_len > 0) {
+ if (*name == '\r' || *name == '\n' ||
+ *name == '\t' || *name == ' ') {
+ name++;
+ break;
+ }
+ name--;
+ line_len--;
+ len++;
+ }
+ end = name;
+ } else {
+ len = strcspn(line, " \t\r\n");
+ name = line;
+ line += len;
+ end = line + line_len;
+ }
+
if ((entry->name = malloc(len + 1)) == NULL) {
archive_set_error(&a->archive, errno, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
- memcpy(entry->name, line, len);
+ memcpy(entry->name, name, len);
entry->name[len] = '\0';
parse_escapes(entry->name, entry);
- line += len;
for (iter = *global; iter != NULL; iter = iter->next) {
r = add_option(a, &entry->options, iter->value,
strlen(iter->value));
@@ -786,6 +897,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
next = line + strspn(line, " \t\r\n");
if (*next == '\0')
return (ARCHIVE_OK);
+ if (next >= end)
+ return (ARCHIVE_OK);
line = next;
next = line + strcspn(line, " \t\r\n");
eq = strchr(line, '=');
@@ -810,7 +923,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
char *p;
struct mtree_option *global;
struct mtree_entry *last_entry;
- int r;
+ int r, is_form_d;
mtree->archive_format = ARCHIVE_FORMAT_MTREE;
mtree->archive_format_name = "mtree";
@@ -818,6 +931,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
global = NULL;
last_entry = NULL;
+ (void)detect_form(a, &is_form_d);
+
for (counter = 1; ; ++counter) {
len = readline(a, mtree, &p, 65536);
if (len == 0) {
@@ -827,7 +942,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
}
if (len < 0) {
free_options(global);
- return (len);
+ return ((int)len);
}
/* Leading whitespace is never significant, ignore it. */
while (*p == ' ' || *p == '\t') {
@@ -840,8 +955,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
if (*p == '\r' || *p == '\n' || *p == '\0')
continue;
if (*p != '/') {
- r = process_add_entry(a, mtree, &global, p,
- &last_entry);
+ r = process_add_entry(a, mtree, &global, p, len,
+ &last_entry, is_form_d);
} else if (strncmp(p, "/set", 4) == 0) {
if (p[4] != ' ' && p[4] != '\t')
break;
@@ -1007,7 +1122,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
if (archive_entry_filetype(entry) == AE_IFREG ||
archive_entry_filetype(entry) == AE_IFDIR) {
- mtree->fd = open(path, O_RDONLY | O_BINARY);
+ mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(mtree->fd);
if (mtree->fd == -1 &&
(errno != ENOENT ||
archive_strlen(&mtree->contents_name) > 0)) {
@@ -1090,15 +1206,19 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
* if it wasn't already parsed from the specification.
*/
if (st != NULL) {
- if ((parsed_kws & MTREE_HAS_DEVICE) == 0 &&
+ if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
(archive_entry_filetype(entry) == AE_IFCHR ||
archive_entry_filetype(entry) == AE_IFBLK))
archive_entry_set_rdev(entry, st->st_rdev);
- if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0)
+ if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_gid(entry, st->st_gid);
- if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0)
+ if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_uid(entry, st->st_uid);
- if ((parsed_kws & MTREE_HAS_MTIME) == 0) {
+ if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtimespec.tv_nsec);
@@ -1118,11 +1238,14 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
}
- if ((parsed_kws & MTREE_HAS_NLINK) == 0)
+ if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_nlink(entry, st->st_nlink);
- if ((parsed_kws & MTREE_HAS_PERM) == 0)
+ if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_perm(entry, st->st_mode);
- if ((parsed_kws & MTREE_HAS_SIZE) == 0)
+ if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
+ (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_size(entry, st->st_size);
archive_entry_set_ino(entry, st->st_ino);
archive_entry_set_dev(entry, st->st_dev);
@@ -1182,7 +1305,7 @@ parse_device(struct archive *a, struct archive_entry *entry, char *val)
comma1 = strchr(val, ',');
if (comma1 == NULL) {
- archive_entry_set_dev(entry, mtree_atol10(&val));
+ archive_entry_set_dev(entry, (dev_t)mtree_atol10(&val));
return (ARCHIVE_OK);
}
++comma1;
@@ -1193,8 +1316,8 @@ parse_device(struct archive *a, struct archive_entry *entry, char *val)
return (ARCHIVE_WARN);
}
++comma2;
- archive_entry_set_rdevmajor(entry, mtree_atol(&comma1));
- archive_entry_set_rdevminor(entry, mtree_atol(&comma2));
+ archive_entry_set_rdevmajor(entry, (dev_t)mtree_atol(&comma1));
+ archive_entry_set_rdevminor(entry, (dev_t)mtree_atol(&comma2));
return (ARCHIVE_OK);
}
@@ -1212,6 +1335,10 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (*key == '\0')
return (ARCHIVE_OK);
+ if (strcmp(key, "nochange") == 0) {
+ *parsed_kws |= MTREE_HAS_NOCHANGE;
+ return (ARCHIVE_OK);
+ }
if (strcmp(key, "optional") == 0) {
*parsed_kws |= MTREE_HAS_OPTIONAL;
return (ARCHIVE_OK);
@@ -1279,7 +1406,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (val[0] >= '0' && val[0] <= '9') {
*parsed_kws |= MTREE_HAS_PERM;
archive_entry_set_perm(entry,
- mtree_atol8(&val));
+ (mode_t)mtree_atol8(&val));
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@@ -1291,7 +1418,8 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
case 'n':
if (strcmp(key, "nlink") == 0) {
*parsed_kws |= MTREE_HAS_NLINK;
- archive_entry_set_nlink(entry, mtree_atol10(&val));
+ archive_entry_set_nlink(entry,
+ (unsigned int)mtree_atol10(&val));
break;
}
case 'r':
@@ -1433,7 +1561,7 @@ read_data(struct archive_read *a, const void **buff, size_t *size, int64_t *offs
*buff = mtree->buff;
*offset = mtree->offset;
if ((int64_t)mtree->buffsize > mtree->cur_size - mtree->offset)
- bytes_to_read = mtree->cur_size - mtree->offset;
+ bytes_to_read = (size_t)(mtree->cur_size - mtree->offset);
else
bytes_to_read = mtree->buffsize;
bytes_read = read(mtree->fd, mtree->buff, bytes_to_read);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
index d5a8d86..dc1563d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
@@ -136,7 +136,7 @@
#define MAX_SYMBOLS 20
/*
- * Considering L1,L2 cache miss and a calling of write sytem-call,
+ * Considering L1,L2 cache miss and a calling of write system-call,
* the best size of the output buffer(uncompressed buffer) is 128K.
* If the structure of extracting process is changed, this value
* might be researched again.
@@ -199,6 +199,13 @@ struct lzss
int64_t position;
};
+struct data_block_offsets
+{
+ int64_t header_size;
+ int64_t start_offset;
+ int64_t end_offset;
+};
+
struct rar
{
/* Entries from main RAR header */
@@ -217,6 +224,7 @@ struct rar
long mnsec;
mode_t mode;
char *filename;
+ char *filename_save;
size_t filename_allocated;
/* File header optional entries */
@@ -234,6 +242,7 @@ struct rar
int64_t bytes_uncopied;
int64_t offset;
int64_t offset_outgoing;
+ int64_t offset_seek;
char valid;
unsigned int unp_offset;
unsigned int unp_buffer_size;
@@ -243,6 +252,10 @@ struct rar
char entry_eof;
unsigned long crc_calculated;
int found_first_header;
+ char has_endarc_header;
+ struct data_block_offsets *dbo;
+ unsigned int cursor;
+ unsigned int nodes;
/* LZSS members */
struct huffman_code maincode;
@@ -301,11 +314,13 @@ static int archive_read_format_rar_read_header(struct archive_read *,
static int archive_read_format_rar_read_data(struct archive_read *,
const void **, size_t *, int64_t *);
static int archive_read_format_rar_read_data_skip(struct archive_read *a);
+static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t,
+ int);
static int archive_read_format_rar_cleanup(struct archive_read *);
/* Support functions */
static int read_header(struct archive_read *, struct archive_entry *, char);
-static time_t get_time(int time);
+static time_t get_time(int);
static int read_exttime(const char *, struct rar *, const char *);
static int read_symlink_stored(struct archive_read *, struct archive_entry *,
struct archive_string_conv *);
@@ -328,6 +343,7 @@ static int make_table_recurse(struct archive_read *, struct huffman_code *, int,
static int64_t expand(struct archive_read *, int64_t);
static int copy_from_lzss_window(struct archive_read *, const void **,
int64_t, int);
+static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
/*
* Bit stream reader.
@@ -449,11 +465,9 @@ rar_br_fillup(struct archive_read *a, struct rar_br *br)
__archive_read_consume(a, rar->bytes_unconsumed);
rar->bytes_unconsumed = 0;
}
- br->next_in = __archive_read_ahead(a, 1, &(br->avail_in));
+ br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
if (br->next_in == NULL)
return (0);
- if (br->avail_in > rar->bytes_remaining)
- br->avail_in = rar->bytes_remaining;
if (br->avail_in == 0)
return (0);
}
@@ -473,15 +487,13 @@ rar_br_preparation(struct archive_read *a, struct rar_br *br)
struct rar *rar = (struct rar *)(a->format->data);
if (rar->bytes_remaining > 0) {
- br->next_in = __archive_read_ahead(a, 1, &(br->avail_in));
+ br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
if (br->next_in == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated RAR file data");
return (ARCHIVE_FATAL);
}
- if (br->avail_in > rar->bytes_remaining)
- br->avail_in = rar->bytes_remaining;
if (br->cache_avail == 0)
(void)rar_br_fillup(a, br);
}
@@ -522,7 +534,7 @@ lzss_size(struct lzss *lzss)
static inline int
lzss_offset_for_position(struct lzss *lzss, int64_t pos)
{
- return pos & lzss->mask;
+ return (int)(pos & lzss->mask);
}
static inline unsigned char *
@@ -642,6 +654,7 @@ archive_read_support_format_rar(struct archive *_a)
archive_read_format_rar_read_header,
archive_read_format_rar_read_data,
archive_read_format_rar_read_data_skip,
+ archive_read_format_rar_seek_data,
archive_read_format_rar_cleanup);
if (r != ARCHIVE_OK)
@@ -757,11 +770,13 @@ archive_read_format_rar_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "rar: unknown keyword ``%s''", key);
-
- return (ret);
+ return (ret);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -842,13 +857,6 @@ archive_read_format_rar_read_header(struct archive_read *a,
sizeof(rar->reserved2));
}
- if (rar->main_flags & MHD_VOLUME ||
- rar->main_flags & MHD_FIRSTVOLUME)
- {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "RAR volume support unavailable.");
- return (ARCHIVE_FATAL);
- }
if (rar->main_flags & MHD_PASSWORD)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -856,7 +864,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
return (ARCHIVE_FATAL);
}
- crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2);
+ crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
@@ -873,6 +881,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
case SUB_HEAD:
case PROTECT_HEAD:
case SIGN_HEAD:
+ case ENDARC_HEAD:
flags = archive_le16dec(p + 3);
skip = archive_le16dec(p + 5);
if (skip < 7) {
@@ -898,13 +907,15 @@ archive_read_format_rar_read_header(struct archive_read *a,
p = h;
}
- crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2);
+ crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
}
__archive_read_consume(a, skip);
+ if (head_type == ENDARC_HEAD)
+ return (ARCHIVE_EOF);
break;
case NEWSUB_HEAD:
@@ -912,9 +923,6 @@ archive_read_format_rar_read_header(struct archive_read *a,
return ret;
break;
- case ENDARC_HEAD:
- return (ARCHIVE_EOF);
-
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file");
@@ -936,10 +944,12 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
rar->bytes_unconsumed = 0;
}
- if (rar->entry_eof) {
+ if (rar->entry_eof || rar->offset_seek >= rar->unp_size) {
*buff = NULL;
*size = 0;
*offset = rar->offset;
+ if (*offset < rar->unp_size)
+ *offset = rar->unp_size;
return (ARCHIVE_EOF);
}
@@ -973,6 +983,7 @@ archive_read_format_rar_read_data_skip(struct archive_read *a)
{
struct rar *rar;
int64_t bytes_skipped;
+ int ret;
rar = (struct rar *)(a->format->data);
@@ -987,9 +998,179 @@ archive_read_format_rar_read_data_skip(struct archive_read *a)
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
}
+
+ /* Compressed data to skip must be read from each header in a multivolume
+ * archive.
+ */
+ if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)
+ {
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret == (ARCHIVE_EOF))
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret != (ARCHIVE_OK))
+ return ret;
+ return archive_read_format_rar_read_data_skip(a);
+ }
+
return (ARCHIVE_OK);
}
+static int64_t
+archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
+ int whence)
+{
+ int64_t client_offset, ret;
+ unsigned int i;
+ struct rar *rar = (struct rar *)(a->format->data);
+
+ if (rar->compression_method == COMPRESS_METHOD_STORE)
+ {
+ /* Modify the offset for use with SEEK_SET */
+ switch (whence)
+ {
+ case SEEK_CUR:
+ client_offset = rar->offset_seek;
+ break;
+ case SEEK_END:
+ client_offset = rar->unp_size;
+ break;
+ case SEEK_SET:
+ default:
+ client_offset = 0;
+ }
+ client_offset += offset;
+ if (client_offset < 0)
+ {
+ /* Can't seek past beginning of data block */
+ return -1;
+ }
+ else if (client_offset > rar->unp_size)
+ {
+ /*
+ * Set the returned offset but only seek to the end of
+ * the data block.
+ */
+ rar->offset_seek = client_offset;
+ client_offset = rar->unp_size;
+ }
+
+ client_offset += rar->dbo[0].start_offset;
+ i = 0;
+ while (i < rar->cursor)
+ {
+ i++;
+ client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset;
+ }
+ if (rar->main_flags & MHD_VOLUME)
+ {
+ /* Find the appropriate offset among the multivolume archive */
+ while (1)
+ {
+ if (client_offset < rar->dbo[rar->cursor].start_offset &&
+ rar->file_flags & FHD_SPLIT_BEFORE)
+ {
+ /* Search backwards for the correct data block */
+ if (rar->cursor == 0)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Attempt to seek past beginning of RAR data block");
+ return (ARCHIVE_FAILED);
+ }
+ rar->cursor--;
+ client_offset -= rar->dbo[rar->cursor+1].start_offset -
+ rar->dbo[rar->cursor].end_offset;
+ if (client_offset < rar->dbo[rar->cursor].start_offset)
+ continue;
+ ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset -
+ rar->dbo[rar->cursor].header_size, SEEK_SET);
+ if (ret < (ARCHIVE_OK))
+ return ret;
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret != (ARCHIVE_OK))
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Error during seek of RAR file");
+ return (ARCHIVE_FAILED);
+ }
+ rar->cursor--;
+ break;
+ }
+ else if (client_offset > rar->dbo[rar->cursor].end_offset &&
+ rar->file_flags & FHD_SPLIT_AFTER)
+ {
+ /* Search forward for the correct data block */
+ rar->cursor++;
+ if (rar->cursor < rar->nodes &&
+ client_offset > rar->dbo[rar->cursor].end_offset)
+ {
+ client_offset += rar->dbo[rar->cursor].start_offset -
+ rar->dbo[rar->cursor-1].end_offset;
+ continue;
+ }
+ rar->cursor--;
+ ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset,
+ SEEK_SET);
+ if (ret < (ARCHIVE_OK))
+ return ret;
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret == (ARCHIVE_EOF))
+ {
+ rar->has_endarc_header = 1;
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ }
+ if (ret != (ARCHIVE_OK))
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Error during seek of RAR file");
+ return (ARCHIVE_FAILED);
+ }
+ client_offset += rar->dbo[rar->cursor].start_offset -
+ rar->dbo[rar->cursor-1].end_offset;
+ continue;
+ }
+ break;
+ }
+ }
+
+ ret = __archive_read_seek(a, client_offset, SEEK_SET);
+ if (ret < (ARCHIVE_OK))
+ return ret;
+ rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret;
+ i = rar->cursor;
+ while (i > 0)
+ {
+ i--;
+ ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset;
+ }
+ ret -= rar->dbo[0].start_offset;
+
+ /* Always restart reading the file after a seek */
+ a->read_data_block = NULL;
+ a->read_data_offset = 0;
+ a->read_data_output_offset = 0;
+ a->read_data_remaining = 0;
+ rar->bytes_unconsumed = 0;
+ rar->offset = 0;
+
+ /*
+ * If a seek past the end of file was requested, return the requested
+ * offset.
+ */
+ if (ret == rar->unp_size && rar->offset_seek > rar->unp_size)
+ return rar->offset_seek;
+
+ /* Return the new offset */
+ rar->offset_seek = ret;
+ return rar->offset_seek;
+ }
+ else
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Seeking of compressed RAR files is unsupported");
+ }
+ return (ARCHIVE_FAILED);
+}
+
static int
archive_read_format_rar_cleanup(struct archive_read *a)
{
@@ -998,6 +1179,8 @@ archive_read_format_rar_cleanup(struct archive_read *a)
rar = (struct rar *)(a->format->data);
free_codes(a);
free(rar->filename);
+ free(rar->filename_save);
+ free(rar->dbo);
free(rar->unp_buffer);
free(rar->lzss.window);
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
@@ -1021,7 +1204,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
char *strp;
char packed_size[8];
char unp_size[8];
- int time;
+ int ttime;
struct archive_string_conv *sconv, *fn_sconv;
unsigned long crc32_val;
int ret = (ARCHIVE_OK), ret2;
@@ -1047,7 +1230,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
memcpy(&rar_header, p, sizeof(rar_header));
rar->file_flags = archive_le16dec(rar_header.flags);
header_size = archive_le16dec(rar_header.size);
- if (header_size < sizeof(file_header) + 7) {
+ if (header_size < (int64_t)sizeof(file_header) + 7) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid header size");
return (ARCHIVE_FATAL);
@@ -1082,11 +1265,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
- if ((h = __archive_read_ahead(a, header_size - 7, NULL)) == NULL)
+ if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
return (ARCHIVE_FATAL);
/* File Header CRC check. */
- crc32_val = crc32(crc32_val, h, header_size - 7);
+ crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7));
if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
@@ -1100,8 +1283,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
rar->compression_method = file_header.method;
- time = archive_le32dec(file_header.file_time);
- rar->mtime = get_time(time);
+ ttime = archive_le32dec(file_header.file_time);
+ rar->mtime = get_time(ttime);
rar->file_crc = archive_le32dec(file_header.file_crc);
@@ -1129,9 +1312,6 @@ read_header(struct archive_read *a, struct archive_entry *entry,
rar->unp_size = archive_le32dec(file_header.unp_size);
}
- /* TODO: Need to use CRC check for these kind of cases.
- * For now, check if sizes are not < 0.
- */
if (rar->packed_size < 0 || rar->unp_size < 0)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -1139,6 +1319,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
+ rar->bytes_remaining = rar->packed_size;
+
/* TODO: RARv3 subblocks contain comments. For now the complete block is
* consumed at the end.
*/
@@ -1146,7 +1328,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
size_t distance = p - (const char *)h;
header_size += rar->packed_size;
/* Make sure we have the extended data. */
- if ((h = __archive_read_ahead(a, header_size - 7, NULL)) == NULL)
+ if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
return (ARCHIVE_FATAL);
p = h;
endp = p + header_size - 7;
@@ -1159,13 +1341,17 @@ read_header(struct archive_read *a, struct archive_entry *entry,
"Invalid filename size");
return (ARCHIVE_FATAL);
}
- if (rar->filename_allocated < filename_size+2) {
- rar->filename = realloc(rar->filename, filename_size+2);
- if (rar->filename == NULL) {
+ if (rar->filename_allocated < filename_size * 2 + 2) {
+ char *newptr;
+ size_t newsize = filename_size * 2 + 2;
+ newptr = realloc(rar->filename, newsize);
+ if (newptr == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Couldn't allocate memory.");
return (ARCHIVE_FATAL);
}
+ rar->filename = newptr;
+ rar->filename_allocated = newsize;
}
filename = rar->filename;
memcpy(filename, p, filename_size);
@@ -1174,15 +1360,17 @@ read_header(struct archive_read *a, struct archive_entry *entry,
{
if (filename_size != strlen(filename))
{
- unsigned char highbyte, flagbits, flagbyte, length, offset;
+ unsigned char highbyte, flagbits, flagbyte;
+ unsigned fn_end, offset;
end = filename_size;
+ fn_end = filename_size * 2;
filename_size = 0;
- offset = strlen(filename) + 1;
+ offset = (unsigned)strlen(filename) + 1;
highbyte = *(p + offset++);
flagbits = 0;
flagbyte = 0;
- while (offset < end && filename_size < end)
+ while (offset < end && filename_size < fn_end)
{
if (!flagbits)
{
@@ -1208,19 +1396,26 @@ read_header(struct archive_read *a, struct archive_entry *entry,
break;
case 3:
{
- length = *(p + offset++);
- while (length)
- {
- if (filename_size >= end)
- break;
- filename[filename_size++] = *(p + offset);
+ char extra, high;
+ uint8_t length = *(p + offset++);
+
+ if (length & 0x80) {
+ extra = *(p + offset++);
+ high = (char)highbyte;
+ } else
+ extra = high = 0;
+ length = (length & 0x7f) + 2;
+ while (length && filename_size < fn_end) {
+ unsigned cp = filename_size >> 1;
+ filename[filename_size++] = high;
+ filename[filename_size++] = p[cp] + extra;
length--;
}
}
break;
}
}
- if (filename_size >= end) {
+ if (filename_size > fn_end) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid filename");
return (ARCHIVE_FATAL);
@@ -1272,6 +1467,51 @@ read_header(struct archive_read *a, struct archive_entry *entry,
p += filename_size;
}
+ /* Split file in multivolume RAR. No more need to process header. */
+ if (rar->filename_save &&
+ !memcmp(rar->filename, rar->filename_save, filename_size + 1))
+ {
+ __archive_read_consume(a, header_size - 7);
+ rar->cursor++;
+ if (rar->cursor >= rar->nodes)
+ {
+ rar->nodes++;
+ if ((rar->dbo =
+ realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
+ return (ARCHIVE_FATAL);
+ }
+ rar->dbo[rar->cursor].header_size = header_size;
+ rar->dbo[rar->cursor].start_offset = -1;
+ rar->dbo[rar->cursor].end_offset = -1;
+ }
+ if (rar->dbo[rar->cursor].start_offset < 0)
+ {
+ rar->dbo[rar->cursor].start_offset = a->filter->position;
+ rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
+ rar->packed_size;
+ }
+ return ret;
+ }
+
+ rar->filename_save = (char*)realloc(rar->filename_save,
+ filename_size + 1);
+ memcpy(rar->filename_save, rar->filename, filename_size + 1);
+
+ /* Set info for seeking */
+ free(rar->dbo);
+ if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
+ return (ARCHIVE_FATAL);
+ }
+ rar->dbo[0].header_size = header_size;
+ rar->dbo[0].start_offset = -1;
+ rar->dbo[0].end_offset = -1;
+ rar->cursor = 0;
+ rar->nodes = 1;
+
if (rar->file_flags & FHD_SALT)
{
if (p + 8 > endp) {
@@ -1292,6 +1532,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
__archive_read_consume(a, header_size - 7);
+ rar->dbo[0].start_offset = a->filter->position;
+ rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
switch(file_header.host_os)
{
@@ -1318,9 +1560,10 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
- rar->bytes_remaining = rar->packed_size;
rar->bytes_uncopied = rar->bytes_unconsumed = 0;
- rar->lzss.position = rar->dictionary_size = rar->offset = 0;
+ rar->lzss.position = rar->offset = 0;
+ rar->offset_seek = 0;
+ rar->dictionary_size = 0;
rar->offset_outgoing = 0;
rar->br.cache_avail = 0;
rar->br.avail_in = 0;
@@ -1381,15 +1624,15 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
static time_t
-get_time(int time)
+get_time(int ttime)
{
struct tm tm;
- tm.tm_sec = 2 * (time & 0x1f);
- tm.tm_min = (time >> 5) & 0x3f;
- tm.tm_hour = (time >> 11) & 0x1f;
- tm.tm_mday = (time >> 16) & 0x1f;
- tm.tm_mon = ((time >> 21) & 0x0f) - 1;
- tm.tm_year = ((time >> 25) & 0x7f) + 80;
+ tm.tm_sec = 2 * (ttime & 0x1f);
+ tm.tm_min = (ttime >> 5) & 0x3f;
+ tm.tm_hour = (ttime >> 11) & 0x1f;
+ tm.tm_mday = (ttime >> 16) & 0x1f;
+ tm.tm_mon = ((ttime >> 21) & 0x0f) - 1;
+ tm.tm_year = ((ttime >> 25) & 0x7f) + 80;
tm.tm_isdst = -1;
return mktime(&tm);
}
@@ -1398,7 +1641,7 @@ static int
read_exttime(const char *p, struct rar *rar, const char *endp)
{
unsigned rmode, flags, rem, j, count;
- int time, i;
+ int ttime, i;
struct tm *tm;
time_t t;
long nsec;
@@ -1420,8 +1663,8 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
{
if (p + 4 > endp)
return (-1);
- time = archive_le32dec(p);
- t = get_time(time);
+ ttime = archive_le32dec(p);
+ t = get_time(ttime);
p += 4;
}
rem = 0;
@@ -1475,11 +1718,12 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
int ret = (ARCHIVE_OK);
rar = (struct rar *)(a->format->data);
- if ((h = __archive_read_ahead(a, rar->packed_size, NULL)) == NULL)
+ if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
return (ARCHIVE_FATAL);
p = h;
- if (archive_entry_copy_symlink_l(entry, p, rar->packed_size, sconv))
+ if (archive_entry_copy_symlink_l(entry,
+ p, (size_t)rar->packed_size, sconv))
{
if (errno == ENOMEM)
{
@@ -1504,7 +1748,8 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
ssize_t bytes_avail;
rar = (struct rar *)(a->format->data);
- if (rar->bytes_remaining == 0)
+ if (rar->bytes_remaining == 0 &&
+ !(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER))
{
*buff = NULL;
*size = 0;
@@ -1518,23 +1763,23 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
return (ARCHIVE_EOF);
}
- *buff = __archive_read_ahead(a, 1, &bytes_avail);
+ *buff = rar_read_ahead(a, 1, &bytes_avail);
if (bytes_avail <= 0)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated RAR file data");
return (ARCHIVE_FATAL);
}
- if (bytes_avail > rar->bytes_remaining)
- bytes_avail = rar->bytes_remaining;
*size = bytes_avail;
*offset = rar->offset;
rar->offset += bytes_avail;
+ rar->offset_seek += bytes_avail;
rar->bytes_remaining -= bytes_avail;
rar->bytes_unconsumed = bytes_avail;
/* Calculate File CRC. */
- rar->crc_calculated = crc32(rar->crc_calculated, *buff, bytes_avail);
+ rar->crc_calculated = crc32(rar->crc_calculated, *buff,
+ (unsigned)bytes_avail);
return (ARCHIVE_OK);
}
@@ -1564,7 +1809,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
- rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
+ rar->crc_calculated = crc32(rar->crc_calculated, *buff,
+ (unsigned)*size);
rar->unp_offset = 0;
return (ARCHIVE_OK);
}
@@ -1585,8 +1831,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset))
bs = rar->unp_buffer_size - rar->unp_offset;
else
- bs = rar->bytes_uncopied;
- ret = copy_from_lzss_window(a, buff, rar->offset, bs);
+ bs = (size_t)rar->bytes_uncopied;
+ ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
if (ret != ARCHIVE_OK)
return (ret);
rar->offset += bs;
@@ -1597,7 +1843,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
- rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
+ rar->crc_calculated = crc32(rar->crc_calculated, *buff,
+ (unsigned)*size);
return (ret);
}
continue;
@@ -1713,8 +1960,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset))
bs = rar->unp_buffer_size - rar->unp_offset;
else
- bs = rar->bytes_uncopied;
- ret = copy_from_lzss_window(a, buff, rar->offset, bs);
+ bs = (size_t)rar->bytes_uncopied;
+ ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
if (ret != ARCHIVE_OK)
return (ret);
rar->offset += bs;
@@ -1730,7 +1977,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
- rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
+ rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size);
return ret;
}
@@ -1973,17 +2220,21 @@ parse_codes(struct archive_read *a)
/* Seems as though dictionary sizes are not used. Even so, minimize
* memory usage as much as possible.
*/
+ void *new_window;
+ unsigned int new_size;
+
if (rar->unp_size >= DICTIONARY_MAX_SIZE)
- rar->dictionary_size = DICTIONARY_MAX_SIZE;
+ new_size = DICTIONARY_MAX_SIZE;
else
- rar->dictionary_size = rar_fls(rar->unp_size) << 1;
- rar->lzss.window = (unsigned char *)realloc(rar->lzss.window,
- rar->dictionary_size);
- if (rar->lzss.window == NULL) {
+ new_size = rar_fls((unsigned int)rar->unp_size) << 1;
+ new_window = realloc(rar->lzss.window, new_size);
+ if (new_window == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for uncompressed data.");
return (ARCHIVE_FATAL);
}
+ rar->lzss.window = (unsigned char *)new_window;
+ rar->dictionary_size = new_size;
memset(rar->lzss.window, 0, rar->dictionary_size);
rar->lzss.mask = rar->dictionary_size - 1;
}
@@ -2221,10 +2472,12 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
static int
new_node(struct huffman_code *code)
{
- code->tree = (struct huffman_tree_node *)realloc(code->tree,
- (code->numentries + 1) * sizeof(*code->tree));
- if (code->tree == NULL)
+ void *new_tree;
+
+ new_tree = realloc(code->tree, (code->numentries + 1) * sizeof(*code->tree));
+ if (new_tree == NULL)
return (-1);
+ code->tree = (struct huffman_tree_node *)new_tree;
code->tree[code->numentries].branches[0] = -1;
code->tree[code->numentries].branches[1] = -2;
return 1;
@@ -2239,8 +2492,8 @@ make_table(struct archive_read *a, struct huffman_code *code)
code->tablesize = code->maxlength;
code->table =
- (struct huffman_table_entry *)malloc(sizeof(*code->table)
- * (1 << code->tablesize));
+ (struct huffman_table_entry *)calloc(1, sizeof(*code->table)
+ * ((size_t)1 << code->tablesize));
return make_table_recurse(a, code, 0, code->table, 0, code->tablesize);
}
@@ -2408,9 +2661,9 @@ expand(struct archive_read *a, int64_t end)
if ((lensymbol = read_next_symbol(a, &rar->lengthcode)) < 0)
goto bad_data;
- if (lensymbol > sizeof(lengthbases)/sizeof(lengthbases[0]))
+ if (lensymbol > (int)(sizeof(lengthbases)/sizeof(lengthbases[0])))
goto bad_data;
- if (lensymbol > sizeof(lengthbits)/sizeof(lengthbits[0]))
+ if (lensymbol > (int)(sizeof(lengthbits)/sizeof(lengthbits[0])))
goto bad_data;
len = lengthbases[lensymbol] + 2;
if (lengthbits[lensymbol] > 0) {
@@ -2442,9 +2695,9 @@ expand(struct archive_read *a, int64_t end)
}
else
{
- if (symbol-271 > sizeof(lengthbases)/sizeof(lengthbases[0]))
+ if (symbol-271 > (int)(sizeof(lengthbases)/sizeof(lengthbases[0])))
goto bad_data;
- if (symbol-271 > sizeof(lengthbits)/sizeof(lengthbits[0]))
+ if (symbol-271 > (int)(sizeof(lengthbits)/sizeof(lengthbits[0])))
goto bad_data;
len = lengthbases[symbol-271]+3;
if(lengthbits[symbol-271] > 0) {
@@ -2456,9 +2709,9 @@ expand(struct archive_read *a, int64_t end)
if ((offssymbol = read_next_symbol(a, &rar->offsetcode)) < 0)
goto bad_data;
- if (offssymbol > sizeof(offsetbases)/sizeof(offsetbases[0]))
+ if (offssymbol > (int)(sizeof(offsetbases)/sizeof(offsetbases[0])))
goto bad_data;
- if (offssymbol > sizeof(offsetbits)/sizeof(offsetbits[0]))
+ if (offssymbol > (int)(sizeof(offsetbits)/sizeof(offsetbits[0])))
goto bad_data;
offs = offsetbases[offssymbol]+1;
if(offsetbits[offssymbol] > 0)
@@ -2572,3 +2825,34 @@ copy_from_lzss_window(struct archive_read *a, const void **buffer,
*buffer = NULL;
return (ARCHIVE_OK);
}
+
+static const void *
+rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
+{
+ struct rar *rar = (struct rar *)(a->format->data);
+ const void *h = __archive_read_ahead(a, min, avail);
+ int ret;
+ if (avail)
+ {
+ if (a->read_data_is_posix_read && *avail > (ssize_t)a->read_data_requested)
+ *avail = a->read_data_requested;
+ if (*avail > rar->bytes_remaining)
+ *avail = (ssize_t)rar->bytes_remaining;
+ if (*avail < 0)
+ return NULL;
+ else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
+ rar->file_flags & FHD_SPLIT_AFTER)
+ {
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ if (ret == (ARCHIVE_EOF))
+ {
+ rar->has_endarc_header = 1;
+ ret = archive_read_format_rar_read_header(a, a->entry);
+ }
+ if (ret != (ARCHIVE_OK))
+ return NULL;
+ return rar_read_ahead(a, min, avail);
+ }
+ }
+ return h;
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c
index df2c00c..8434978 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_raw.c
@@ -77,6 +77,7 @@ archive_read_support_format_raw(struct archive *_a)
archive_read_format_raw_read_header,
archive_read_format_raw_read_data,
archive_read_format_raw_read_data_skip,
+ NULL,
archive_read_format_raw_cleanup);
if (r != ARCHIVE_OK)
free(info);
@@ -157,7 +158,7 @@ archive_read_format_raw_read_data(struct archive_read *a,
/* Record and return an error. */
*size = 0;
*offset = info->offset;
- return (avail);
+ return ((int)avail);
}
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
index 89a1d4f..e9523cb 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -210,10 +210,10 @@ static int read_body_to_string(struct archive_read *, struct tar *,
struct archive_string *, const void *h, size_t *);
static int solaris_sparse_parse(struct archive_read *, struct tar *,
struct archive_entry *, const char *);
-static int64_t tar_atol(const char *, unsigned);
-static int64_t tar_atol10(const char *, unsigned);
-static int64_t tar_atol256(const char *, unsigned);
-static int64_t tar_atol8(const char *, unsigned);
+static int64_t tar_atol(const char *, size_t);
+static int64_t tar_atol10(const char *, size_t);
+static int64_t tar_atol256(const char *, size_t);
+static int64_t tar_atol8(const char *, size_t);
static int tar_read_header(struct archive_read *, struct tar *,
struct archive_entry *, size_t *);
static int tohex(int c);
@@ -253,6 +253,7 @@ archive_read_support_format_tar(struct archive *_a)
archive_read_format_tar_read_header,
archive_read_format_tar_read_data,
archive_read_format_tar_skip,
+ NULL,
archive_read_format_tar_cleanup);
if (r != ARCHIVE_OK)
@@ -369,7 +370,7 @@ archive_read_format_tar_options(struct archive_read *a,
/* Handle UTF-8 filnames as libarchive 2.x */
tar->compat_2x = (val != NULL)?1:0;
tar->init_default_conversion = tar->compat_2x;
- ret = ARCHIVE_OK;
+ return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -383,11 +384,13 @@ archive_read_format_tar_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "tar: unknown keyword ``%s''", key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
/* utility function- this exists to centralize the logic of tracking
@@ -525,56 +528,57 @@ archive_read_format_tar_read_data(struct archive_read *a,
tar = (struct tar *)(a->format->data);
-skip_hole:
- /* Remove exhausted entries from sparse list. */
- while (tar->sparse_list != NULL &&
- tar->sparse_list->remaining == 0) {
- p = tar->sparse_list;
- tar->sparse_list = p->next;
- free(p);
- }
+ for (;;) {
+ /* Remove exhausted entries from sparse list. */
+ while (tar->sparse_list != NULL &&
+ tar->sparse_list->remaining == 0) {
+ p = tar->sparse_list;
+ tar->sparse_list = p->next;
+ free(p);
+ }
- if (tar->entry_bytes_unconsumed) {
- __archive_read_consume(a, tar->entry_bytes_unconsumed);
- tar->entry_bytes_unconsumed = 0;
- }
+ if (tar->entry_bytes_unconsumed) {
+ __archive_read_consume(a, tar->entry_bytes_unconsumed);
+ tar->entry_bytes_unconsumed = 0;
+ }
- /* If we're at end of file, return EOF. */
- if (tar->sparse_list == NULL || tar->entry_bytes_remaining == 0) {
- if (__archive_read_consume(a, tar->entry_padding) < 0)
- return (ARCHIVE_FATAL);
- tar->entry_padding = 0;
- *buff = NULL;
- *size = 0;
- *offset = tar->realsize;
- return (ARCHIVE_EOF);
- }
+ /* If we're at end of file, return EOF. */
+ if (tar->sparse_list == NULL ||
+ tar->entry_bytes_remaining == 0) {
+ if (__archive_read_consume(a, tar->entry_padding) < 0)
+ return (ARCHIVE_FATAL);
+ tar->entry_padding = 0;
+ *buff = NULL;
+ *size = 0;
+ *offset = tar->realsize;
+ return (ARCHIVE_EOF);
+ }
- *buff = __archive_read_ahead(a, 1, &bytes_read);
- if (bytes_read < 0)
- return (ARCHIVE_FATAL);
- if (*buff == NULL) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Truncated tar archive");
- return (ARCHIVE_FATAL);
+ *buff = __archive_read_ahead(a, 1, &bytes_read);
+ if (bytes_read < 0)
+ return (ARCHIVE_FATAL);
+ if (*buff == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Truncated tar archive");
+ return (ARCHIVE_FATAL);
+ }
+ if (bytes_read > tar->entry_bytes_remaining)
+ bytes_read = (ssize_t)tar->entry_bytes_remaining;
+ /* Don't read more than is available in the
+ * current sparse block. */
+ if (tar->sparse_list->remaining < bytes_read)
+ bytes_read = (ssize_t)tar->sparse_list->remaining;
+ *size = bytes_read;
+ *offset = tar->sparse_list->offset;
+ tar->sparse_list->remaining -= bytes_read;
+ tar->sparse_list->offset += bytes_read;
+ tar->entry_bytes_remaining -= bytes_read;
+ tar->entry_bytes_unconsumed = bytes_read;
+
+ if (!tar->sparse_list->hole)
+ return (ARCHIVE_OK);
+ /* Current is hole data and skip this. */
}
- if (bytes_read > tar->entry_bytes_remaining)
- bytes_read = tar->entry_bytes_remaining;
- /* Don't read more than is available in the
- * current sparse block. */
- if (tar->sparse_list->remaining < bytes_read)
- bytes_read = tar->sparse_list->remaining;
- *size = bytes_read;
- *offset = tar->sparse_list->offset;
- tar->sparse_list->remaining -= bytes_read;
- tar->sparse_list->offset += bytes_read;
- tar->entry_bytes_remaining -= bytes_read;
- tar->entry_bytes_unconsumed = bytes_read;
-
- if (tar->sparse_list->hole)
- goto skip_hole;
-
- return (ARCHIVE_OK);
}
static int
@@ -613,13 +617,14 @@ tar_read_header(struct archive_read *a, struct tar *tar,
int err;
const char *h;
const struct archive_entry_header_ustar *header;
+ const struct archive_entry_header_gnutar *gnuheader;
tar_flush_unconsumed(a, unconsumed);
/* Read 512-byte header record */
h = __archive_read_ahead(a, 512, &bytes);
if (bytes < 0)
- return (bytes);
+ return ((int)bytes);
if (bytes == 0) { /* EOF at a block boundary. */
/* Some writers do omit the block of nulls. <sigh> */
return (ARCHIVE_EOF);
@@ -700,7 +705,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
err = header_pax_extensions(a, tar, entry, h, unconsumed);
break;
default:
- if (memcmp(header->magic, "ustar \0", 8) == 0) {
+ gnuheader = (const struct archive_entry_header_gnutar *)h;
+ if (memcmp(gnuheader->magic, "ustar \0", 8) == 0) {
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive.archive_format_name = "GNU tar format";
err = header_gnutar(a, tar, entry, h, unconsumed);
@@ -749,7 +755,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
tar->entry_bytes_remaining -= bytes_read;
if (bytes_read < 0)
- return (bytes_read);
+ return ((int)bytes_read);
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -784,7 +790,7 @@ checksum(struct archive_read *a, const void *h)
* Test the checksum. Note that POSIX specifies _unsigned_
* bytes for this calculation.
*/
- sum = tar_atol(header->checksum, sizeof(header->checksum));
+ sum = (int)tar_atol(header->checksum, sizeof(header->checksum));
check = 0;
for (i = 0; i < 148; i++)
check += (unsigned char)bytes[i];
@@ -845,7 +851,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
* more to make sure that we don't overrun acl_text later.
*/
header = (const struct archive_entry_header_ustar *)h;
- size = tar_atol(header->size, sizeof(header->size));
+ size = (size_t)tar_atol(header->size, sizeof(header->size));
err = read_body_to_string(a, tar, &(tar->acl_text), h, unconsumed);
if (err != ARCHIVE_OK)
return (err);
@@ -1019,7 +1025,7 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
}
/* Fail if we can't make our buffer big enough. */
- if (archive_string_ensure(as, size+1) == NULL) {
+ if (archive_string_ensure(as, (size_t)size+1) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory");
return (ARCHIVE_FATAL);
@@ -1028,15 +1034,15 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
tar_flush_unconsumed(a, unconsumed);
/* Read the body into the string. */
- *unconsumed = (size + 511) & ~ 511;
+ *unconsumed = (size_t)((size + 511) & ~ 511);
src = __archive_read_ahead(a, *unconsumed, NULL);
if (src == NULL) {
*unconsumed = 0;
return (ARCHIVE_FATAL);
}
- memcpy(as->s, src, size);
+ memcpy(as->s, src, (size_t)size);
as->s[size] = '\0';
- as->length = size;
+ as->length = (size_t)size;
return (ARCHIVE_OK);
}
@@ -1066,7 +1072,8 @@ header_common(struct archive_read *a, struct tar *tar,
archive_string_empty(&(tar->entry_linkpath));
/* Parse out the numeric fields (all are octal) */
- archive_entry_set_mode(entry, tar_atol(header->mode, sizeof(header->mode)));
+ archive_entry_set_mode(entry,
+ (mode_t)tar_atol(header->mode, sizeof(header->mode)));
archive_entry_set_uid(entry, tar_atol(header->uid, sizeof(header->uid)));
archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid)));
tar->entry_bytes_remaining = tar_atol(header->size, sizeof(header->size));
@@ -1308,13 +1315,13 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
* Q: Is the above idea really possible? Even
* when there are GNU or pax extension entries?
*/
- data = __archive_read_ahead(a, size, NULL);
+ data = __archive_read_ahead(a, (size_t)size, NULL);
if (data == NULL) {
*unconsumed = 0;
return (ARCHIVE_FATAL);
}
- archive_entry_copy_mac_metadata(entry, data, size);
- *unconsumed = (size + 511) & ~ 511;
+ archive_entry_copy_mac_metadata(entry, data, (size_t)size);
+ *unconsumed = (size_t)((size + 511) & ~ 511);
tar_flush_unconsumed(a, unconsumed);
return (tar_read_header(a, tar, entry, unconsumed));
}
@@ -1422,9 +1429,9 @@ header_ustar(struct archive_read *a, struct tar *tar,
/* Parse out device numbers only for char and block specials. */
if (header->typeflag[0] == '3' || header->typeflag[0] == '4') {
- archive_entry_set_rdevmajor(entry,
+ archive_entry_set_rdevmajor(entry, (dev_t)
tar_atol(header->rdevmajor, sizeof(header->rdevmajor)));
- archive_entry_set_rdevminor(entry,
+ archive_entry_set_rdevminor(entry, (dev_t)
tar_atol(header->rdevminor, sizeof(header->rdevminor)));
}
@@ -1661,6 +1668,9 @@ pax_attribute(struct archive_read *a, struct tar *tar,
long n;
int err = ARCHIVE_OK, r;
+ if (value == NULL)
+ value = ""; /* Disable compiler warning; do not pass
+ * NULL pointer to strlen(). */
switch (key[0]) {
case 'G':
/* GNU "0.0" sparse pax format. */
@@ -1707,11 +1717,11 @@ pax_attribute(struct archive_read *a, struct tar *tar,
/* GNU "1.0" sparse pax format */
if (strcmp(key, "GNU.sparse.major") == 0) {
- tar->sparse_gnu_major = tar_atol10(value, strlen(value));
+ tar->sparse_gnu_major = (int)tar_atol10(value, strlen(value));
tar->sparse_gnu_pending = 1;
}
if (strcmp(key, "GNU.sparse.minor") == 0) {
- tar->sparse_gnu_minor = tar_atol10(value, strlen(value));
+ tar->sparse_gnu_minor = (int)tar_atol10(value, strlen(value));
tar->sparse_gnu_pending = 1;
}
if (strcmp(key, "GNU.sparse.name") == 0) {
@@ -1794,20 +1804,20 @@ pax_attribute(struct archive_read *a, struct tar *tar,
}
} else if (strcmp(key, "SCHILY.devmajor") == 0) {
archive_entry_set_rdevmajor(entry,
- tar_atol10(value, strlen(value)));
+ (dev_t)tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.devminor") == 0) {
archive_entry_set_rdevminor(entry,
- tar_atol10(value, strlen(value)));
+ (dev_t)tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.fflags") == 0) {
archive_entry_copy_fflags_text(entry, value);
} else if (strcmp(key, "SCHILY.dev") == 0) {
archive_entry_set_dev(entry,
- tar_atol10(value, strlen(value)));
+ (dev_t)tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.ino") == 0) {
archive_entry_set_ino(entry,
tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.nlink") == 0) {
- archive_entry_set_nlink(entry,
+ archive_entry_set_nlink(entry, (unsigned)
tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
@@ -2016,9 +2026,9 @@ header_gnutar(struct archive_read *a, struct tar *tar,
/* Parse out device numbers only for char and block specials */
if (header->typeflag[0] == '3' || header->typeflag[0] == '4') {
- archive_entry_set_rdevmajor(entry,
+ archive_entry_set_rdevmajor(entry, (dev_t)
tar_atol(header->rdevmajor, sizeof(header->rdevmajor)));
- archive_entry_set_rdevminor(entry,
+ archive_entry_set_rdevminor(entry, (dev_t)
tar_atol(header->rdevminor, sizeof(header->rdevminor)));
} else
archive_entry_set_rdev(entry, 0);
@@ -2253,7 +2263,8 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
* don't require this, but they should.
*/
do {
- bytes_read = readline(a, tar, &p, tar_min(*remaining, 100), unconsumed);
+ bytes_read = readline(a, tar, &p,
+ (ssize_t)tar_min(*remaining, 100), unconsumed);
if (bytes_read <= 0)
return (ARCHIVE_FATAL);
*remaining -= bytes_read;
@@ -2294,7 +2305,7 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
remaining = tar->entry_bytes_remaining;
/* Parse entries. */
- entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
+ entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
if (entries < 0)
return (ARCHIVE_FATAL);
/* Parse the individual entries. */
@@ -2312,16 +2323,16 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
}
/* Skip rest of block... */
tar_flush_unconsumed(a, unconsumed);
- bytes_read = tar->entry_bytes_remaining - remaining;
+ bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
to_skip = 0x1ff & -bytes_read;
if (to_skip != __archive_read_consume(a, to_skip))
return (ARCHIVE_FATAL);
- return (bytes_read + to_skip);
+ return ((ssize_t)(bytes_read + to_skip));
}
/*
* Solaris pax extension for a sparse file. This is recorded with the
- * data and hole pairs. The way recording sparse infomation by Solaris'
+ * data and hole pairs. The way recording sparse information by Solaris'
* pax simply indicates where data and sparse are, so the stored contents
* consist of both data and hole.
*/
@@ -2333,6 +2344,8 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar,
int64_t start, end;
int hole = 1;
+ (void)entry; /* UNUSED */
+
end = 0;
if (*p == ' ')
p++;
@@ -2380,7 +2393,7 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar,
* On read, this implementation supports both extensions.
*/
static int64_t
-tar_atol(const char *p, unsigned char_cnt)
+tar_atol(const char *p, size_t char_cnt)
{
/*
* Technically, GNU tar considers a field to be in base-256
@@ -2397,70 +2410,55 @@ tar_atol(const char *p, unsigned char_cnt)
* it does obey locale.
*/
static int64_t
-tar_atol8(const char *p, unsigned char_cnt)
+tar_atol_base_n(const char *p, size_t char_cnt, int base)
{
int64_t l, limit, last_digit_limit;
- int digit, sign, base;
+ int digit, sign;
- base = 8;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
- while (*p == ' ' || *p == '\t')
+ /* the pointer will not be dereferenced if char_cnt is zero
+ * due to the way the && operator is evaulated.
+ */
+ while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
p++;
- if (*p == '-') {
+ char_cnt--;
+ }
+
+ sign = 1;
+ if (char_cnt != 0 && *p == '-') {
sign = -1;
p++;
- } else
- sign = 1;
+ char_cnt--;
+ }
l = 0;
- digit = *p - '0';
- while (digit >= 0 && digit < base && char_cnt-- > 0) {
- if (l>limit || (l == limit && digit > last_digit_limit)) {
- l = INT64_MAX; /* Truncate on overflow. */
- break;
+ if (char_cnt != 0) {
+ digit = *p - '0';
+ while (digit >= 0 && digit < base && char_cnt != 0) {
+ if (l>limit || (l == limit && digit > last_digit_limit)) {
+ l = INT64_MAX; /* Truncate on overflow. */
+ break;
+ }
+ l = (l * base) + digit;
+ digit = *++p - '0';
+ char_cnt--;
}
- l = (l * base) + digit;
- digit = *++p - '0';
}
return (sign < 0) ? -l : l;
}
-/*
- * Note that this implementation does not (and should not!) obey
- * locale settings; you cannot simply substitute strtol here, since
- * it does obey locale.
- */
static int64_t
-tar_atol10(const char *p, unsigned char_cnt)
+tar_atol8(const char *p, size_t char_cnt)
{
- int64_t l, limit, last_digit_limit;
- int base, digit, sign;
-
- base = 10;
- limit = INT64_MAX / base;
- last_digit_limit = INT64_MAX % base;
-
- while (*p == ' ' || *p == '\t')
- p++;
- if (*p == '-') {
- sign = -1;
- p++;
- } else
- sign = 1;
+ return tar_atol_base_n(p, char_cnt, 8);
+}
- l = 0;
- digit = *p - '0';
- while (digit >= 0 && digit < base && char_cnt-- > 0) {
- if (l > limit || (l == limit && digit > last_digit_limit)) {
- l = INT64_MAX; /* Truncate on overflow. */
- break;
- }
- l = (l * base) + digit;
- digit = *++p - '0';
- }
- return (sign < 0) ? -l : l;
+static int64_t
+tar_atol10(const char *p, size_t char_cnt)
+{
+ return tar_atol_base_n(p, char_cnt, 10);
}
/*
@@ -2469,7 +2467,7 @@ tar_atol10(const char *p, unsigned char_cnt)
* ignored.
*/
static int64_t
-tar_atol256(const char *_p, unsigned char_cnt)
+tar_atol256(const char *_p, size_t char_cnt)
{
int64_t l, upper_limit, lower_limit;
const unsigned char *p = (const unsigned char *)_p;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
index 0834e6f..2530e34 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
@@ -183,9 +183,9 @@ struct xar_file {
time_t mtime;
time_t atime;
struct archive_string uname;
- uid_t uid;
+ int64_t uid;
struct archive_string gname;
- gid_t gid;
+ int64_t gid;
mode_t mode;
dev_t dev;
dev_t devmajor;
@@ -467,6 +467,7 @@ archive_read_support_format_xar(struct archive *_a)
xar_read_header,
xar_read_data,
xar_read_data_skip,
+ NULL,
xar_cleanup);
if (r != ARCHIVE_OK)
free(xar);
@@ -602,7 +603,8 @@ read_toc(struct archive_read *a)
r = move_reading_point(a, xar->toc_chksum_offset);
if (r != ARCHIVE_OK)
return (r);
- b = __archive_read_ahead(a, xar->toc_chksum_size, &bytes);
+ b = __archive_read_ahead(a,
+ (size_t)xar->toc_chksum_size, &bytes);
if (bytes < 0)
return ((int)bytes);
if ((uint64_t)bytes < xar->toc_chksum_size) {
@@ -611,7 +613,8 @@ read_toc(struct archive_read *a)
"Truncated archive file");
return (ARCHIVE_FATAL);
}
- r = checksum_final(a, b, xar->toc_chksum_size, NULL, 0);
+ r = checksum_final(a, b,
+ (size_t)xar->toc_chksum_size, NULL, 0);
__archive_read_consume(a, xar->toc_chksum_size);
xar->offset += xar->toc_chksum_size;
if (r != ARCHIVE_OK)
@@ -2065,7 +2068,7 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list)
xar->file->hdnext = xar->hdlink_orgs;
xar->hdlink_orgs = xar->file;
} else {
- xar->file->link = atol10(attr->value,
+ xar->file->link = (unsigned)atol10(attr->value,
strlen(attr->value));
if (xar->file->link > 0)
if (add_link(a, xar, xar->file) != ARCHIVE_OK) {
@@ -2624,6 +2627,7 @@ strappend_base64(struct xar *xar,
const unsigned char *b;
size_t len;
+ (void)xar; /* UNUSED */
len = 0;
out = buff;
b = (const unsigned char *)s;
@@ -2760,7 +2764,7 @@ xml_data(void *userData, const char *s, int len)
xar->file->has |= HAS_MODE;
xar->file->mode =
(xar->file->mode & AE_IFMT) |
- (atol8(s, len) & ~AE_IFMT);
+ ((mode_t)(atol8(s, len)) & ~AE_IFMT);
break;
case FILE_GROUP:
xar->file->has |= HAS_GID;
@@ -3075,12 +3079,15 @@ xml2_xmlattr_setup(struct archive_read *a,
attr->name = strdup(
(const char *)xmlTextReaderConstLocalName(reader));
if (attr->name == NULL) {
+ free(attr);
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
attr->value = strdup(
(const char *)xmlTextReaderConstValue(reader));
if (attr->value == NULL) {
+ free(attr->name);
+ free(attr);
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
index d150802..2fdc08b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2004 Tim Kientzle
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,23 +38,26 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102
#endif
#include "archive.h"
+#include "archive_endian.h"
#include "archive_entry.h"
#include "archive_entry_locale.h"
#include "archive_private.h"
+#include "archive_rb.h"
#include "archive_read_private.h"
-#include "archive_endian.h"
#ifndef HAVE_ZLIB_H
#include "archive_crc32.h"
#endif
struct zip_entry {
+ struct archive_rb_node node;
int64_t local_header_offset;
int64_t compressed_size;
int64_t uncompressed_size;
int64_t gid;
int64_t uid;
struct archive_entry *entry;
+ struct archive_string rsrcname;
time_t mtime;
time_t atime;
time_t ctime;
@@ -67,15 +70,19 @@ struct zip_entry {
struct zip {
/* Structural information about the archive. */
+ int64_t end_of_central_directory_offset;
int64_t central_directory_offset;
size_t central_directory_size;
size_t central_directory_entries;
char have_central_directory;
+ int64_t offset;
/* List of entries (seekable Zip only) */
size_t entries_remaining;
struct zip_entry *zip_entries;
struct zip_entry *entry;
+ struct archive_rb_tree tree;
+ struct archive_rb_tree tree_rsrc;
size_t unconsumed;
@@ -116,29 +123,36 @@ struct zip {
#define ZIP_STRONG_ENCRYPTED (1<<6)
#define ZIP_UTF8_NAME (1<<11)
-static int archive_read_format_zip_streamable_bid(struct archive_read *, int);
-static int archive_read_format_zip_seekable_bid(struct archive_read *, int);
+static int archive_read_format_zip_streamable_bid(struct archive_read *,
+ int);
+static int archive_read_format_zip_seekable_bid(struct archive_read *,
+ int);
static int archive_read_format_zip_options(struct archive_read *,
const char *, const char *);
static int archive_read_format_zip_cleanup(struct archive_read *);
static int archive_read_format_zip_read_data(struct archive_read *,
const void **, size_t *, int64_t *);
static int archive_read_format_zip_read_data_skip(struct archive_read *a);
-static int archive_read_format_zip_seekable_read_header(struct archive_read *,
- struct archive_entry *);
-static int archive_read_format_zip_streamable_read_header(struct archive_read *,
- struct archive_entry *);
+static int archive_read_format_zip_seekable_read_header(
+ struct archive_read *, struct archive_entry *);
+static int archive_read_format_zip_streamable_read_header(
+ struct archive_read *, struct archive_entry *);
+static ssize_t zip_get_local_file_header_size(struct archive_read *, size_t);
#ifdef HAVE_ZLIB_H
+static int zip_deflate_init(struct archive_read *, struct zip *);
static int zip_read_data_deflate(struct archive_read *a, const void **buff,
size_t *size, int64_t *offset);
#endif
static int zip_read_data_none(struct archive_read *a, const void **buff,
size_t *size, int64_t *offset);
static int zip_read_local_file_header(struct archive_read *a,
- struct archive_entry *entry, struct zip *);
+ struct archive_entry *entry, struct zip *);
static time_t zip_time(const char *);
static const char *compression_name(int compression);
-static void process_extra(const char *, size_t, struct zip_entry *);
+static void process_extra(const char *, size_t, struct zip_entry *);
+
+int archive_read_support_format_zip_streamable(struct archive *);
+int archive_read_support_format_zip_seekable(struct archive *);
int
archive_read_support_format_zip_streamable(struct archive *_a)
@@ -166,6 +180,7 @@ archive_read_support_format_zip_streamable(struct archive *_a)
archive_read_format_zip_streamable_read_header,
archive_read_format_zip_read_data,
archive_read_format_zip_read_data_skip,
+ NULL,
archive_read_format_zip_cleanup);
if (r != ARCHIVE_OK)
@@ -199,6 +214,7 @@ archive_read_support_format_zip_seekable(struct archive *_a)
archive_read_format_zip_seekable_read_header,
archive_read_format_zip_read_data,
archive_read_format_zip_read_data_skip,
+ NULL,
archive_read_format_zip_cleanup);
if (r != ARCHIVE_OK)
@@ -217,14 +233,13 @@ archive_read_support_format_zip(struct archive *a)
}
/*
- * TODO: This is a performance sink because it forces
- * the read core to drop buffered data from the start
- * of file, which will then have to be re-read again
- * if this bidder loses.
+ * TODO: This is a performance sink because it forces the read core to
+ * drop buffered data from the start of file, which will then have to
+ * be re-read again if this bidder loses.
*
- * Consider passing in the winning bid value to subsequent
- * bidders so that this bidder in particular can avoid
- * seeking if it knows it's going to lose anyway.
+ * We workaround this a little by passing in the best bid so far so
+ * that later bidders can do nothing if they know they'll never
+ * outbid. But we can certainly do better...
*/
static int
archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
@@ -249,8 +264,48 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
/* First four bytes are signature for end of central directory
record. Four zero bytes ensure this isn't a multi-volume
Zip file (which we don't yet support). */
- if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0)
- return 0;
+ if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0) {
+ int64_t i, tail;
+ int found;
+
+ /*
+ * If there is a comment in end of central directory
+ * record, 22 bytes are too short. we have to read more
+ * to properly detect the record. Hopefully, a length
+ * of the comment is not longer than 16362 bytes(16K-22).
+ */
+ if (filesize + 22 > 1024 * 16) {
+ tail = 1024 * 16;
+ filesize = __archive_read_seek(a, tail * -1, SEEK_END);
+ } else {
+ tail = filesize + 22;
+ filesize = __archive_read_seek(a, 0, SEEK_SET);
+ }
+ if (filesize < 0)
+ return 0;
+ if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL)
+ return 0;
+ for (found = 0, i = 0;!found && i < tail - 22;) {
+ switch (p[i]) {
+ case 'P':
+ if (memcmp(p+i,
+ "PK\005\006\000\000\000\000", 8) == 0) {
+ p += i;
+ filesize += tail -
+ (22 + archive_le16dec(p+20));
+ found = 1;
+ } else
+ i += 8;
+ break;
+ case 'K': i += 7; break;
+ case 005: i += 6; break;
+ case 006: i += 5; break;
+ default: i += 1; break;
+ }
+ }
+ if (!found)
+ return 0;
+ }
/* Since we've already done the hard work of finding the
end of central directory record, let's save the important
@@ -258,12 +313,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
zip->central_directory_entries = archive_le16dec(p + 10);
zip->central_directory_size = archive_le32dec(p + 12);
zip->central_directory_offset = archive_le32dec(p + 16);
+ zip->end_of_central_directory_offset = filesize;
/* Just one volume, so central dir must all be on this volume. */
if (zip->central_directory_entries != archive_le16dec(p + 8))
return 0;
/* Central directory can't extend beyond end of this file. */
- if (zip->central_directory_offset + zip->central_directory_size > filesize)
+ if (zip->central_directory_offset +
+ (int64_t)zip->central_directory_size > filesize)
return 0;
/* This is just a tiny bit higher than the maximum returned by
@@ -273,18 +330,117 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
}
static int
+cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2)
+{
+ const struct zip_entry *e1 = (const struct zip_entry *)n1;
+ const struct zip_entry *e2 = (const struct zip_entry *)n2;
+
+ return ((int)(e2->local_header_offset - e1->local_header_offset));
+}
+
+static int
+cmp_key(const struct archive_rb_node *n, const void *key)
+{
+ /* This function won't be called */
+ (void)n; /* UNUSED */
+ (void)key; /* UNUSED */
+ return 1;
+}
+
+static int
+rsrc_cmp_node(const struct archive_rb_node *n1,
+ const struct archive_rb_node *n2)
+{
+ const struct zip_entry *e1 = (const struct zip_entry *)n1;
+ const struct zip_entry *e2 = (const struct zip_entry *)n2;
+
+ return (strcmp(e2->rsrcname.s, e1->rsrcname.s));
+}
+
+static int
+rsrc_cmp_key(const struct archive_rb_node *n, const void *key)
+{
+ const struct zip_entry *e = (const struct zip_entry *)n;
+ return (strcmp((const char *)key, e->rsrcname.s));
+}
+
+static const char *
+rsrc_basename(const char *name, size_t name_length)
+{
+ const char *s, *r;
+
+ r = s = name;
+ for (;;) {
+ s = memchr(s, '/', name_length - (s - name));
+ if (s == NULL)
+ break;
+ r = ++s;
+ }
+ return (r);
+}
+
+static void
+expose_parent_dirs(struct zip *zip, const char *name, size_t name_length)
+{
+ struct archive_string str;
+ struct zip_entry *dir;
+ char *s;
+
+ archive_string_init(&str);
+ archive_strncpy(&str, name, name_length);
+ for (;;) {
+ s = strrchr(str.s, '/');
+ if (s == NULL)
+ break;
+ *s = '\0';
+ /* Transfer the parent directory from zip->tree_rsrc RB
+ * tree to zip->tree RB tree to expose. */
+ dir = (struct zip_entry *)
+ __archive_rb_tree_find_node(&zip->tree_rsrc, str.s);
+ if (dir == NULL)
+ break;
+ __archive_rb_tree_remove_node(&zip->tree_rsrc, &dir->node);
+ archive_string_free(&dir->rsrcname);
+ __archive_rb_tree_insert_node(&zip->tree, &dir->node);
+ }
+ archive_string_free(&str);
+}
+
+static int
slurp_central_directory(struct archive_read *a, struct zip *zip)
{
unsigned i;
+ int64_t correction;
+ static const struct archive_rb_tree_ops rb_ops = {
+ &cmp_node, &cmp_key
+ };
+ static const struct archive_rb_tree_ops rb_rsrc_ops = {
+ &rsrc_cmp_node, &rsrc_cmp_key
+ };
+
+ /*
+ * Consider the archive file we are reading may be SFX.
+ * So we have to calculate a SFX header size to revise
+ * ZIP header offsets.
+ */
+ correction = zip->end_of_central_directory_offset -
+ (zip->central_directory_offset + zip->central_directory_size);
+ /* The central directory offset is relative value, and so
+ * we revise this offset for SFX. */
+ zip->central_directory_offset += correction;
__archive_read_seek(a, zip->central_directory_offset, SEEK_SET);
+ zip->offset = zip->central_directory_offset;
+ __archive_rb_tree_init(&zip->tree, &rb_ops);
+ __archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops);
- zip->zip_entries = calloc(zip->central_directory_entries, sizeof(struct zip_entry));
+ zip->zip_entries = calloc(zip->central_directory_entries,
+ sizeof(struct zip_entry));
for (i = 0; i < zip->central_directory_entries; ++i) {
struct zip_entry *zip_entry = &zip->zip_entries[i];
size_t filename_length, extra_length, comment_length;
uint32_t external_attributes;
- const char *p;
+ const char *name, *p, *r;
if ((p = __archive_read_ahead(a, 46, NULL)) == NULL)
return ARCHIVE_FATAL;
@@ -298,7 +454,7 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
zip_entry->system = p[5];
/* version_required = archive_le16dec(p + 6); */
zip_entry->flags = archive_le16dec(p + 8);
- zip_entry->compression = archive_le16dec(p + 10);
+ zip_entry->compression = (char)archive_le16dec(p + 10);
zip_entry->mtime = zip_time(p + 12);
zip_entry->crc32 = archive_le32dec(p + 16);
zip_entry->compressed_size = archive_le32dec(p + 20);
@@ -309,31 +465,233 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
/* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */
/* internal_attributes = archive_le16dec(p + 36); */ /* text bit */
external_attributes = archive_le32dec(p + 38);
- zip_entry->local_header_offset = archive_le32dec(p + 42);
+ zip_entry->local_header_offset =
+ archive_le32dec(p + 42) + correction;
+ /* If we can't guess the mode, leave it zero here;
+ when we read the local file header we might get
+ more information. */
+ zip_entry->mode = 0;
if (zip_entry->system == 3) {
zip_entry->mode = external_attributes >> 16;
+ }
+
+ /*
+ * Mac resource fork files are stored under the
+ * "__MACOSX/" directory, so we should check if
+ * it is.
+ */
+ /* Make sure we have the file name. */
+ if ((p = __archive_read_ahead(a, 46 + filename_length, NULL))
+ == NULL)
+ return ARCHIVE_FATAL;
+ name = p + 46;
+ r = rsrc_basename(name, filename_length);
+ if (filename_length >= 9 &&
+ strncmp("__MACOSX/", name, 9) == 0) {
+ /* If this file is not a resource fork nor
+ * a directory. We should treat it as a non
+ * resource fork file to expose it. */
+ if (name[filename_length-1] != '/' &&
+ (r - name < 3 || r[0] != '.' || r[1] != '_')) {
+ __archive_rb_tree_insert_node(&zip->tree,
+ &zip_entry->node);
+ /* Expose its parent directories. */
+ expose_parent_dirs(zip, name, filename_length);
+ } else {
+ /* This file is a resource fork file or
+ * a directory. */
+ archive_strncpy(&(zip_entry->rsrcname), name,
+ filename_length);
+ __archive_rb_tree_insert_node(&zip->tree_rsrc,
+ &zip_entry->node);
+ }
} else {
- zip_entry->mode = AE_IFREG | 0777;
+ /* Generate resource fork name to find its resource
+ * file at zip->tree_rsrc. */
+ archive_strcpy(&(zip_entry->rsrcname), "__MACOSX/");
+ archive_strncat(&(zip_entry->rsrcname), name, r - name);
+ archive_strcat(&(zip_entry->rsrcname), "._");
+ archive_strncat(&(zip_entry->rsrcname),
+ name + (r - name), filename_length - (r - name));
+ /* Register an entry to RB tree to sort it by
+ * file offset. */
+ __archive_rb_tree_insert_node(&zip->tree,
+ &zip_entry->node);
}
- /* Do we need to parse filename here? */
- /* Or can we wait until we read the local header? */
+ /* We don't read the filename until we get to the
+ local file header. Reading it here would speed up
+ table-of-contents operations (removing the need to
+ find and read local file header to get the
+ filename) at the cost of requiring a lot of extra
+ space. */
+ /* We don't read the extra block here. We assume it
+ will be duplicated at the local file header. */
__archive_read_consume(a,
46 + filename_length + extra_length + comment_length);
}
- /* TODO: Sort zip entries. */
-
return ARCHIVE_OK;
}
+static int64_t
+zip_read_consume(struct archive_read *a, int64_t bytes)
+{
+ struct zip *zip = (struct zip *)a->format->data;
+ int64_t skip;
+
+ skip = __archive_read_consume(a, bytes);
+ if (skip > 0)
+ zip->offset += skip;
+ return (skip);
+}
+
+static int
+zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
+ struct zip_entry *rsrc)
+{
+ struct zip *zip = (struct zip *)a->format->data;
+ unsigned char *metadata, *mp;
+ int64_t offset = zip->offset;
+ size_t remaining_bytes, metadata_bytes;
+ ssize_t hsize;
+ int ret = ARCHIVE_OK, eof;
+
+ switch(rsrc->compression) {
+ case 0: /* No compression. */
+#ifdef HAVE_ZLIB_H
+ case 8: /* Deflate compression. */
+#endif
+ break;
+ default: /* Unsupported compression. */
+ /* Return a warning. */
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Unsupported ZIP compression method (%s)",
+ compression_name(rsrc->compression));
+ /* We can't decompress this entry, but we will
+ * be able to skip() it and try the next entry. */
+ return (ARCHIVE_WARN);
+ }
+
+ if (rsrc->uncompressed_size > (128 * 1024)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Mac metadata is too large: %jd > 128K bytes",
+ (intmax_t)rsrc->uncompressed_size);
+ return (ARCHIVE_WARN);
+ }
+
+ metadata = malloc((size_t)rsrc->uncompressed_size);
+ if (metadata == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Mac metadata");
+ return (ARCHIVE_FATAL);
+ }
+
+ if (zip->offset < rsrc->local_header_offset)
+ zip_read_consume(a, rsrc->local_header_offset - zip->offset);
+ else if (zip->offset != rsrc->local_header_offset) {
+ __archive_read_seek(a, rsrc->local_header_offset, SEEK_SET);
+ zip->offset = zip->entry->local_header_offset;
+ }
+
+ hsize = zip_get_local_file_header_size(a, 0);
+ zip_read_consume(a, hsize);
+
+ remaining_bytes = (size_t)rsrc->compressed_size;
+ metadata_bytes = (size_t)rsrc->uncompressed_size;
+ mp = metadata;
+ eof = 0;
+ while (!eof && remaining_bytes) {
+ const unsigned char *p;
+ ssize_t bytes_avail;
+ size_t bytes_used;
+
+ p = __archive_read_ahead(a, 1, &bytes_avail);
+ if (p == NULL) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated ZIP file header");
+ ret = ARCHIVE_WARN;
+ goto exit_mac_metadata;
+ }
+ if ((size_t)bytes_avail > remaining_bytes)
+ bytes_avail = remaining_bytes;
+ switch(rsrc->compression) {
+ case 0: /* No compression. */
+ memcpy(mp, p, bytes_avail);
+ bytes_used = (size_t)bytes_avail;
+ metadata_bytes -= bytes_used;
+ mp += bytes_used;
+ if (metadata_bytes == 0)
+ eof = 1;
+ break;
+#ifdef HAVE_ZLIB_H
+ case 8: /* Deflate compression. */
+ {
+ int r;
+
+ ret = zip_deflate_init(a, zip);
+ if (ret != ARCHIVE_OK)
+ goto exit_mac_metadata;
+ zip->stream.next_in =
+ (Bytef *)(uintptr_t)(const void *)p;
+ zip->stream.avail_in = (uInt)bytes_avail;
+ zip->stream.total_in = 0;
+ zip->stream.next_out = mp;
+ zip->stream.avail_out = (uInt)metadata_bytes;
+ zip->stream.total_out = 0;
+
+ r = inflate(&zip->stream, 0);
+ switch (r) {
+ case Z_OK:
+ break;
+ case Z_STREAM_END:
+ eof = 1;
+ break;
+ case Z_MEM_ERROR:
+ archive_set_error(&a->archive, ENOMEM,
+ "Out of memory for ZIP decompression");
+ ret = ARCHIVE_FATAL;
+ goto exit_mac_metadata;
+ default:
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "ZIP decompression failed (%d)", r);
+ ret = ARCHIVE_FATAL;
+ goto exit_mac_metadata;
+ }
+ bytes_used = zip->stream.total_in;
+ metadata_bytes -= zip->stream.total_out;
+ mp += zip->stream.total_out;
+ break;
+ }
+#endif
+ default:
+ bytes_used = 0;
+ break;
+ }
+ zip_read_consume(a, bytes_used);
+ remaining_bytes -= bytes_used;
+ }
+ archive_entry_copy_mac_metadata(entry, metadata,
+ (size_t)rsrc->uncompressed_size - metadata_bytes);
+
+ __archive_read_seek(a, offset, SEEK_SET);
+ zip->offset = offset;
+exit_mac_metadata:
+ zip->decompress_init = 0;
+ free(metadata);
+ return (ret);
+}
+
static int
archive_read_format_zip_seekable_read_header(struct archive_read *a,
struct archive_entry *entry)
{
struct zip *zip = (struct zip *)a->format->data;
- int r;
+ struct zip_entry *rsrc;
+ int r, ret = ARCHIVE_OK;
a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
if (a->archive.archive_format_name == NULL)
@@ -344,26 +702,45 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
zip->entries_remaining = zip->central_directory_entries;
if (r != ARCHIVE_OK)
return r;
- zip->entry = zip->zip_entries;
- } else {
- ++zip->entry;
+ /* Get first entry whose local header offset is lower than
+ * other entries in the archive file. */
+ zip->entry =
+ (struct zip_entry *)ARCHIVE_RB_TREE_MIN(&zip->tree);
+ } else if (zip->entry != NULL) {
+ /* Get next entry in local header offset order. */
+ zip->entry = (struct zip_entry *)__archive_rb_tree_iterate(
+ &zip->tree, &zip->entry->node, ARCHIVE_RB_DIR_RIGHT);
}
- if (zip->entries_remaining <= 0)
+ if (zip->entries_remaining <= 0 || zip->entry == NULL)
return ARCHIVE_EOF;
--zip->entries_remaining;
- /* TODO: If entries are sorted by offset within the file, we
- should be able to skip here instead of seeking. Skipping is
- typically faster (easier for I/O layer to optimize). */
- __archive_read_seek(a, zip->entry->local_header_offset, SEEK_SET);
+ if (zip->entry->rsrcname.s)
+ rsrc = (struct zip_entry *)__archive_rb_tree_find_node(
+ &zip->tree_rsrc, zip->entry->rsrcname.s);
+ else
+ rsrc = NULL;
+
+ /* File entries are sorted by the header offset, we should mostly
+ * use zip_read_consume to advance a read point to avoid redundant
+ * data reading. */
+ if (zip->offset < zip->entry->local_header_offset)
+ zip_read_consume(a,
+ zip->entry->local_header_offset - zip->offset);
+ else if (zip->offset != zip->entry->local_header_offset) {
+ __archive_read_seek(a, zip->entry->local_header_offset,
+ SEEK_SET);
+ zip->offset = zip->entry->local_header_offset;
+ }
zip->unconsumed = 0;
r = zip_read_local_file_header(a, entry, zip);
if (r != ARCHIVE_OK)
return r;
if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) {
const void *p;
- size_t linkname_length = archive_entry_size(entry);
+ struct archive_string_conv *sconv;
+ size_t linkname_length = (size_t)archive_entry_size(entry);
archive_entry_set_size(entry, 0);
p = __archive_read_ahead(a, linkname_length, NULL);
@@ -373,17 +750,45 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a,
return ARCHIVE_FATAL;
}
+ sconv = zip->sconv;
+ if (sconv == NULL && (zip->entry->flags & ZIP_UTF8_NAME))
+ sconv = zip->sconv_utf8;
+ if (sconv == NULL)
+ sconv = zip->sconv_default;
if (archive_entry_copy_symlink_l(entry, p, linkname_length,
- NULL) != 0) {
- /* NOTE: If the last argument is NULL, this will
- * fail only by memeory allocation failure. */
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate memory for Symlink");
- return (ARCHIVE_FATAL);
+ sconv) != 0) {
+ if (errno != ENOMEM && sconv == zip->sconv_utf8 &&
+ (zip->entry->flags & ZIP_UTF8_NAME))
+ archive_entry_copy_symlink_l(entry, p,
+ linkname_length, NULL);
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Symlink");
+ return (ARCHIVE_FATAL);
+ }
+ /*
+ * Since there is no character-set regulation for
+ * symlink name, do not report the conversion error
+ * in an automatic conversion.
+ */
+ if (sconv != zip->sconv_utf8 ||
+ (zip->entry->flags & ZIP_UTF8_NAME) == 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Symlink cannot be converted "
+ "from %s to current locale.",
+ archive_string_conversion_charset_name(
+ sconv));
+ ret = ARCHIVE_WARN;
+ }
}
- /* TODO: handle character-set issues? */
}
- return ARCHIVE_OK;
+ if (rsrc) {
+ int ret2 = zip_read_mac_metadata(a, entry, rsrc);
+ if (ret2 < ret)
+ ret = ret2;
+ }
+ return (ret);
}
static int
@@ -410,6 +815,11 @@ archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid)
return (30);
}
+ /* TODO: It's worth looking ahead a little bit for a valid
+ * PK signature. In particular, that would make it possible
+ * to read some UUEncoded SFX files or SFX files coming from
+ * a network socket. */
+
return (0);
}
@@ -424,11 +834,12 @@ archive_read_format_zip_options(struct archive_read *a,
if (strcmp(key, "compat-2x") == 0) {
/* Handle filnames as libarchive 2.x */
zip->init_default_conversion = (val != NULL) ? 1 : 0;
- ret = ARCHIVE_OK;
+ return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "zip: hdrcharset option needs a character-set name");
+ "zip: hdrcharset option needs a character-set name"
+ );
else {
zip->sconv = archive_string_conversion_from_charset(
&a->archive, val, 0);
@@ -439,11 +850,13 @@ archive_read_format_zip_options(struct archive_read *a,
} else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "zip: unknown keyword ``%s''", key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -462,7 +875,8 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
if (zip->zip_entries == NULL) {
zip->zip_entries = malloc(sizeof(struct zip_entry));
if (zip->zip_entries == NULL) {
- archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ archive_set_error(&a->archive, ENOMEM,
+ "Out of memory");
return ARCHIVE_FATAL;
}
}
@@ -470,7 +884,7 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
memset(zip->entry, 0, sizeof(struct zip_entry));
/* Search ahead for the next local file header. */
- __archive_read_consume(a, zip->unconsumed);
+ zip_read_consume(a, zip->unconsumed);
zip->unconsumed = 0;
for (;;) {
int64_t skipped = 0;
@@ -490,8 +904,9 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
if (p[2] == '\003' && p[3] == '\004') {
/* Regular file entry. */
- __archive_read_consume(a, skipped);
- return zip_read_local_file_header(a, entry, zip);
+ zip_read_consume(a, skipped);
+ return zip_read_local_file_header(a,
+ entry, zip);
}
if (p[2] == '\005' && p[3] == '\006')
@@ -501,8 +916,31 @@ archive_read_format_zip_streamable_read_header(struct archive_read *a,
++p;
++skipped;
}
- __archive_read_consume(a, skipped);
+ zip_read_consume(a, skipped);
+ }
+}
+
+static ssize_t
+zip_get_local_file_header_size(struct archive_read *a, size_t extra)
+{
+ const char *p;
+ ssize_t filename_length, extra_length;
+
+ if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Truncated ZIP file header");
+ return (ARCHIVE_WARN);
+ }
+ p += extra;
+
+ if (memcmp(p, "PK\003\004", 4) != 0) {
+ archive_set_error(&a->archive, -1, "Damaged Zip archive");
+ return ARCHIVE_WARN;
}
+ filename_length = archive_le16dec(p + 26);
+ extra_length = archive_le16dec(p + 28);
+
+ return (30 + filename_length + extra_length);
}
/*
@@ -550,7 +988,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
version = p[4];
zip_entry->system = p[5];
zip_entry->flags = archive_le16dec(p + 6);
- zip_entry->compression = archive_le16dec(p + 8);
+ zip_entry->compression = (char)archive_le16dec(p + 8);
zip_entry->mtime = zip_time(p + 10);
local_crc32 = archive_le32dec(p + 14);
compressed_size = archive_le32dec(p + 18);
@@ -558,11 +996,11 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
filename_length = archive_le16dec(p + 26);
extra_length = archive_le16dec(p + 28);
- __archive_read_consume(a, 30);
+ zip_read_consume(a, 30);
if (zip->have_central_directory) {
- /* If we read the central dir entry, we must have size information
- as well, so ignore the length-at-end flag. */
+ /* If we read the central dir entry, we must have size
+ * information as well, so ignore the length-at-end flag. */
zip_entry->flags &= ~ZIP_LENGTH_AT_END;
/* If we have values from both the local file header
and the central directory, warn about mismatches
@@ -570,19 +1008,22 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
writers always put zero in the local header; don't
bother warning about that. */
if (local_crc32 != 0 && local_crc32 != zip_entry->crc32) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Inconsistent CRC32 values");
ret = ARCHIVE_WARN;
}
if (compressed_size != 0
&& compressed_size != zip_entry->compressed_size) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Inconsistent compressed size");
ret = ARCHIVE_WARN;
}
if (uncompressed_size != 0
&& uncompressed_size != zip_entry->uncompressed_size) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Inconsistent uncompressed size");
ret = ARCHIVE_WARN;
}
@@ -628,7 +1069,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
archive_string_conversion_charset_name(sconv));
ret = ARCHIVE_WARN;
}
- __archive_read_consume(a, filename_length);
+ zip_read_consume(a, filename_length);
if (zip_entry->mode == 0) {
/* Especially in streaming mode, we can end up
@@ -640,14 +1081,14 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
if (len > 0 && wp[len - 1] == L'/')
zip_entry->mode = AE_IFDIR | 0777;
else
- zip_entry->mode = AE_IFREG | 0777;
+ zip_entry->mode = AE_IFREG | 0666;
} else {
cp = archive_entry_pathname(entry);
len = (cp != NULL)?strlen(cp):0;
if (len > 0 && cp[len - 1] == '/')
zip_entry->mode = AE_IFDIR | 0777;
else
- zip_entry->mode = AE_IFREG | 0777;
+ zip_entry->mode = AE_IFREG | 0666;
}
}
@@ -658,7 +1099,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
process_extra(h, extra_length, zip_entry);
- __archive_read_consume(a, extra_length);
+ zip_read_consume(a, extra_length);
/* Populate some additional entry fields: */
archive_entry_set_mode(entry, zip_entry->mode);
@@ -702,8 +1143,8 @@ compression_name(int compression)
"deflation"
};
- if (compression <
- sizeof(compression_names)/sizeof(compression_names[0]))
+ if (0 <= compression && compression <
+ (int)(sizeof(compression_names)/sizeof(compression_names[0])))
return compression_names[compression];
else
return "??";
@@ -755,7 +1196,7 @@ archive_read_format_zip_read_data(struct archive_read *a,
return (ARCHIVE_FAILED);
}
- __archive_read_consume(a, zip->unconsumed);
+ zip_read_consume(a, zip->unconsumed);
zip->unconsumed = 0;
switch(zip->entry->compression) {
@@ -781,13 +1222,16 @@ archive_read_format_zip_read_data(struct archive_read *a,
return (r);
/* Update checksum */
if (*size)
- zip->entry_crc32 = crc32(zip->entry_crc32, *buff, *size);
+ zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
+ (unsigned)*size);
/* If we hit the end, swallow any end-of-data marker. */
if (zip->end_of_entry) {
/* Check file size, CRC against these values. */
- if (zip->entry->compressed_size != zip->entry_compressed_bytes_read) {
+ if (zip->entry->compressed_size !=
+ zip->entry_compressed_bytes_read) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "ZIP compressed data is wrong size (read %jd, expected %jd)",
+ "ZIP compressed data is wrong size "
+ "(read %jd, expected %jd)",
(intmax_t)zip->entry_compressed_bytes_read,
(intmax_t)zip->entry->compressed_size);
return (ARCHIVE_WARN);
@@ -797,7 +1241,8 @@ archive_read_format_zip_read_data(struct archive_read *a,
if ((zip->entry->uncompressed_size & UINT32_MAX)
!= (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "ZIP uncompressed data is wrong size (read %jd, expected %jd)",
+ "ZIP uncompressed data is wrong size "
+ "(read %jd, expected %jd)",
(intmax_t)zip->entry_uncompressed_bytes_read,
(intmax_t)zip->entry->uncompressed_size);
return (ARCHIVE_WARN);
@@ -846,6 +1291,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
const char *buff;
ssize_t bytes_avail;
+ (void)offset; /* UNUSED */
+
zip = (struct zip *)(a->format->data);
if (zip->entry->flags & ZIP_LENGTH_AT_END) {
@@ -858,7 +1305,8 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
that are longer than this, so a failure to get at
least 16 bytes really does indicate a truncated
file. */
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file data");
return (ARCHIVE_FATAL);
}
@@ -867,8 +1315,10 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
if (p[0] == 'P' && p[1] == 'K'
&& p[2] == '\007' && p[3] == '\010'
&& archive_le32dec(p + 4) == zip->entry_crc32
- && archive_le32dec(p + 8) == zip->entry_compressed_bytes_read
- && archive_le32dec(p + 12) == zip->entry_uncompressed_bytes_read) {
+ && archive_le32dec(p + 8) ==
+ zip->entry_compressed_bytes_read
+ && archive_le32dec(p + 12) ==
+ zip->entry_uncompressed_bytes_read) {
zip->entry->crc32 = archive_le32dec(p + 4);
zip->entry->compressed_size = archive_le32dec(p + 8);
zip->entry->uncompressed_size = archive_le32dec(p + 12);
@@ -879,9 +1329,10 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
/* If not at EOF, ensure we consume at least one byte. */
++p;
- /* Scan forward until we see where a PK\007\010 signature might be. */
- /* Return bytes up until that point. On the next call, the code
- above will verify the data descriptor. */
+ /* Scan forward until we see where a PK\007\010 signature
+ * might be. */
+ /* Return bytes up until that point. On the next call,
+ * the code above will verify the data descriptor. */
while (p < buff + bytes_avail - 4) {
if (p[3] == 'P') { p += 3; }
else if (p[3] == 'K') { p += 2; }
@@ -900,12 +1351,13 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
/* Grab a bunch of bytes. */
buff = __archive_read_ahead(a, 1, &bytes_avail);
if (bytes_avail <= 0) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file data");
return (ARCHIVE_FATAL);
}
if (bytes_avail > zip->entry_bytes_remaining)
- bytes_avail = zip->entry_bytes_remaining;
+ bytes_avail = (ssize_t)zip->entry_bytes_remaining;
}
*size = bytes_avail;
zip->entry_bytes_remaining -= bytes_avail;
@@ -918,6 +1370,31 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
#ifdef HAVE_ZLIB_H
static int
+zip_deflate_init(struct archive_read *a, struct zip *zip)
+{
+ int r;
+
+ /* If we haven't yet read any data, initialize the decompressor. */
+ if (!zip->decompress_init) {
+ if (zip->stream_valid)
+ r = inflateReset(&zip->stream);
+ else
+ r = inflateInit2(&zip->stream,
+ -15 /* Don't check for zlib header */);
+ if (r != Z_OK) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Can't initialize ZIP decompression.");
+ return (ARCHIVE_FATAL);
+ }
+ /* Stream structure has been set up. */
+ zip->stream_valid = 1;
+ /* We've initialized decompression for this stream. */
+ zip->decompress_init = 1;
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
zip_read_data_deflate(struct archive_read *a, const void **buff,
size_t *size, int64_t *offset)
{
@@ -926,6 +1403,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
const void *compressed_buff;
int r;
+ (void)offset; /* UNUSED */
+
zip = (struct zip *)(a->format->data);
/* If the buffer hasn't been allocated, allocate it now. */
@@ -940,23 +1419,9 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
}
}
- /* If we haven't yet read any data, initialize the decompressor. */
- if (!zip->decompress_init) {
- if (zip->stream_valid)
- r = inflateReset(&zip->stream);
- else
- r = inflateInit2(&zip->stream,
- -15 /* Don't check for zlib header */);
- if (r != Z_OK) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Can't initialize ZIP decompression.");
- return (ARCHIVE_FATAL);
- }
- /* Stream structure has been set up. */
- zip->stream_valid = 1;
- /* We've initialized decompression for this stream. */
- zip->decompress_init = 1;
- }
+ r = zip_deflate_init(a, zip);
+ if (r != ARCHIVE_OK)
+ return (r);
/*
* Note: '1' here is a performance optimization.
@@ -967,7 +1432,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
compressed_buff = __archive_read_ahead(a, 1, &bytes_avail);
if (0 == (zip->entry->flags & ZIP_LENGTH_AT_END)
&& bytes_avail > zip->entry_bytes_remaining) {
- bytes_avail = zip->entry_bytes_remaining;
+ bytes_avail = (ssize_t)zip->entry_bytes_remaining;
}
if (bytes_avail <= 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -982,10 +1447,10 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
* cast to remove 'const'.
*/
zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff;
- zip->stream.avail_in = bytes_avail;
+ zip->stream.avail_in = (uInt)bytes_avail;
zip->stream.total_in = 0;
zip->stream.next_out = zip->uncompressed_buffer;
- zip->stream.avail_out = zip->uncompressed_buffer_size;
+ zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size;
zip->stream.total_out = 0;
r = inflate(&zip->stream, 0);
@@ -1007,7 +1472,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
/* Consume as much as the compressor actually used. */
bytes_avail = zip->stream.total_in;
- __archive_read_consume(a, bytes_avail);
+ zip_read_consume(a, bytes_avail);
zip->entry_bytes_remaining -= bytes_avail;
zip->entry_compressed_bytes_read += bytes_avail;
@@ -1025,7 +1490,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
return (ARCHIVE_FATAL);
}
/* Consume the optional PK\007\010 marker. */
- if (p[0] == 'P' && p[1] == 'K' && p[2] == '\007' && p[3] == '\010') {
+ if (p[0] == 'P' && p[1] == 'K' &&
+ p[2] == '\007' && p[3] == '\010') {
zip->entry->crc32 = archive_le32dec(p + 4);
zip->entry->compressed_size = archive_le32dec(p + 8);
zip->entry->uncompressed_size = archive_le32dec(p + 12);
@@ -1047,14 +1513,11 @@ archive_read_format_zip_read_data_skip(struct archive_read *a)
/* If we've already read to end of data, we're done. */
if (zip->end_of_entry)
return (ARCHIVE_OK);
- /* If we're seeking, we're done. */
- if (zip->have_central_directory)
- return (ARCHIVE_OK);
/* So we know we're streaming... */
if (0 == (zip->entry->flags & ZIP_LENGTH_AT_END)) {
/* We know the compressed length, so we can just skip. */
- int64_t bytes_skipped = __archive_read_consume(a,
+ int64_t bytes_skipped = zip_read_consume(a,
zip->entry_bytes_remaining + zip->unconsumed);
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
@@ -1077,36 +1540,36 @@ archive_read_format_zip_read_data_skip(struct archive_read *a)
if (r != ARCHIVE_OK)
return (r);
}
- break;
+ return ARCHIVE_OK;
#endif
default: /* Uncompressed or unknown. */
/* Scan for a PK\007\010 signature. */
- __archive_read_consume(a, zip->unconsumed);
+ zip_read_consume(a, zip->unconsumed);
zip->unconsumed = 0;
for (;;) {
const char *p, *buff;
ssize_t bytes_avail;
buff = __archive_read_ahead(a, 16, &bytes_avail);
if (bytes_avail < 16) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file data");
return (ARCHIVE_FATAL);
}
p = buff;
- while (p < buff + bytes_avail - 16) {
+ while (p <= buff + bytes_avail - 16) {
if (p[3] == 'P') { p += 3; }
else if (p[3] == 'K') { p += 2; }
else if (p[3] == '\007') { p += 1; }
else if (p[3] == '\010' && p[2] == '\007'
&& p[1] == 'K' && p[0] == 'P') {
- __archive_read_consume(a, p - buff + 16);
+ zip_read_consume(a, p - buff + 16);
return ARCHIVE_OK;
} else { p += 4; }
}
- __archive_read_consume(a, p - buff);
+ zip_read_consume(a, p - buff);
}
}
- return ARCHIVE_OK;
}
static int
@@ -1119,6 +1582,11 @@ archive_read_format_zip_cleanup(struct archive_read *a)
if (zip->stream_valid)
inflateEnd(&zip->stream);
#endif
+ if (zip->zip_entries && zip->central_directory_entries) {
+ unsigned i;
+ for (i = 0; i < zip->central_directory_entries; i++)
+ archive_string_free(&(zip->zip_entries[i].rsrcname));
+ }
free(zip->zip_entries);
free(zip->uncompressed_buffer);
archive_string_free(&(zip->extra));
@@ -1201,11 +1669,14 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
/* Info-ZIP Unix Extra Field (old version) "UX". */
if (datasize >= 8) {
zip_entry->atime = archive_le32dec(p + offset);
- zip_entry->mtime = archive_le32dec(p + offset + 4);
+ zip_entry->mtime =
+ archive_le32dec(p + offset + 4);
}
if (datasize >= 12) {
- zip_entry->uid = archive_le16dec(p + offset + 8);
- zip_entry->gid = archive_le16dec(p + offset + 10);
+ zip_entry->uid =
+ archive_le16dec(p + offset + 8);
+ zip_entry->gid =
+ archive_le16dec(p + offset + 10);
}
break;
}
@@ -1219,7 +1690,8 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
if (datasize >= 2)
zip_entry->uid = archive_le16dec(p + offset);
if (datasize >= 4)
- zip_entry->gid = archive_le16dec(p + offset + 2);
+ zip_entry->gid =
+ archive_le16dec(p + offset + 2);
break;
case 0x7875:
{
@@ -1231,22 +1703,26 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
/* get a uid size. */
uidsize = p[offset+1];
if (uidsize == 2)
- zip_entry->uid = archive_le16dec(
- p + offset + 2);
+ zip_entry->uid =
+ archive_le16dec(
+ p + offset + 2);
else if (uidsize == 4 && datasize >= 6)
- zip_entry->uid = archive_le32dec(
- p + offset + 2);
+ zip_entry->uid =
+ archive_le32dec(
+ p + offset + 2);
}
if (datasize >= (2 + uidsize + 3)) {
/* get a gid size. */
gidsize = p[offset+2+uidsize];
if (gidsize == 2)
- zip_entry->gid = archive_le16dec(
- p+offset+2+uidsize+1);
+ zip_entry->gid =
+ archive_le16dec(
+ p+offset+2+uidsize+1);
else if (gidsize == 4 &&
datasize >= (2 + uidsize + 5))
- zip_entry->gid = archive_le32dec(
- p+offset+2+uidsize+1);
+ zip_entry->gid =
+ archive_le32dec(
+ p+offset+2+uidsize+1);
}
}
break;
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c
index 370a5fc..87f9288 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.c
+++ b/Utilities/cmlibarchive/libarchive/archive_string.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2011 Tim Kientzle
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,9 +61,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_string.c 201095 2009-12-28 02:33
#include <windows.h>
#include <locale.h>
#endif
-#if defined(__APPLE__)
-#include <CoreServices/CoreServices.h>
-#endif
#include "archive_endian.h"
#include "archive_private.h"
@@ -115,11 +112,6 @@ struct archive_string_conv {
#endif
/* A temporary buffer for normalization. */
struct archive_string utftmp;
-#if defined(__APPLE__)
- UnicodeToTextInfo uniInfo;
- struct archive_string utf16nfc;
- struct archive_string utf16nfd;
-#endif
int (*converter[2])(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
int nconverter;
@@ -164,29 +156,29 @@ static int archive_string_append_from_wcs_in_codepage(struct archive_string *,
static int is_big_endian(void);
static int strncat_in_codepage(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
-static int win_strncat_from_utf16be(struct archive_string *, const void *, size_t,
- struct archive_string_conv *);
-static int win_strncat_from_utf16le(struct archive_string *, const void *, size_t,
- struct archive_string_conv *);
-static int win_strncat_to_utf16be(struct archive_string *, const void *, size_t,
- struct archive_string_conv *);
-static int win_strncat_to_utf16le(struct archive_string *, const void *, size_t,
- struct archive_string_conv *);
-#endif
-static int best_effort_strncat_from_utf16be(struct archive_string *, const void *,
+static int win_strncat_from_utf16be(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
-static int best_effort_strncat_from_utf16le(struct archive_string *, const void *,
+static int win_strncat_from_utf16le(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
-static int best_effort_strncat_to_utf16be(struct archive_string *, const void *,
+static int win_strncat_to_utf16be(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
-static int best_effort_strncat_to_utf16le(struct archive_string *, const void *,
+static int win_strncat_to_utf16le(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
+#endif
+static int best_effort_strncat_from_utf16be(struct archive_string *,
+ const void *, size_t, struct archive_string_conv *);
+static int best_effort_strncat_from_utf16le(struct archive_string *,
+ const void *, size_t, struct archive_string_conv *);
+static int best_effort_strncat_to_utf16be(struct archive_string *,
+ const void *, size_t, struct archive_string_conv *);
+static int best_effort_strncat_to_utf16le(struct archive_string *,
+ const void *, size_t, struct archive_string_conv *);
#if defined(HAVE_ICONV)
static int iconv_strncat_in_locale(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
#endif
-static int best_effort_strncat_in_locale(struct archive_string *, const void *,
- size_t, struct archive_string_conv *);
+static int best_effort_strncat_in_locale(struct archive_string *,
+ const void *, size_t, struct archive_string_conv *);
static int _utf8_to_unicode(uint32_t *, const char *, size_t);
static int utf8_to_unicode(uint32_t *, const char *, size_t);
static inline uint32_t combine_surrogate_pair(uint32_t, uint32_t);
@@ -201,10 +193,8 @@ static int strncat_from_utf8_to_utf8(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
static int archive_string_normalize_C(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
-#if defined(__APPLE__)
static int archive_string_normalize_D(struct archive_string *, const void *,
size_t, struct archive_string_conv *);
-#endif
static int archive_string_append_unicode(struct archive_string *,
const void *, size_t, struct archive_string_conv *);
@@ -238,7 +228,8 @@ archive_string_concat(struct archive_string *dest, struct archive_string *src)
}
void
-archive_wstring_concat(struct archive_wstring *dest, struct archive_wstring *src)
+archive_wstring_concat(struct archive_wstring *dest,
+ struct archive_wstring *src)
{
if (archive_wstring_append(dest, src->s, src->length) == NULL)
__archive_errx(1, "Out of memory");
@@ -443,10 +434,7 @@ int
archive_wstring_append_from_mbs(struct archive_wstring *dest,
const char *p, size_t len)
{
- int r = archive_wstring_append_from_mbs_in_codepage(dest, p, len, NULL);
- if (r != 0 && errno == ENOMEM)
- __archive_errx(1, "No memory");
- return (r);
+ return archive_wstring_append_from_mbs_in_codepage(dest, p, len, NULL);
}
static int
@@ -479,7 +467,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
*ws++ = (wchar_t)*mp++;
count++;
}
- } else if (sc != NULL && (sc->flag & SCONV_NORMALIZATION_C)) {
+ } else if (sc != NULL &&
+ (sc->flag & (SCONV_NORMALIZATION_C | SCONV_NORMALIZATION_D))) {
/*
* Normalize UTF-8 and UTF-16BE and convert it directly
* to UTF-16 as wchar_t.
@@ -495,31 +484,36 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
if (sc->flag & SCONV_FROM_UTF16) {
/*
* UTF-16BE/LE NFD ===> UTF-16 NFC
+ * UTF-16BE/LE NFC ===> UTF-16 NFD
*/
- count = utf16nbytes(s, length);
+ count = (int)utf16nbytes(s, length);
} else {
/*
* UTF-8 NFD ===> UTF-16 NFC
+ * UTF-8 NFC ===> UTF-16 NFD
*/
- count = mbsnbytes(s, length);
+ count = (int)mbsnbytes(s, length);
}
u16.s = (char *)dest->s;
u16.length = dest->length << 1;;
u16.buffer_length = dest->buffer_length;
- ret = archive_string_normalize_C(&u16, s, count, sc);
+ if (sc->flag & SCONV_NORMALIZATION_C)
+ ret = archive_string_normalize_C(&u16, s, count, sc);
+ else
+ ret = archive_string_normalize_D(&u16, s, count, sc);
dest->s = (wchar_t *)u16.s;
dest->length = u16.length >> 1;
dest->buffer_length = u16.buffer_length;
sc->flag = saved_flag;/* restore the saved flag. */
return (ret);
} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
- count = utf16nbytes(s, length);
+ count = (int)utf16nbytes(s, length);
count >>= 1; /* to be WCS length */
/* Allocate memory for WCS. */
if (NULL == archive_wstring_ensure(dest,
dest->length + count + 1))
return (-1);
- wmemcpy(dest->s + dest->length, (wchar_t *)s, count);
+ wmemcpy(dest->s + dest->length, (const wchar_t *)s, count);
if ((sc->flag & SCONV_FROM_UTF16BE) && !is_big_endian()) {
uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
int b;
@@ -537,6 +531,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
}
} else {
DWORD mbflag;
+ size_t buffsize;
if (sc == NULL)
mbflag = 0;
@@ -548,83 +543,30 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
} else
mbflag = MB_PRECOMPOSED;
- if (length == 0) {
- /*
- * We do not need to convert any characters but make
- * sure `dest' has a valid buffer(no NULL pointer).
- */
- if (NULL == archive_wstring_ensure(dest,
- dest->length + 1))
+ buffsize = dest->length + length + 1;
+ do {
+ /* Allocate memory for WCS. */
+ if (NULL == archive_wstring_ensure(dest, buffsize))
return (-1);
- dest->s[dest->length] = L'\0';
- return (0);
- }
-
- /*
- * Count how many bytes are needed for WCS.
- */
- count = MultiByteToWideChar(from_cp,
- mbflag, s, length, NULL, 0);
- if (count == 0) {
- if (dest->s == NULL) {
- if (NULL == archive_wstring_ensure(dest,
- dest->length + 1))
- return (-1);
+ /* Convert MBS to WCS. */
+ count = MultiByteToWideChar(from_cp,
+ mbflag, s, (int)length, dest->s + dest->length,
+ (int)(dest->buffer_length >> 1) -1);
+ if (count == 0 &&
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ /* Expand the WCS buffer. */
+ buffsize = dest->buffer_length << 1;
+ continue;
}
- dest->s[dest->length] = L'\0';
- return (-1);
- }
- /* Allocate memory for WCS. */
- if (NULL == archive_wstring_ensure(dest,
- dest->length + count + 1))
- return (-1);
- /* Convert MBS to WCS. */
- count = MultiByteToWideChar(from_cp,
- mbflag, s, length, dest->s + dest->length, count);
- if (count == 0)
- ret = -1;
+ if (count == 0 && length != 0)
+ ret = -1;
+ } while (0);
}
dest->length += count;
dest->s[dest->length] = L'\0';
return (ret);
}
-#elif defined(HAVE_MBSNRTOWCS)
-
-/*
- * Convert MBS to WCS.
- * Note: returns -1 if conversion fails.
- */
-int
-archive_wstring_append_from_mbs(struct archive_wstring *dest,
- const char *p, size_t len)
-{
- size_t r;
- /*
- * No single byte will be more than one wide character,
- * so this length estimate will always be big enough.
- */
- size_t wcs_length = len;
- size_t mbs_length = len;
- const char *mbs = p;
- wchar_t *wcs;
- mbstate_t shift_state;
-
- memset(&shift_state, 0, sizeof(shift_state));
- if (NULL == archive_wstring_ensure(dest, dest->length + wcs_length + 1))
- __archive_errx(1,
- "No memory for archive_wstring_append_from_mbs()");
- wcs = dest->s + dest->length;
- r = mbsnrtowcs(wcs, &mbs, mbs_length, wcs_length, &shift_state);
- if (r != (size_t)-1) {
- dest->length += r;
- dest->s[dest->length] = L'\0';
- return (0);
- }
- dest->s[dest->length] = L'\0';
- return (-1);
-}
-
#else
/*
@@ -636,6 +578,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
const char *p, size_t len)
{
size_t r;
+ int ret_val = 0;
/*
* No single byte will be more than one wide character,
* so this length estimate will always be big enough.
@@ -650,23 +593,36 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
memset(&shift_state, 0, sizeof(shift_state));
#endif
if (NULL == archive_wstring_ensure(dest, dest->length + wcs_length + 1))
- __archive_errx(1,
- "No memory for archive_wstring_append_from_mbs()");
+ return (-1);
wcs = dest->s + dest->length;
/*
* We cannot use mbsrtowcs/mbstowcs here because those may convert
* extra MBS when strlen(p) > len and one wide character consis of
* multi bytes.
*/
- while (wcs_length > 0 && *mbs && mbs_length > 0) {
+ while (*mbs && mbs_length > 0) {
+ if (wcs_length == 0) {
+ dest->length = wcs - dest->s;
+ dest->s[dest->length] = L'\0';
+ wcs_length = mbs_length;
+ if (NULL == archive_wstring_ensure(dest,
+ dest->length + wcs_length + 1))
+ return (-1);
+ wcs = dest->s + dest->length;
+ }
#if HAVE_MBRTOWC
r = mbrtowc(wcs, mbs, wcs_length, &shift_state);
#else
r = mbtowc(wcs, mbs, wcs_length);
#endif
if (r == (size_t)-1 || r == (size_t)-2) {
- dest->s[dest->length] = L'\0';
- return (-1);
+ ret_val = -1;
+ if (errno == EILSEQ) {
+ ++mbs;
+ --mbs_length;
+ continue;
+ } else
+ break;
}
if (r == 0 || r > mbs_length)
break;
@@ -677,7 +633,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
}
dest->length = wcs - dest->s;
dest->s[dest->length] = L'\0';
- return (0);
+ return (ret_val);
}
#endif
@@ -697,10 +653,7 @@ int
archive_string_append_from_wcs(struct archive_string *as,
const wchar_t *w, size_t len)
{
- int r = archive_string_append_from_wcs_in_codepage(as, w, len, NULL);
- if (r != 0 && errno == ENOMEM)
- __archive_errx(1, "No memory");
- return (r);
+ return archive_string_append_from_wcs_in_codepage(as, w, len, NULL);
}
static int
@@ -774,7 +727,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
else
dp = &defchar_used;
count = WideCharToMultiByte(to_cp, 0, ws, wslen,
- as->s + as->length, as->buffer_length-1, NULL, dp);
+ as->s + as->length, (int)as->buffer_length-1, NULL, dp);
if (count == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Expand the MBS buffer and retry. */
@@ -792,73 +745,6 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
return (defchar_used?-1:ret);
}
-#elif defined(HAVE_WCSNRTOMBS)
-
-/*
- * Translates a wide character string into current locale character set
- * and appends to the archive_string. Note: returns -1 if conversion
- * fails.
- */
-int
-archive_string_append_from_wcs(struct archive_string *as,
- const wchar_t *w, size_t len)
-{
- mbstate_t shift_state;
- size_t r, ndest, nwc;
- char *dest;
- const wchar_t *wp, *wpp;
- int ret_val = 0;
-
- wp = w;
- nwc = len;
- ndest = len * 2;
- /* Initialize the shift state. */
- memset(&shift_state, 0, sizeof(shift_state));
- while (nwc > 0) {
- /* Allocate buffer for MBS. */
- if (archive_string_ensure(as, as->length + ndest + 1) == NULL)
- __archive_errx(1, "Out of memory");
-
- dest = as->s + as->length;
- wpp = wp;
- r = wcsnrtombs(dest, &wp, nwc,
- as->buffer_length - as->length -1,
- &shift_state);
- if (r == (size_t)-1) {
- if (errno == EILSEQ) {
- /* Retry conversion just for safe WCS. */
- size_t xwc = wp - wpp;
- wp = wpp;
- r = wcsnrtombs(dest, &wp, xwc,
- as->buffer_length - as->length -1,
- &shift_state);
- if (r == (size_t)-1)
- /* This would not happen. */
- return (-1);
- as->length += r;
- nwc -= wp - wpp;
- /* Skip an illegal wide char. */
- as->s[as->length++] = '?';
- wp++;
- nwc--;
- ret_val = -1;
- continue;
- } else {
- ret_val = -1;
- break;
- }
- }
- as->length += r;
- if (wp == NULL || (wp - wpp) >= nwc)
- break;
- /* Get a remaining WCS lenth. */
- nwc -= wp - wpp;
- }
- /* All wide characters are translated to MBS. */
- as->s[as->length] = '\0';
- return (ret_val);
-}
-
#elif defined(HAVE_WCTOMB) || defined(HAVE_WCRTOMB)
/*
@@ -893,7 +779,7 @@ archive_string_append_from_wcs(struct archive_string *as,
* as->s is still NULL.
*/
if (archive_string_ensure(as, as->length + len + 1) == NULL)
- __archive_errx(1, "Out of memory");
+ return (-1);
p = as->s + as->length;
end = as->s + as->buffer_length - MB_CUR_MAX -1;
@@ -904,7 +790,7 @@ archive_string_append_from_wcs(struct archive_string *as,
/* Re-allocate buffer for MBS. */
if (archive_string_ensure(as,
as->length + len * 2 + 1) == NULL)
- __archive_errx(1, "Out of memory");
+ return (-1);
p = as->s + as->length;
end = as->s + as->buffer_length - MB_CUR_MAX -1;
}
@@ -946,6 +832,7 @@ archive_string_append_from_wcs(struct archive_string *as,
(void)as;/* UNUSED */
(void)w;/* UNUSED */
(void)len;/* UNUSED */
+ errno = ENOSYS;
return (-1);
}
@@ -987,27 +874,6 @@ add_sconv_object(struct archive *a, struct archive_string_conv *sc)
*psc = sc;
}
-#if defined(__APPLE__)
-
-static int
-createUniInfo(struct archive_string_conv *sconv)
-{
- UnicodeMapping map;
- OSStatus err;
-
- map.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
- kUnicodeNoSubset, kUnicode16BitFormat);
- map.otherEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
- kUnicodeHFSPlusDecompVariant, kUnicode16BitFormat);
- map.mappingVersion = kUnicodeUseLatestMapping;
-
- sconv->uniInfo = NULL;
- err = CreateUnicodeToTextInfo(&map, &(sconv->uniInfo));
- return ((err == noErr)? 0: -1);
-}
-
-#endif /* __APPLE__ */
-
static void
add_converter(struct archive_string_conv *sc, int (*converter)
(struct archive_string *, const void *, size_t,
@@ -1066,9 +932,11 @@ setup_converter(struct archive_string_conv *sc)
if (sc->flag & SCONV_BEST_EFFORT) {
if (sc->flag & SCONV_TO_UTF16BE)
- add_converter(sc, best_effort_strncat_to_utf16be);
+ add_converter(sc,
+ best_effort_strncat_to_utf16be);
else
- add_converter(sc, best_effort_strncat_to_utf16le);
+ add_converter(sc,
+ best_effort_strncat_to_utf16le);
} else
/* Make sure we have no converter. */
sc->nconverter = 0;
@@ -1082,12 +950,9 @@ setup_converter(struct archive_string_conv *sc)
/*
* At least we should normalize a UTF-16BE string.
*/
-#if defined(__APPLE__)
if (sc->flag & SCONV_NORMALIZATION_D)
add_converter(sc,archive_string_normalize_D);
- else
-#endif
- if (sc->flag & SCONV_NORMALIZATION_C)
+ else if (sc->flag & SCONV_NORMALIZATION_C)
add_converter(sc, archive_string_normalize_C);
if (sc->flag & SCONV_TO_UTF8) {
@@ -1135,12 +1000,9 @@ setup_converter(struct archive_string_conv *sc)
/*
* At least we should normalize a UTF-8 string.
*/
-#if defined(__APPLE__)
if (sc->flag & SCONV_NORMALIZATION_D)
add_converter(sc,archive_string_normalize_D);
- else
-#endif
- if (sc->flag & SCONV_NORMALIZATION_C)
+ else if (sc->flag & SCONV_NORMALIZATION_C)
add_converter(sc, archive_string_normalize_C);
/*
@@ -1174,6 +1036,16 @@ setup_converter(struct archive_string_conv *sc)
#if HAVE_ICONV
if (sc->cd != (iconv_t)-1) {
add_converter(sc, iconv_strncat_in_locale);
+ /*
+ * iconv generally does not support UTF-8-MAC and so
+ * we have to the output of iconv from NFC to NFD if
+ * need.
+ */
+ if ((sc->flag & SCONV_FROM_CHARSET) &&
+ (sc->flag & SCONV_TO_UTF8)) {
+ if (sc->flag & SCONV_NORMALIZATION_D)
+ add_converter(sc, archive_string_normalize_D);
+ }
return;
}
#endif
@@ -1253,10 +1125,6 @@ create_sconv_object(const char *fc, const char *tc,
return (NULL);
}
archive_string_init(&sc->utftmp);
-#if defined(__APPLE__)
- archive_string_init(&sc->utf16nfc);
- archive_string_init(&sc->utf16nfd);
-#endif
if (flag & SCONV_TO_CHARSET) {
/*
@@ -1286,7 +1154,7 @@ create_sconv_object(const char *fc, const char *tc,
* Check if "from charset" and "to charset" are the same.
*/
if (strcmp(fc, tc) == 0 ||
- (sc->from_cp != -1 && sc->from_cp == sc->to_cp))
+ (sc->from_cp != (unsigned)-1 && sc->from_cp == sc->to_cp))
sc->same = 1;
else
sc->same = 0;
@@ -1335,13 +1203,35 @@ create_sconv_object(const char *fc, const char *tc,
if ((flag & SCONV_FROM_CHARSET) &&
(flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8))) {
#if defined(__APPLE__)
- if (flag & SCONV_TO_UTF8) {
- if (createUniInfo(sc) == 0)
- flag |= SCONV_NORMALIZATION_D;
- } else
+ if (flag & SCONV_TO_UTF8)
+ flag |= SCONV_NORMALIZATION_D;
+ else
#endif
flag |= SCONV_NORMALIZATION_C;
}
+#if defined(__APPLE__)
+ /*
+ * In case writing an archive file, make sure that a filename
+ * going to be passed to iconv is a Unicode NFC string since
+ * a filename in HFS Plus filesystem is a Unicode NFD one and
+ * iconv cannot handle it with "UTF-8" charset. It is simpler
+ * than a use of "UTF-8-MAC" charset.
+ */
+ if ((flag & SCONV_TO_CHARSET) &&
+ (flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) &&
+ !(flag & (SCONV_TO_UTF16 | SCONV_TO_UTF8)))
+ flag |= SCONV_NORMALIZATION_C;
+ /*
+ * In case reading an archive file. make sure that a filename
+ * will be passed to users is a Unicode NFD string in order to
+ * correctly compare the filename with other one which comes
+ * from HFS Plus filesystem.
+ */
+ if ((flag & SCONV_FROM_CHARSET) &&
+ !(flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) &&
+ (flag & SCONV_TO_UTF8))
+ flag |= SCONV_NORMALIZATION_D;
+#endif
#if defined(HAVE_ICONV)
sc->cd_w = (iconv_t)-1;
@@ -1353,46 +1243,6 @@ create_sconv_object(const char *fc, const char *tc,
(flag & SCONV_WIN_CP)) {
/* This case we won't use iconv. */
sc->cd = (iconv_t)-1;
-#if defined(__APPLE__)
- } else if ((flag & SCONV_FROM_CHARSET) && (flag & SCONV_TO_UTF8)) {
- /*
- * In case reading an archive file.
- * Translate non-Unicode filenames in an archive file to
- * UTF-8-MAC filenames.
- */
- sc->cd = iconv_open("UTF-8-MAC", fc);
- if (sc->cd == (iconv_t)-1) {
- if ((sc->flag & SCONV_BEST_EFFORT) &&
- strcmp(fc, "CP932") == 0) {
- sc->cd = iconv_open("UTF-8-MAC", "SJIS");
- if (sc->cd == (iconv_t)-1) {
- sc->cd = iconv_open(tc, fc);
- if (sc->cd == (iconv_t)-1)
- sc->cd = iconv_open(tc, "SJIS");
- }
- } else
- sc->cd = iconv_open(tc, fc);
- }
- } else if ((flag & SCONV_TO_CHARSET) && (flag & SCONV_FROM_UTF8)) {
- /*
- * In case writing an archive file.
- * Translate UTF-8-MAC filenames in HFS Plus to non-Unicode
- * filenames.
- */
- sc->cd = iconv_open(tc, "UTF-8-MAC");
- if (sc->cd == (iconv_t)-1) {
- if ((sc->flag & SCONV_BEST_EFFORT) &&
- strcmp(tc, "CP932") == 0) {
- sc->cd = iconv_open("SJIS", "UTF-8-MAC");
- if (sc->cd == (iconv_t)-1) {
- sc->cd = iconv_open(tc, fc);
- if (sc->cd == (iconv_t)-1)
- sc->cd = iconv_open("SJIS", fc);
- }
- } else
- sc->cd = iconv_open(tc, fc);
- }
-#endif
} else {
sc->cd = iconv_open(tc, fc);
if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) {
@@ -1428,7 +1278,7 @@ create_sconv_object(const char *fc, const char *tc,
sc->flag = flag;
/*
- * Setup converters.
+ * Set up converters.
*/
setup_converter(sc);
@@ -1450,12 +1300,6 @@ free_sconv_object(struct archive_string_conv *sc)
if (sc->cd_w != (iconv_t)-1)
iconv_close(sc->cd_w);
#endif
-#if defined(__APPLE__)
- archive_string_free(&sc->utf16nfc);
- archive_string_free(&sc->utf16nfd);
- if (sc->uniInfo != NULL)
- DisposeUnicodeToTextInfo(&(sc->uniInfo));
-#endif
free(sc);
}
@@ -1646,7 +1490,7 @@ make_codepage_from_charset(const char *charset)
* Return ANSI Code Page of current locale set by setlocale().
*/
static unsigned
-get_current_codepage()
+get_current_codepage(void)
{
char *locale, *p;
unsigned cp;
@@ -1721,7 +1565,7 @@ static struct {
* Return OEM Code Page of current locale set by setlocale().
*/
static unsigned
-get_current_oemcp()
+get_current_oemcp(void)
{
int i;
char *locale, *p;
@@ -1750,7 +1594,7 @@ get_current_oemcp()
*/
static unsigned
-get_current_codepage()
+get_current_codepage(void)
{
return (-1);/* Unknown */
}
@@ -1761,7 +1605,7 @@ make_codepage_from_charset(const char *charset)
return (-1);/* Unknown */
}
static unsigned
-get_current_oemcp()
+get_current_oemcp(void)
{
return (-1);/* Unknown */
}
@@ -1995,11 +1839,37 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt)
#else
if ((sc->flag & SCONV_UTF8_LIBARCHIVE_2) == 0) {
sc->flag |= SCONV_UTF8_LIBARCHIVE_2;
- /* Re-setup string converters. */
+ /* Set up string converters. */
setup_converter(sc);
}
#endif
break;
+ case SCONV_SET_OPT_NORMALIZATION_C:
+ if ((sc->flag & SCONV_NORMALIZATION_C) == 0) {
+ sc->flag |= SCONV_NORMALIZATION_C;
+ sc->flag &= ~SCONV_NORMALIZATION_D;
+ /* Set up string converters. */
+ setup_converter(sc);
+ }
+ break;
+ case SCONV_SET_OPT_NORMALIZATION_D:
+#if defined(HAVE_ICONV)
+ /*
+ * If iconv will take the string, do not change the
+ * setting of the normalization.
+ */
+ if (!(sc->flag & SCONV_WIN_CP) &&
+ (sc->flag & (SCONV_FROM_UTF16 | SCONV_FROM_UTF8)) &&
+ !(sc->flag & (SCONV_TO_UTF16 | SCONV_TO_UTF8)))
+ break;
+#endif
+ if ((sc->flag & SCONV_NORMALIZATION_D) == 0) {
+ sc->flag |= SCONV_NORMALIZATION_D;
+ sc->flag &= ~SCONV_NORMALIZATION_C;
+ /* Set up string converters. */
+ setup_converter(sc);
+ }
+ break;
default:
break;
}
@@ -2009,8 +1879,8 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt)
*
* Copy one archive_string to another in locale conversion.
*
- * archive_strncpy_in_locale();
- * archive_strcpy_in_locale();
+ * archive_strncat_l();
+ * archive_strncpy_l();
*
*/
@@ -2056,15 +1926,15 @@ utf16nbytes(const void *_p, size_t n)
}
int
-archive_strncpy_in_locale(struct archive_string *as, const void *_p, size_t n,
+archive_strncpy_l(struct archive_string *as, const void *_p, size_t n,
struct archive_string_conv *sc)
{
as->length = 0;
- return (archive_strncat_in_locale(as, _p, n, sc));
+ return (archive_strncat_l(as, _p, n, sc));
}
int
-archive_strncat_in_locale(struct archive_string *as, const void *_p, size_t n,
+archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
struct archive_string_conv *sc)
{
const void *s;
@@ -2127,7 +1997,7 @@ static int
iconv_strncat_in_locale(struct archive_string *as, const void *_p,
size_t length, struct archive_string_conv *sc)
{
- ICONV_CONST char *inp;
+ ICONV_CONST char *itp;
size_t remaining;
iconv_t cd;
char *outp;
@@ -2148,12 +2018,12 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
return (-1);
cd = sc->cd;
- inp = (char *)(uintptr_t)_p;
+ itp = (char *)(uintptr_t)_p;
remaining = length;
outp = as->s + as->length;
avail = as->buffer_length - as->length - to_size;
while (remaining >= (size_t)from_size) {
- size_t result = iconv(cd, &inp, &remaining, &outp, &avail);
+ size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
if (result != (size_t)-1)
break; /* Conversion completed. */
@@ -2195,7 +2065,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
*outp++ = '?';
avail--;
}
- inp += from_size;
+ itp += from_size;
remaining -= from_size;
return_value = -1; /* failure */
} else {
@@ -2275,7 +2145,7 @@ invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc)
if (codepage != CP_UTF8)
mbflag |= MB_PRECOMPOSED;
- if (MultiByteToWideChar(codepage, mbflag, p, n, NULL, 0) == 0)
+ if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
return (-1); /* Invalid */
return (0); /* Okay */
}
@@ -2332,8 +2202,8 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
size_t length, struct archive_string_conv *sc)
{
size_t remaining;
- char *outp;
- const char *inp;
+ char *otp;
+ const uint8_t *itp;
size_t avail;
int return_value = 0; /* success */
@@ -2357,41 +2227,41 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
return (-1);
remaining = length;
- inp = (const char *)_p;
- outp = as->s + as->length;
+ itp = (const uint8_t *)_p;
+ otp = as->s + as->length;
avail = as->buffer_length - as->length -1;
- while (*inp && remaining > 0) {
- if (*inp < 0 && (sc->flag & SCONV_TO_UTF8)) {
+ while (*itp && remaining > 0) {
+ if (*itp > 127 && (sc->flag & SCONV_TO_UTF8)) {
if (avail < UTF8_R_CHAR_SIZE) {
- as->length = outp - as->s;
+ as->length = otp - as->s;
if (NULL == archive_string_ensure(as,
as->buffer_length + remaining +
UTF8_R_CHAR_SIZE))
return (-1);
- outp = as->s + as->length;
+ otp = as->s + as->length;
avail = as->buffer_length - as->length -1;
}
/*
* When coping a string in UTF-8, unknown character
* should be U+FFFD (replacement character).
*/
- UTF8_SET_R_CHAR(outp);
- outp += UTF8_R_CHAR_SIZE;
+ UTF8_SET_R_CHAR(otp);
+ otp += UTF8_R_CHAR_SIZE;
avail -= UTF8_R_CHAR_SIZE;
- inp++;
+ itp++;
remaining--;
return_value = -1;
- } else if (*inp < 0) {
- *outp++ = '?';
- inp++;
+ } else if (*itp > 127) {
+ *otp++ = '?';
+ itp++;
remaining--;
return_value = -1;
} else {
- *outp++ = *inp++;
+ *otp++ = (char)*itp++;
remaining--;
}
}
- as->length = outp - as->s;
+ as->length = otp - as->s;
as->s[as->length] = '\0';
return (return_value);
}
@@ -2452,7 +2322,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
/* Invalide sequence or there are not plenty bytes. */
if ((int)n < cnt) {
- cnt = n;
+ cnt = (int)n;
for (i = 1; i < cnt; i++) {
if ((s[i] & 0xc0) != 0x80) {
cnt = i;
@@ -2521,7 +2391,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
else
cnt = 1;
if ((int)n < cnt)
- cnt = n;
+ cnt = (int)n;
for (i = 1; i < cnt; i++) {
if ((s[i] & 0xc0) != 0x80) {
cnt = i;
@@ -2577,11 +2447,12 @@ combine_surrogate_pair(uint32_t uc, uint32_t uc2)
static int
cesu8_to_unicode(uint32_t *pwc, const char *s, size_t n)
{
- uint32_t wc, wc2;
+ uint32_t wc = 0;
int cnt;
cnt = _utf8_to_unicode(&wc, s, n);
if (cnt == 3 && IS_HIGH_SURROGATE_LA(wc)) {
+ uint32_t wc2 = 0;
if (n - 3 < 3) {
/* Invalid byte sequence. */
goto invalid_sequence;
@@ -2773,8 +2644,8 @@ unicode_to_utf16le(char *p, size_t remaining, uint32_t uc)
* If any surrogate pair are found, it would be canonicalized.
*/
static int
-strncat_from_utf8_to_utf8(struct archive_string *as, const void *_p, size_t len,
- struct archive_string_conv *sc)
+strncat_from_utf8_to_utf8(struct archive_string *as, const void *_p,
+ size_t len, struct archive_string_conv *sc)
{
const char *s;
char *p, *endp;
@@ -3250,8 +3121,8 @@ archive_string_normalize_C(struct archive_string *as, const void *_p,
/*
* Remove ucx[i] by shifting
- * follwoing code points.
- */
+ * following code points.
+ */
for (j = i; j+1 < ucx_size; j++) {
ucx[j] = ucx[j+1];
ccx[j] = ccx[j+1];
@@ -3320,122 +3191,224 @@ archive_string_normalize_C(struct archive_string *as, const void *_p,
return (ret);
}
-#if defined(__APPLE__)
-
-/*
- * Normalize UTF-8 characters to Form D and copy the result.
- */
static int
-archive_string_normalize_D(struct archive_string *as, const void *_p,
- size_t len, struct archive_string_conv *sc)
+get_nfd(uint32_t *cp1, uint32_t *cp2, uint32_t uc)
{
- const UniChar *inp;
- char *outp;
- size_t newsize;
- ByteCount inCount, outCount;
- ByteCount inAvail, outAvail;
- OSStatus err;
- int ret, saved_flag;
+ int t, b;
/*
- * Convert the current string to UTF-16LE for normalization.
- * The character-set of the current string must be UTF-16BE or
- * UTF-8.
+ * These are not converted to NFD on Mac OS.
*/
- archive_string_empty(&(sc->utf16nfc));
- saved_flag = sc->flag;/* save a flag. */
- sc->flag &= ~(SCONV_TO_UTF16BE | SCONV_TO_UTF8);
- sc->flag |= SCONV_TO_UTF16LE;
- ret = archive_string_append_unicode(&(sc->utf16nfc), _p, len, sc);
- sc->flag = saved_flag;/* restore the saved flag */
- if (archive_strlen(&(sc->utf16nfc)) == 0) {
- if (archive_string_ensure(as, as->length + 1) == NULL)
- return (-1);
- return (ret);
- }
-
+ if ((uc >= 0x2000 && uc <= 0x2FFF) ||
+ (uc >= 0xF900 && uc <= 0xFAFF) ||
+ (uc >= 0x2F800 && uc <= 0x2FAFF))
+ return (0);
/*
- * Normalize an NFC string to be an NFD(HFS Plus version).
+ * Those code points are not converted to NFD on Mac OS.
+ * I do not know the reason because it is undocumented.
+ * NFC NFD
+ * 1109A ==> 11099 110BA
+ * 1109C ==> 1109B 110BA
+ * 110AB ==> 110A5 110BA
*/
- newsize = sc->utf16nfc.length + 2;
- if (archive_string_ensure(&(sc->utf16nfd), newsize) == NULL)
- return (-1);
+ if (uc == 0x1109A || uc == 0x1109C || uc == 0x110AB)
+ return (0);
- inp = (UniChar *)sc->utf16nfc.s;
- inAvail = archive_strlen(&(sc->utf16nfc));
- sc->utf16nfd.length = 0;
- outp = sc->utf16nfd.s;
- outAvail = sc->utf16nfd.buffer_length -2;
+ t = 0;
+ b = sizeof(u_decomposition_table)/sizeof(u_decomposition_table[0]) -1;
+ while (b >= t) {
+ int m = (t + b) / 2;
+ if (u_decomposition_table[m].nfc < uc)
+ t = m + 1;
+ else if (u_decomposition_table[m].nfc > uc)
+ b = m - 1;
+ else {
+ *cp1 = u_decomposition_table[m].cp1;
+ *cp2 = u_decomposition_table[m].cp2;
+ return (1);
+ }
+ }
+ return (0);
+}
- do {
- /* Reinitialize all state information. */
- if (ResetUnicodeToTextInfo(sc->uniInfo) != noErr)
- goto return_no_changed_data;
-
- inCount = outCount = 0;
- err = ConvertFromUnicodeToText(sc->uniInfo,
- inAvail, inp,
- kUnicodeDefaultDirectionMask, 0, NULL, NULL, NULL,
- outAvail, &inCount, &outCount, outp);
-
- if (err == noErr) {
- sc->utf16nfd.length = outCount;
- sc->utf16nfd.s[sc->utf16nfd.length] = 0;
- sc->utf16nfd.s[sc->utf16nfd.length+1] = 0;
- } else if (err == kTECOutputBufferFullStatus) {
- newsize = inAvail - inCount;
- if (newsize > inAvail)
- newsize = inAvail;
- newsize += sc->utf16nfd.buffer_length + 2;
- if (archive_string_ensure(&(sc->utf16nfd), newsize)
- == NULL)
- return (-1);
- outp = sc->utf16nfd.s;
- outAvail = sc->utf16nfd.buffer_length -2;
- } else
- goto return_no_changed_data;
- } while (err == kTECOutputBufferFullStatus);
+#define REPLACE_UC_WITH(cp) do { \
+ uc = cp; \
+ ucptr = NULL; \
+} while (0)
- /*
- * If there is a next-step conversion, we should convert
- * a UTF-16LE(NFD) string back to the original Unicode type.
- */
- saved_flag = sc->flag;/* save a flag. */
- if (!(sc->flag &
- (SCONV_TO_UTF16BE | SCONV_TO_UTF16LE | SCONV_TO_UTF8))) {
+/*
+ * Normalize UTF-8 characters to Form D and copy the result.
+ */
+static int
+archive_string_normalize_D(struct archive_string *as, const void *_p,
+ size_t len, struct archive_string_conv *sc)
+{
+ const char *s = (const char *)_p;
+ char *p, *endp;
+ uint32_t uc, uc2;
+ size_t w;
+ int always_replace, n, n2, ret = 0, spair, ts, tm;
+ int (*parse)(uint32_t *, const char *, size_t);
+ size_t (*unparse)(char *, size_t, uint32_t);
+
+ always_replace = 1;
+ ts = 1;/* text size. */
+ if (sc->flag & SCONV_TO_UTF16BE) {
+ unparse = unicode_to_utf16be;
+ ts = 2;
+ if (sc->flag & SCONV_FROM_UTF16BE)
+ always_replace = 0;
+ } else if (sc->flag & SCONV_TO_UTF16LE) {
+ unparse = unicode_to_utf16le;
+ ts = 2;
+ if (sc->flag & SCONV_FROM_UTF16LE)
+ always_replace = 0;
+ } else if (sc->flag & SCONV_TO_UTF8) {
+ unparse = unicode_to_utf8;
+ if (sc->flag & SCONV_FROM_UTF8)
+ always_replace = 0;
+ } else {
/*
* This case is going to be converted to another
* character-set through iconv.
*/
- if (sc->flag & SCONV_FROM_UTF16BE)
- sc->flag |= SCONV_TO_UTF16BE;
- else if (sc->flag & SCONV_FROM_UTF16LE)
- sc->flag |= SCONV_TO_UTF16LE;
+ always_replace = 0;
+ if (sc->flag & SCONV_FROM_UTF16BE) {
+ unparse = unicode_to_utf16be;
+ ts = 2;
+ } else if (sc->flag & SCONV_FROM_UTF16LE) {
+ unparse = unicode_to_utf16le;
+ ts = 2;
+ } else {
+ unparse = unicode_to_utf8;
+ }
+ }
+
+ if (sc->flag & SCONV_FROM_UTF16BE) {
+ parse = utf16be_to_unicode;
+ tm = 1;
+ spair = 4;/* surrogate pair size in UTF-16. */
+ } else if (sc->flag & SCONV_FROM_UTF16LE) {
+ parse = utf16le_to_unicode;
+ tm = 1;
+ spair = 4;/* surrogate pair size in UTF-16. */
+ } else {
+ parse = cesu8_to_unicode;
+ tm = ts;
+ spair = 6;/* surrogate pair size in UTF-8. */
+ }
+
+ if (archive_string_ensure(as, as->length + len * tm + ts) == NULL)
+ return (-1);
+
+ p = as->s + as->length;
+ endp = as->s + as->buffer_length - ts;
+ while ((n = parse(&uc, s, len)) != 0) {
+ const char *ucptr;
+ uint32_t cp1, cp2;
+ int SIndex;
+ struct {
+ uint32_t uc;
+ int ccc;
+ } fdc[FDC_MAX];
+ int fdi, fdj;
+ int ccc;
+
+check_first_code:
+ if (n < 0) {
+ /* Use a replaced unicode character. */
+ UNPARSE(p, endp, uc);
+ s += n*-1;
+ len -= n*-1;
+ ret = -1;
+ continue;
+ } else if (n == spair || always_replace)
+ /* uc is converted from a surrogate pair.
+ * this should be treated as a changed code. */
+ ucptr = NULL;
else
- sc->flag |= SCONV_TO_UTF8;
+ ucptr = s;
+ s += n;
+ len -= n;
+
+ /* Hangul Decomposition. */
+ if ((SIndex = uc - HC_SBASE) >= 0 && SIndex < HC_SCOUNT) {
+ int L = HC_LBASE + SIndex / HC_NCOUNT;
+ int V = HC_VBASE + (SIndex % HC_NCOUNT) / HC_TCOUNT;
+ int T = HC_TBASE + SIndex % HC_TCOUNT;
+
+ REPLACE_UC_WITH(L);
+ WRITE_UC();
+ REPLACE_UC_WITH(V);
+ WRITE_UC();
+ if (T != HC_TBASE) {
+ REPLACE_UC_WITH(T);
+ WRITE_UC();
+ }
+ continue;
+ }
+ if (IS_DECOMPOSABLE_BLOCK(uc) && CCC(uc) != 0) {
+ WRITE_UC();
+ continue;
+ }
+
+ fdi = 0;
+ while (get_nfd(&cp1, &cp2, uc) && fdi < FDC_MAX) {
+ int k;
+
+ for (k = fdi; k > 0; k--)
+ fdc[k] = fdc[k-1];
+ fdc[0].ccc = CCC(cp2);
+ fdc[0].uc = cp2;
+ fdi++;
+ REPLACE_UC_WITH(cp1);
+ }
+
+ /* Read following code points. */
+ while ((n2 = parse(&uc2, s, len)) > 0 &&
+ (ccc = CCC(uc2)) != 0 && fdi < FDC_MAX) {
+ int j, k;
+
+ s += n2;
+ len -= n2;
+ for (j = 0; j < fdi; j++) {
+ if (fdc[j].ccc > ccc)
+ break;
+ }
+ if (j < fdi) {
+ for (k = fdi; k > j; k--)
+ fdc[k] = fdc[k-1];
+ fdc[j].ccc = ccc;
+ fdc[j].uc = uc2;
+ } else {
+ fdc[fdi].ccc = ccc;
+ fdc[fdi].uc = uc2;
+ }
+ fdi++;
+ }
+
+ WRITE_UC();
+ for (fdj = 0; fdj < fdi; fdj++) {
+ REPLACE_UC_WITH(fdc[fdj].uc);
+ WRITE_UC();
+ }
+
+ if (n2 == 0)
+ break;
+ REPLACE_UC_WITH(uc2);
+ n = n2;
+ goto check_first_code;
}
- sc->flag &= ~(SCONV_FROM_UTF16BE | SCONV_FROM_UTF8);
- sc->flag |= SCONV_FROM_UTF16LE;
- if (archive_string_append_unicode(as, sc->utf16nfd.s,
- sc->utf16nfd.length, sc) != 0)
- ret = -1;
- sc->flag = saved_flag;/* restore the saved flag */
+ as->length = p - as->s;
+ as->s[as->length] = '\0';
+ if (ts == 2)
+ as->s[as->length+1] = '\0';
return (ret);
-
-return_no_changed_data:
- /*
- * Something conversion error happend, so we return a no normalized
- * string with an error.
- */
- (void)archive_string_append_unicode(as, _p, len, sc);
- return (-1);
}
-#endif /* __APPLE__ */
-
/*
- * libarchive 2.x made incorrect UTF-8 strings in the wrong assumuption
- * that WCS is Unicode. it is true for servel platforms but some are false.
+ * libarchive 2.x made incorrect UTF-8 strings in the wrong assumption
+ * that WCS is Unicode. It is true for several platforms but some are false.
* And then people who did not use UTF-8 locale on the non Unicode WCS
* platform and made a tar file with libarchive(mostly bsdtar) 2.x. Those
* now cannot get right filename from libarchive 3.x and later since we
@@ -3505,9 +3478,9 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
* Translates the wide-character into the current locale MBS.
*/
#if HAVE_WCRTOMB
- n = wcrtomb(p, wc, &shift_state);
+ n = (int)wcrtomb(p, wc, &shift_state);
#else
- n = wctomb(p, wc);
+ n = (int)wctomb(p, wc);
#endif
if (n == -1)
return (-1);
@@ -3606,13 +3579,13 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
do {
defchar = 0;
ll = WideCharToMultiByte(sc->to_cp, 0,
- (LPCWSTR)u16, bytes>>1, mbs, mbs_size,
+ (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
NULL, &defchar);
if (ll == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Need more buffer for MBS. */
ll = WideCharToMultiByte(sc->to_cp, 0,
- (LPCWSTR)u16, bytes, NULL, 0, NULL, NULL);
+ (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
if (archive_string_ensure(as, ll +1) == NULL)
return (-1);
mbs = as->s + as->length;
@@ -3629,15 +3602,15 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
}
static int
-win_strncat_from_utf16be(struct archive_string *as, const void *_p, size_t bytes,
- struct archive_string_conv *sc)
+win_strncat_from_utf16be(struct archive_string *as, const void *_p,
+ size_t bytes, struct archive_string_conv *sc)
{
return (win_strncat_from_utf16(as, _p, bytes, sc, 1));
}
static int
-win_strncat_from_utf16le(struct archive_string *as, const void *_p, size_t bytes,
- struct archive_string_conv *sc)
+win_strncat_from_utf16le(struct archive_string *as, const void *_p,
+ size_t bytes, struct archive_string_conv *sc)
{
return (win_strncat_from_utf16(as, _p, bytes, sc, 0));
}
@@ -3655,8 +3628,8 @@ is_big_endian(void)
* Return -1 if conversion failes.
*/
static int
-win_strncat_to_utf16(struct archive_string *as16, const void *_p, size_t length,
- struct archive_string_conv *sc, int bigendian)
+win_strncat_to_utf16(struct archive_string *as16, const void *_p,
+ size_t length, struct archive_string_conv *sc, int bigendian)
{
const char *s = (const char *)_p;
char *u16;
@@ -3689,12 +3662,12 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p, size_t length,
}
do {
count = MultiByteToWideChar(sc->from_cp,
- MB_PRECOMPOSED, s, length, (LPWSTR)u16, (int)avail>>1);
+ MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
if (count == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Need more buffer for UTF-16 string */
count = MultiByteToWideChar(sc->from_cp,
- MB_PRECOMPOSED, s, length, NULL, 0);
+ MB_PRECOMPOSED, s, (int)length, NULL, 0);
if (archive_string_ensure(as16, (count +1) * 2)
== NULL)
return (-1);
@@ -3732,15 +3705,15 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p, size_t length,
}
static int
-win_strncat_to_utf16be(struct archive_string *as16, const void *_p, size_t length,
- struct archive_string_conv *sc)
+win_strncat_to_utf16be(struct archive_string *as16, const void *_p,
+ size_t length, struct archive_string_conv *sc)
{
return (win_strncat_to_utf16(as16, _p, length, sc, 1));
}
static int
-win_strncat_to_utf16le(struct archive_string *as16, const void *_p, size_t length,
- struct archive_string_conv *sc)
+win_strncat_to_utf16le(struct archive_string *as16, const void *_p,
+ size_t length, struct archive_string_conv *sc)
{
return (win_strncat_to_utf16(as16, _p, length, sc, 0));
}
@@ -3914,7 +3887,7 @@ archive_mstring_get_utf8(struct archive *a, struct archive_mstring *aes,
sc = archive_string_conversion_to_charset(a, "UTF-8", 1);
if (sc == NULL)
return (-1);/* Couldn't allocate memory for sc. */
- r = archive_strncpy_in_locale(&(aes->aes_mbs), aes->aes_mbs.s,
+ r = archive_strncpy_l(&(aes->aes_mbs), aes->aes_mbs.s,
aes->aes_mbs.length, sc);
if (a == NULL)
free_sconv_object(sc);
@@ -4043,7 +4016,7 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes,
*length = aes->aes_mbs.length;
return (0);
}
- ret = archive_strncpy_in_locale(&(aes->aes_mbs_in_locale),
+ ret = archive_strncpy_l(&(aes->aes_mbs_in_locale),
aes->aes_mbs.s, aes->aes_mbs.length, sc);
*p = aes->aes_mbs_in_locale.s;
if (length != NULL)
@@ -4084,7 +4057,8 @@ archive_mstring_copy_mbs_len(struct archive_mstring *aes, const char *mbs,
int
archive_mstring_copy_wcs(struct archive_mstring *aes, const wchar_t *wcs)
{
- return archive_mstring_copy_wcs_len(aes, wcs, wcs == NULL ? 0 : wcslen(wcs));
+ return archive_mstring_copy_wcs_len(aes, wcs,
+ wcs == NULL ? 0 : wcslen(wcs));
}
int
@@ -4143,7 +4117,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes,
* Translate multi-bytes from some character-set to UTF-8.
*/
sc->cd = sc->cd_w;
- r = archive_strncpy_in_locale(&(aes->aes_utf8), mbs, len, sc);
+ r = archive_strncpy_l(&(aes->aes_utf8), mbs, len, sc);
sc->cd = cd;
if (r != 0) {
aes->aes_set = 0;
@@ -4175,7 +4149,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes,
aes->aes_set = 0;
}
#else
- r = archive_strncpy_in_locale(&(aes->aes_mbs), mbs, len, sc);
+ r = archive_strncpy_l(&(aes->aes_mbs), mbs, len, sc);
if (r == 0)
aes->aes_set = AES_SET_MBS; /* Only MBS form is set now. */
else
@@ -4219,7 +4193,7 @@ archive_mstring_update_utf8(struct archive *a, struct archive_mstring *aes,
sc = archive_string_conversion_from_charset(a, "UTF-8", 1);
if (sc == NULL)
return (-1);/* Couldn't allocate memory for sc. */
- r = archive_strcpy_in_locale(&(aes->aes_mbs), utf8, sc);
+ r = archive_strcpy_l(&(aes->aes_mbs), utf8, sc);
if (a == NULL)
free_sconv_object(sc);
if (r != 0)
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.h b/Utilities/cmlibarchive/libarchive/archive_string.h
index 0e4c9b9..23f4916 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.h
+++ b/Utilities/cmlibarchive/libarchive/archive_string.h
@@ -110,18 +110,20 @@ archive_string_conversion_charset_name(struct archive_string_conv *);
void
archive_string_conversion_set_opt(struct archive_string_conv *, int);
#define SCONV_SET_OPT_UTF8_LIBARCHIVE2X 1
+#define SCONV_SET_OPT_NORMALIZATION_C 2
+#define SCONV_SET_OPT_NORMALIZATION_D 4
/* Copy one archive_string to another in locale conversion.
* Return -1 if conversion failes. */
int
-archive_strncpy_in_locale(struct archive_string *, const void *, size_t,
+archive_strncpy_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
/* Copy one archive_string to another in locale conversion.
* Return -1 if conversion failes. */
int
-archive_strncat_in_locale(struct archive_string *, const void *, size_t,
+archive_strncat_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
@@ -162,8 +164,8 @@ archive_wstrcat(struct archive_wstring *, const wchar_t *);
archive_strncpy((as), (p), ((p) == NULL ? 0 : strlen(p)))
#define archive_wstrcpy(as,p) \
archive_wstrncpy((as), (p), ((p) == NULL ? 0 : wcslen(p)))
-#define archive_strcpy_in_locale(as,p,lo) \
- archive_strncpy_in_locale((as), (p), ((p) == NULL ? 0 : strlen(p)), (lo))
+#define archive_strcpy_l(as,p,lo) \
+ archive_strncpy_l((as), (p), ((p) == NULL ? 0 : strlen(p)), (lo))
/* Copy a C string to an archive_string with limit, resizing as necessary. */
#define archive_strncpy(as,p,l) \
diff --git a/Utilities/cmlibarchive/libarchive/archive_string_composition.h b/Utilities/cmlibarchive/libarchive/archive_string_composition.h
index cc4bf46..be41e33 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string_composition.h
+++ b/Utilities/cmlibarchive/libarchive/archive_string_composition.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 libarchive Project
+ * Copyright (c) 2011-2012 libarchive Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
/*
* ATTENTION!
* This file is generated by build/utils/gen_archive_string_composition_h.sh
- * from http://unicode.org/Public/UNIDATA/UnicodeData.txt
+ * from http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
*
* See also http://unicode.org/report/tr15/
*/
@@ -1348,4 +1348,945 @@ static const unsigned char ccc_index[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,37,38,};
+struct unicode_decomposition_table {
+ uint32_t nfc;
+ uint32_t cp1;
+ uint32_t cp2;
+};
+
+static const struct unicode_decomposition_table u_decomposition_table[] = {
+ { 0x000C0 , 0x00041 , 0x00300 },
+ { 0x000C1 , 0x00041 , 0x00301 },
+ { 0x000C2 , 0x00041 , 0x00302 },
+ { 0x000C3 , 0x00041 , 0x00303 },
+ { 0x000C4 , 0x00041 , 0x00308 },
+ { 0x000C5 , 0x00041 , 0x0030A },
+ { 0x000C7 , 0x00043 , 0x00327 },
+ { 0x000C8 , 0x00045 , 0x00300 },
+ { 0x000C9 , 0x00045 , 0x00301 },
+ { 0x000CA , 0x00045 , 0x00302 },
+ { 0x000CB , 0x00045 , 0x00308 },
+ { 0x000CC , 0x00049 , 0x00300 },
+ { 0x000CD , 0x00049 , 0x00301 },
+ { 0x000CE , 0x00049 , 0x00302 },
+ { 0x000CF , 0x00049 , 0x00308 },
+ { 0x000D1 , 0x0004E , 0x00303 },
+ { 0x000D2 , 0x0004F , 0x00300 },
+ { 0x000D3 , 0x0004F , 0x00301 },
+ { 0x000D4 , 0x0004F , 0x00302 },
+ { 0x000D5 , 0x0004F , 0x00303 },
+ { 0x000D6 , 0x0004F , 0x00308 },
+ { 0x000D9 , 0x00055 , 0x00300 },
+ { 0x000DA , 0x00055 , 0x00301 },
+ { 0x000DB , 0x00055 , 0x00302 },
+ { 0x000DC , 0x00055 , 0x00308 },
+ { 0x000DD , 0x00059 , 0x00301 },
+ { 0x000E0 , 0x00061 , 0x00300 },
+ { 0x000E1 , 0x00061 , 0x00301 },
+ { 0x000E2 , 0x00061 , 0x00302 },
+ { 0x000E3 , 0x00061 , 0x00303 },
+ { 0x000E4 , 0x00061 , 0x00308 },
+ { 0x000E5 , 0x00061 , 0x0030A },
+ { 0x000E7 , 0x00063 , 0x00327 },
+ { 0x000E8 , 0x00065 , 0x00300 },
+ { 0x000E9 , 0x00065 , 0x00301 },
+ { 0x000EA , 0x00065 , 0x00302 },
+ { 0x000EB , 0x00065 , 0x00308 },
+ { 0x000EC , 0x00069 , 0x00300 },
+ { 0x000ED , 0x00069 , 0x00301 },
+ { 0x000EE , 0x00069 , 0x00302 },
+ { 0x000EF , 0x00069 , 0x00308 },
+ { 0x000F1 , 0x0006E , 0x00303 },
+ { 0x000F2 , 0x0006F , 0x00300 },
+ { 0x000F3 , 0x0006F , 0x00301 },
+ { 0x000F4 , 0x0006F , 0x00302 },
+ { 0x000F5 , 0x0006F , 0x00303 },
+ { 0x000F6 , 0x0006F , 0x00308 },
+ { 0x000F9 , 0x00075 , 0x00300 },
+ { 0x000FA , 0x00075 , 0x00301 },
+ { 0x000FB , 0x00075 , 0x00302 },
+ { 0x000FC , 0x00075 , 0x00308 },
+ { 0x000FD , 0x00079 , 0x00301 },
+ { 0x000FF , 0x00079 , 0x00308 },
+ { 0x00100 , 0x00041 , 0x00304 },
+ { 0x00101 , 0x00061 , 0x00304 },
+ { 0x00102 , 0x00041 , 0x00306 },
+ { 0x00103 , 0x00061 , 0x00306 },
+ { 0x00104 , 0x00041 , 0x00328 },
+ { 0x00105 , 0x00061 , 0x00328 },
+ { 0x00106 , 0x00043 , 0x00301 },
+ { 0x00107 , 0x00063 , 0x00301 },
+ { 0x00108 , 0x00043 , 0x00302 },
+ { 0x00109 , 0x00063 , 0x00302 },
+ { 0x0010A , 0x00043 , 0x00307 },
+ { 0x0010B , 0x00063 , 0x00307 },
+ { 0x0010C , 0x00043 , 0x0030C },
+ { 0x0010D , 0x00063 , 0x0030C },
+ { 0x0010E , 0x00044 , 0x0030C },
+ { 0x0010F , 0x00064 , 0x0030C },
+ { 0x00112 , 0x00045 , 0x00304 },
+ { 0x00113 , 0x00065 , 0x00304 },
+ { 0x00114 , 0x00045 , 0x00306 },
+ { 0x00115 , 0x00065 , 0x00306 },
+ { 0x00116 , 0x00045 , 0x00307 },
+ { 0x00117 , 0x00065 , 0x00307 },
+ { 0x00118 , 0x00045 , 0x00328 },
+ { 0x00119 , 0x00065 , 0x00328 },
+ { 0x0011A , 0x00045 , 0x0030C },
+ { 0x0011B , 0x00065 , 0x0030C },
+ { 0x0011C , 0x00047 , 0x00302 },
+ { 0x0011D , 0x00067 , 0x00302 },
+ { 0x0011E , 0x00047 , 0x00306 },
+ { 0x0011F , 0x00067 , 0x00306 },
+ { 0x00120 , 0x00047 , 0x00307 },
+ { 0x00121 , 0x00067 , 0x00307 },
+ { 0x00122 , 0x00047 , 0x00327 },
+ { 0x00123 , 0x00067 , 0x00327 },
+ { 0x00124 , 0x00048 , 0x00302 },
+ { 0x00125 , 0x00068 , 0x00302 },
+ { 0x00128 , 0x00049 , 0x00303 },
+ { 0x00129 , 0x00069 , 0x00303 },
+ { 0x0012A , 0x00049 , 0x00304 },
+ { 0x0012B , 0x00069 , 0x00304 },
+ { 0x0012C , 0x00049 , 0x00306 },
+ { 0x0012D , 0x00069 , 0x00306 },
+ { 0x0012E , 0x00049 , 0x00328 },
+ { 0x0012F , 0x00069 , 0x00328 },
+ { 0x00130 , 0x00049 , 0x00307 },
+ { 0x00134 , 0x0004A , 0x00302 },
+ { 0x00135 , 0x0006A , 0x00302 },
+ { 0x00136 , 0x0004B , 0x00327 },
+ { 0x00137 , 0x0006B , 0x00327 },
+ { 0x00139 , 0x0004C , 0x00301 },
+ { 0x0013A , 0x0006C , 0x00301 },
+ { 0x0013B , 0x0004C , 0x00327 },
+ { 0x0013C , 0x0006C , 0x00327 },
+ { 0x0013D , 0x0004C , 0x0030C },
+ { 0x0013E , 0x0006C , 0x0030C },
+ { 0x00143 , 0x0004E , 0x00301 },
+ { 0x00144 , 0x0006E , 0x00301 },
+ { 0x00145 , 0x0004E , 0x00327 },
+ { 0x00146 , 0x0006E , 0x00327 },
+ { 0x00147 , 0x0004E , 0x0030C },
+ { 0x00148 , 0x0006E , 0x0030C },
+ { 0x0014C , 0x0004F , 0x00304 },
+ { 0x0014D , 0x0006F , 0x00304 },
+ { 0x0014E , 0x0004F , 0x00306 },
+ { 0x0014F , 0x0006F , 0x00306 },
+ { 0x00150 , 0x0004F , 0x0030B },
+ { 0x00151 , 0x0006F , 0x0030B },
+ { 0x00154 , 0x00052 , 0x00301 },
+ { 0x00155 , 0x00072 , 0x00301 },
+ { 0x00156 , 0x00052 , 0x00327 },
+ { 0x00157 , 0x00072 , 0x00327 },
+ { 0x00158 , 0x00052 , 0x0030C },
+ { 0x00159 , 0x00072 , 0x0030C },
+ { 0x0015A , 0x00053 , 0x00301 },
+ { 0x0015B , 0x00073 , 0x00301 },
+ { 0x0015C , 0x00053 , 0x00302 },
+ { 0x0015D , 0x00073 , 0x00302 },
+ { 0x0015E , 0x00053 , 0x00327 },
+ { 0x0015F , 0x00073 , 0x00327 },
+ { 0x00160 , 0x00053 , 0x0030C },
+ { 0x00161 , 0x00073 , 0x0030C },
+ { 0x00162 , 0x00054 , 0x00327 },
+ { 0x00163 , 0x00074 , 0x00327 },
+ { 0x00164 , 0x00054 , 0x0030C },
+ { 0x00165 , 0x00074 , 0x0030C },
+ { 0x00168 , 0x00055 , 0x00303 },
+ { 0x00169 , 0x00075 , 0x00303 },
+ { 0x0016A , 0x00055 , 0x00304 },
+ { 0x0016B , 0x00075 , 0x00304 },
+ { 0x0016C , 0x00055 , 0x00306 },
+ { 0x0016D , 0x00075 , 0x00306 },
+ { 0x0016E , 0x00055 , 0x0030A },
+ { 0x0016F , 0x00075 , 0x0030A },
+ { 0x00170 , 0x00055 , 0x0030B },
+ { 0x00171 , 0x00075 , 0x0030B },
+ { 0x00172 , 0x00055 , 0x00328 },
+ { 0x00173 , 0x00075 , 0x00328 },
+ { 0x00174 , 0x00057 , 0x00302 },
+ { 0x00175 , 0x00077 , 0x00302 },
+ { 0x00176 , 0x00059 , 0x00302 },
+ { 0x00177 , 0x00079 , 0x00302 },
+ { 0x00178 , 0x00059 , 0x00308 },
+ { 0x00179 , 0x0005A , 0x00301 },
+ { 0x0017A , 0x0007A , 0x00301 },
+ { 0x0017B , 0x0005A , 0x00307 },
+ { 0x0017C , 0x0007A , 0x00307 },
+ { 0x0017D , 0x0005A , 0x0030C },
+ { 0x0017E , 0x0007A , 0x0030C },
+ { 0x001A0 , 0x0004F , 0x0031B },
+ { 0x001A1 , 0x0006F , 0x0031B },
+ { 0x001AF , 0x00055 , 0x0031B },
+ { 0x001B0 , 0x00075 , 0x0031B },
+ { 0x001CD , 0x00041 , 0x0030C },
+ { 0x001CE , 0x00061 , 0x0030C },
+ { 0x001CF , 0x00049 , 0x0030C },
+ { 0x001D0 , 0x00069 , 0x0030C },
+ { 0x001D1 , 0x0004F , 0x0030C },
+ { 0x001D2 , 0x0006F , 0x0030C },
+ { 0x001D3 , 0x00055 , 0x0030C },
+ { 0x001D4 , 0x00075 , 0x0030C },
+ { 0x001D5 , 0x000DC , 0x00304 },
+ { 0x001D6 , 0x000FC , 0x00304 },
+ { 0x001D7 , 0x000DC , 0x00301 },
+ { 0x001D8 , 0x000FC , 0x00301 },
+ { 0x001D9 , 0x000DC , 0x0030C },
+ { 0x001DA , 0x000FC , 0x0030C },
+ { 0x001DB , 0x000DC , 0x00300 },
+ { 0x001DC , 0x000FC , 0x00300 },
+ { 0x001DE , 0x000C4 , 0x00304 },
+ { 0x001DF , 0x000E4 , 0x00304 },
+ { 0x001E0 , 0x00226 , 0x00304 },
+ { 0x001E1 , 0x00227 , 0x00304 },
+ { 0x001E2 , 0x000C6 , 0x00304 },
+ { 0x001E3 , 0x000E6 , 0x00304 },
+ { 0x001E6 , 0x00047 , 0x0030C },
+ { 0x001E7 , 0x00067 , 0x0030C },
+ { 0x001E8 , 0x0004B , 0x0030C },
+ { 0x001E9 , 0x0006B , 0x0030C },
+ { 0x001EA , 0x0004F , 0x00328 },
+ { 0x001EB , 0x0006F , 0x00328 },
+ { 0x001EC , 0x001EA , 0x00304 },
+ { 0x001ED , 0x001EB , 0x00304 },
+ { 0x001EE , 0x001B7 , 0x0030C },
+ { 0x001EF , 0x00292 , 0x0030C },
+ { 0x001F0 , 0x0006A , 0x0030C },
+ { 0x001F4 , 0x00047 , 0x00301 },
+ { 0x001F5 , 0x00067 , 0x00301 },
+ { 0x001F8 , 0x0004E , 0x00300 },
+ { 0x001F9 , 0x0006E , 0x00300 },
+ { 0x001FA , 0x000C5 , 0x00301 },
+ { 0x001FB , 0x000E5 , 0x00301 },
+ { 0x001FC , 0x000C6 , 0x00301 },
+ { 0x001FD , 0x000E6 , 0x00301 },
+ { 0x001FE , 0x000D8 , 0x00301 },
+ { 0x001FF , 0x000F8 , 0x00301 },
+ { 0x00200 , 0x00041 , 0x0030F },
+ { 0x00201 , 0x00061 , 0x0030F },
+ { 0x00202 , 0x00041 , 0x00311 },
+ { 0x00203 , 0x00061 , 0x00311 },
+ { 0x00204 , 0x00045 , 0x0030F },
+ { 0x00205 , 0x00065 , 0x0030F },
+ { 0x00206 , 0x00045 , 0x00311 },
+ { 0x00207 , 0x00065 , 0x00311 },
+ { 0x00208 , 0x00049 , 0x0030F },
+ { 0x00209 , 0x00069 , 0x0030F },
+ { 0x0020A , 0x00049 , 0x00311 },
+ { 0x0020B , 0x00069 , 0x00311 },
+ { 0x0020C , 0x0004F , 0x0030F },
+ { 0x0020D , 0x0006F , 0x0030F },
+ { 0x0020E , 0x0004F , 0x00311 },
+ { 0x0020F , 0x0006F , 0x00311 },
+ { 0x00210 , 0x00052 , 0x0030F },
+ { 0x00211 , 0x00072 , 0x0030F },
+ { 0x00212 , 0x00052 , 0x00311 },
+ { 0x00213 , 0x00072 , 0x00311 },
+ { 0x00214 , 0x00055 , 0x0030F },
+ { 0x00215 , 0x00075 , 0x0030F },
+ { 0x00216 , 0x00055 , 0x00311 },
+ { 0x00217 , 0x00075 , 0x00311 },
+ { 0x00218 , 0x00053 , 0x00326 },
+ { 0x00219 , 0x00073 , 0x00326 },
+ { 0x0021A , 0x00054 , 0x00326 },
+ { 0x0021B , 0x00074 , 0x00326 },
+ { 0x0021E , 0x00048 , 0x0030C },
+ { 0x0021F , 0x00068 , 0x0030C },
+ { 0x00226 , 0x00041 , 0x00307 },
+ { 0x00227 , 0x00061 , 0x00307 },
+ { 0x00228 , 0x00045 , 0x00327 },
+ { 0x00229 , 0x00065 , 0x00327 },
+ { 0x0022A , 0x000D6 , 0x00304 },
+ { 0x0022B , 0x000F6 , 0x00304 },
+ { 0x0022C , 0x000D5 , 0x00304 },
+ { 0x0022D , 0x000F5 , 0x00304 },
+ { 0x0022E , 0x0004F , 0x00307 },
+ { 0x0022F , 0x0006F , 0x00307 },
+ { 0x00230 , 0x0022E , 0x00304 },
+ { 0x00231 , 0x0022F , 0x00304 },
+ { 0x00232 , 0x00059 , 0x00304 },
+ { 0x00233 , 0x00079 , 0x00304 },
+ { 0x00385 , 0x000A8 , 0x00301 },
+ { 0x00386 , 0x00391 , 0x00301 },
+ { 0x00388 , 0x00395 , 0x00301 },
+ { 0x00389 , 0x00397 , 0x00301 },
+ { 0x0038A , 0x00399 , 0x00301 },
+ { 0x0038C , 0x0039F , 0x00301 },
+ { 0x0038E , 0x003A5 , 0x00301 },
+ { 0x0038F , 0x003A9 , 0x00301 },
+ { 0x00390 , 0x003CA , 0x00301 },
+ { 0x003AA , 0x00399 , 0x00308 },
+ { 0x003AB , 0x003A5 , 0x00308 },
+ { 0x003AC , 0x003B1 , 0x00301 },
+ { 0x003AD , 0x003B5 , 0x00301 },
+ { 0x003AE , 0x003B7 , 0x00301 },
+ { 0x003AF , 0x003B9 , 0x00301 },
+ { 0x003B0 , 0x003CB , 0x00301 },
+ { 0x003CA , 0x003B9 , 0x00308 },
+ { 0x003CB , 0x003C5 , 0x00308 },
+ { 0x003CC , 0x003BF , 0x00301 },
+ { 0x003CD , 0x003C5 , 0x00301 },
+ { 0x003CE , 0x003C9 , 0x00301 },
+ { 0x003D3 , 0x003D2 , 0x00301 },
+ { 0x003D4 , 0x003D2 , 0x00308 },
+ { 0x00400 , 0x00415 , 0x00300 },
+ { 0x00401 , 0x00415 , 0x00308 },
+ { 0x00403 , 0x00413 , 0x00301 },
+ { 0x00407 , 0x00406 , 0x00308 },
+ { 0x0040C , 0x0041A , 0x00301 },
+ { 0x0040D , 0x00418 , 0x00300 },
+ { 0x0040E , 0x00423 , 0x00306 },
+ { 0x00419 , 0x00418 , 0x00306 },
+ { 0x00439 , 0x00438 , 0x00306 },
+ { 0x00450 , 0x00435 , 0x00300 },
+ { 0x00451 , 0x00435 , 0x00308 },
+ { 0x00453 , 0x00433 , 0x00301 },
+ { 0x00457 , 0x00456 , 0x00308 },
+ { 0x0045C , 0x0043A , 0x00301 },
+ { 0x0045D , 0x00438 , 0x00300 },
+ { 0x0045E , 0x00443 , 0x00306 },
+ { 0x00476 , 0x00474 , 0x0030F },
+ { 0x00477 , 0x00475 , 0x0030F },
+ { 0x004C1 , 0x00416 , 0x00306 },
+ { 0x004C2 , 0x00436 , 0x00306 },
+ { 0x004D0 , 0x00410 , 0x00306 },
+ { 0x004D1 , 0x00430 , 0x00306 },
+ { 0x004D2 , 0x00410 , 0x00308 },
+ { 0x004D3 , 0x00430 , 0x00308 },
+ { 0x004D6 , 0x00415 , 0x00306 },
+ { 0x004D7 , 0x00435 , 0x00306 },
+ { 0x004DA , 0x004D8 , 0x00308 },
+ { 0x004DB , 0x004D9 , 0x00308 },
+ { 0x004DC , 0x00416 , 0x00308 },
+ { 0x004DD , 0x00436 , 0x00308 },
+ { 0x004DE , 0x00417 , 0x00308 },
+ { 0x004DF , 0x00437 , 0x00308 },
+ { 0x004E2 , 0x00418 , 0x00304 },
+ { 0x004E3 , 0x00438 , 0x00304 },
+ { 0x004E4 , 0x00418 , 0x00308 },
+ { 0x004E5 , 0x00438 , 0x00308 },
+ { 0x004E6 , 0x0041E , 0x00308 },
+ { 0x004E7 , 0x0043E , 0x00308 },
+ { 0x004EA , 0x004E8 , 0x00308 },
+ { 0x004EB , 0x004E9 , 0x00308 },
+ { 0x004EC , 0x0042D , 0x00308 },
+ { 0x004ED , 0x0044D , 0x00308 },
+ { 0x004EE , 0x00423 , 0x00304 },
+ { 0x004EF , 0x00443 , 0x00304 },
+ { 0x004F0 , 0x00423 , 0x00308 },
+ { 0x004F1 , 0x00443 , 0x00308 },
+ { 0x004F2 , 0x00423 , 0x0030B },
+ { 0x004F3 , 0x00443 , 0x0030B },
+ { 0x004F4 , 0x00427 , 0x00308 },
+ { 0x004F5 , 0x00447 , 0x00308 },
+ { 0x004F8 , 0x0042B , 0x00308 },
+ { 0x004F9 , 0x0044B , 0x00308 },
+ { 0x00622 , 0x00627 , 0x00653 },
+ { 0x00623 , 0x00627 , 0x00654 },
+ { 0x00624 , 0x00648 , 0x00654 },
+ { 0x00625 , 0x00627 , 0x00655 },
+ { 0x00626 , 0x0064A , 0x00654 },
+ { 0x006C0 , 0x006D5 , 0x00654 },
+ { 0x006C2 , 0x006C1 , 0x00654 },
+ { 0x006D3 , 0x006D2 , 0x00654 },
+ { 0x00929 , 0x00928 , 0x0093C },
+ { 0x00931 , 0x00930 , 0x0093C },
+ { 0x00934 , 0x00933 , 0x0093C },
+ { 0x009CB , 0x009C7 , 0x009BE },
+ { 0x009CC , 0x009C7 , 0x009D7 },
+ { 0x00B48 , 0x00B47 , 0x00B56 },
+ { 0x00B4B , 0x00B47 , 0x00B3E },
+ { 0x00B4C , 0x00B47 , 0x00B57 },
+ { 0x00B94 , 0x00B92 , 0x00BD7 },
+ { 0x00BCA , 0x00BC6 , 0x00BBE },
+ { 0x00BCB , 0x00BC7 , 0x00BBE },
+ { 0x00BCC , 0x00BC6 , 0x00BD7 },
+ { 0x00C48 , 0x00C46 , 0x00C56 },
+ { 0x00CC0 , 0x00CBF , 0x00CD5 },
+ { 0x00CC7 , 0x00CC6 , 0x00CD5 },
+ { 0x00CC8 , 0x00CC6 , 0x00CD6 },
+ { 0x00CCA , 0x00CC6 , 0x00CC2 },
+ { 0x00CCB , 0x00CCA , 0x00CD5 },
+ { 0x00D4A , 0x00D46 , 0x00D3E },
+ { 0x00D4B , 0x00D47 , 0x00D3E },
+ { 0x00D4C , 0x00D46 , 0x00D57 },
+ { 0x00DDA , 0x00DD9 , 0x00DCA },
+ { 0x00DDC , 0x00DD9 , 0x00DCF },
+ { 0x00DDD , 0x00DDC , 0x00DCA },
+ { 0x00DDE , 0x00DD9 , 0x00DDF },
+ { 0x01026 , 0x01025 , 0x0102E },
+ { 0x01B06 , 0x01B05 , 0x01B35 },
+ { 0x01B08 , 0x01B07 , 0x01B35 },
+ { 0x01B0A , 0x01B09 , 0x01B35 },
+ { 0x01B0C , 0x01B0B , 0x01B35 },
+ { 0x01B0E , 0x01B0D , 0x01B35 },
+ { 0x01B12 , 0x01B11 , 0x01B35 },
+ { 0x01B3B , 0x01B3A , 0x01B35 },
+ { 0x01B3D , 0x01B3C , 0x01B35 },
+ { 0x01B40 , 0x01B3E , 0x01B35 },
+ { 0x01B41 , 0x01B3F , 0x01B35 },
+ { 0x01B43 , 0x01B42 , 0x01B35 },
+ { 0x01E00 , 0x00041 , 0x00325 },
+ { 0x01E01 , 0x00061 , 0x00325 },
+ { 0x01E02 , 0x00042 , 0x00307 },
+ { 0x01E03 , 0x00062 , 0x00307 },
+ { 0x01E04 , 0x00042 , 0x00323 },
+ { 0x01E05 , 0x00062 , 0x00323 },
+ { 0x01E06 , 0x00042 , 0x00331 },
+ { 0x01E07 , 0x00062 , 0x00331 },
+ { 0x01E08 , 0x000C7 , 0x00301 },
+ { 0x01E09 , 0x000E7 , 0x00301 },
+ { 0x01E0A , 0x00044 , 0x00307 },
+ { 0x01E0B , 0x00064 , 0x00307 },
+ { 0x01E0C , 0x00044 , 0x00323 },
+ { 0x01E0D , 0x00064 , 0x00323 },
+ { 0x01E0E , 0x00044 , 0x00331 },
+ { 0x01E0F , 0x00064 , 0x00331 },
+ { 0x01E10 , 0x00044 , 0x00327 },
+ { 0x01E11 , 0x00064 , 0x00327 },
+ { 0x01E12 , 0x00044 , 0x0032D },
+ { 0x01E13 , 0x00064 , 0x0032D },
+ { 0x01E14 , 0x00112 , 0x00300 },
+ { 0x01E15 , 0x00113 , 0x00300 },
+ { 0x01E16 , 0x00112 , 0x00301 },
+ { 0x01E17 , 0x00113 , 0x00301 },
+ { 0x01E18 , 0x00045 , 0x0032D },
+ { 0x01E19 , 0x00065 , 0x0032D },
+ { 0x01E1A , 0x00045 , 0x00330 },
+ { 0x01E1B , 0x00065 , 0x00330 },
+ { 0x01E1C , 0x00228 , 0x00306 },
+ { 0x01E1D , 0x00229 , 0x00306 },
+ { 0x01E1E , 0x00046 , 0x00307 },
+ { 0x01E1F , 0x00066 , 0x00307 },
+ { 0x01E20 , 0x00047 , 0x00304 },
+ { 0x01E21 , 0x00067 , 0x00304 },
+ { 0x01E22 , 0x00048 , 0x00307 },
+ { 0x01E23 , 0x00068 , 0x00307 },
+ { 0x01E24 , 0x00048 , 0x00323 },
+ { 0x01E25 , 0x00068 , 0x00323 },
+ { 0x01E26 , 0x00048 , 0x00308 },
+ { 0x01E27 , 0x00068 , 0x00308 },
+ { 0x01E28 , 0x00048 , 0x00327 },
+ { 0x01E29 , 0x00068 , 0x00327 },
+ { 0x01E2A , 0x00048 , 0x0032E },
+ { 0x01E2B , 0x00068 , 0x0032E },
+ { 0x01E2C , 0x00049 , 0x00330 },
+ { 0x01E2D , 0x00069 , 0x00330 },
+ { 0x01E2E , 0x000CF , 0x00301 },
+ { 0x01E2F , 0x000EF , 0x00301 },
+ { 0x01E30 , 0x0004B , 0x00301 },
+ { 0x01E31 , 0x0006B , 0x00301 },
+ { 0x01E32 , 0x0004B , 0x00323 },
+ { 0x01E33 , 0x0006B , 0x00323 },
+ { 0x01E34 , 0x0004B , 0x00331 },
+ { 0x01E35 , 0x0006B , 0x00331 },
+ { 0x01E36 , 0x0004C , 0x00323 },
+ { 0x01E37 , 0x0006C , 0x00323 },
+ { 0x01E38 , 0x01E36 , 0x00304 },
+ { 0x01E39 , 0x01E37 , 0x00304 },
+ { 0x01E3A , 0x0004C , 0x00331 },
+ { 0x01E3B , 0x0006C , 0x00331 },
+ { 0x01E3C , 0x0004C , 0x0032D },
+ { 0x01E3D , 0x0006C , 0x0032D },
+ { 0x01E3E , 0x0004D , 0x00301 },
+ { 0x01E3F , 0x0006D , 0x00301 },
+ { 0x01E40 , 0x0004D , 0x00307 },
+ { 0x01E41 , 0x0006D , 0x00307 },
+ { 0x01E42 , 0x0004D , 0x00323 },
+ { 0x01E43 , 0x0006D , 0x00323 },
+ { 0x01E44 , 0x0004E , 0x00307 },
+ { 0x01E45 , 0x0006E , 0x00307 },
+ { 0x01E46 , 0x0004E , 0x00323 },
+ { 0x01E47 , 0x0006E , 0x00323 },
+ { 0x01E48 , 0x0004E , 0x00331 },
+ { 0x01E49 , 0x0006E , 0x00331 },
+ { 0x01E4A , 0x0004E , 0x0032D },
+ { 0x01E4B , 0x0006E , 0x0032D },
+ { 0x01E4C , 0x000D5 , 0x00301 },
+ { 0x01E4D , 0x000F5 , 0x00301 },
+ { 0x01E4E , 0x000D5 , 0x00308 },
+ { 0x01E4F , 0x000F5 , 0x00308 },
+ { 0x01E50 , 0x0014C , 0x00300 },
+ { 0x01E51 , 0x0014D , 0x00300 },
+ { 0x01E52 , 0x0014C , 0x00301 },
+ { 0x01E53 , 0x0014D , 0x00301 },
+ { 0x01E54 , 0x00050 , 0x00301 },
+ { 0x01E55 , 0x00070 , 0x00301 },
+ { 0x01E56 , 0x00050 , 0x00307 },
+ { 0x01E57 , 0x00070 , 0x00307 },
+ { 0x01E58 , 0x00052 , 0x00307 },
+ { 0x01E59 , 0x00072 , 0x00307 },
+ { 0x01E5A , 0x00052 , 0x00323 },
+ { 0x01E5B , 0x00072 , 0x00323 },
+ { 0x01E5C , 0x01E5A , 0x00304 },
+ { 0x01E5D , 0x01E5B , 0x00304 },
+ { 0x01E5E , 0x00052 , 0x00331 },
+ { 0x01E5F , 0x00072 , 0x00331 },
+ { 0x01E60 , 0x00053 , 0x00307 },
+ { 0x01E61 , 0x00073 , 0x00307 },
+ { 0x01E62 , 0x00053 , 0x00323 },
+ { 0x01E63 , 0x00073 , 0x00323 },
+ { 0x01E64 , 0x0015A , 0x00307 },
+ { 0x01E65 , 0x0015B , 0x00307 },
+ { 0x01E66 , 0x00160 , 0x00307 },
+ { 0x01E67 , 0x00161 , 0x00307 },
+ { 0x01E68 , 0x01E62 , 0x00307 },
+ { 0x01E69 , 0x01E63 , 0x00307 },
+ { 0x01E6A , 0x00054 , 0x00307 },
+ { 0x01E6B , 0x00074 , 0x00307 },
+ { 0x01E6C , 0x00054 , 0x00323 },
+ { 0x01E6D , 0x00074 , 0x00323 },
+ { 0x01E6E , 0x00054 , 0x00331 },
+ { 0x01E6F , 0x00074 , 0x00331 },
+ { 0x01E70 , 0x00054 , 0x0032D },
+ { 0x01E71 , 0x00074 , 0x0032D },
+ { 0x01E72 , 0x00055 , 0x00324 },
+ { 0x01E73 , 0x00075 , 0x00324 },
+ { 0x01E74 , 0x00055 , 0x00330 },
+ { 0x01E75 , 0x00075 , 0x00330 },
+ { 0x01E76 , 0x00055 , 0x0032D },
+ { 0x01E77 , 0x00075 , 0x0032D },
+ { 0x01E78 , 0x00168 , 0x00301 },
+ { 0x01E79 , 0x00169 , 0x00301 },
+ { 0x01E7A , 0x0016A , 0x00308 },
+ { 0x01E7B , 0x0016B , 0x00308 },
+ { 0x01E7C , 0x00056 , 0x00303 },
+ { 0x01E7D , 0x00076 , 0x00303 },
+ { 0x01E7E , 0x00056 , 0x00323 },
+ { 0x01E7F , 0x00076 , 0x00323 },
+ { 0x01E80 , 0x00057 , 0x00300 },
+ { 0x01E81 , 0x00077 , 0x00300 },
+ { 0x01E82 , 0x00057 , 0x00301 },
+ { 0x01E83 , 0x00077 , 0x00301 },
+ { 0x01E84 , 0x00057 , 0x00308 },
+ { 0x01E85 , 0x00077 , 0x00308 },
+ { 0x01E86 , 0x00057 , 0x00307 },
+ { 0x01E87 , 0x00077 , 0x00307 },
+ { 0x01E88 , 0x00057 , 0x00323 },
+ { 0x01E89 , 0x00077 , 0x00323 },
+ { 0x01E8A , 0x00058 , 0x00307 },
+ { 0x01E8B , 0x00078 , 0x00307 },
+ { 0x01E8C , 0x00058 , 0x00308 },
+ { 0x01E8D , 0x00078 , 0x00308 },
+ { 0x01E8E , 0x00059 , 0x00307 },
+ { 0x01E8F , 0x00079 , 0x00307 },
+ { 0x01E90 , 0x0005A , 0x00302 },
+ { 0x01E91 , 0x0007A , 0x00302 },
+ { 0x01E92 , 0x0005A , 0x00323 },
+ { 0x01E93 , 0x0007A , 0x00323 },
+ { 0x01E94 , 0x0005A , 0x00331 },
+ { 0x01E95 , 0x0007A , 0x00331 },
+ { 0x01E96 , 0x00068 , 0x00331 },
+ { 0x01E97 , 0x00074 , 0x00308 },
+ { 0x01E98 , 0x00077 , 0x0030A },
+ { 0x01E99 , 0x00079 , 0x0030A },
+ { 0x01E9B , 0x0017F , 0x00307 },
+ { 0x01EA0 , 0x00041 , 0x00323 },
+ { 0x01EA1 , 0x00061 , 0x00323 },
+ { 0x01EA2 , 0x00041 , 0x00309 },
+ { 0x01EA3 , 0x00061 , 0x00309 },
+ { 0x01EA4 , 0x000C2 , 0x00301 },
+ { 0x01EA5 , 0x000E2 , 0x00301 },
+ { 0x01EA6 , 0x000C2 , 0x00300 },
+ { 0x01EA7 , 0x000E2 , 0x00300 },
+ { 0x01EA8 , 0x000C2 , 0x00309 },
+ { 0x01EA9 , 0x000E2 , 0x00309 },
+ { 0x01EAA , 0x000C2 , 0x00303 },
+ { 0x01EAB , 0x000E2 , 0x00303 },
+ { 0x01EAC , 0x01EA0 , 0x00302 },
+ { 0x01EAD , 0x01EA1 , 0x00302 },
+ { 0x01EAE , 0x00102 , 0x00301 },
+ { 0x01EAF , 0x00103 , 0x00301 },
+ { 0x01EB0 , 0x00102 , 0x00300 },
+ { 0x01EB1 , 0x00103 , 0x00300 },
+ { 0x01EB2 , 0x00102 , 0x00309 },
+ { 0x01EB3 , 0x00103 , 0x00309 },
+ { 0x01EB4 , 0x00102 , 0x00303 },
+ { 0x01EB5 , 0x00103 , 0x00303 },
+ { 0x01EB6 , 0x01EA0 , 0x00306 },
+ { 0x01EB7 , 0x01EA1 , 0x00306 },
+ { 0x01EB8 , 0x00045 , 0x00323 },
+ { 0x01EB9 , 0x00065 , 0x00323 },
+ { 0x01EBA , 0x00045 , 0x00309 },
+ { 0x01EBB , 0x00065 , 0x00309 },
+ { 0x01EBC , 0x00045 , 0x00303 },
+ { 0x01EBD , 0x00065 , 0x00303 },
+ { 0x01EBE , 0x000CA , 0x00301 },
+ { 0x01EBF , 0x000EA , 0x00301 },
+ { 0x01EC0 , 0x000CA , 0x00300 },
+ { 0x01EC1 , 0x000EA , 0x00300 },
+ { 0x01EC2 , 0x000CA , 0x00309 },
+ { 0x01EC3 , 0x000EA , 0x00309 },
+ { 0x01EC4 , 0x000CA , 0x00303 },
+ { 0x01EC5 , 0x000EA , 0x00303 },
+ { 0x01EC6 , 0x01EB8 , 0x00302 },
+ { 0x01EC7 , 0x01EB9 , 0x00302 },
+ { 0x01EC8 , 0x00049 , 0x00309 },
+ { 0x01EC9 , 0x00069 , 0x00309 },
+ { 0x01ECA , 0x00049 , 0x00323 },
+ { 0x01ECB , 0x00069 , 0x00323 },
+ { 0x01ECC , 0x0004F , 0x00323 },
+ { 0x01ECD , 0x0006F , 0x00323 },
+ { 0x01ECE , 0x0004F , 0x00309 },
+ { 0x01ECF , 0x0006F , 0x00309 },
+ { 0x01ED0 , 0x000D4 , 0x00301 },
+ { 0x01ED1 , 0x000F4 , 0x00301 },
+ { 0x01ED2 , 0x000D4 , 0x00300 },
+ { 0x01ED3 , 0x000F4 , 0x00300 },
+ { 0x01ED4 , 0x000D4 , 0x00309 },
+ { 0x01ED5 , 0x000F4 , 0x00309 },
+ { 0x01ED6 , 0x000D4 , 0x00303 },
+ { 0x01ED7 , 0x000F4 , 0x00303 },
+ { 0x01ED8 , 0x01ECC , 0x00302 },
+ { 0x01ED9 , 0x01ECD , 0x00302 },
+ { 0x01EDA , 0x001A0 , 0x00301 },
+ { 0x01EDB , 0x001A1 , 0x00301 },
+ { 0x01EDC , 0x001A0 , 0x00300 },
+ { 0x01EDD , 0x001A1 , 0x00300 },
+ { 0x01EDE , 0x001A0 , 0x00309 },
+ { 0x01EDF , 0x001A1 , 0x00309 },
+ { 0x01EE0 , 0x001A0 , 0x00303 },
+ { 0x01EE1 , 0x001A1 , 0x00303 },
+ { 0x01EE2 , 0x001A0 , 0x00323 },
+ { 0x01EE3 , 0x001A1 , 0x00323 },
+ { 0x01EE4 , 0x00055 , 0x00323 },
+ { 0x01EE5 , 0x00075 , 0x00323 },
+ { 0x01EE6 , 0x00055 , 0x00309 },
+ { 0x01EE7 , 0x00075 , 0x00309 },
+ { 0x01EE8 , 0x001AF , 0x00301 },
+ { 0x01EE9 , 0x001B0 , 0x00301 },
+ { 0x01EEA , 0x001AF , 0x00300 },
+ { 0x01EEB , 0x001B0 , 0x00300 },
+ { 0x01EEC , 0x001AF , 0x00309 },
+ { 0x01EED , 0x001B0 , 0x00309 },
+ { 0x01EEE , 0x001AF , 0x00303 },
+ { 0x01EEF , 0x001B0 , 0x00303 },
+ { 0x01EF0 , 0x001AF , 0x00323 },
+ { 0x01EF1 , 0x001B0 , 0x00323 },
+ { 0x01EF2 , 0x00059 , 0x00300 },
+ { 0x01EF3 , 0x00079 , 0x00300 },
+ { 0x01EF4 , 0x00059 , 0x00323 },
+ { 0x01EF5 , 0x00079 , 0x00323 },
+ { 0x01EF6 , 0x00059 , 0x00309 },
+ { 0x01EF7 , 0x00079 , 0x00309 },
+ { 0x01EF8 , 0x00059 , 0x00303 },
+ { 0x01EF9 , 0x00079 , 0x00303 },
+ { 0x01F00 , 0x003B1 , 0x00313 },
+ { 0x01F01 , 0x003B1 , 0x00314 },
+ { 0x01F02 , 0x01F00 , 0x00300 },
+ { 0x01F03 , 0x01F01 , 0x00300 },
+ { 0x01F04 , 0x01F00 , 0x00301 },
+ { 0x01F05 , 0x01F01 , 0x00301 },
+ { 0x01F06 , 0x01F00 , 0x00342 },
+ { 0x01F07 , 0x01F01 , 0x00342 },
+ { 0x01F08 , 0x00391 , 0x00313 },
+ { 0x01F09 , 0x00391 , 0x00314 },
+ { 0x01F0A , 0x01F08 , 0x00300 },
+ { 0x01F0B , 0x01F09 , 0x00300 },
+ { 0x01F0C , 0x01F08 , 0x00301 },
+ { 0x01F0D , 0x01F09 , 0x00301 },
+ { 0x01F0E , 0x01F08 , 0x00342 },
+ { 0x01F0F , 0x01F09 , 0x00342 },
+ { 0x01F10 , 0x003B5 , 0x00313 },
+ { 0x01F11 , 0x003B5 , 0x00314 },
+ { 0x01F12 , 0x01F10 , 0x00300 },
+ { 0x01F13 , 0x01F11 , 0x00300 },
+ { 0x01F14 , 0x01F10 , 0x00301 },
+ { 0x01F15 , 0x01F11 , 0x00301 },
+ { 0x01F18 , 0x00395 , 0x00313 },
+ { 0x01F19 , 0x00395 , 0x00314 },
+ { 0x01F1A , 0x01F18 , 0x00300 },
+ { 0x01F1B , 0x01F19 , 0x00300 },
+ { 0x01F1C , 0x01F18 , 0x00301 },
+ { 0x01F1D , 0x01F19 , 0x00301 },
+ { 0x01F20 , 0x003B7 , 0x00313 },
+ { 0x01F21 , 0x003B7 , 0x00314 },
+ { 0x01F22 , 0x01F20 , 0x00300 },
+ { 0x01F23 , 0x01F21 , 0x00300 },
+ { 0x01F24 , 0x01F20 , 0x00301 },
+ { 0x01F25 , 0x01F21 , 0x00301 },
+ { 0x01F26 , 0x01F20 , 0x00342 },
+ { 0x01F27 , 0x01F21 , 0x00342 },
+ { 0x01F28 , 0x00397 , 0x00313 },
+ { 0x01F29 , 0x00397 , 0x00314 },
+ { 0x01F2A , 0x01F28 , 0x00300 },
+ { 0x01F2B , 0x01F29 , 0x00300 },
+ { 0x01F2C , 0x01F28 , 0x00301 },
+ { 0x01F2D , 0x01F29 , 0x00301 },
+ { 0x01F2E , 0x01F28 , 0x00342 },
+ { 0x01F2F , 0x01F29 , 0x00342 },
+ { 0x01F30 , 0x003B9 , 0x00313 },
+ { 0x01F31 , 0x003B9 , 0x00314 },
+ { 0x01F32 , 0x01F30 , 0x00300 },
+ { 0x01F33 , 0x01F31 , 0x00300 },
+ { 0x01F34 , 0x01F30 , 0x00301 },
+ { 0x01F35 , 0x01F31 , 0x00301 },
+ { 0x01F36 , 0x01F30 , 0x00342 },
+ { 0x01F37 , 0x01F31 , 0x00342 },
+ { 0x01F38 , 0x00399 , 0x00313 },
+ { 0x01F39 , 0x00399 , 0x00314 },
+ { 0x01F3A , 0x01F38 , 0x00300 },
+ { 0x01F3B , 0x01F39 , 0x00300 },
+ { 0x01F3C , 0x01F38 , 0x00301 },
+ { 0x01F3D , 0x01F39 , 0x00301 },
+ { 0x01F3E , 0x01F38 , 0x00342 },
+ { 0x01F3F , 0x01F39 , 0x00342 },
+ { 0x01F40 , 0x003BF , 0x00313 },
+ { 0x01F41 , 0x003BF , 0x00314 },
+ { 0x01F42 , 0x01F40 , 0x00300 },
+ { 0x01F43 , 0x01F41 , 0x00300 },
+ { 0x01F44 , 0x01F40 , 0x00301 },
+ { 0x01F45 , 0x01F41 , 0x00301 },
+ { 0x01F48 , 0x0039F , 0x00313 },
+ { 0x01F49 , 0x0039F , 0x00314 },
+ { 0x01F4A , 0x01F48 , 0x00300 },
+ { 0x01F4B , 0x01F49 , 0x00300 },
+ { 0x01F4C , 0x01F48 , 0x00301 },
+ { 0x01F4D , 0x01F49 , 0x00301 },
+ { 0x01F50 , 0x003C5 , 0x00313 },
+ { 0x01F51 , 0x003C5 , 0x00314 },
+ { 0x01F52 , 0x01F50 , 0x00300 },
+ { 0x01F53 , 0x01F51 , 0x00300 },
+ { 0x01F54 , 0x01F50 , 0x00301 },
+ { 0x01F55 , 0x01F51 , 0x00301 },
+ { 0x01F56 , 0x01F50 , 0x00342 },
+ { 0x01F57 , 0x01F51 , 0x00342 },
+ { 0x01F59 , 0x003A5 , 0x00314 },
+ { 0x01F5B , 0x01F59 , 0x00300 },
+ { 0x01F5D , 0x01F59 , 0x00301 },
+ { 0x01F5F , 0x01F59 , 0x00342 },
+ { 0x01F60 , 0x003C9 , 0x00313 },
+ { 0x01F61 , 0x003C9 , 0x00314 },
+ { 0x01F62 , 0x01F60 , 0x00300 },
+ { 0x01F63 , 0x01F61 , 0x00300 },
+ { 0x01F64 , 0x01F60 , 0x00301 },
+ { 0x01F65 , 0x01F61 , 0x00301 },
+ { 0x01F66 , 0x01F60 , 0x00342 },
+ { 0x01F67 , 0x01F61 , 0x00342 },
+ { 0x01F68 , 0x003A9 , 0x00313 },
+ { 0x01F69 , 0x003A9 , 0x00314 },
+ { 0x01F6A , 0x01F68 , 0x00300 },
+ { 0x01F6B , 0x01F69 , 0x00300 },
+ { 0x01F6C , 0x01F68 , 0x00301 },
+ { 0x01F6D , 0x01F69 , 0x00301 },
+ { 0x01F6E , 0x01F68 , 0x00342 },
+ { 0x01F6F , 0x01F69 , 0x00342 },
+ { 0x01F70 , 0x003B1 , 0x00300 },
+ { 0x01F72 , 0x003B5 , 0x00300 },
+ { 0x01F74 , 0x003B7 , 0x00300 },
+ { 0x01F76 , 0x003B9 , 0x00300 },
+ { 0x01F78 , 0x003BF , 0x00300 },
+ { 0x01F7A , 0x003C5 , 0x00300 },
+ { 0x01F7C , 0x003C9 , 0x00300 },
+ { 0x01F80 , 0x01F00 , 0x00345 },
+ { 0x01F81 , 0x01F01 , 0x00345 },
+ { 0x01F82 , 0x01F02 , 0x00345 },
+ { 0x01F83 , 0x01F03 , 0x00345 },
+ { 0x01F84 , 0x01F04 , 0x00345 },
+ { 0x01F85 , 0x01F05 , 0x00345 },
+ { 0x01F86 , 0x01F06 , 0x00345 },
+ { 0x01F87 , 0x01F07 , 0x00345 },
+ { 0x01F88 , 0x01F08 , 0x00345 },
+ { 0x01F89 , 0x01F09 , 0x00345 },
+ { 0x01F8A , 0x01F0A , 0x00345 },
+ { 0x01F8B , 0x01F0B , 0x00345 },
+ { 0x01F8C , 0x01F0C , 0x00345 },
+ { 0x01F8D , 0x01F0D , 0x00345 },
+ { 0x01F8E , 0x01F0E , 0x00345 },
+ { 0x01F8F , 0x01F0F , 0x00345 },
+ { 0x01F90 , 0x01F20 , 0x00345 },
+ { 0x01F91 , 0x01F21 , 0x00345 },
+ { 0x01F92 , 0x01F22 , 0x00345 },
+ { 0x01F93 , 0x01F23 , 0x00345 },
+ { 0x01F94 , 0x01F24 , 0x00345 },
+ { 0x01F95 , 0x01F25 , 0x00345 },
+ { 0x01F96 , 0x01F26 , 0x00345 },
+ { 0x01F97 , 0x01F27 , 0x00345 },
+ { 0x01F98 , 0x01F28 , 0x00345 },
+ { 0x01F99 , 0x01F29 , 0x00345 },
+ { 0x01F9A , 0x01F2A , 0x00345 },
+ { 0x01F9B , 0x01F2B , 0x00345 },
+ { 0x01F9C , 0x01F2C , 0x00345 },
+ { 0x01F9D , 0x01F2D , 0x00345 },
+ { 0x01F9E , 0x01F2E , 0x00345 },
+ { 0x01F9F , 0x01F2F , 0x00345 },
+ { 0x01FA0 , 0x01F60 , 0x00345 },
+ { 0x01FA1 , 0x01F61 , 0x00345 },
+ { 0x01FA2 , 0x01F62 , 0x00345 },
+ { 0x01FA3 , 0x01F63 , 0x00345 },
+ { 0x01FA4 , 0x01F64 , 0x00345 },
+ { 0x01FA5 , 0x01F65 , 0x00345 },
+ { 0x01FA6 , 0x01F66 , 0x00345 },
+ { 0x01FA7 , 0x01F67 , 0x00345 },
+ { 0x01FA8 , 0x01F68 , 0x00345 },
+ { 0x01FA9 , 0x01F69 , 0x00345 },
+ { 0x01FAA , 0x01F6A , 0x00345 },
+ { 0x01FAB , 0x01F6B , 0x00345 },
+ { 0x01FAC , 0x01F6C , 0x00345 },
+ { 0x01FAD , 0x01F6D , 0x00345 },
+ { 0x01FAE , 0x01F6E , 0x00345 },
+ { 0x01FAF , 0x01F6F , 0x00345 },
+ { 0x01FB0 , 0x003B1 , 0x00306 },
+ { 0x01FB1 , 0x003B1 , 0x00304 },
+ { 0x01FB2 , 0x01F70 , 0x00345 },
+ { 0x01FB3 , 0x003B1 , 0x00345 },
+ { 0x01FB4 , 0x003AC , 0x00345 },
+ { 0x01FB6 , 0x003B1 , 0x00342 },
+ { 0x01FB7 , 0x01FB6 , 0x00345 },
+ { 0x01FB8 , 0x00391 , 0x00306 },
+ { 0x01FB9 , 0x00391 , 0x00304 },
+ { 0x01FBA , 0x00391 , 0x00300 },
+ { 0x01FBC , 0x00391 , 0x00345 },
+ { 0x01FC1 , 0x000A8 , 0x00342 },
+ { 0x01FC2 , 0x01F74 , 0x00345 },
+ { 0x01FC3 , 0x003B7 , 0x00345 },
+ { 0x01FC4 , 0x003AE , 0x00345 },
+ { 0x01FC6 , 0x003B7 , 0x00342 },
+ { 0x01FC7 , 0x01FC6 , 0x00345 },
+ { 0x01FC8 , 0x00395 , 0x00300 },
+ { 0x01FCA , 0x00397 , 0x00300 },
+ { 0x01FCC , 0x00397 , 0x00345 },
+ { 0x01FCD , 0x01FBF , 0x00300 },
+ { 0x01FCE , 0x01FBF , 0x00301 },
+ { 0x01FCF , 0x01FBF , 0x00342 },
+ { 0x01FD0 , 0x003B9 , 0x00306 },
+ { 0x01FD1 , 0x003B9 , 0x00304 },
+ { 0x01FD2 , 0x003CA , 0x00300 },
+ { 0x01FD6 , 0x003B9 , 0x00342 },
+ { 0x01FD7 , 0x003CA , 0x00342 },
+ { 0x01FD8 , 0x00399 , 0x00306 },
+ { 0x01FD9 , 0x00399 , 0x00304 },
+ { 0x01FDA , 0x00399 , 0x00300 },
+ { 0x01FDD , 0x01FFE , 0x00300 },
+ { 0x01FDE , 0x01FFE , 0x00301 },
+ { 0x01FDF , 0x01FFE , 0x00342 },
+ { 0x01FE0 , 0x003C5 , 0x00306 },
+ { 0x01FE1 , 0x003C5 , 0x00304 },
+ { 0x01FE2 , 0x003CB , 0x00300 },
+ { 0x01FE4 , 0x003C1 , 0x00313 },
+ { 0x01FE5 , 0x003C1 , 0x00314 },
+ { 0x01FE6 , 0x003C5 , 0x00342 },
+ { 0x01FE7 , 0x003CB , 0x00342 },
+ { 0x01FE8 , 0x003A5 , 0x00306 },
+ { 0x01FE9 , 0x003A5 , 0x00304 },
+ { 0x01FEA , 0x003A5 , 0x00300 },
+ { 0x01FEC , 0x003A1 , 0x00314 },
+ { 0x01FED , 0x000A8 , 0x00300 },
+ { 0x01FF2 , 0x01F7C , 0x00345 },
+ { 0x01FF3 , 0x003C9 , 0x00345 },
+ { 0x01FF4 , 0x003CE , 0x00345 },
+ { 0x01FF6 , 0x003C9 , 0x00342 },
+ { 0x01FF7 , 0x01FF6 , 0x00345 },
+ { 0x01FF8 , 0x0039F , 0x00300 },
+ { 0x01FFA , 0x003A9 , 0x00300 },
+ { 0x01FFC , 0x003A9 , 0x00345 },
+ { 0x0219A , 0x02190 , 0x00338 },
+ { 0x0219B , 0x02192 , 0x00338 },
+ { 0x021AE , 0x02194 , 0x00338 },
+ { 0x021CD , 0x021D0 , 0x00338 },
+ { 0x021CE , 0x021D4 , 0x00338 },
+ { 0x021CF , 0x021D2 , 0x00338 },
+ { 0x02204 , 0x02203 , 0x00338 },
+ { 0x02209 , 0x02208 , 0x00338 },
+ { 0x0220C , 0x0220B , 0x00338 },
+ { 0x02224 , 0x02223 , 0x00338 },
+ { 0x02226 , 0x02225 , 0x00338 },
+ { 0x02241 , 0x0223C , 0x00338 },
+ { 0x02244 , 0x02243 , 0x00338 },
+ { 0x02247 , 0x02245 , 0x00338 },
+ { 0x02249 , 0x02248 , 0x00338 },
+ { 0x02260 , 0x0003D , 0x00338 },
+ { 0x02262 , 0x02261 , 0x00338 },
+ { 0x0226D , 0x0224D , 0x00338 },
+ { 0x0226E , 0x0003C , 0x00338 },
+ { 0x0226F , 0x0003E , 0x00338 },
+ { 0x02270 , 0x02264 , 0x00338 },
+ { 0x02271 , 0x02265 , 0x00338 },
+ { 0x02274 , 0x02272 , 0x00338 },
+ { 0x02275 , 0x02273 , 0x00338 },
+ { 0x02278 , 0x02276 , 0x00338 },
+ { 0x02279 , 0x02277 , 0x00338 },
+ { 0x02280 , 0x0227A , 0x00338 },
+ { 0x02281 , 0x0227B , 0x00338 },
+ { 0x02284 , 0x02282 , 0x00338 },
+ { 0x02285 , 0x02283 , 0x00338 },
+ { 0x02288 , 0x02286 , 0x00338 },
+ { 0x02289 , 0x02287 , 0x00338 },
+ { 0x022AC , 0x022A2 , 0x00338 },
+ { 0x022AD , 0x022A8 , 0x00338 },
+ { 0x022AE , 0x022A9 , 0x00338 },
+ { 0x022AF , 0x022AB , 0x00338 },
+ { 0x022E0 , 0x0227C , 0x00338 },
+ { 0x022E1 , 0x0227D , 0x00338 },
+ { 0x022E2 , 0x02291 , 0x00338 },
+ { 0x022E3 , 0x02292 , 0x00338 },
+ { 0x022EA , 0x022B2 , 0x00338 },
+ { 0x022EB , 0x022B3 , 0x00338 },
+ { 0x022EC , 0x022B4 , 0x00338 },
+ { 0x022ED , 0x022B5 , 0x00338 },
+ { 0x0304C , 0x0304B , 0x03099 },
+ { 0x0304E , 0x0304D , 0x03099 },
+ { 0x03050 , 0x0304F , 0x03099 },
+ { 0x03052 , 0x03051 , 0x03099 },
+ { 0x03054 , 0x03053 , 0x03099 },
+ { 0x03056 , 0x03055 , 0x03099 },
+ { 0x03058 , 0x03057 , 0x03099 },
+ { 0x0305A , 0x03059 , 0x03099 },
+ { 0x0305C , 0x0305B , 0x03099 },
+ { 0x0305E , 0x0305D , 0x03099 },
+ { 0x03060 , 0x0305F , 0x03099 },
+ { 0x03062 , 0x03061 , 0x03099 },
+ { 0x03065 , 0x03064 , 0x03099 },
+ { 0x03067 , 0x03066 , 0x03099 },
+ { 0x03069 , 0x03068 , 0x03099 },
+ { 0x03070 , 0x0306F , 0x03099 },
+ { 0x03071 , 0x0306F , 0x0309A },
+ { 0x03073 , 0x03072 , 0x03099 },
+ { 0x03074 , 0x03072 , 0x0309A },
+ { 0x03076 , 0x03075 , 0x03099 },
+ { 0x03077 , 0x03075 , 0x0309A },
+ { 0x03079 , 0x03078 , 0x03099 },
+ { 0x0307A , 0x03078 , 0x0309A },
+ { 0x0307C , 0x0307B , 0x03099 },
+ { 0x0307D , 0x0307B , 0x0309A },
+ { 0x03094 , 0x03046 , 0x03099 },
+ { 0x0309E , 0x0309D , 0x03099 },
+ { 0x030AC , 0x030AB , 0x03099 },
+ { 0x030AE , 0x030AD , 0x03099 },
+ { 0x030B0 , 0x030AF , 0x03099 },
+ { 0x030B2 , 0x030B1 , 0x03099 },
+ { 0x030B4 , 0x030B3 , 0x03099 },
+ { 0x030B6 , 0x030B5 , 0x03099 },
+ { 0x030B8 , 0x030B7 , 0x03099 },
+ { 0x030BA , 0x030B9 , 0x03099 },
+ { 0x030BC , 0x030BB , 0x03099 },
+ { 0x030BE , 0x030BD , 0x03099 },
+ { 0x030C0 , 0x030BF , 0x03099 },
+ { 0x030C2 , 0x030C1 , 0x03099 },
+ { 0x030C5 , 0x030C4 , 0x03099 },
+ { 0x030C7 , 0x030C6 , 0x03099 },
+ { 0x030C9 , 0x030C8 , 0x03099 },
+ { 0x030D0 , 0x030CF , 0x03099 },
+ { 0x030D1 , 0x030CF , 0x0309A },
+ { 0x030D3 , 0x030D2 , 0x03099 },
+ { 0x030D4 , 0x030D2 , 0x0309A },
+ { 0x030D6 , 0x030D5 , 0x03099 },
+ { 0x030D7 , 0x030D5 , 0x0309A },
+ { 0x030D9 , 0x030D8 , 0x03099 },
+ { 0x030DA , 0x030D8 , 0x0309A },
+ { 0x030DC , 0x030DB , 0x03099 },
+ { 0x030DD , 0x030DB , 0x0309A },
+ { 0x030F4 , 0x030A6 , 0x03099 },
+ { 0x030F7 , 0x030EF , 0x03099 },
+ { 0x030F8 , 0x030F0 , 0x03099 },
+ { 0x030F9 , 0x030F1 , 0x03099 },
+ { 0x030FA , 0x030F2 , 0x03099 },
+ { 0x030FE , 0x030FD , 0x03099 },
+ { 0x1109A , 0x11099 , 0x110BA },
+ { 0x1109C , 0x1109B , 0x110BA },
+ { 0x110AB , 0x110A5 , 0x110BA },
+};
+
#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */
+
diff --git a/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c b/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c
index 7d7d971..964ea2b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c
+++ b/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c
@@ -38,7 +38,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_string_sprintf.c 189435 2009-03-
* here. This is only used to format error messages, so doesn't
* require any floating-point support or field-width handling.
*/
-
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
#include <stdio.h>
#include "archive_string.h"
@@ -129,7 +131,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
break;
case 'c':
s = va_arg(ap, int);
- archive_strappend_char(as, s);
+ archive_strappend_char(as, (char)s);
break;
case 'd':
switch(long_flag) {
@@ -146,7 +148,9 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
pw = va_arg(ap, wchar_t *);
if (pw == NULL)
pw = L"(null)";
- archive_string_append_from_wcs(as, pw, wcslen(pw));
+ if (archive_string_append_from_wcs(as, pw,
+ wcslen(pw)) != 0 && errno == ENOMEM)
+ __archive_errx(1, "Out of memory");
break;
default:
p2 = va_arg(ap, char *);
@@ -160,7 +164,9 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
pw = va_arg(ap, wchar_t *);
if (pw == NULL)
pw = L"(null)";
- archive_string_append_from_wcs(as, pw, wcslen(pw));
+ if (archive_string_append_from_wcs(as, pw,
+ wcslen(pw)) != 0 && errno == ENOMEM)
+ __archive_errx(1, "Out of memory");
break;
case 'o': case 'u': case 'x': case 'X':
/* Common handling for unsigned integer formats. */
diff --git a/Utilities/cmlibarchive/libarchive/archive_util.3 b/Utilities/cmlibarchive/libarchive/archive_util.3
index cd05d03..99ab842 100644
--- a/Utilities/cmlibarchive/libarchive/archive_util.3
+++ b/Utilities/cmlibarchive/libarchive/archive_util.3
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_util.3 201098 2009-12-28 02:58:14Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd January 8, 2005
+.Dd February 2, 2012
.Dt ARCHIVE_UTIL 3
.Os
.Sh NAME
@@ -43,6 +43,8 @@
.Nm archive_position ,
.Nm archive_set_error
.Nd libarchive utility functions
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft void
diff --git a/Utilities/cmlibarchive/libarchive/archive_util.c b/Utilities/cmlibarchive/libarchive/archive_util.c
index e0852a3..34d8081 100644
--- a/Utilities/cmlibarchive/libarchive/archive_util.c
+++ b/Utilities/cmlibarchive/libarchive/archive_util.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2009,2010 Michihiro NAKAJIMA
+ * Copyright (c) 2009-2012 Michihiro NAKAJIMA
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
@@ -50,6 +50,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#include "archive_private.h"
#include "archive_string.h"
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
/* Generic initialization of 'struct archive' objects. */
int
__archive_clean(struct archive *a)
@@ -239,12 +243,13 @@ __archive_mktemp(const char *tmpdir)
errno = ENOMEM;
goto exit_tmpfile;
}
- GetTempPathW(l, tmp);
+ GetTempPathW((DWORD)l, tmp);
archive_wstrcpy(&temp_name, tmp);
free(tmp);
} else {
- archive_wstring_append_from_mbs(&temp_name, tmpdir,
- strlen(tmpdir));
+ if (archive_wstring_append_from_mbs(&temp_name, tmpdir,
+ strlen(tmpdir)) < 0)
+ goto exit_tmpfile;
if (temp_name.s[temp_name.length-1] != L'/')
archive_wstrappend_wchar(&temp_name, L'/');
}
@@ -292,7 +297,8 @@ __archive_mktemp(const char *tmpdir)
/* Generate a random file name through CryptGenRandom(). */
p = xp;
- if (!CryptGenRandom(hProv, (ep - p)*sizeof(wchar_t), (BYTE*)p)) {
+ if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
+ (BYTE*)p)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
@@ -384,6 +390,7 @@ __archive_mktemp(const char *tmpdir)
fd = mkstemp(temp_name.s);
if (fd < 0)
goto exit_tmpfile;
+ __archive_ensure_cloexec_flag(fd);
unlink(temp_name.s);
exit_tmpfile:
archive_string_free(&temp_name);
@@ -437,7 +444,8 @@ __archive_mktemp(const char *tmpdir)
archive_strcat(&temp_name, "XXXXXXXXXX");
ep = temp_name.s + archive_strlen(&temp_name);
- fd = open("/dev/random", O_RDONLY);
+ fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
if (fd < 0)
seed = time(NULL);
else {
@@ -451,10 +459,12 @@ __archive_mktemp(const char *tmpdir)
p = tp;
while (p < ep)
*p++ = num[((unsigned)rand_r(&seed)) % sizeof(num)];
- fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR, 0600);
+ fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
+ 0600);
} while (fd < 0 && errno == EEXIST);
if (fd < 0)
goto exit_tmpfile;
+ __archive_ensure_cloexec_flag(fd);
unlink(temp_name.s);
exit_tmpfile:
archive_string_free(&temp_name);
@@ -463,3 +473,29 @@ exit_tmpfile:
#endif /* HAVE_MKSTEMP */
#endif /* !_WIN32 || __CYGWIN__ */
+
+/*
+ * Set FD_CLOEXEC flag to a file descriptor if it is not set.
+ * We have to set the flag if the platform does not provide O_CLOEXEC
+ * or F_DUPFD_CLOEXEC flags.
+ *
+ * Note: This function is absolutely called after creating a new file
+ * descriptor even if the platform seemingly provides O_CLOEXEC or
+ * F_DUPFD_CLOEXEC macros because it is possible that the platform
+ * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it.
+ */
+void
+__archive_ensure_cloexec_flag(int fd)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ (void)fd; /* UNSED */
+#else
+ int flags;
+
+ if (fd >= 0) {
+ flags = fcntl(fd, F_GETFD);
+ if (flags != -1 && (flags & FD_CLOEXEC) == 0)
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+ }
+#endif
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_virtual.c b/Utilities/cmlibarchive/libarchive/archive_virtual.c
index 752dc17..0c4155f 100644
--- a/Utilities/cmlibarchive/libarchive/archive_virtual.c
+++ b/Utilities/cmlibarchive/libarchive/archive_virtual.c
@@ -67,8 +67,17 @@ archive_read_close(struct archive *a)
}
int
+archive_write_fail(struct archive *a)
+{
+ a->state = ARCHIVE_STATE_FATAL;
+ return a->state;
+}
+
+int
archive_write_free(struct archive *a)
{
+ if (a == NULL)
+ return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
}
@@ -77,13 +86,15 @@ archive_write_free(struct archive *a)
int
archive_write_finish(struct archive *a)
{
- return ((a->vtable->archive_free)(a));
+ return archive_write_free(a);
}
#endif
int
archive_read_free(struct archive *a)
{
+ if (a == NULL)
+ return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
}
@@ -92,7 +103,7 @@ archive_read_free(struct archive *a)
int
archive_read_finish(struct archive *a)
{
- return ((a->vtable->archive_free)(a));
+ return archive_read_free(a);
}
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.c b/Utilities/cmlibarchive/libarchive/archive_windows.c
index 8f5d566..d3bf758 100644
--- a/Utilities/cmlibarchive/libarchive/archive_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_windows.c
@@ -48,6 +48,7 @@
#include "archive_platform.h"
#include "archive_private.h"
+#include "archive_entry.h"
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
@@ -109,7 +110,7 @@ getino(struct ustat *ub)
ULARGE_INTEGER ino64;
ino64.QuadPart = ub->st_ino;
/* I don't know this hashing is correct way */
- return (ino64.LowPart ^ (ino64.LowPart >> INOSIZE));
+ return ((ino_t)(ino64.LowPart ^ (ino64.LowPart >> INOSIZE)));
}
/*
@@ -153,7 +154,7 @@ __la_win_permissive_name_w(const wchar_t *wname)
if (l == 0)
return (NULL);
/* NOTE: GetFullPathNameW has a bug that if the length of the file
- * name is just one that return imcomplete buffer size. Thus, we
+ * name is just 1 then it returns incomplete buffer size. Thus, we
* have to add three to the size to allocate a sufficient buffer
* size for the full-pathname of the file name. */
l += 3;
@@ -424,7 +425,7 @@ __la_read(int fd, void *buf, size_t nbytes)
/* Convert Windows FILETIME to UTC */
__inline static void
-fileTimeToUTC(const FILETIME *filetime, time_t *time, long *ns)
+fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns)
{
ULARGE_INTEGER utc;
@@ -432,10 +433,10 @@ fileTimeToUTC(const FILETIME *filetime, time_t *time, long *ns)
utc.LowPart = filetime->dwLowDateTime;
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
- *time = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
+ *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
} else {
- *time = 0;
+ *t = 0;
*ns = 0;
}
}
@@ -458,7 +459,7 @@ __hstat(HANDLE handle, struct ustat *st)
ULARGE_INTEGER ino64;
DWORD ftype;
mode_t mode;
- time_t time;
+ time_t t;
long ns;
switch (ftype = GetFileType(handle)) {
@@ -515,14 +516,14 @@ __hstat(HANDLE handle, struct ustat *st)
mode |= S_IFREG;
st->st_mode = mode;
- fileTimeToUTC(&info.ftLastAccessTime, &time, &ns);
- st->st_atime = time;
+ fileTimeToUTC(&info.ftLastAccessTime, &t, &ns);
+ st->st_atime = t;
st->st_atime_nsec = ns;
- fileTimeToUTC(&info.ftLastWriteTime, &time, &ns);
- st->st_mtime = time;
+ fileTimeToUTC(&info.ftLastWriteTime, &t, &ns);
+ st->st_mtime = t;
st->st_mtime_nsec = ns;
- fileTimeToUTC(&info.ftCreationTime, &time, &ns);
- st->st_ctime = time;
+ fileTimeToUTC(&info.ftCreationTime, &t, &ns);
+ st->st_ctime = t;
st->st_ctime_nsec = ns;
st->st_size =
((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
@@ -558,7 +559,7 @@ copy_stat(struct stat *st, struct ustat *us)
st->st_ino = getino(us);
st->st_mode = us->st_mode;
st->st_nlink = us->st_nlink;
- st->st_size = us->st_size;
+ st->st_size = (off_t)us->st_size;
st->st_uid = us->st_uid;
st->st_dev = us->st_dev;
st->st_rdev = us->st_rdev;
@@ -632,35 +633,22 @@ __la_stat(const char *path, struct stat *st)
* This waitpid is limited implementation.
*/
pid_t
-__la_waitpid(pid_t wpid, int *status, int option)
+__la_waitpid(HANDLE child, int *status, int option)
{
- HANDLE child;
- DWORD cs, ret;
+ DWORD cs;
(void)option;/* UNUSED */
- *status = 0;
- child = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, wpid);
- if (child == NULL) {
- la_dosmaperr(GetLastError());
- return (-1);
- }
- ret = WaitForSingleObject(child, INFINITE);
- if (ret == WAIT_FAILED) {
- CloseHandle(child);
- la_dosmaperr(GetLastError());
- return (-1);
- }
- if (GetExitCodeProcess(child, &cs) == 0) {
- CloseHandle(child);
- la_dosmaperr(GetLastError());
- return (-1);
- }
- if (cs == STILL_ACTIVE)
- *status = 0x100;
- else
- *status = (int)(cs & 0xff);
- CloseHandle(child);
- return (wpid);
+ do {
+ if (GetExitCodeProcess(child, &cs) == 0) {
+ CloseHandle(child);
+ la_dosmaperr(GetLastError());
+ *status = 0;
+ return (-1);
+ }
+ } while (cs == STILL_ACTIVE);
+
+ *status = (int)(cs & 0xff);
+ return (0);
}
ssize_t
@@ -691,6 +679,113 @@ __la_write(int fd, const void *buf, size_t nbytes)
}
/*
+ * Replace the Windows path separator '\' with '/'.
+ */
+static int
+replace_pathseparator(struct archive_wstring *ws, const wchar_t *wp)
+{
+ wchar_t *w;
+ size_t path_length;
+
+ if (wp == NULL)
+ return(0);
+ if (wcschr(wp, L'\\') == NULL)
+ return(0);
+ path_length = wcslen(wp);
+ if (archive_wstring_ensure(ws, path_length) == NULL)
+ return(-1);
+ archive_wstrncpy(ws, wp, path_length);
+ for (w = ws->s; *w; w++) {
+ if (*w == L'\\')
+ *w = L'/';
+ }
+ return(1);
+}
+
+static int
+fix_pathseparator(struct archive_entry *entry)
+{
+ struct archive_wstring ws;
+ const wchar_t *wp;
+ int ret = ARCHIVE_OK;
+
+ archive_string_init(&ws);
+ wp = archive_entry_pathname_w(entry);
+ switch (replace_pathseparator(&ws, wp)) {
+ case 0: /* Not replaced. */
+ break;
+ case 1: /* Replaced. */
+ archive_entry_copy_pathname_w(entry, ws.s);
+ break;
+ default:
+ ret = ARCHIVE_FAILED;
+ }
+ wp = archive_entry_hardlink_w(entry);
+ switch (replace_pathseparator(&ws, wp)) {
+ case 0: /* Not replaced. */
+ break;
+ case 1: /* Replaced. */
+ archive_entry_copy_hardlink_w(entry, ws.s);
+ break;
+ default:
+ ret = ARCHIVE_FAILED;
+ }
+ wp = archive_entry_symlink_w(entry);
+ switch (replace_pathseparator(&ws, wp)) {
+ case 0: /* Not replaced. */
+ break;
+ case 1: /* Replaced. */
+ archive_entry_copy_symlink_w(entry, ws.s);
+ break;
+ default:
+ ret = ARCHIVE_FAILED;
+ }
+ archive_wstring_free(&ws);
+ return(ret);
+}
+
+struct archive_entry *
+__la_win_entry_in_posix_pathseparator(struct archive_entry *entry)
+{
+ struct archive_entry *entry_main;
+ const wchar_t *wp;
+ int has_backslash = 0;
+ int ret;
+
+ wp = archive_entry_pathname_w(entry);
+ if (wp != NULL && wcschr(wp, L'\\') != NULL)
+ has_backslash = 1;
+ if (!has_backslash) {
+ wp = archive_entry_hardlink_w(entry);
+ if (wp != NULL && wcschr(wp, L'\\') != NULL)
+ has_backslash = 1;
+ }
+ if (!has_backslash) {
+ wp = archive_entry_symlink_w(entry);
+ if (wp != NULL && wcschr(wp, L'\\') != NULL)
+ has_backslash = 1;
+ }
+ /*
+ * If there is no backslach chars, return the original.
+ */
+ if (!has_backslash)
+ return (entry);
+
+ /* Copy entry so we can modify it as needed. */
+ entry_main = archive_entry_clone(entry);
+ if (entry_main == NULL)
+ return (NULL);
+ /* Replace the Windows path-separator '\' with '/'. */
+ ret = fix_pathseparator(entry_main);
+ if (ret < ARCHIVE_WARN) {
+ archive_entry_free(entry_main);
+ return (NULL);
+ }
+ return (entry_main);
+}
+
+
+/*
* The following function was modified from PostgreSQL sources and is
* subject to the copyright below.
*/
@@ -796,7 +891,7 @@ __la_dosmaperr(unsigned long e)
return;
}
- for (i = 0; i < sizeof(doserrors); i++)
+ for (i = 0; i < (int)sizeof(doserrors); i++)
{
if (doserrors[i].winerr == e)
{
diff --git a/Utilities/cmlibarchive/libarchive/archive_windows.h b/Utilities/cmlibarchive/libarchive/archive_windows.h
index c581af3..620810c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_windows.h
+++ b/Utilities/cmlibarchive/libarchive/archive_windows.h
@@ -49,6 +49,9 @@
#define LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED
/* Start of configuration for native Win32 */
+#ifndef MINGW_HAS_SECURE_API
+#define MINGW_HAS_SECURE_API 1
+#endif
#include <errno.h>
#define set_errno(val) ((errno)=val)
@@ -72,7 +75,6 @@
//#define EFTYPE 7
#if defined(_MSC_VER)
-/* TODO: Fix the code, don't suppress the warnings. */
#pragma warning(push,1)
#pragma warning(disable:4761) /* integral size mismatch in argument; conversion supplied */
#endif
@@ -95,8 +97,14 @@
#ifndef fileno
#define fileno _fileno
#endif
+#ifdef fstat
+#undef fstat
+#endif
#define fstat __la_fstat
#if !defined(__BORLANDC__)
+#ifdef lseek
+#undef lseek
+#endif
#define lseek _lseeki64
#else
#define lseek __la_lseek
@@ -108,6 +116,9 @@
#if !defined(__BORLANDC__)
#define setmode _setmode
#endif
+#ifdef stat
+#undef stat
+#endif
#define stat(path,stref) __la_stat(path,stref)
#if !defined(__BORLANDC__)
#define strdup _strdup
@@ -257,7 +268,7 @@ extern __int64 __la_lseek(int fd, __int64 offset, int whence);
extern int __la_open(const char *path, int flags, ...);
extern ssize_t __la_read(int fd, void *buf, size_t nbytes);
extern int __la_stat(const char *path, struct stat *st);
-extern pid_t __la_waitpid(pid_t wpid, int *status, int option);
+extern pid_t __la_waitpid(HANDLE child, int *status, int option);
extern ssize_t __la_write(int fd, const void *buf, size_t nbytes);
#define _stat64i32(path, st) __la_stat(path, st)
@@ -270,6 +281,8 @@ extern wchar_t *__la_win_permissive_name(const char *name);
extern wchar_t *__la_win_permissive_name_w(const wchar_t *wname);
extern void __la_dosmaperr(unsigned long e);
#define la_dosmaperr(e) __la_dosmaperr(e)
+extern struct archive_entry *__la_win_entry_in_posix_pathseparator(
+ struct archive_entry *);
#if defined(HAVE_WCRTOMB) && defined(__BORLANDC__)
typedef int mbstate_t;
@@ -278,14 +291,14 @@ size_t wcrtomb(char *, wchar_t, mbstate_t *);
#if defined(_MSC_VER) && _MSC_VER < 1300
WINBASEAPI BOOL WINAPI GetVolumePathNameW(
- LPCWSTR lpszFileName,
- LPWSTR lpszVolumePathName,
- DWORD cchBufferLength
- );
+ LPCWSTR lpszFileName,
+ LPWSTR lpszVolumePathName,
+ DWORD cchBufferLength
+ );
# if _WIN32_WINNT < 0x0500 /* windows.h not providing 0x500 API */
typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
- LARGE_INTEGER FileOffset;
- LARGE_INTEGER Length;
+ LARGE_INTEGER FileOffset;
+ LARGE_INTEGER Length;
} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER;
# define FSCTL_SET_SPARSE \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA)
diff --git a/Utilities/cmlibarchive/libarchive/archive_write.3 b/Utilities/cmlibarchive/libarchive/archive_write.3
index f87386a..228bc2c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write.3
@@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE 3
.Os
.Sh NAME
.Nm archive_write
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Sh DESCRIPTION
diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c
index b4b3867..b296069 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write.c
@@ -232,6 +232,10 @@ __archive_write_filter(struct archive_write_filter *f,
int r;
if (length == 0)
return(ARCHIVE_OK);
+ if (f->write == NULL)
+ /* If unset, a fatal error has already ocuured, so this filter
+ * didn't open. We cannot write anything. */
+ return(ARCHIVE_FATAL);
r = (f->write)(f, buff, length);
f->bytes_written += length;
return (r);
@@ -323,43 +327,43 @@ archive_write_client_write(struct archive_write_filter *f,
{
struct archive_write *a = (struct archive_write *)f->archive;
struct archive_none *state = (struct archive_none *)f->data;
- const char *buff = (const char *)_buff;
- ssize_t remaining, to_copy;
- ssize_t bytes_written;
-
- remaining = length;
-
- /*
- * If there is no buffer for blocking, just pass the data
- * straight through to the client write callback. In
- * particular, this supports "no write delay" operation for
- * special applications. Just set the block size to zero.
- */
- if (state->buffer_size == 0) {
- while (remaining > 0) {
- bytes_written = (a->client_writer)(&a->archive,
- a->client_data, buff, remaining);
- if (bytes_written <= 0)
- return (ARCHIVE_FATAL);
- remaining -= bytes_written;
- buff += bytes_written;
- }
- return (ARCHIVE_OK);
- }
-
- /* If the copy buffer isn't empty, try to fill it. */
- if (state->avail < state->buffer_size) {
- /* If buffer is not empty... */
- /* ... copy data into buffer ... */
- to_copy = ((size_t)remaining > state->avail) ?
+ const char *buff = (const char *)_buff;
+ ssize_t remaining, to_copy;
+ ssize_t bytes_written;
+
+ remaining = length;
+
+ /*
+ * If there is no buffer for blocking, just pass the data
+ * straight through to the client write callback. In
+ * particular, this supports "no write delay" operation for
+ * special applications. Just set the block size to zero.
+ */
+ if (state->buffer_size == 0) {
+ while (remaining > 0) {
+ bytes_written = (a->client_writer)(&a->archive,
+ a->client_data, buff, remaining);
+ if (bytes_written <= 0)
+ return (ARCHIVE_FATAL);
+ remaining -= bytes_written;
+ buff += bytes_written;
+ }
+ return (ARCHIVE_OK);
+ }
+
+ /* If the copy buffer isn't empty, try to fill it. */
+ if (state->avail < state->buffer_size) {
+ /* If buffer is not empty... */
+ /* ... copy data into buffer ... */
+ to_copy = ((size_t)remaining > state->avail) ?
state->avail : (size_t)remaining;
- memcpy(state->next, buff, to_copy);
- state->next += to_copy;
- state->avail -= to_copy;
- buff += to_copy;
- remaining -= to_copy;
- /* ... if it's full, write it out. */
- if (state->avail == 0) {
+ memcpy(state->next, buff, to_copy);
+ state->next += to_copy;
+ state->avail -= to_copy;
+ buff += to_copy;
+ remaining -= to_copy;
+ /* ... if it's full, write it out. */
+ if (state->avail == 0) {
char *p = state->buffer;
size_t to_write = state->buffer_size;
while (to_write > 0) {
@@ -375,70 +379,72 @@ archive_write_client_write(struct archive_write_filter *f,
p += bytes_written;
to_write -= bytes_written;
}
- state->next = state->buffer;
- state->avail = state->buffer_size;
- }
- }
-
- while ((size_t)remaining > state->buffer_size) {
- /* Write out full blocks directly to client. */
- bytes_written = (a->client_writer)(&a->archive,
- a->client_data, buff, state->buffer_size);
- if (bytes_written <= 0)
- return (ARCHIVE_FATAL);
- buff += bytes_written;
- remaining -= bytes_written;
- }
-
- if (remaining > 0) {
- /* Copy last bit into copy buffer. */
- memcpy(state->next, buff, remaining);
- state->next += remaining;
- state->avail -= remaining;
- }
- return (ARCHIVE_OK);
+ state->next = state->buffer;
+ state->avail = state->buffer_size;
+ }
+ }
+
+ while ((size_t)remaining >= state->buffer_size) {
+ /* Write out full blocks directly to client. */
+ bytes_written = (a->client_writer)(&a->archive,
+ a->client_data, buff, state->buffer_size);
+ if (bytes_written <= 0)
+ return (ARCHIVE_FATAL);
+ buff += bytes_written;
+ remaining -= bytes_written;
+ }
+
+ if (remaining > 0) {
+ /* Copy last bit into copy buffer. */
+ memcpy(state->next, buff, remaining);
+ state->next += remaining;
+ state->avail -= remaining;
+ }
+ return (ARCHIVE_OK);
}
static int
archive_write_client_close(struct archive_write_filter *f)
{
struct archive_write *a = (struct archive_write *)f->archive;
- struct archive_none *state = (struct archive_none *)f->data;
- ssize_t block_length;
- ssize_t target_block_length;
- ssize_t bytes_written;
- int ret = ARCHIVE_OK;
-
- /* If there's pending data, pad and write the last block */
- if (state->next != state->buffer) {
- block_length = state->buffer_size - state->avail;
-
- /* Tricky calculation to determine size of last block */
- if (a->bytes_in_last_block <= 0)
- /* Default or Zero: pad to full block */
- target_block_length = a->bytes_per_block;
- else
- /* Round to next multiple of bytes_in_last_block. */
- target_block_length = a->bytes_in_last_block *
- ( (block_length + a->bytes_in_last_block - 1) /
- a->bytes_in_last_block);
- if (target_block_length > a->bytes_per_block)
- target_block_length = a->bytes_per_block;
- if (block_length < target_block_length) {
- memset(state->next, 0,
- target_block_length - block_length);
- block_length = target_block_length;
- }
- bytes_written = (a->client_writer)(&a->archive,
- a->client_data, state->buffer, block_length);
- ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK;
- }
+ struct archive_none *state = (struct archive_none *)f->data;
+ ssize_t block_length;
+ ssize_t target_block_length;
+ ssize_t bytes_written;
+ int ret = ARCHIVE_OK;
+
+ /* If there's pending data, pad and write the last block */
+ if (state->next != state->buffer) {
+ block_length = state->buffer_size - state->avail;
+
+ /* Tricky calculation to determine size of last block */
+ if (a->bytes_in_last_block <= 0)
+ /* Default or Zero: pad to full block */
+ target_block_length = a->bytes_per_block;
+ else
+ /* Round to next multiple of bytes_in_last_block. */
+ target_block_length = a->bytes_in_last_block *
+ ( (block_length + a->bytes_in_last_block - 1) /
+ a->bytes_in_last_block);
+ if (target_block_length > a->bytes_per_block)
+ target_block_length = a->bytes_per_block;
+ if (block_length < target_block_length) {
+ memset(state->next, 0,
+ target_block_length - block_length);
+ block_length = target_block_length;
+ }
+ bytes_written = (a->client_writer)(&a->archive,
+ a->client_data, state->buffer, block_length);
+ ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK;
+ }
if (a->client_closer)
(*a->client_closer)(&a->archive, a->client_data);
free(state->buffer);
- free(state);
- a->client_data = NULL;
- return (ret);
+ free(state);
+ /* Clear the close handler myself not to be called again. */
+ f->close = NULL;
+ a->client_data = NULL;
+ return (ret);
}
/*
@@ -623,7 +629,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
if (a->skip_file_set &&
archive_entry_dev_is_set(entry) &&
archive_entry_ino_is_set(entry) &&
- archive_entry_dev(entry) == a->skip_file_dev &&
+ archive_entry_dev(entry) == (dev_t)a->skip_file_dev &&
archive_entry_ino64(entry) == a->skip_file_ino) {
archive_set_error(&a->archive, 0,
"Can't add archive to itself");
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c
new file mode 100644
index 0000000..81dd683
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2012 Ondrej Holy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+
+/* A table that maps filter codes to functions. */
+static
+struct { int code; int (*setter)(struct archive *); } codes[] =
+{
+ { ARCHIVE_FILTER_NONE, archive_write_add_filter_none },
+ { ARCHIVE_FILTER_GZIP, archive_write_add_filter_gzip },
+ { ARCHIVE_FILTER_BZIP2, archive_write_add_filter_bzip2 },
+ { ARCHIVE_FILTER_COMPRESS, archive_write_add_filter_compress },
+ { ARCHIVE_FILTER_GRZIP, archive_write_add_filter_grzip },
+ { ARCHIVE_FILTER_LRZIP, archive_write_add_filter_lrzip },
+ { ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip },
+ { ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma },
+ { ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip },
+ { ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode },
+ { ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
+ { -1, NULL }
+};
+
+int
+archive_write_add_filter(struct archive *a, int code)
+{
+ int i;
+
+ for (i = 0; codes[i].code != -1; i++) {
+ if (code == codes[i].code)
+ return ((codes[i].setter)(a));
+ }
+
+ archive_set_error(a, EINVAL, "No such filter");
+ return (ARCHIVE_FATAL);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c
new file mode 100644
index 0000000..85eb087
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_b64encode.c
@@ -0,0 +1,314 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_string.h"
+#include "archive_write_private.h"
+
+#define LBYTES 57
+
+struct private_b64encode {
+ int mode;
+ struct archive_string name;
+ struct archive_string encoded_buff;
+ size_t bs;
+ size_t hold_len;
+ unsigned char hold[LBYTES];
+};
+
+static int archive_filter_b64encode_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_filter_b64encode_open(struct archive_write_filter *);
+static int archive_filter_b64encode_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_filter_b64encode_close(struct archive_write_filter *);
+static int archive_filter_b64encode_free(struct archive_write_filter *);
+static void b64_encode(struct archive_string *, const unsigned char *, size_t);
+static int64_t atol8(const char *, size_t);
+
+static const char base64[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/'
+};
+
+/*
+ * Add a compress filter to this write handle.
+ */
+int
+archive_write_add_filter_b64encode(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct private_b64encode *state;
+
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_uu");
+
+ state = (struct private_b64encode *)calloc(1, sizeof(*state));
+ if (state == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for b64encode filter");
+ return (ARCHIVE_FATAL);
+ }
+ archive_strcpy(&state->name, "-");
+ state->mode = 0644;
+
+ f->data = state;
+ f->name = "b64encode";
+ f->code = ARCHIVE_FILTER_UU;
+ f->open = archive_filter_b64encode_open;
+ f->options = archive_filter_b64encode_options;
+ f->write = archive_filter_b64encode_write;
+ f->close = archive_filter_b64encode_close;
+ f->free = archive_filter_b64encode_free;
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Set write options.
+ */
+static int
+archive_filter_b64encode_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+
+ if (strcmp(key, "mode") == 0) {
+ if (value == NULL) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "mode option requires octal digits");
+ return (ARCHIVE_FAILED);
+ }
+ state->mode = (int)atol8(value, strlen(value)) & 0777;
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "name") == 0) {
+ if (value == NULL) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "name option requires a string");
+ return (ARCHIVE_FAILED);
+ }
+ archive_strcpy(&state->name, value);
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Setup callback.
+ */
+static int
+archive_filter_b64encode_open(struct archive_write_filter *f)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+ size_t bs = 65536, bpb;
+ int ret;
+
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of the of bytes
+ * per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+
+ state->bs = bs;
+ if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for b64encode buffer");
+ return (ARCHIVE_FATAL);
+ }
+
+ archive_string_sprintf(&state->encoded_buff, "begin-base64 %o %s\n",
+ state->mode, state->name.s);
+
+ f->data = state;
+ return (0);
+}
+
+static void
+b64_encode(struct archive_string *as, const unsigned char *p, size_t len)
+{
+ int c;
+
+ for (; len >= 3; p += 3, len -= 3) {
+ c = p[0] >> 2;
+ archive_strappend_char(as, base64[c]);
+ c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
+ archive_strappend_char(as, base64[c]);
+ c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
+ archive_strappend_char(as, base64[c]);
+ c = p[2] & 0x3f;
+ archive_strappend_char(as, base64[c]);
+ }
+ if (len > 0) {
+ c = p[0] >> 2;
+ archive_strappend_char(as, base64[c]);
+ c = (p[0] & 0x03) << 4;
+ if (len == 1) {
+ archive_strappend_char(as, base64[c]);
+ archive_strappend_char(as, '=');
+ archive_strappend_char(as, '=');
+ } else {
+ c |= (p[1] & 0xf0) >> 4;
+ archive_strappend_char(as, base64[c]);
+ c = (p[1] & 0x0f) << 2;
+ archive_strappend_char(as, base64[c]);
+ archive_strappend_char(as, '=');
+ }
+ }
+ archive_strappend_char(as, '\n');
+}
+
+/*
+ * Write data to the encoded stream.
+ */
+static int
+archive_filter_b64encode_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+ const unsigned char *p = buff;
+ int ret = ARCHIVE_OK;
+
+ if (length == 0)
+ return (ret);
+
+ if (state->hold_len) {
+ while (state->hold_len < LBYTES && length > 0) {
+ state->hold[state->hold_len++] = *p++;
+ length--;
+ }
+ if (state->hold_len < LBYTES)
+ return (ret);
+ b64_encode(&state->encoded_buff, state->hold, LBYTES);
+ state->hold_len = 0;
+ }
+
+ for (; length >= LBYTES; length -= LBYTES, p += LBYTES)
+ b64_encode(&state->encoded_buff, p, LBYTES);
+
+ /* Save remaining bytes. */
+ if (length > 0) {
+ memcpy(state->hold, p, length);
+ state->hold_len = length;
+ }
+ while (archive_strlen(&state->encoded_buff) >= state->bs) {
+ ret = __archive_write_filter(f->next_filter,
+ state->encoded_buff.s, state->bs);
+ memmove(state->encoded_buff.s,
+ state->encoded_buff.s + state->bs,
+ state->encoded_buff.length - state->bs);
+ state->encoded_buff.length -= state->bs;
+ }
+
+ return (ret);
+}
+
+
+/*
+ * Finish the compression...
+ */
+static int
+archive_filter_b64encode_close(struct archive_write_filter *f)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+ int ret, ret2;
+
+ /* Flush remaining bytes. */
+ if (state->hold_len != 0)
+ b64_encode(&state->encoded_buff, state->hold, state->hold_len);
+ archive_string_sprintf(&state->encoded_buff, "====\n");
+ /* Write the last block */
+ archive_write_set_bytes_in_last_block(f->archive, 1);
+ ret = __archive_write_filter(f->next_filter,
+ state->encoded_buff.s, archive_strlen(&state->encoded_buff));
+ ret2 = __archive_write_close_filter(f->next_filter);
+ if (ret > ret2)
+ ret = ret2;
+ return (ret);
+}
+
+static int
+archive_filter_b64encode_free(struct archive_write_filter *f)
+{
+ struct private_b64encode *state = (struct private_b64encode *)f->data;
+
+ archive_string_free(&state->name);
+ archive_string_free(&state->encoded_buff);
+ free(state);
+ return (ARCHIVE_OK);
+}
+
+static int64_t
+atol8(const char *p, size_t char_cnt)
+{
+ int64_t l;
+ int digit;
+
+ l = 0;
+ while (char_cnt-- > 0) {
+ if (*p >= '0' && *p <= '7')
+ digit = *p - '0';
+ else
+ break;
+ p++;
+ l <<= 3;
+ l |= digit;
+ }
+ return (l);
+}
+
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c
new file mode 100644
index 0000000..e4cba4a
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+
+/* A table that maps names to functions. */
+static
+struct { const char *name; int (*setter)(struct archive *); } names[] =
+{
+ { "b64encode", archive_write_add_filter_b64encode },
+ { "bzip2", archive_write_add_filter_bzip2 },
+ { "compress", archive_write_add_filter_compress },
+ { "grzip", archive_write_add_filter_grzip },
+ { "gzip", archive_write_add_filter_gzip },
+ { "lrzip", archive_write_add_filter_lrzip },
+ { "lzip", archive_write_add_filter_lzip },
+ { "lzma", archive_write_add_filter_lzma },
+ { "lzop", archive_write_add_filter_lzop },
+ { "uuencode", archive_write_add_filter_uuencode },
+ { "xz", archive_write_add_filter_xz },
+ { NULL, NULL }
+};
+
+int
+archive_write_add_filter_by_name(struct archive *a, const char *name)
+{
+ int i;
+
+ for (i = 0; names[i].name != NULL; i++) {
+ if (strcmp(name, names[i].name) == 0)
+ return ((names[i].setter)(a));
+ }
+
+ archive_set_error(a, EINVAL, "No such filter '%s'", name);
+ a->state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c
index 096a6a4..6526f51 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_bzip2.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,32 +55,18 @@ archive_write_set_compression_bzip2(struct archive *a)
}
#endif
-#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
-int
-archive_write_add_filter_bzip2(struct archive *a)
-{
- archive_set_error(a, ARCHIVE_ERRNO_MISC,
- "bzip2 compression not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-#else
-/* Don't compile this if we don't have bzlib. */
-
struct private_data {
int compression_level;
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
bz_stream stream;
int64_t total_in;
char *compressed;
size_t compressed_buffer_size;
+#else
+ struct archive_write_program_data *pdata;
+#endif
};
-/*
- * Yuck. bzlib.h is not const-correct, so I need this one bit
- * of ugly hackery to convert a const * pointer to a non-const pointer.
- */
-#define SET_NEXT_IN(st,src) \
- (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
-
static int archive_compressor_bzip2_close(struct archive_write_filter *);
static int archive_compressor_bzip2_free(struct archive_write_filter *);
static int archive_compressor_bzip2_open(struct archive_write_filter *);
@@ -87,8 +74,6 @@ static int archive_compressor_bzip2_options(struct archive_write_filter *,
const char *, const char *);
static int archive_compressor_bzip2_write(struct archive_write_filter *,
const void *, size_t);
-static int drive_compressor(struct archive_write_filter *,
- struct private_data *, int finishing);
/*
* Add a bzip2 compression filter to this write handle.
@@ -115,11 +100,64 @@ archive_write_add_filter_bzip2(struct archive *_a)
f->close = &archive_compressor_bzip2_close;
f->free = &archive_compressor_bzip2_free;
f->open = &archive_compressor_bzip2_open;
- f->code = ARCHIVE_COMPRESSION_BZIP2;
+ f->code = ARCHIVE_FILTER_BZIP2;
f->name = "bzip2";
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 0;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Using external bzip2 program");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+/*
+ * Set write options.
+ */
+static int
+archive_compressor_bzip2_options(struct archive_write_filter *f,
+ const char *key, const char *value)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
+ value[1] != '\0')
+ return (ARCHIVE_WARN);
+ data->compression_level = value[0] - '0';
+ /* Make '0' be a synonym for '1'. */
+ /* This way, bzip2 compressor supports the same 0..9
+ * range of levels as gzip. */
+ if (data->compression_level < 1)
+ data->compression_level = 1;
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
+#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
+/* Don't compile this if we don't have bzlib. */
+
+/*
+ * Yuck. bzlib.h is not const-correct, so I need this one bit
+ * of ugly hackery to convert a const * pointer to a non-const pointer.
+ */
+#define SET_NEXT_IN(st,src) \
+ (st)->stream.next_in = (char *)(uintptr_t)(const void *)(src)
+static int drive_compressor(struct archive_write_filter *,
+ struct private_data *, int finishing);
+
/*
* Setup callback.
*/
@@ -133,10 +171,18 @@ archive_compressor_bzip2_open(struct archive_write_filter *f)
if (ret != 0)
return (ret);
- /* TODO: Find a better way to size this. (Maybe look at the */
- /* block size expected by the following filter?) */
if (data->compressed == NULL) {
- data->compressed_buffer_size = 65536;
+ size_t bs = 65536, bpb;
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of the of bytes
+ * per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+ data->compressed_buffer_size = bs;
data->compressed
= (char *)malloc(data->compressed_buffer_size);
if (data->compressed == NULL) {
@@ -187,31 +233,6 @@ archive_compressor_bzip2_open(struct archive_write_filter *f)
}
/*
- * Set write options.
- */
-static int
-archive_compressor_bzip2_options(struct archive_write_filter *f,
- const char *key, const char *value)
-{
- struct private_data *data = (struct private_data *)f->data;
-
- if (strcmp(key, "compression-level") == 0) {
- if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
- value[1] != '\0')
- return (ARCHIVE_WARN);
- data->compression_level = value[0] - '0';
- /* Make '0' be a synonym for '1'. */
- /* This way, bzip2 compressor supports the same 0..9
- * range of levels as gzip. */
- if (data->compression_level < 1)
- data->compression_level = 1;
- return (ARCHIVE_OK);
- }
-
- return (ARCHIVE_WARN);
-}
-
-/*
* Write data to the compressed stream.
*
* Returns ARCHIVE_OK if all data written, error otherwise.
@@ -332,4 +353,55 @@ drive_compressor(struct archive_write_filter *f,
}
}
+#else /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
+
+static int
+archive_compressor_bzip2_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "bzip2");
+
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strcat(&as, " -");
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+ f->write = archive_compressor_bzip2_write;
+
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_compressor_bzip2_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_bzip2_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+static int
+archive_compressor_bzip2_free(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ __archive_write_program_free(data->pdata);
+ free(data);
+ return (ARCHIVE_OK);
+}
+
#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c
index 465ff0e..26fcef4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_compress.c
@@ -135,7 +135,7 @@ archive_write_add_filter_compress(struct archive *_a)
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_compress");
f->open = &archive_compressor_compress_open;
- f->code = ARCHIVE_COMPRESSION_COMPRESS;
+ f->code = ARCHIVE_FILTER_COMPRESS;
f->name = "compress";
return (ARCHIVE_OK);
}
@@ -148,8 +148,9 @@ archive_compressor_compress_open(struct archive_write_filter *f)
{
int ret;
struct private_data *state;
+ size_t bs = 65536, bpb;
- f->code = ARCHIVE_COMPRESSION_COMPRESS;
+ f->code = ARCHIVE_FILTER_COMPRESS;
f->name = "compress";
ret = __archive_write_open_filter(f->next_filter);
@@ -163,7 +164,16 @@ archive_compressor_compress_open(struct archive_write_filter *f)
return (ARCHIVE_FATAL);
}
- state->compressed_buffer_size = 65536;
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of the of bytes
+ * per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+ state->compressed_buffer_size = bs;
state->compressed = malloc(state->compressed_buffer_size);
if (state->compressed == NULL) {
@@ -386,12 +396,12 @@ archive_compressor_compress_write(struct archive_write_filter *f,
state->checkpoint = state->in_count + CHECK_GAP;
- if (state->in_count <= 0x007fffff)
- ratio = state->in_count * 256 / state->out_count;
- else if ((ratio = state->out_count / 256) == 0)
+ if (state->in_count <= 0x007fffff && state->out_count != 0)
+ ratio = (int)(state->in_count * 256 / state->out_count);
+ else if ((ratio = (int)(state->out_count / 256)) == 0)
ratio = 0x7fffffff;
else
- ratio = state->in_count / ratio;
+ ratio = (int)(state->in_count / ratio);
if (ratio > state->compress_ratio)
state->compress_ratio = ratio;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_grzip.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_grzip.c
new file mode 100644
index 0000000..8dc287e
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_grzip.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include "archive.h"
+#include "archive_write_private.h"
+
+struct write_grzip {
+ struct archive_write_program_data *pdata;
+};
+
+static int archive_write_grzip_open(struct archive_write_filter *);
+static int archive_write_grzip_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_write_grzip_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_write_grzip_close(struct archive_write_filter *);
+static int archive_write_grzip_free(struct archive_write_filter *);
+
+int
+archive_write_add_filter_grzip(struct archive *_a)
+{
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct write_grzip *data;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_grzip");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+
+ f->name = "grzip";
+ f->code = ARCHIVE_FILTER_GRZIP;
+ f->data = data;
+ f->open = archive_write_grzip_open;
+ f->options = archive_write_grzip_options;
+ f->write = archive_write_grzip_write;
+ f->close = archive_write_grzip_close;
+ f->free = archive_write_grzip_free;
+
+ /* Note: This filter always uses an external program, so we
+ * return "warn" to inform of the fact. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external grzip program for grzip compression");
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_grzip_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ (void)f; /* UNUSED */
+ (void)key; /* UNUSED */
+ (void)value; /* UNUSED */
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_grzip_open(struct archive_write_filter *f)
+{
+ struct write_grzip *data = (struct write_grzip *)f->data;
+
+ return __archive_write_program_open(f, data->pdata, "grzip");
+}
+
+static int
+archive_write_grzip_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct write_grzip *data = (struct write_grzip *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_write_grzip_close(struct archive_write_filter *f)
+{
+ struct write_grzip *data = (struct write_grzip *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+static int
+archive_write_grzip_free(struct archive_write_filter *f)
+{
+ struct write_grzip *data = (struct write_grzip *)f->data;
+
+ __archive_write_program_free(data->pdata);
+ free(data);
+ return (ARCHIVE_OK);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c
index d08ee26..db18fd9 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_gzip.c 201
#include "archive.h"
#include "archive_private.h"
+#include "archive_string.h"
#include "archive_write_private.h"
#if ARCHIVE_VERSION_NUMBER < 4000000
@@ -54,24 +55,20 @@ archive_write_set_compression_gzip(struct archive *a)
}
#endif
-#ifndef HAVE_ZLIB_H
-int
-archive_write_add_filter_gzip(struct archive *a)
-{
- archive_set_error(a, ARCHIVE_ERRNO_MISC,
- "gzip compression not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-#else
/* Don't compile this if we don't have zlib. */
struct private_data {
int compression_level;
+ int timestamp;
+#ifdef HAVE_ZLIB_H
z_stream stream;
int64_t total_in;
unsigned char *compressed;
size_t compressed_buffer_size;
unsigned long crc;
+#else
+ struct archive_write_program_data *pdata;
+#endif
};
/*
@@ -88,8 +85,10 @@ static int archive_compressor_gzip_write(struct archive_write_filter *,
const void *, size_t);
static int archive_compressor_gzip_close(struct archive_write_filter *);
static int archive_compressor_gzip_free(struct archive_write_filter *);
+#ifdef HAVE_ZLIB_H
static int drive_compressor(struct archive_write_filter *,
struct private_data *, int finishing);
+#endif
/*
@@ -110,16 +109,72 @@ archive_write_add_filter_gzip(struct archive *_a)
return (ARCHIVE_FATAL);
}
f->data = data;
- data->compression_level = Z_DEFAULT_COMPRESSION;
f->open = &archive_compressor_gzip_open;
f->options = &archive_compressor_gzip_options;
f->close = &archive_compressor_gzip_close;
f->free = &archive_compressor_gzip_free;
- f->code = ARCHIVE_COMPRESSION_GZIP;
+ f->code = ARCHIVE_FILTER_GZIP;
f->name = "gzip";
+#ifdef HAVE_ZLIB_H
+ data->compression_level = Z_DEFAULT_COMPRESSION;
return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(&a->archive, ENOMEM, "Out of memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 0;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Using external gzip program");
+ return (ARCHIVE_WARN);
+#endif
}
+static int
+archive_compressor_gzip_free(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+#ifdef HAVE_ZLIB_H
+ free(data->compressed);
+#else
+ __archive_write_program_free(data->pdata);
+#endif
+ free(data);
+ f->data = NULL;
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Set write options.
+ */
+static int
+archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
+ value[1] != '\0')
+ return (ARCHIVE_WARN);
+ data->compression_level = value[0] - '0';
+ return (ARCHIVE_OK);
+ }
+ if (strcmp(key, "timestamp") == 0) {
+ data->timestamp = (value == NULL)?-1:1;
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+#ifdef HAVE_ZLIB_H
/*
* Setup callback.
*/
@@ -128,14 +183,23 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
int ret;
- time_t t;
ret = __archive_write_open_filter(f->next_filter);
if (ret != ARCHIVE_OK)
return (ret);
if (data->compressed == NULL) {
- data->compressed_buffer_size = 65536;
+ size_t bs = 65536, bpb;
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of
+ * the of bytes per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+ data->compressed_buffer_size = bs;
data->compressed
= (unsigned char *)malloc(data->compressed_buffer_size);
if (data->compressed == NULL) {
@@ -147,18 +211,21 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
data->crc = crc32(0L, NULL, 0);
data->stream.next_out = data->compressed;
- data->stream.avail_out = data->compressed_buffer_size;
+ data->stream.avail_out = (uInt)data->compressed_buffer_size;
/* Prime output buffer with a gzip header. */
- t = time(NULL);
data->compressed[0] = 0x1f; /* GZip signature bytes */
data->compressed[1] = 0x8b;
data->compressed[2] = 0x08; /* "Deflate" compression */
data->compressed[3] = 0; /* No options */
- data->compressed[4] = (t)&0xff; /* Timestamp */
- data->compressed[5] = (t>>8)&0xff;
- data->compressed[6] = (t>>16)&0xff;
- data->compressed[7] = (t>>24)&0xff;
+ if (data->timestamp >= 0) {
+ time_t t = time(NULL);
+ data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */
+ data->compressed[5] = (uint8_t)(t>>8)&0xff;
+ data->compressed[6] = (uint8_t)(t>>16)&0xff;
+ data->compressed[7] = (uint8_t)(t>>24)&0xff;
+ } else
+ memset(&data->compressed[4], 0, 4);
data->compressed[8] = 0; /* No deflate options */
data->compressed[9] = 3; /* OS=Unix */
data->stream.next_out += 10;
@@ -191,8 +258,8 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
"compression library: invalid setup parameter");
break;
case Z_MEM_ERROR:
- archive_set_error(f->archive, ENOMEM, "Internal error initializing "
- "compression library");
+ archive_set_error(f->archive, ENOMEM,
+ "Internal error initializing compression library");
break;
case Z_VERSION_ERROR:
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
@@ -205,25 +272,6 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
}
/*
- * Set write options.
- */
-static int
-archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
- const char *value)
-{
- struct private_data *data = (struct private_data *)f->data;
-
- if (strcmp(key, "compression-level") == 0) {
- if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
- value[1] != '\0')
- return (ARCHIVE_WARN);
- data->compression_level = value[0] - '0';
- return (ARCHIVE_OK);
- }
- return (ARCHIVE_WARN);
-}
-
-/*
* Write data to the compressed stream.
*/
static int
@@ -234,12 +282,12 @@ archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
int ret;
/* Update statistics */
- data->crc = crc32(data->crc, (const Bytef *)buff, length);
+ data->crc = crc32(data->crc, (const Bytef *)buff, (uInt)length);
data->total_in += length;
/* Compress input data to output buffer */
SET_NEXT_IN(data, buff);
- data->stream.avail_in = length;
+ data->stream.avail_in = (uInt)length;
if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK)
return (ret);
@@ -266,14 +314,14 @@ archive_compressor_gzip_close(struct archive_write_filter *f)
}
if (ret == ARCHIVE_OK) {
/* Build and write out 8-byte trailer. */
- trailer[0] = (data->crc)&0xff;
- trailer[1] = (data->crc >> 8)&0xff;
- trailer[2] = (data->crc >> 16)&0xff;
- trailer[3] = (data->crc >> 24)&0xff;
- trailer[4] = (data->total_in)&0xff;
- trailer[5] = (data->total_in >> 8)&0xff;
- trailer[6] = (data->total_in >> 16)&0xff;
- trailer[7] = (data->total_in >> 24)&0xff;
+ trailer[0] = (uint8_t)(data->crc)&0xff;
+ trailer[1] = (uint8_t)(data->crc >> 8)&0xff;
+ trailer[2] = (uint8_t)(data->crc >> 16)&0xff;
+ trailer[3] = (uint8_t)(data->crc >> 24)&0xff;
+ trailer[4] = (uint8_t)(data->total_in)&0xff;
+ trailer[5] = (uint8_t)(data->total_in >> 8)&0xff;
+ trailer[6] = (uint8_t)(data->total_in >> 16)&0xff;
+ trailer[7] = (uint8_t)(data->total_in >> 24)&0xff;
ret = __archive_write_filter(f->next_filter, trailer, 8);
}
@@ -289,16 +337,6 @@ archive_compressor_gzip_close(struct archive_write_filter *f)
return (r1 < ret ? r1 : ret);
}
-static int
-archive_compressor_gzip_free(struct archive_write_filter *f)
-{
- struct private_data *data = (struct private_data *)f->data;
- free(data->compressed);
- free(data);
- f->data = NULL;
- return (ARCHIVE_OK);
-}
-
/*
* Utility function to push input data through compressor,
* writing full output blocks as necessary.
@@ -320,7 +358,8 @@ drive_compressor(struct archive_write_filter *f,
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
data->stream.next_out = data->compressed;
- data->stream.avail_out = data->compressed_buffer_size;
+ data->stream.avail_out =
+ (uInt)data->compressed_buffer_size;
}
/* If there's nothing to do, we're done. */
@@ -353,4 +392,51 @@ drive_compressor(struct archive_write_filter *f,
}
}
+#else /* HAVE_ZLIB_H */
+
+static int
+archive_compressor_gzip_open(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "gzip");
+
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strcat(&as, " -");
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+ if (data->timestamp < 0)
+ /* Do not save timestamp. */
+ archive_strcat(&as, " -n");
+ else if (data->timestamp > 0)
+ /* Save timestamp. */
+ archive_strcat(&as, " -N");
+
+ f->write = archive_compressor_gzip_write;
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_compressor_gzip_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_gzip_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
#endif /* HAVE_ZLIB_H */
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lrzip.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lrzip.c
new file mode 100644
index 0000000..85fdf6a
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lrzip.c
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_string.h"
+#include "archive_write_private.h"
+
+struct write_lrzip {
+ struct archive_write_program_data *pdata;
+ int compression_level;
+ enum { lzma = 0, bzip2, gzip, lzo, zpaq } compression;
+};
+
+static int archive_write_lrzip_open(struct archive_write_filter *);
+static int archive_write_lrzip_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_write_lrzip_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_write_lrzip_close(struct archive_write_filter *);
+static int archive_write_lrzip_free(struct archive_write_filter *);
+
+int
+archive_write_add_filter_lrzip(struct archive *_a)
+{
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct write_lrzip *data;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_lrzip");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+
+ f->name = "lrzip";
+ f->code = ARCHIVE_FILTER_LRZIP;
+ f->data = data;
+ f->open = archive_write_lrzip_open;
+ f->options = archive_write_lrzip_options;
+ f->write = archive_write_lrzip_write;
+ f->close = archive_write_lrzip_close;
+ f->free = archive_write_lrzip_free;
+
+ /* Note: This filter always uses an external program, so we
+ * return "warn" to inform of the fact. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external lrzip program for lrzip compression");
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_lrzip_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+
+ if (strcmp(key, "compression") == 0) {
+ if (value == NULL)
+ return (ARCHIVE_WARN);
+ else if (strcmp(value, "bzip2") == 0)
+ data->compression = bzip2;
+ else if (strcmp(value, "gzip") == 0)
+ data->compression = gzip;
+ else if (strcmp(value, "lzo") == 0)
+ data->compression = lzo;
+ else if (strcmp(value, "zpaq") == 0)
+ data->compression = zpaq;
+ else
+ return (ARCHIVE_WARN);
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "compression-level") == 0) {
+ if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
+ value[1] != '\0')
+ return (ARCHIVE_WARN);
+ data->compression_level = value[0] - '0';
+ return (ARCHIVE_OK);
+ }
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_lrzip_open(struct archive_write_filter *f)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "lrzip -q");
+
+ /* Specify compression type. */
+ switch (data->compression) {
+ case lzma:/* default compression */
+ break;
+ case bzip2:
+ archive_strcat(&as, " -b");
+ break;
+ case gzip:
+ archive_strcat(&as, " -g");
+ break;
+ case lzo:
+ archive_strcat(&as, " -l");
+ break;
+ case zpaq:
+ archive_strcat(&as, " -z");
+ break;
+ }
+
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strcat(&as, " -L ");
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_write_lrzip_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_write_lrzip_close(struct archive_write_filter *f)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+static int
+archive_write_lrzip_free(struct archive_write_filter *f)
+{
+ struct write_lrzip *data = (struct write_lrzip *)f->data;
+
+ __archive_write_program_free(data->pdata);
+ free(data);
+ return (ARCHIVE_OK);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lzop.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lzop.c
new file mode 100644
index 0000000..088ecea
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lzop.c
@@ -0,0 +1,486 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+//#undef HAVE_LZO_LZOCONF_H
+//#undef HAVE_LZO_LZO1X_H
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <time.h>
+#ifdef HAVE_LZO_LZOCONF_H
+#include <lzo/lzoconf.h>
+#endif
+#ifdef HAVE_LZO_LZO1X_H
+#include <lzo/lzo1x.h>
+#endif
+
+#include "archive.h"
+#include "archive_string.h"
+#include "archive_endian.h"
+#include "archive_write_private.h"
+
+enum lzo_method {
+ METHOD_LZO1X_1 = 1,
+ METHOD_LZO1X_1_15 = 2,
+ METHOD_LZO1X_999 = 3
+};
+struct write_lzop {
+ int compression_level;
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+ unsigned char *uncompressed;
+ size_t uncompressed_buffer_size;
+ size_t uncompressed_avail_bytes;
+ unsigned char *compressed;
+ size_t compressed_buffer_size;
+ enum lzo_method method;
+ unsigned char level;
+ lzo_voidp work_buffer;
+ lzo_uint32 work_buffer_size;
+ char header_written;
+#else
+ struct archive_write_program_data *pdata;
+#endif
+};
+
+static int archive_write_lzop_open(struct archive_write_filter *);
+static int archive_write_lzop_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_write_lzop_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_write_lzop_close(struct archive_write_filter *);
+static int archive_write_lzop_free(struct archive_write_filter *);
+
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+/* Maximum block size. */
+#define BLOCK_SIZE (256 * 1024)
+/* Block infomation is composed of uncompressed size(4 bytes),
+ * compressed size(4 bytes) and the checksum of uncompressed data(4 bytes)
+ * in this lzop writer. */
+#define BLOCK_INfO_SIZE 12
+
+#define HEADER_VERSION 9
+#define HEADER_LIBVERSION 11
+#define HEADER_METHOD 15
+#define HEADER_LEVEL 16
+#define HEADER_MTIME_LOW 25
+#define HEADER_MTIME_HIGH 29
+#define HEADER_H_CHECKSUM 34
+
+/*
+ * Header template.
+ */
+static const unsigned char header[] = {
+ /* LZOP Magic code 9 bytes */
+ 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a,
+ /* LZOP utility version(fake data) 2 bytes */
+ 0x10, 0x30,
+ /* LZO library version 2 bytes */
+ 0x09, 0x40,
+ /* Minimum required LZO library version 2 bytes */
+ 0x09, 0x40,
+ /* Method */
+ 1,
+ /* Level */
+ 5,
+ /* Flags 4 bytes
+ * -OS Unix
+ * -Stdout
+ * -Stdin
+ * -Adler32 used for uncompressed data 4 bytes */
+ 0x03, 0x00, 0x00, 0x0d,
+ /* Mode (AE_IFREG | 0644) 4 bytes */
+ 0x00, 0x00, 0x81, 0xa4,
+ /* Mtime low 4 bytes */
+ 0x00, 0x00, 0x00, 0x00,
+ /* Mtime high 4 bytes */
+ 0x00, 0x00, 0x00, 0x00,
+ /* Filename length */
+ 0x00,
+ /* Header checksum 4 bytes */
+ 0x00, 0x00, 0x00, 0x00,
+};
+#endif
+
+int
+archive_write_add_filter_lzop(struct archive *_a)
+{
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct write_lzop *data;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_lzop");
+
+ data = calloc(1, sizeof(*data));
+ if (data == NULL) {
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+
+ f->name = "lzop";
+ f->code = ARCHIVE_FILTER_LZOP;
+ f->data = data;
+ f->open = archive_write_lzop_open;
+ f->options = archive_write_lzop_options;
+ f->write = archive_write_lzop_write;
+ f->close = archive_write_lzop_close;
+ f->free = archive_write_lzop_free;
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+ if (lzo_init() != LZO_E_OK) {
+ free(data);
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "lzo_init(type check) failed");
+ return (ARCHIVE_FATAL);
+ }
+ if (lzo_version() < 0x940) {
+ free(data);
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "liblzo library is too old(%s < 0.940)",
+ lzo_version_string());
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 5;
+ return (ARCHIVE_OK);
+#else
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL) {
+ free(data);
+ archive_set_error(_a, ENOMEM, "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ data->compression_level = 0;
+ /* Note: We return "warn" to inform of using an external lzop
+ * program. */
+ archive_set_error(_a, ARCHIVE_ERRNO_MISC,
+ "Using external lzop program for lzop compression");
+ return (ARCHIVE_WARN);
+#endif
+}
+
+static int
+archive_write_lzop_free(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+ free(data->uncompressed);
+ free(data->compressed);
+ free(data->work_buffer);
+#else
+ __archive_write_program_free(data->pdata);
+#endif
+ free(data);
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_lzop_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+
+ if (strcmp(key, "compression-level") == 0) {
+ if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
+ value[1] != '\0')
+ return (ARCHIVE_WARN);
+ data->compression_level = value[0] - '0';
+ return (ARCHIVE_OK);
+ }
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
+static int
+archive_write_lzop_open(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ int ret;
+
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ switch (data->compression_level) {
+ case 1:
+ data->method = METHOD_LZO1X_1_15; data->level = 1; break;
+ default:
+ case 2: case 3: case 4: case 5: case 6:
+ data->method = METHOD_LZO1X_1; data->level = 5; break;
+ case 7:
+ data->method = METHOD_LZO1X_999; data->level = 7; break;
+ case 8:
+ data->method = METHOD_LZO1X_999; data->level = 8; break;
+ case 9:
+ data->method = METHOD_LZO1X_999; data->level = 9; break;
+ }
+ switch (data->method) {
+ case METHOD_LZO1X_1:
+ data->work_buffer_size = LZO1X_1_MEM_COMPRESS; break;
+ case METHOD_LZO1X_1_15:
+ data->work_buffer_size = LZO1X_1_15_MEM_COMPRESS; break;
+ case METHOD_LZO1X_999:
+ data->work_buffer_size = LZO1X_999_MEM_COMPRESS; break;
+ }
+ if (data->work_buffer == NULL) {
+ data->work_buffer = (lzo_voidp)malloc(data->work_buffer_size);
+ if (data->work_buffer == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ if (data->compressed == NULL) {
+ data->compressed_buffer_size = sizeof(header) +
+ BLOCK_SIZE + (BLOCK_SIZE >> 4) + 64 + 3;
+ data->compressed = (unsigned char *)
+ malloc(data->compressed_buffer_size);
+ if (data->compressed == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ if (data->uncompressed == NULL) {
+ data->uncompressed_buffer_size = BLOCK_SIZE;
+ data->uncompressed = (unsigned char *)
+ malloc(data->uncompressed_buffer_size);
+ if (data->uncompressed == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for compression buffer");
+ return (ARCHIVE_FATAL);
+ }
+ data->uncompressed_avail_bytes = BLOCK_SIZE;
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+make_header(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ int64_t t;
+ uint32_t checksum;
+
+ memcpy(data->compressed, header, sizeof(header));
+ /* Overwrite library version. */
+ data->compressed[HEADER_LIBVERSION] = (unsigned char )
+ (lzo_version() >> 8) & 0xff;
+ data->compressed[HEADER_LIBVERSION + 1] = (unsigned char )
+ lzo_version() & 0xff;
+ /* Overwrite method and level. */
+ data->compressed[HEADER_METHOD] = (unsigned char)data->method;
+ data->compressed[HEADER_LEVEL] = data->level;
+ /* Overwrite mtime with current time. */
+ t = (int64_t)time(NULL);
+ archive_be32enc(&data->compressed[HEADER_MTIME_LOW],
+ (uint32_t)(t & 0xffffffff));
+ archive_be32enc(&data->compressed[HEADER_MTIME_HIGH],
+ (uint32_t)((t >> 32) & 0xffffffff));
+ /* Overwrite header checksum with calculated value. */
+ checksum = lzo_adler32(1, data->compressed + HEADER_VERSION,
+ (lzo_uint)(HEADER_H_CHECKSUM - HEADER_VERSION));
+ archive_be32enc(&data->compressed[HEADER_H_CHECKSUM], checksum);
+ return (sizeof(header));
+}
+
+static int
+drive_compressor(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ unsigned char *p;
+ const int block_info_bytes = 12;
+ int header_bytes, r;
+ lzo_uint usize, csize;
+ uint32_t checksum;
+
+ if (!data->header_written) {
+ header_bytes = make_header(f);
+ data->header_written = 1;
+ } else
+ header_bytes = 0;
+ p = data->compressed;
+
+ usize = (lzo_uint)
+ (data->uncompressed_buffer_size - data->uncompressed_avail_bytes);
+ csize = 0;
+ switch (data->method) {
+ default:
+ case METHOD_LZO1X_1:
+ r = lzo1x_1_compress(data->uncompressed, usize,
+ p + header_bytes + block_info_bytes, &csize,
+ data->work_buffer);
+ break;
+ case METHOD_LZO1X_1_15:
+ r = lzo1x_1_15_compress(data->uncompressed, usize,
+ p + header_bytes + block_info_bytes, &csize,
+ data->work_buffer);
+ break;
+ case METHOD_LZO1X_999:
+ r = lzo1x_999_compress_level(data->uncompressed, usize,
+ p + header_bytes + block_info_bytes, &csize,
+ data->work_buffer, NULL, 0, 0, data->level);
+ break;
+ }
+ if (r != LZO_E_OK) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "Lzop compression failed: returned status %d", r);
+ return (ARCHIVE_FATAL);
+ }
+
+ /* Store uncompressed size. */
+ archive_be32enc(p + header_bytes, (uint32_t)usize);
+ /* Store the checksum of the uncompressed data. */
+ checksum = lzo_adler32(1, data->uncompressed, usize);
+ archive_be32enc(p + header_bytes + 8, checksum);
+
+ if (csize < usize) {
+ /* Store compressed size. */
+ archive_be32enc(p + header_bytes + 4, (uint32_t)csize);
+ r = __archive_write_filter(f->next_filter, data->compressed,
+ header_bytes + block_info_bytes + csize);
+ } else {
+ /*
+ * This case, we output uncompressed data instead.
+ */
+ /* Store uncompressed size as compressed size. */
+ archive_be32enc(p + header_bytes + 4, (uint32_t)usize);
+ r = __archive_write_filter(f->next_filter, data->compressed,
+ header_bytes + block_info_bytes);
+ if (r != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ r = __archive_write_filter(f->next_filter, data->uncompressed,
+ usize);
+ }
+
+ if (r != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_lzop_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ const char *p = buff;
+ int r;
+
+ do {
+ if (data->uncompressed_avail_bytes > length) {
+ memcpy(data->uncompressed
+ + data->uncompressed_buffer_size
+ - data->uncompressed_avail_bytes,
+ p, length);
+ data->uncompressed_avail_bytes -= length;
+ return (ARCHIVE_OK);
+ }
+
+ memcpy(data->uncompressed + data->uncompressed_buffer_size
+ - data->uncompressed_avail_bytes,
+ p, data->uncompressed_avail_bytes);
+ length -= data->uncompressed_avail_bytes;
+ p += data->uncompressed_avail_bytes;
+ data->uncompressed_avail_bytes = 0;
+
+ r = drive_compressor(f);
+ if (r != ARCHIVE_OK) return (r);
+ data->uncompressed_avail_bytes = BLOCK_SIZE;
+ } while (length);
+
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_lzop_close(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ const uint32_t endmark = 0;
+ int r;
+
+ if (data->uncompressed_avail_bytes < BLOCK_SIZE) {
+ /* Compress and output remaining data. */
+ r = drive_compressor(f);
+ if (r != ARCHIVE_OK)
+ return (r);
+ }
+ /* Write a zero uncompressed size as the end mark of the series of
+ * compressed block. */
+ r = __archive_write_filter(f->next_filter, &endmark, sizeof(endmark));
+ if (r != ARCHIVE_OK)
+ return (r);
+ return (__archive_write_close_filter(f->next_filter));
+}
+
+#else
+static int
+archive_write_lzop_open(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+ struct archive_string as;
+ int r;
+
+ archive_string_init(&as);
+ archive_strcpy(&as, "lzop");
+ /* Specify compression level. */
+ if (data->compression_level > 0) {
+ archive_strappend_char(&as, ' ');
+ archive_strappend_char(&as, '-');
+ archive_strappend_char(&as, '0' + data->compression_level);
+ }
+
+ r = __archive_write_program_open(f, data->pdata, as.s);
+ archive_string_free(&as);
+ return (r);
+}
+
+static int
+archive_write_lzop_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_write_lzop_close(struct archive_write_filter *f)
+{
+ struct write_lzop *data = (struct write_lzop *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
index 3dcc9df..fc232da 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Joerg Sonnenberger
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +45,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_program.c
#include "archive.h"
#include "archive_private.h"
+#include "archive_string.h"
#include "archive_write_private.h"
+#include "filter_fork.h"
#if ARCHIVE_VERSION_NUMBER < 4000000
int
@@ -55,36 +58,24 @@ archive_write_set_compression_program(struct archive *a, const char *cmd)
}
#endif
-/* This capability is only available on POSIX systems. */
-#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
- !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
-
-/*
- * On non-Posix systems, allow the program to build, but choke if
- * this function is actually invoked.
- */
-int
-archive_write_add_filter_program(struct archive *_a, const char *cmd)
-{
- archive_set_error(_a, -1,
- "External compression programs not supported on this platform");
- return (ARCHIVE_FATAL);
-}
-
+struct archive_write_program_data {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ HANDLE child;
#else
-
-#include "filter_fork.h"
-
-struct private_data {
- char *cmd;
- char *description;
pid_t child;
+#endif
int child_stdin, child_stdout;
char *child_buf;
size_t child_buf_len, child_buf_avail;
};
+struct private_data {
+ struct archive_write_program_data *pdata;
+ struct archive_string description;
+ char *cmd;
+};
+
static int archive_compressor_program_open(struct archive_write_filter *);
static int archive_compressor_program_write(struct archive_write_filter *,
const void *, size_t);
@@ -99,35 +90,125 @@ int
archive_write_add_filter_program(struct archive *_a, const char *cmd)
{
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
- struct archive_write *a = (struct archive_write *)_a;
struct private_data *data;
static const char *prefix = "Program: ";
- archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_program");
- data = calloc(1, sizeof(*data));
- if (data == NULL) {
- archive_set_error(&a->archive, ENOMEM, "Out of memory");
- return (ARCHIVE_FATAL);
- }
+
+ f->data = calloc(1, sizeof(*data));
+ if (f->data == NULL)
+ goto memerr;
+ data = (struct private_data *)f->data;
+
data->cmd = strdup(cmd);
- data->description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
- strcpy(data->description, prefix);
- strcat(data->description, cmd);
-
- f->name = data->description;
- f->data = data;
- f->open = &archive_compressor_program_open;
- f->code = ARCHIVE_COMPRESSION_PROGRAM;
+ if (data->cmd == NULL)
+ goto memerr;
+
+ data->pdata = __archive_write_program_allocate();
+ if (data->pdata == NULL)
+ goto memerr;
+
+ /* Make up a description string. */
+ if (archive_string_ensure(&data->description,
+ strlen(prefix) + strlen(cmd) + 1) == NULL)
+ goto memerr;
+ archive_strcpy(&data->description, prefix);
+ archive_strcat(&data->description, cmd);
+
+ f->name = data->description.s;
+ f->code = ARCHIVE_FILTER_PROGRAM;
+ f->open = archive_compressor_program_open;
+ f->write = archive_compressor_program_write;
+ f->close = archive_compressor_program_close;
+ f->free = archive_compressor_program_free;
return (ARCHIVE_OK);
+memerr:
+ archive_compressor_program_free(f);
+ archive_set_error(_a, ENOMEM,
+ "Can't allocate memory for filter program");
+ return (ARCHIVE_FATAL);
}
-/*
- * Setup callback.
- */
static int
archive_compressor_program_open(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_open(f, data->pdata, data->cmd);
+}
+
+static int
+archive_compressor_program_write(struct archive_write_filter *f,
+ const void *buff, size_t length)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_write(f, data->pdata, buff, length);
+}
+
+static int
+archive_compressor_program_close(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ return __archive_write_program_close(f, data->pdata);
+}
+
+static int
+archive_compressor_program_free(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
+
+ if (data) {
+ free(data->cmd);
+ archive_string_free(&data->description);
+ __archive_write_program_free(data->pdata);
+ free(data);
+ f->data = NULL;
+ }
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Allocate resources for executing an external program.
+ */
+struct archive_write_program_data *
+__archive_write_program_allocate(void)
+{
+ struct archive_write_program_data *data;
+
+ data = calloc(1, sizeof(struct archive_write_program_data));
+ if (data == NULL)
+ return (data);
+ data->child_stdin = -1;
+ data->child_stdout = -1;
+ return (data);
+}
+
+/*
+ * Release the resources.
+ */
+int
+__archive_write_program_free(struct archive_write_program_data *data)
+{
+
+ if (data) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ if (data->child)
+ CloseHandle(data->child);
+#endif
+ free(data->child_buf);
+ free(data);
+ }
+ return (ARCHIVE_OK);
+}
+
+int
+__archive_write_program_open(struct archive_write_filter *f,
+ struct archive_write_program_data *data, const char *cmd)
+{
+ pid_t child;
int ret;
ret = __archive_write_open_filter(f->next_filter);
@@ -146,23 +227,34 @@ archive_compressor_program_open(struct archive_write_filter *f)
}
}
- if ((data->child = __archive_create_child(data->cmd,
- &data->child_stdin, &data->child_stdout)) == -1) {
+ child = __archive_create_child(cmd, &data->child_stdin,
+ &data->child_stdout);
+ if (child == -1) {
archive_set_error(f->archive, EINVAL,
"Can't initialise filter");
return (ARCHIVE_FATAL);
}
-
- f->write = archive_compressor_program_write;
- f->close = archive_compressor_program_close;
- f->free = archive_compressor_program_free;
- return (0);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ data->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child);
+ if (data->child == NULL) {
+ close(data->child_stdin);
+ data->child_stdin = -1;
+ close(data->child_stdout);
+ data->child_stdout = -1;
+ archive_set_error(f->archive, EINVAL,
+ "Can't initialise filter");
+ return (ARCHIVE_FATAL);
+ }
+#else
+ data->child = child;
+#endif
+ return (ARCHIVE_OK);
}
static ssize_t
-child_write(struct archive_write_filter *f, const char *buf, size_t buf_len)
+child_write(struct archive_write_filter *f,
+ struct archive_write_program_data *data, const char *buf, size_t buf_len)
{
- struct private_data *data = f->data;
ssize_t ret;
if (data->child_stdin == -1)
@@ -171,75 +263,75 @@ child_write(struct archive_write_filter *f, const char *buf, size_t buf_len)
if (buf_len == 0)
return (-1);
-restart_write:
- do {
- ret = write(data->child_stdin, buf, buf_len);
- } while (ret == -1 && errno == EINTR);
-
- if (ret > 0)
- return (ret);
- if (ret == 0) {
- close(data->child_stdin);
- data->child_stdin = -1;
- fcntl(data->child_stdout, F_SETFL, 0);
- return (0);
- }
- if (ret == -1 && errno != EAGAIN)
- return (-1);
-
- if (data->child_stdout == -1) {
- fcntl(data->child_stdin, F_SETFL, 0);
- __archive_check_child(data->child_stdin, data->child_stdout);
- goto restart_write;
- }
-
- do {
- ret = read(data->child_stdout,
- data->child_buf + data->child_buf_avail,
- data->child_buf_len - data->child_buf_avail);
- } while (ret == -1 && errno == EINTR);
+ for (;;) {
+ do {
+ ret = write(data->child_stdin, buf, buf_len);
+ } while (ret == -1 && errno == EINTR);
+
+ if (ret > 0)
+ return (ret);
+ if (ret == 0) {
+ close(data->child_stdin);
+ data->child_stdin = -1;
+ fcntl(data->child_stdout, F_SETFL, 0);
+ return (0);
+ }
+ if (ret == -1 && errno != EAGAIN)
+ return (-1);
+
+ if (data->child_stdout == -1) {
+ fcntl(data->child_stdin, F_SETFL, 0);
+ __archive_check_child(data->child_stdin,
+ data->child_stdout);
+ continue;
+ }
- if (ret == 0 || (ret == -1 && errno == EPIPE)) {
- close(data->child_stdout);
- data->child_stdout = -1;
- fcntl(data->child_stdin, F_SETFL, 0);
- goto restart_write;
- }
- if (ret == -1 && errno == EAGAIN) {
- __archive_check_child(data->child_stdin, data->child_stdout);
- goto restart_write;
- }
- if (ret == -1)
- return (-1);
+ do {
+ ret = read(data->child_stdout,
+ data->child_buf + data->child_buf_avail,
+ data->child_buf_len - data->child_buf_avail);
+ } while (ret == -1 && errno == EINTR);
- data->child_buf_avail += ret;
+ if (ret == 0 || (ret == -1 && errno == EPIPE)) {
+ close(data->child_stdout);
+ data->child_stdout = -1;
+ fcntl(data->child_stdin, F_SETFL, 0);
+ continue;
+ }
+ if (ret == -1 && errno == EAGAIN) {
+ __archive_check_child(data->child_stdin,
+ data->child_stdout);
+ continue;
+ }
+ if (ret == -1)
+ return (-1);
- ret = __archive_write_filter(f->next_filter,
- data->child_buf, data->child_buf_avail);
- if (ret <= 0)
- return (-1);
+ data->child_buf_avail += ret;
- if ((size_t)ret < data->child_buf_avail) {
- memmove(data->child_buf, data->child_buf + ret,
- data->child_buf_avail - ret);
+ ret = __archive_write_filter(f->next_filter,
+ data->child_buf, data->child_buf_avail);
+ if (ret != ARCHIVE_OK)
+ return (-1);
+ data->child_buf_avail = 0;
}
- data->child_buf_avail -= ret;
- goto restart_write;
}
/*
- * Write data to the compressed stream.
+ * Write data to the filter stream.
*/
-static int
-archive_compressor_program_write(struct archive_write_filter *f,
- const void *buff, size_t length)
+int
+__archive_write_program_write(struct archive_write_filter *f,
+ struct archive_write_program_data *data, const void *buff, size_t length)
{
ssize_t ret;
const char *buf;
+ if (data->child == 0)
+ return (ARCHIVE_OK);
+
buf = buff;
while (length > 0) {
- ret = child_write(f, buf, length);
+ ret = child_write(f, data, buf, length);
if (ret == -1 || ret == 0) {
archive_set_error(f->archive, EIO,
"Can't write to filter");
@@ -251,17 +343,19 @@ archive_compressor_program_write(struct archive_write_filter *f,
return (ARCHIVE_OK);
}
-
/*
- * Finish the compression...
+ * Finish the filtering...
*/
-static int
-archive_compressor_program_close(struct archive_write_filter *f)
+int
+__archive_write_program_close(struct archive_write_filter *f,
+ struct archive_write_program_data *data)
{
- struct private_data *data = (struct private_data *)f->data;
int ret, r1, status;
ssize_t bytes_read;
+ if (data->child == 0)
+ return __archive_write_close_filter(f->next_filter);
+
ret = 0;
close(data->child_stdin);
data->child_stdin = -1;
@@ -302,6 +396,10 @@ cleanup:
close(data->child_stdout);
while (waitpid(data->child, &status, 0) == -1 && errno == EINTR)
continue;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ CloseHandle(data->child);
+#endif
+ data->child = 0;
if (status != 0) {
archive_set_error(f->archive, EIO,
@@ -312,16 +410,3 @@ cleanup:
return (r1 < ret ? r1 : ret);
}
-static int
-archive_compressor_program_free(struct archive_write_filter *f)
-{
- struct private_data *data = (struct private_data *)f->data;
- free(data->cmd);
- free(data->description);
- free(data->child_buf);
- free(data);
- f->data = NULL;
- return (ARCHIVE_OK);
-}
-
-#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_uuencode.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_uuencode.c
new file mode 100644
index 0000000..23d9c15
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_uuencode.c
@@ -0,0 +1,305 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+
+__FBSDID("$FreeBSD$");
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_private.h"
+#include "archive_string.h"
+#include "archive_write_private.h"
+
+#define LBYTES 45
+
+struct private_uuencode {
+ int mode;
+ struct archive_string name;
+ struct archive_string encoded_buff;
+ size_t bs;
+ size_t hold_len;
+ unsigned char hold[LBYTES];
+};
+
+static int archive_filter_uuencode_options(struct archive_write_filter *,
+ const char *, const char *);
+static int archive_filter_uuencode_open(struct archive_write_filter *);
+static int archive_filter_uuencode_write(struct archive_write_filter *,
+ const void *, size_t);
+static int archive_filter_uuencode_close(struct archive_write_filter *);
+static int archive_filter_uuencode_free(struct archive_write_filter *);
+static void uu_encode(struct archive_string *, const unsigned char *, size_t);
+static int64_t atol8(const char *, size_t);
+
+/*
+ * Add a compress filter to this write handle.
+ */
+int
+archive_write_add_filter_uuencode(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct archive_write_filter *f = __archive_write_allocate_filter(_a);
+ struct private_uuencode *state;
+
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_add_filter_uu");
+
+ state = (struct private_uuencode *)calloc(1, sizeof(*state));
+ if (state == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for uuencode filter");
+ return (ARCHIVE_FATAL);
+ }
+ archive_strcpy(&state->name, "-");
+ state->mode = 0644;
+
+ f->data = state;
+ f->name = "uuencode";
+ f->code = ARCHIVE_FILTER_UU;
+ f->open = archive_filter_uuencode_open;
+ f->options = archive_filter_uuencode_options;
+ f->write = archive_filter_uuencode_write;
+ f->close = archive_filter_uuencode_close;
+ f->free = archive_filter_uuencode_free;
+
+ return (ARCHIVE_OK);
+}
+
+/*
+ * Set write options.
+ */
+static int
+archive_filter_uuencode_options(struct archive_write_filter *f, const char *key,
+ const char *value)
+{
+ struct private_uuencode *state = (struct private_uuencode *)f->data;
+
+ if (strcmp(key, "mode") == 0) {
+ if (value == NULL) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "mode option requires octal digits");
+ return (ARCHIVE_FAILED);
+ }
+ state->mode = (int)atol8(value, strlen(value)) & 0777;
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "name") == 0) {
+ if (value == NULL) {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "name option requires a string");
+ return (ARCHIVE_FAILED);
+ }
+ archive_strcpy(&state->name, value);
+ return (ARCHIVE_OK);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Setup callback.
+ */
+static int
+archive_filter_uuencode_open(struct archive_write_filter *f)
+{
+ struct private_uuencode *state = (struct private_uuencode *)f->data;
+ size_t bs = 65536, bpb;
+ int ret;
+
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of the of bytes
+ * per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+
+ state->bs = bs;
+ if (archive_string_ensure(&state->encoded_buff, bs + 512) == NULL) {
+ archive_set_error(f->archive, ENOMEM,
+ "Can't allocate data for uuencode buffer");
+ return (ARCHIVE_FATAL);
+ }
+
+ archive_string_sprintf(&state->encoded_buff, "begin %o %s\n",
+ state->mode, state->name.s);
+
+ f->data = state;
+ return (0);
+}
+
+static void
+uu_encode(struct archive_string *as, const unsigned char *p, size_t len)
+{
+ int c;
+
+ c = (int)len;
+ archive_strappend_char(as, c?c + 0x20:'`');
+ for (; len >= 3; p += 3, len -= 3) {
+ c = p[0] >> 2;
+ archive_strappend_char(as, c?c + 0x20:'`');
+ c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
+ archive_strappend_char(as, c?c + 0x20:'`');
+ c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
+ archive_strappend_char(as, c?c + 0x20:'`');
+ c = p[2] & 0x3f;
+ archive_strappend_char(as, c?c + 0x20:'`');
+ }
+ if (len > 0) {
+ c = p[0] >> 2;
+ archive_strappend_char(as, c?c + 0x20:'`');
+ c = (p[0] & 0x03) << 4;
+ if (len == 1) {
+ archive_strappend_char(as, c?c + 0x20:'`');
+ archive_strappend_char(as, '`');
+ archive_strappend_char(as, '`');
+ } else {
+ c |= (p[1] & 0xf0) >> 4;
+ archive_strappend_char(as, c?c + 0x20:'`');
+ c = (p[1] & 0x0f) << 2;
+ archive_strappend_char(as, c?c + 0x20:'`');
+ archive_strappend_char(as, '`');
+ }
+ }
+ archive_strappend_char(as, '\n');
+}
+
+/*
+ * Write data to the encoded stream.
+ */
+static int
+archive_filter_uuencode_write(struct archive_write_filter *f, const void *buff,
+ size_t length)
+{
+ struct private_uuencode *state = (struct private_uuencode *)f->data;
+ const unsigned char *p = buff;
+ int ret = ARCHIVE_OK;
+
+ if (length == 0)
+ return (ret);
+
+ if (state->hold_len) {
+ while (state->hold_len < LBYTES && length > 0) {
+ state->hold[state->hold_len++] = *p++;
+ length--;
+ }
+ if (state->hold_len < LBYTES)
+ return (ret);
+ uu_encode(&state->encoded_buff, state->hold, LBYTES);
+ state->hold_len = 0;
+ }
+
+ for (; length >= LBYTES; length -= LBYTES, p += LBYTES)
+ uu_encode(&state->encoded_buff, p, LBYTES);
+
+ /* Save remaining bytes. */
+ if (length > 0) {
+ memcpy(state->hold, p, length);
+ state->hold_len = length;
+ }
+ while (archive_strlen(&state->encoded_buff) >= state->bs) {
+ ret = __archive_write_filter(f->next_filter,
+ state->encoded_buff.s, state->bs);
+ memmove(state->encoded_buff.s,
+ state->encoded_buff.s + state->bs,
+ state->encoded_buff.length - state->bs);
+ state->encoded_buff.length -= state->bs;
+ }
+
+ return (ret);
+}
+
+
+/*
+ * Finish the compression...
+ */
+static int
+archive_filter_uuencode_close(struct archive_write_filter *f)
+{
+ struct private_uuencode *state = (struct private_uuencode *)f->data;
+ int ret, ret2;
+
+ /* Flush remaining bytes. */
+ if (state->hold_len != 0)
+ uu_encode(&state->encoded_buff, state->hold, state->hold_len);
+ archive_string_sprintf(&state->encoded_buff, "`\nend\n");
+ /* Write the last block */
+ archive_write_set_bytes_in_last_block(f->archive, 1);
+ ret = __archive_write_filter(f->next_filter,
+ state->encoded_buff.s, archive_strlen(&state->encoded_buff));
+ ret2 = __archive_write_close_filter(f->next_filter);
+ if (ret > ret2)
+ ret = ret2;
+ return (ret);
+}
+
+static int
+archive_filter_uuencode_free(struct archive_write_filter *f)
+{
+ struct private_uuencode *state = (struct private_uuencode *)f->data;
+
+ archive_string_free(&state->name);
+ archive_string_free(&state->encoded_buff);
+ free(state);
+ return (ARCHIVE_OK);
+}
+
+static int64_t
+atol8(const char *p, size_t char_cnt)
+{
+ int64_t l;
+ int digit;
+
+ l = 0;
+ while (char_cnt-- > 0) {
+ if (*p >= '0' && *p <= '7')
+ digit = *p - '0';
+ else
+ break;
+ p++;
+ l <<= 3;
+ l |= digit;
+ }
+ return (l);
+}
+
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
index b067752..fa73311 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 2009,2010 Michihiro NAKAJIMA
* Copyright (c) 2003-2010 Tim Kientzle
+ * Copyright (c) 2009-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -172,7 +172,7 @@ archive_write_add_filter_xz(struct archive *_a)
f = __archive_write_allocate_filter(_a);
r = common_setup(f);
if (r == ARCHIVE_OK) {
- f->code = ARCHIVE_COMPRESSION_XZ;
+ f->code = ARCHIVE_FILTER_XZ;
f->name = "xz";
}
return (r);
@@ -192,7 +192,7 @@ archive_write_add_filter_lzma(struct archive *_a)
f = __archive_write_allocate_filter(_a);
r = common_setup(f);
if (r == ARCHIVE_OK) {
- f->code = ARCHIVE_COMPRESSION_LZMA;
+ f->code = ARCHIVE_FILTER_LZMA;
f->name = "lzma";
}
return (r);
@@ -209,7 +209,7 @@ archive_write_add_filter_lzip(struct archive *_a)
f = __archive_write_allocate_filter(_a);
r = common_setup(f);
if (r == ARCHIVE_OK) {
- f->code = ARCHIVE_COMPRESSION_LZIP;
+ f->code = ARCHIVE_FILTER_LZIP;
f->name = "lzip";
}
return (r);
@@ -225,12 +225,12 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f,
data->stream = lzma_stream_init_data;
data->stream.next_out = data->compressed;
data->stream.avail_out = data->compressed_buffer_size;
- if (f->code == ARCHIVE_COMPRESSION_XZ)
+ if (f->code == ARCHIVE_FILTER_XZ)
ret = lzma_stream_encoder(&(data->stream),
data->lzmafilters, LZMA_CHECK_CRC64);
- else if (f->code == ARCHIVE_COMPRESSION_LZMA)
+ else if (f->code == ARCHIVE_FILTER_LZMA)
ret = lzma_alone_encoder(&(data->stream), &data->lzma_opt);
- else { /* ARCHIVE_COMPRESSION_LZIP */
+ else { /* ARCHIVE_FILTER_LZIP */
int dict_size = data->lzma_opt.dict_size;
int ds, log2dic, wedges;
@@ -298,7 +298,17 @@ archive_compressor_xz_open(struct archive_write_filter *f)
return (ret);
if (data->compressed == NULL) {
- data->compressed_buffer_size = 65536;
+ size_t bs = 65536, bpb;
+ if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
+ /* Buffer size should be a multiple number of the of bytes
+ * per block for performance. */
+ bpb = archive_write_get_bytes_per_block(f->archive);
+ if (bpb > bs)
+ bs = bpb;
+ else if (bpb != 0)
+ bs -= bs % bpb;
+ }
+ data->compressed_buffer_size = bs;
data->compressed
= (unsigned char *)malloc(data->compressed_buffer_size);
if (data->compressed == NULL) {
@@ -311,7 +321,7 @@ archive_compressor_xz_open(struct archive_write_filter *f)
f->write = archive_compressor_xz_write;
/* Initialize compression library. */
- if (f->code == ARCHIVE_COMPRESSION_LZIP) {
+ if (f->code == ARCHIVE_FILTER_LZIP) {
const struct option_value *val =
&option_values[data->compression_level];
@@ -365,6 +375,9 @@ archive_compressor_xz_options(struct archive_write_filter *f,
return (ARCHIVE_OK);
}
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
return (ARCHIVE_WARN);
}
@@ -380,7 +393,7 @@ archive_compressor_xz_write(struct archive_write_filter *f,
/* Update statistics */
data->total_in += length;
- if (f->code == ARCHIVE_COMPRESSION_LZIP)
+ if (f->code == ARCHIVE_FILTER_LZIP)
data->crc32 = lzma_crc32(buff, length, data->crc32);
/* Compress input data to output buffer */
@@ -409,7 +422,7 @@ archive_compressor_xz_close(struct archive_write_filter *f)
ret = __archive_write_filter(f->next_filter,
data->compressed,
data->compressed_buffer_size - data->stream.avail_out);
- if (f->code == ARCHIVE_COMPRESSION_LZIP && ret == ARCHIVE_OK) {
+ if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) {
archive_le32enc(data->compressed, data->crc32);
archive_le64enc(data->compressed+4, data->total_in);
archive_le64enc(data->compressed+12, data->total_out + 20);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_blocksize.3 b/Utilities/cmlibarchive/libarchive/archive_write_blocksize.3
index 96c7538..afd84ea 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_blocksize.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_blocksize.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_BLOCKSIZE 3
.Os
.Sh NAME
@@ -33,6 +33,8 @@
.Nm archive_write_get_bytes_in_last_block ,
.Nm archive_write_set_bytes_in_last_block
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_data.3 b/Utilities/cmlibarchive/libarchive/archive_write_data.3
index fc399bc..cfd5cd5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_data.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_data.3
@@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 23, 2011
-.Dt ARCHIVE_WRITE 3
+.Dd February 2, 2012
+.Dt ARCHIVE_WRITE_DATA 3
.Os
.Sh NAME
.Nm archive_write_data
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft ssize_t
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk.3 b/Utilities/cmlibarchive/libarchive/archive_write_disk.3
index ffadb04..fa925cc 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk.3
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libarchive/archive_write_disk.3,v 1.4 2008/09/04 05:22:00 kientzle Exp $
+.\" $FreeBSD$
.\"
-.Dd August 5, 2008
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_DISK 3
.Os
.Sh NAME
@@ -42,6 +42,8 @@
.Nm archive_write_finish
.Nm archive_write_free
.Nd functions for creating objects on disk
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c
new file mode 100644
index 0000000..9797203
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c
@@ -0,0 +1,249 @@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $");
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#define _ACL_PRIVATE /* For debugging */
+#include <sys/acl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_acl_private.h"
+#include "archive_write_disk_private.h"
+
+#if !defined(HAVE_POSIX_ACL) || !defined(ACL_TYPE_NFS4)
+/* Default empty function body to satisfy mainline code. */
+int
+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl)
+{
+ (void)a; /* UNUSED */
+ (void)fd; /* UNUSED */
+ (void)name; /* UNUSED */
+ (void)abstract_acl; /* UNUSED */
+ return (ARCHIVE_OK);
+}
+
+#else
+
+static int set_acl(struct archive *, int fd, const char *,
+ struct archive_acl *,
+ acl_type_t, int archive_entry_acl_type, const char *tn);
+
+/*
+ * XXX TODO: What about ACL types other than ACCESS and DEFAULT?
+ */
+int
+archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl)
+{
+ int ret;
+
+ if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) {
+ ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
+ return (ret);
+ } else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) {
+ ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4,
+ ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
+ return (ret);
+ } else
+ return ARCHIVE_OK;
+}
+
+static struct {
+ int archive_perm;
+ int platform_perm;
+} acl_perm_map[] = {
+ {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
+ {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
+ {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
+ {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
+ {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
+ {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
+ {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
+ {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
+ {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
+ {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
+ {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
+ {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
+ {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
+ {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
+};
+
+static struct {
+ int archive_inherit;
+ int platform_inherit;
+} acl_inherit_map[] = {
+ {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
+};
+
+static int
+set_acl(struct archive *a, int fd, const char *name,
+ struct archive_acl *abstract_acl,
+ acl_type_t acl_type, int ae_requested_type, const char *tname)
+{
+ acl_t acl;
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+ acl_flagset_t acl_flagset;
+ int ret;
+ int ae_type, ae_permset, ae_tag, ae_id;
+ uid_t ae_uid;
+ gid_t ae_gid;
+ const char *ae_name;
+ int entries;
+ int i;
+
+ ret = ARCHIVE_OK;
+ entries = archive_acl_reset(abstract_acl, ae_requested_type);
+ if (entries == 0)
+ return (ARCHIVE_OK);
+ acl = acl_init(entries);
+ while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
+ &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
+ acl_create_entry(&acl, &acl_entry);
+
+ switch (ae_tag) {
+ case ARCHIVE_ENTRY_ACL_USER:
+ acl_set_tag_type(acl_entry, ACL_USER);
+ ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
+ acl_set_qualifier(acl_entry, &ae_uid);
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP:
+ acl_set_tag_type(acl_entry, ACL_GROUP);
+ ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
+ acl_set_qualifier(acl_entry, &ae_gid);
+ break;
+ case ARCHIVE_ENTRY_ACL_USER_OBJ:
+ acl_set_tag_type(acl_entry, ACL_USER_OBJ);
+ break;
+ case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
+ acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
+ break;
+ case ARCHIVE_ENTRY_ACL_MASK:
+ acl_set_tag_type(acl_entry, ACL_MASK);
+ break;
+ case ARCHIVE_ENTRY_ACL_OTHER:
+ acl_set_tag_type(acl_entry, ACL_OTHER);
+ break;
+ case ARCHIVE_ENTRY_ACL_EVERYONE:
+ acl_set_tag_type(acl_entry, ACL_EVERYONE);
+ break;
+ default:
+ /* XXX */
+ break;
+ }
+
+ switch (ae_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+ acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+ acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+ acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+ acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ // These don't translate directly into the system ACL.
+ break;
+ default:
+ // XXX error handling here.
+ break;
+ }
+
+ acl_get_permset(acl_entry, &acl_permset);
+ acl_clear_perms(acl_permset);
+
+ for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
+ if (ae_permset & acl_perm_map[i].archive_perm)
+ acl_add_perm(acl_permset,
+ acl_perm_map[i].platform_perm);
+ }
+
+ acl_get_flagset_np(acl_entry, &acl_flagset);
+ acl_clear_flags_np(acl_flagset);
+ for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
+ if (ae_permset & acl_inherit_map[i].archive_inherit)
+ acl_add_flag_np(acl_flagset,
+ acl_inherit_map[i].platform_inherit);
+ }
+ }
+
+ /* Try restoring the ACL through 'fd' if we can. */
+#if HAVE_ACL_SET_FD
+ if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
+ ret = ARCHIVE_OK;
+ else
+#else
+#if HAVE_ACL_SET_FD_NP
+ if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
+ ret = ARCHIVE_OK;
+ else
+#endif
+#endif
+#if HAVE_ACL_SET_LINK_NP
+ if (acl_set_link_np(name, acl_type, acl) != 0) {
+ archive_set_error(a, errno, "Failed to set %s acl", tname);
+ ret = ARCHIVE_WARN;
+ }
+#else
+ /* TODO: Skip this if 'name' is a symlink. */
+ if (acl_set_file(name, acl_type, acl) != 0) {
+ archive_set_error(a, errno, "Failed to set %s acl", tname);
+ ret = ARCHIVE_WARN;
+ }
+#endif
+ acl_free(acl);
+ return (ret);
+}
+#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
index 99afab2..b69c873 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2010 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,15 +39,14 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#endif
-#ifdef HAVE_SYS_XATTR_H
+#if defined(HAVE_SYS_XATTR_H)
#include <sys/xattr.h>
+#elif defined(HAVE_ATTR_XATTR_H)
+#include <attr/xattr.h>
#endif
#ifdef HAVE_SYS_EA_H
#include <sys/ea.h>
#endif
-#ifdef HAVE_ATTR_XATTR_H
-#include <attr/xattr.h>
-#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@@ -118,6 +118,10 @@ __FBSDID("$FreeBSD$");
#endif
#endif
+#ifdef HAVE_ZLIB_H
+#include <cm_zlib.h>
+#endif
+
/* TODO: Support Mac OS 'quarantine' feature. This is really just a
* standard tag to mark files that have been downloaded as "tainted".
* On Mac OS, we should mark the extracted files as tainted if the
@@ -127,12 +131,17 @@ __FBSDID("$FreeBSD$");
#include "archive.h"
#include "archive_acl_private.h"
#include "archive_string.h"
+#include "archive_endian.h"
#include "archive_entry.h"
#include "archive_private.h"
+#include "archive_write_disk_private.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
struct fixup_entry {
struct fixup_entry *next;
@@ -172,6 +181,7 @@ struct fixup_entry {
#define TODO_SUID_CHECK 0x08000000
#define TODO_SGID 0x04000000
#define TODO_SGID_CHECK 0x02000000
+#define TODO_APPLEDOUBLE 0x01000000
#define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID)
#define TODO_TIMES ARCHIVE_EXTRACT_TIME
#define TODO_OWNER ARCHIVE_EXTRACT_OWNER
@@ -179,6 +189,7 @@ struct fixup_entry {
#define TODO_ACLS ARCHIVE_EXTRACT_ACL
#define TODO_XATTR ARCHIVE_EXTRACT_XATTR
#define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA
+#define TODO_HFS_COMPRESSION ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED
struct archive_write_disk {
struct archive archive;
@@ -188,8 +199,8 @@ struct archive_write_disk {
struct fixup_entry *current_fixup;
int64_t user_uid;
int skip_file_set;
- dev_t skip_file_dev;
- ino_t skip_file_ino;
+ int64_t skip_file_dev;
+ int64_t skip_file_ino;
time_t start_time;
int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
@@ -239,6 +250,36 @@ struct archive_write_disk {
/* UID/GID to use in restoring this entry. */
int64_t uid;
int64_t gid;
+ /*
+ * HFS+ Compression.
+ */
+ /* Xattr "com.apple.decmpfs". */
+ uint32_t decmpfs_attr_size;
+ unsigned char *decmpfs_header_p;
+ /* ResourceFork set options used for fsetxattr. */
+ int rsrc_xattr_options;
+ /* Xattr "com.apple.ResourceFork". */
+ unsigned char *resource_fork;
+ size_t resource_fork_allocated_size;
+ unsigned int decmpfs_block_count;
+ uint32_t *decmpfs_block_info;
+ /* Buffer for compressed data. */
+ unsigned char *compressed_buffer;
+ size_t compressed_buffer_size;
+ size_t compressed_buffer_remaining;
+ /* The offset of the ResourceFork where compressed data will
+ * be placed. */
+ uint32_t compressed_rsrc_position;
+ uint32_t compressed_rsrc_position_v;
+ /* Buffer for uncompressed data. */
+ char *uncompressed_buffer;
+ size_t block_remaining_bytes;
+ size_t file_remaining_bytes;
+#ifdef HAVE_ZLIB_H
+ z_stream stream;
+ int stream_valid;
+ int decmpfs_compression_level;
+#endif
};
/*
@@ -256,6 +297,35 @@ struct archive_write_disk {
#define MINIMUM_DIR_MODE 0700
#define MAXIMUM_DIR_MODE 0775
+/*
+ * Maxinum uncompressed size of a decmpfs block.
+ */
+#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024)
+/*
+ * HFS+ compression type.
+ */
+#define CMP_XATTR 3/* Compressed data in xattr. */
+#define CMP_RESOURCE_FORK 4/* Compressed data in resource fork. */
+/*
+ * HFS+ compression resource fork.
+ */
+#define RSRC_H_SIZE 260 /* Base size of Resource fork header. */
+#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */
+/* Size to write compressed data to resource fork. */
+#define COMPRESSED_W_SIZE (64 * 1024)
+/* decmpfs difinitions. */
+#define MAX_DECMPFS_XATTR_SIZE 3802
+#ifndef DECMPFS_XATTR_NAME
+#define DECMPFS_XATTR_NAME "com.apple.decmpfs"
+#endif
+#define DECMPFS_MAGIC 0x636d7066
+#define DECMPFS_COMPRESSION_MAGIC 0
+#define DECMPFS_COMPRESSION_TYPE 4
+#define DECMPFS_UNCOMPRESSED_SIZE 8
+#define DECMPFS_HEADER_SIZE 16
+
+#define HFS_BLOCKS(s) ((s) >> 12)
+
static int check_symlinks(struct archive_write_disk *);
static int create_filesystem_object(struct archive_write_disk *);
static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
@@ -265,13 +335,11 @@ static void edit_deep_directories(struct archive_write_disk *ad);
static int cleanup_pathname(struct archive_write_disk *);
static int create_dir(struct archive_write_disk *, char *);
static int create_parent_dir(struct archive_write_disk *, char *);
+static ssize_t hfs_write_data_block(struct archive_write_disk *,
+ const char *, size_t);
+static int fixup_appledouble(struct archive_write_disk *, const char *);
static int older(struct stat *, struct archive_entry *);
static int restore_entry(struct archive_write_disk *);
-#ifdef HAVE_POSIX_ACL
-static int set_acl(struct archive_write_disk *, int fd, const char *, struct archive_acl *,
- acl_type_t, int archive_entry_acl_type, const char *tn);
-#endif
-static int set_acls(struct archive_write_disk *, int fd, const char *, struct archive_acl *);
static int set_mac_metadata(struct archive_write_disk *, const char *,
const void *, size_t);
static int set_xattrs(struct archive_write_disk *);
@@ -485,6 +553,39 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
else
a->todo |= TODO_MAC_METADATA;
}
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
+ if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) {
+ unsigned long set, clear;
+ archive_entry_fflags(a->entry, &set, &clear);
+ if ((set & ~clear) & UF_COMPRESSED) {
+ a->todo |= TODO_HFS_COMPRESSION;
+ a->decmpfs_block_count = (unsigned)-1;
+ }
+ }
+ if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 &&
+ (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) {
+ a->todo |= TODO_HFS_COMPRESSION;
+ a->decmpfs_block_count = (unsigned)-1;
+ }
+ {
+ const char *p;
+
+ /* Check if the current file name is a type of the
+ * resource fork file. */
+ p = strrchr(a->name, '/');
+ if (p == NULL)
+ p = a->name;
+ else
+ p++;
+ if (p[0] == '.' && p[1] == '_') {
+ /* Do not compress "._XXX" files. */
+ a->todo &= ~TODO_HFS_COMPRESSION;
+ if (a->filesize > 0)
+ a->todo |= TODO_APPLEDOUBLE;
+ }
+ }
+#endif
+
if (a->flags & ARCHIVE_EXTRACT_XATTR)
a->todo |= TODO_XATTR;
if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
@@ -501,6 +602,25 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
ret = restore_entry(a);
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
+ /*
+ * Check if the filesystem the file is restoring on supports
+ * HFS+ Compression. If not, cancel HFS+ Compression.
+ */
+ if (a->todo | TODO_HFS_COMPRESSION) {
+ /*
+ * NOTE: UF_COMPRESSED is ignored even if the filesystem
+ * supports HFS+ Compression because the file should
+ * have at least an extended attriute "com.apple.decmpfs"
+ * before the flag is set to indicate that the file have
+ * been compressed. If hte filesystem does not support
+ * HFS+ Compression the system call will fail.
+ */
+ if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
+ a->todo &= ~TODO_HFS_COMPRESSION;
+ }
+#endif
+
/*
* TODO: There are rumours that some extended attributes must
* be restored before file data is written. If this is true,
@@ -532,6 +652,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
*/
if (a->deferred & TODO_MODE) {
fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
fe->fixup |= TODO_MODE_BASE;
fe->mode = a->mode;
}
@@ -540,6 +662,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
&& (archive_entry_mtime_is_set(entry)
|| archive_entry_atime_is_set(entry))) {
fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
fe->mode = a->mode;
fe->fixup |= TODO_TIMES;
if (archive_entry_atime_is_set(entry)) {
@@ -570,6 +694,9 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
if (a->deferred & TODO_ACLS) {
fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
+ fe->fixup |= TODO_ACLS;
archive_acl_copy(&fe->acl, archive_entry_acl(entry));
}
@@ -579,6 +706,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
if (metadata != NULL && metadata_size > 0) {
fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
fe->mac_metadata = malloc(metadata_size);
if (fe->mac_metadata != NULL) {
memcpy(fe->mac_metadata, metadata, metadata_size);
@@ -590,6 +719,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
if (a->deferred & TODO_FFLAGS) {
fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
fe->fixup |= TODO_FFLAGS;
/* TODO: Complete this.. defer fflags from below. */
}
@@ -707,6 +838,616 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
return (start_size - size);
}
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
+ && defined(HAVE_ZLIB_H)
+
+/*
+ * Set UF_COMPRESSED file flag.
+ * This have to be called after hfs_write_decmpfs() because if the
+ * file does not have "com.apple.decmpfs" xattr the flag is ignored.
+ */
+static int
+hfs_set_compressed_fflag(struct archive_write_disk *a)
+{
+ int r;
+
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
+ return (r);
+
+ a->st.st_flags |= UF_COMPRESSED;
+ if (fchflags(a->fd, a->st.st_flags) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to set UF_COMPRESSED file flag");
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+}
+
+/*
+ * HFS+ Compression decmpfs
+ *
+ * +------------------------------+ +0
+ * | Magic(LE 4 bytes) |
+ * +------------------------------+
+ * | Type(LE 4 bytes) |
+ * +------------------------------+
+ * | Uncompressed size(LE 8 bytes)|
+ * +------------------------------+ +16
+ * | |
+ * | Compressed data |
+ * | (Placed only if Type == 3) |
+ * | |
+ * +------------------------------+ +3802 = MAX_DECMPFS_XATTR_SIZE
+ *
+ * Type is 3: decmpfs has compressed data.
+ * Type is 4: Resource Fork has compressed data.
+ */
+/*
+ * Write "com.apple.decmpfs"
+ */
+static int
+hfs_write_decmpfs(struct archive_write_disk *a)
+{
+ int r;
+ uint32_t compression_type;
+
+ r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p,
+ a->decmpfs_attr_size, 0, 0);
+ if (r < 0) {
+ archive_set_error(&a->archive, errno,
+ "Cannot restore xattr:%s", DECMPFS_XATTR_NAME);
+ compression_type = archive_le32dec(
+ &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]);
+ if (compression_type == CMP_RESOURCE_FORK)
+ fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME,
+ XATTR_SHOWCOMPRESSION);
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+}
+
+/*
+ * HFS+ Compression Resource Fork
+ *
+ * +-----------------------------+
+ * | Header(260 bytes) |
+ * +-----------------------------+
+ * | Block count(LE 4 bytes) |
+ * +-----------------------------+ --+
+ * +-- | Offset (LE 4 bytes) | |
+ * | | [distance from Block count] | | Block 0
+ * | +-----------------------------+ |
+ * | | Compressed size(LE 4 bytes) | |
+ * | +-----------------------------+ --+
+ * | | |
+ * | | .................. |
+ * | | |
+ * | +-----------------------------+ --+
+ * | | Offset (LE 4 bytes) | |
+ * | +-----------------------------+ | Block (Block count -1)
+ * | | Compressed size(LE 4 bytes) | |
+ * +-> +-----------------------------+ --+
+ * | Compressed data(n bytes) | Block 0
+ * +-----------------------------+
+ * | |
+ * | .................. |
+ * | |
+ * +-----------------------------+
+ * | Compressed data(n bytes) | Block (Block count -1)
+ * +-----------------------------+
+ * | Footer(50 bytes) |
+ * +-----------------------------+
+ *
+ */
+/*
+ * Write the header of "com.apple.ResourceFork"
+ */
+static int
+hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff,
+ size_t bytes, uint32_t position)
+{
+ int ret;
+
+ ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes,
+ position, a->rsrc_xattr_options);
+ if (ret < 0) {
+ archive_set_error(&a->archive, errno,
+ "Cannot restore xattr: %s at %u pos %u bytes",
+ XATTR_RESOURCEFORK_NAME,
+ (unsigned)position,
+ (unsigned)bytes);
+ return (ARCHIVE_WARN);
+ }
+ a->rsrc_xattr_options &= ~XATTR_CREATE;
+ return (ARCHIVE_OK);
+}
+
+static int
+hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed)
+{
+ int ret;
+
+ ret = hfs_write_resource_fork(a, a->compressed_buffer,
+ bytes_compressed, a->compressed_rsrc_position);
+ if (ret == ARCHIVE_OK)
+ a->compressed_rsrc_position += bytes_compressed;
+ return (ret);
+}
+
+static int
+hfs_write_resource_fork_header(struct archive_write_disk *a)
+{
+ unsigned char *buff;
+ uint32_t rsrc_bytes;
+ uint32_t rsrc_header_bytes;
+
+ /*
+ * Write resource fork header + block info.
+ */
+ buff = a->resource_fork;
+ rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE;
+ rsrc_header_bytes =
+ RSRC_H_SIZE + /* Header base size. */
+ 4 + /* Block count. */
+ (a->decmpfs_block_count * 8);/* Block info */
+ archive_be32enc(buff, 0x100);
+ archive_be32enc(buff + 4, rsrc_bytes);
+ archive_be32enc(buff + 8, rsrc_bytes - 256);
+ archive_be32enc(buff + 12, 0x32);
+ memset(buff + 16, 0, 240);
+ archive_be32enc(buff + 256, rsrc_bytes - 260);
+ return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0);
+}
+
+static size_t
+hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size)
+{
+ static const char rsrc_footer[RSRC_F_SIZE] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm',
+ 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+ };
+ if (buff_size < sizeof(rsrc_footer))
+ return (0);
+ memcpy(buff, rsrc_footer, sizeof(rsrc_footer));
+ return (sizeof(rsrc_footer));
+}
+
+static int
+hfs_reset_compressor(struct archive_write_disk *a)
+{
+ int ret;
+
+ if (a->stream_valid)
+ ret = deflateReset(&a->stream);
+ else
+ ret = deflateInit(&a->stream, a->decmpfs_compression_level);
+
+ if (ret != Z_OK) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Failed to initialize compressor");
+ return (ARCHIVE_FATAL);
+ } else
+ a->stream_valid = 1;
+
+ return (ARCHIVE_OK);
+}
+
+static int
+hfs_decompress(struct archive_write_disk *a)
+{
+ uint32_t *block_info;
+ unsigned int block_count;
+ uint32_t data_pos, data_size;
+ ssize_t r;
+ ssize_t bytes_written, bytes_to_write;
+ unsigned char *b;
+
+ block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
+ block_count = archive_le32dec(block_info++);
+ while (block_count--) {
+ data_pos = RSRC_H_SIZE + archive_le32dec(block_info++);
+ data_size = archive_le32dec(block_info++);
+ r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME,
+ a->compressed_buffer, data_size, data_pos, 0);
+ if (r != data_size) {
+ archive_set_error(&a->archive,
+ (r < 0)?errno:ARCHIVE_ERRNO_MISC,
+ "Failed to read resource fork");
+ return (ARCHIVE_WARN);
+ }
+ if (a->compressed_buffer[0] == 0xff) {
+ bytes_to_write = data_size -1;
+ b = a->compressed_buffer + 1;
+ } else {
+ uLong dest_len = MAX_DECMPFS_BLOCK_SIZE;
+ int zr;
+
+ zr = uncompress((Bytef *)a->uncompressed_buffer,
+ &dest_len, a->compressed_buffer, data_size);
+ if (zr != Z_OK) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Failed to decompress resource fork");
+ return (ARCHIVE_WARN);
+ }
+ bytes_to_write = dest_len;
+ b = (unsigned char *)a->uncompressed_buffer;
+ }
+ do {
+ bytes_written = write(a->fd, b, bytes_to_write);
+ if (bytes_written < 0) {
+ archive_set_error(&a->archive, errno,
+ "Write failed");
+ return (ARCHIVE_WARN);
+ }
+ bytes_to_write -= bytes_written;
+ b += bytes_written;
+ } while (bytes_to_write > 0);
+ }
+ r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to remove resource fork");
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
+ size_t size)
+{
+ unsigned char *buffer_compressed;
+ size_t bytes_compressed;
+ size_t bytes_used;
+ int ret;
+
+ ret = hfs_reset_compressor(a);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ if (a->compressed_buffer == NULL) {
+ size_t block_size;
+
+ block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE +
+ + compressBound(MAX_DECMPFS_BLOCK_SIZE);
+ a->compressed_buffer = malloc(block_size);
+ if (a->compressed_buffer == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Resource Fork");
+ return (ARCHIVE_FATAL);
+ }
+ a->compressed_buffer_size = block_size;
+ a->compressed_buffer_remaining = block_size;
+ }
+
+ buffer_compressed = a->compressed_buffer +
+ a->compressed_buffer_size - a->compressed_buffer_remaining;
+ a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff;
+ a->stream.avail_in = size;
+ a->stream.next_out = buffer_compressed;
+ a->stream.avail_out = a->compressed_buffer_remaining;
+ do {
+ ret = deflate(&a->stream, Z_FINISH);
+ switch (ret) {
+ case Z_OK:
+ case Z_STREAM_END:
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Failed to compress data");
+ return (ARCHIVE_FAILED);
+ }
+ } while (ret == Z_OK);
+ bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out;
+
+ /*
+ * If the compressed size is larger than the original size,
+ * throw away compressed data, use uncompressed data instead.
+ */
+ if (bytes_compressed > size) {
+ buffer_compressed[0] = 0xFF;/* uncompressed marker. */
+ memcpy(buffer_compressed + 1, buff, size);
+ bytes_compressed = size + 1;
+ }
+ a->compressed_buffer_remaining -= bytes_compressed;
+
+ /*
+ * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE
+ * and the block count in the file is only one, store compressed
+ * data to decmpfs xattr instead of the resource fork.
+ */
+ if (a->decmpfs_block_count == 1 &&
+ (a->decmpfs_attr_size + bytes_compressed)
+ <= MAX_DECMPFS_XATTR_SIZE) {
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
+ CMP_XATTR);
+ memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE,
+ buffer_compressed, bytes_compressed);
+ a->decmpfs_attr_size += bytes_compressed;
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
+ /*
+ * Finish HFS+ Compression.
+ * - Write the decmpfs xattr.
+ * - Set the UF_COMPRESSED file flag.
+ */
+ ret = hfs_write_decmpfs(a);
+ if (ret == ARCHIVE_OK)
+ ret = hfs_set_compressed_fflag(a);
+ return (ret);
+ }
+
+ /* Update block info. */
+ archive_le32enc(a->decmpfs_block_info++,
+ a->compressed_rsrc_position_v - RSRC_H_SIZE);
+ archive_le32enc(a->decmpfs_block_info++, bytes_compressed);
+ a->compressed_rsrc_position_v += bytes_compressed;
+
+ /*
+ * Write the compressed data to the resource fork.
+ */
+ bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining;
+ while (bytes_used >= COMPRESSED_W_SIZE) {
+ ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ bytes_used -= COMPRESSED_W_SIZE;
+ if (bytes_used > COMPRESSED_W_SIZE)
+ memmove(a->compressed_buffer,
+ a->compressed_buffer + COMPRESSED_W_SIZE,
+ bytes_used);
+ else
+ memcpy(a->compressed_buffer,
+ a->compressed_buffer + COMPRESSED_W_SIZE,
+ bytes_used);
+ }
+ a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used;
+
+ /*
+ * If the current block is the last block, write the remaining
+ * compressed data and the resource fork footer.
+ */
+ if (a->file_remaining_bytes == 0) {
+ size_t rsrc_size;
+ int64_t bk;
+
+ /* Append the resource footer. */
+ rsrc_size = hfs_set_resource_fork_footer(
+ a->compressed_buffer + bytes_used,
+ a->compressed_buffer_remaining);
+ ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
+
+ /* If the compressed size is not enouph smaller than
+ * the uncompressed size. cancel HFS+ compression.
+ * TODO: study a behavior of ditto utility and improve
+ * the condition to fall back into no HFS+ compression. */
+ bk = HFS_BLOCKS(a->compressed_rsrc_position);
+ bk += bk >> 7;
+ if (bk > HFS_BLOCKS(a->filesize))
+ return hfs_decompress(a);
+ /*
+ * Write the resourcefork header.
+ */
+ if (ret == ARCHIVE_OK)
+ ret = hfs_write_resource_fork_header(a);
+ /*
+ * Finish HFS+ Compression.
+ * - Write the decmpfs xattr.
+ * - Set the UF_COMPRESSED file flag.
+ */
+ if (ret == ARCHIVE_OK)
+ ret = hfs_write_decmpfs(a);
+ if (ret == ARCHIVE_OK)
+ ret = hfs_set_compressed_fflag(a);
+ }
+ return (ret);
+}
+
+static ssize_t
+hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
+ size_t size)
+{
+ const char *buffer_to_write;
+ size_t bytes_to_write;
+ int ret;
+
+ if (a->decmpfs_block_count == (unsigned)-1) {
+ void *new_block;
+ size_t new_size;
+ unsigned int block_count;
+
+ if (a->decmpfs_header_p == NULL) {
+ new_block = malloc(MAX_DECMPFS_XATTR_SIZE
+ + sizeof(uint32_t));
+ if (new_block == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for decmpfs");
+ return (ARCHIVE_FATAL);
+ }
+ a->decmpfs_header_p = new_block;
+ }
+ a->decmpfs_attr_size = DECMPFS_HEADER_SIZE;
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC],
+ DECMPFS_MAGIC);
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
+ CMP_RESOURCE_FORK);
+ archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE],
+ a->filesize);
+
+ /* Calculate a block count of the file. */
+ block_count =
+ (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) /
+ MAX_DECMPFS_BLOCK_SIZE;
+ /*
+ * Allocate buffer for resource fork.
+ * Set up related pointers;
+ */
+ new_size =
+ RSRC_H_SIZE + /* header */
+ 4 + /* Block count */
+ (block_count * sizeof(uint32_t) * 2) +
+ RSRC_F_SIZE; /* footer */
+ if (new_size > a->resource_fork_allocated_size) {
+ new_block = realloc(a->resource_fork, new_size);
+ if (new_block == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for ResourceFork");
+ return (ARCHIVE_FATAL);
+ }
+ a->resource_fork_allocated_size = new_size;
+ a->resource_fork = new_block;
+ }
+
+ /* Allocate uncompressed buffer */
+ if (a->uncompressed_buffer == NULL) {
+ new_block = malloc(MAX_DECMPFS_BLOCK_SIZE);
+ if (new_block == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for decmpfs");
+ return (ARCHIVE_FATAL);
+ }
+ a->uncompressed_buffer = new_block;
+ }
+ a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
+ a->file_remaining_bytes = a->filesize;
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
+
+ /*
+ * Set up a resource fork.
+ */
+ a->rsrc_xattr_options = XATTR_CREATE;
+ /* Get the position where we are going to set a bunch
+ * of block info. */
+ a->decmpfs_block_info =
+ (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
+ /* Set the block count to the resource fork. */
+ archive_le32enc(a->decmpfs_block_info++, block_count);
+ /* Get the position where we are goint to set compressed
+ * data. */
+ a->compressed_rsrc_position =
+ RSRC_H_SIZE + 4 + (block_count * 8);
+ a->compressed_rsrc_position_v = a->compressed_rsrc_position;
+ a->decmpfs_block_count = block_count;
+ }
+
+ /* Ignore redundant bytes. */
+ if (a->file_remaining_bytes == 0)
+ return ((ssize_t)size);
+
+ /* Do not overrun a block size. */
+ if (size > a->block_remaining_bytes)
+ bytes_to_write = a->block_remaining_bytes;
+ else
+ bytes_to_write = size;
+ /* Do not overrun the file size. */
+ if (bytes_to_write > a->file_remaining_bytes)
+ bytes_to_write = a->file_remaining_bytes;
+
+ /* For efficiency, if a copy length is full of the uncompressed
+ * buffer size, do not copy writing data to it. */
+ if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE)
+ buffer_to_write = buff;
+ else {
+ memcpy(a->uncompressed_buffer +
+ MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes,
+ buff, bytes_to_write);
+ buffer_to_write = a->uncompressed_buffer;
+ }
+ a->block_remaining_bytes -= bytes_to_write;
+ a->file_remaining_bytes -= bytes_to_write;
+
+ if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) {
+ ret = hfs_drive_compressor(a, buffer_to_write,
+ MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes);
+ if (ret < 0)
+ return (ret);
+ a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
+ }
+ /* Ignore redundant bytes. */
+ if (a->file_remaining_bytes == 0)
+ return ((ssize_t)size);
+ return (bytes_to_write);
+}
+
+static ssize_t
+hfs_write_data_block(struct archive_write_disk *a, const char *buff,
+ size_t size)
+{
+ uint64_t start_size = size;
+ ssize_t bytes_written = 0;
+ ssize_t bytes_to_write;
+
+ if (size == 0)
+ return (ARCHIVE_OK);
+
+ if (a->filesize == 0 || a->fd < 0) {
+ archive_set_error(&a->archive, 0,
+ "Attempt to write to an empty file");
+ return (ARCHIVE_WARN);
+ }
+
+ /* If this write would run beyond the file size, truncate it. */
+ if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
+ start_size = size = (size_t)(a->filesize - a->offset);
+
+ /* Write the data. */
+ while (size > 0) {
+ bytes_to_write = size;
+ /* Seek if necessary to the specified offset. */
+ if (a->offset < a->fd_offset) {
+ /* Can't support backword move. */
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Seek failed");
+ return (ARCHIVE_FATAL);
+ } else if (a->offset > a->fd_offset) {
+ int64_t skip = a->offset - a->fd_offset;
+ char nullblock[1024];
+
+ memset(nullblock, 0, sizeof(nullblock));
+ while (skip > 0) {
+ if (skip > (int64_t)sizeof(nullblock))
+ bytes_written = hfs_write_decmpfs_block(
+ a, nullblock, sizeof(nullblock));
+ else
+ bytes_written = hfs_write_decmpfs_block(
+ a, nullblock, skip);
+ if (bytes_written < 0) {
+ archive_set_error(&a->archive, errno,
+ "Write failed");
+ return (ARCHIVE_WARN);
+ }
+ skip -= bytes_written;
+ }
+
+ a->fd_offset = a->offset;
+ }
+ bytes_written =
+ hfs_write_decmpfs_block(a, buff, bytes_to_write);
+ if (bytes_written < 0)
+ return (bytes_written);
+ buff += bytes_written;
+ size -= bytes_written;
+ a->total_bytes_written += bytes_written;
+ a->offset += bytes_written;
+ a->fd_offset = a->offset;
+ }
+ return (start_size - size);
+}
+#else
+static ssize_t
+hfs_write_data_block(struct archive_write_disk *a, const char *buff,
+ size_t size)
+{
+ return (write_data_block(a, buff, size));
+}
+#endif
+
static ssize_t
_archive_write_disk_data_block(struct archive *_a,
const void *buff, size_t size, int64_t offset)
@@ -718,7 +1459,10 @@ _archive_write_disk_data_block(struct archive *_a,
ARCHIVE_STATE_DATA, "archive_write_data_block");
a->offset = offset;
- r = write_data_block(a, buff, size);
+ if (a->todo & TODO_HFS_COMPRESSION)
+ r = hfs_write_data_block(a, buff, size);
+ else
+ r = write_data_block(a, buff, size);
if (r < ARCHIVE_OK)
return (r);
if ((size_t)r < size) {
@@ -737,6 +1481,8 @@ _archive_write_disk_data(struct archive *_a, const void *buff, size_t size)
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
ARCHIVE_STATE_DATA, "archive_write_data");
+ if (a->todo & TODO_HFS_COMPRESSION)
+ return (hfs_write_data_block(a, buff, size));
return (write_data_block(a, buff, size));
}
@@ -761,6 +1507,24 @@ _archive_write_disk_finish_entry(struct archive *_a)
} else if (a->fd_offset == a->filesize) {
/* Last write ended at exactly the filesize; we're done. */
/* Hopefully, this is the common case. */
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
+ } else if (a->todo & TODO_HFS_COMPRESSION) {
+ char null_d[1024];
+ ssize_t r;
+
+ if (a->file_remaining_bytes)
+ memset(null_d, 0, sizeof(null_d));
+ while (a->file_remaining_bytes) {
+ if (a->file_remaining_bytes > sizeof(null_d))
+ r = hfs_write_data_block(
+ a, null_d, sizeof(null_d));
+ else
+ r = hfs_write_data_block(
+ a, null_d, a->file_remaining_bytes);
+ if (r < 0)
+ return ((int)r);
+ }
+#endif
} else {
#if HAVE_FTRUNCATE
if (ftruncate(a->fd, a->filesize) == -1 &&
@@ -799,6 +1563,22 @@ _archive_write_disk_finish_entry(struct archive *_a)
/* Restore metadata. */
/*
+ * This is specific to Mac OS X.
+ * If the current file is an AppleDouble file, it should be
+ * linked with the data fork file and remove it.
+ */
+ if (a->todo & TODO_APPLEDOUBLE) {
+ int r2 = fixup_appledouble(a, a->name);
+ if (r2 == ARCHIVE_EOF) {
+ /* The current file has been successfully linked
+ * with the data fork file and removed. So there
+ * is nothing to do on the current file. */
+ goto finish_metadata;
+ }
+ if (r2 < ret) ret = r2;
+ }
+
+ /*
* Look up the "real" UID only if we're going to need it.
* TODO: the TODO_SGID condition can be dropped here, can't it?
*/
@@ -820,8 +1600,10 @@ _archive_write_disk_finish_entry(struct archive *_a)
* bits. If we set the owner, we know what it is and can skip
* a stat() call to examine the ownership of the file on disk.
*/
- if (a->todo & TODO_OWNER)
- ret = set_ownership(a);
+ if (a->todo & TODO_OWNER) {
+ int r2 = set_ownership(a);
+ if (r2 < ret) ret = r2;
+ }
/*
* set_mode must precede ACLs on systems such as Solaris and
@@ -868,7 +1650,8 @@ _archive_write_disk_finish_entry(struct archive *_a)
size_t metadata_size;
metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
if (metadata != NULL && metadata_size > 0) {
- int r2 = set_mac_metadata(a, archive_entry_pathname(a->entry), metadata, metadata_size);
+ int r2 = set_mac_metadata(a, archive_entry_pathname(
+ a->entry), metadata, metadata_size);
if (r2 < ret) ret = r2;
}
}
@@ -878,12 +1661,13 @@ _archive_write_disk_finish_entry(struct archive *_a)
* ACLs that prevent attribute changes (including time).
*/
if (a->todo & TODO_ACLS) {
- int r2 = set_acls(a, a->fd,
+ int r2 = archive_write_disk_set_acls(&a->archive, a->fd,
archive_entry_pathname(a->entry),
archive_entry_acl(a->entry));
if (r2 < ret) ret = r2;
}
+finish_metadata:
/* If there's an fd, we can close it now. */
if (a->fd >= 0) {
close(a->fd);
@@ -950,12 +1734,12 @@ archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
int64_t
archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
{
- struct archive_write_disk *a = (struct archive_write_disk *)_a;
- archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
- ARCHIVE_STATE_ANY, "archive_write_disk_uid");
- if (a->lookup_uid)
- return (a->lookup_uid)(a->lookup_uid_data, name, id);
- return (id);
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_write_disk_uid");
+ if (a->lookup_uid)
+ return (a->lookup_uid)(a->lookup_uid_data, name, id);
+ return (id);
}
/*
@@ -984,6 +1768,9 @@ archive_write_disk_new(void)
free(a);
return (NULL);
}
+#ifdef HAVE_ZLIB_H
+ a->decmpfs_compression_level = 5;
+#endif
return (&a->archive);
}
@@ -1008,7 +1795,8 @@ edit_deep_directories(struct archive_write_disk *a)
return;
/* Try to record our starting dir. */
- a->restore_pwd = open(".", O_RDONLY | O_BINARY);
+ a->restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(a->restore_pwd);
if (a->restore_pwd < 0)
return;
@@ -1143,9 +1931,10 @@ restore_entry(struct archive_write_disk *a)
/* If it's our archive, we're done. */
if (a->skip_file_set &&
- a->st.st_dev == a->skip_file_dev &&
- a->st.st_ino == a->skip_file_ino) {
- archive_set_error(&a->archive, 0, "Refusing to overwrite archive");
+ a->st.st_dev == (dev_t)a->skip_file_dev &&
+ a->st.st_ino == (ino_t)a->skip_file_ino) {
+ archive_set_error(&a->archive, 0,
+ "Refusing to overwrite archive");
return (ARCHIVE_FAILED);
}
@@ -1163,7 +1952,7 @@ restore_entry(struct archive_write_disk *a)
/* A dir is in the way of a non-dir, rmdir it. */
if (rmdir(a->name) != 0) {
archive_set_error(&a->archive, errno,
- "Can't remove already-existing dir");
+ "Can't replace existing directory with non-directory");
return (ARCHIVE_FAILED);
}
/* Try again. */
@@ -1223,7 +2012,7 @@ create_filesystem_object(struct archive_write_disk *a)
*
* If the hardlink was successfully created and
* the archive doesn't have carry data for it,
- * consider it to be non-authoritive for meta data.
+ * consider it to be non-authoritative for meta data.
* This is consistent with GNU tar and BSD pax.
* If the hardlink does carry data, let the last
* archive entry decide ownership.
@@ -1232,7 +2021,9 @@ create_filesystem_object(struct archive_write_disk *a)
a->todo = 0;
a->deferred = 0;
} else if (r == 0 && a->filesize > 0) {
- a->fd = open(a->name, O_WRONLY | O_TRUNC | O_BINARY);
+ a->fd = open(a->name,
+ O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(a->fd);
if (a->fd < 0)
r = errno;
}
@@ -1261,7 +2052,7 @@ create_filesystem_object(struct archive_write_disk *a)
* that SUID, SGID, etc, require additional work to ensure
* security, so we never restore them at this point.
*/
- mode = final_mode & 0777 & a->user_umask;
+ mode = final_mode & 0777 & ~a->user_umask;
switch (a->mode & AE_IFMT) {
default:
@@ -1269,7 +2060,8 @@ create_filesystem_object(struct archive_write_disk *a)
/* FALLTHROUGH */
case AE_IFREG:
a->fd = open(a->name,
- O_WRONLY | O_CREAT | O_EXCL | O_BINARY, mode);
+ O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode);
+ __archive_ensure_cloexec_flag(a->fd);
r = (a->fd < 0);
break;
case AE_IFCHR:
@@ -1380,7 +2172,8 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup & TODO_MODE_BASE)
chmod(p->name, p->mode);
if (p->fixup & TODO_ACLS)
- set_acls(a, -1, p->name, &p->acl);
+ archive_write_disk_set_acls(&a->archive,
+ -1, p->name, &p->acl);
if (p->fixup & TODO_FFLAGS)
set_fflags_platform(a, -1, p->name,
p->mode, p->fflags_set, 0);
@@ -1418,6 +2211,23 @@ _archive_write_disk_free(struct archive *_a)
archive_string_free(&a->path_safe);
a->archive.magic = 0;
__archive_clean(&a->archive);
+ free(a->decmpfs_header_p);
+ free(a->resource_fork);
+ free(a->compressed_buffer);
+ free(a->uncompressed_buffer);
+#ifdef HAVE_ZLIB_H
+ if (a->stream_valid) {
+ switch (deflateEnd(&a->stream)) {
+ case Z_OK:
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Failed to clean up compressor");
+ ret = ARCHIVE_FATAL;
+ break;
+ }
+ }
+#endif
free(a);
return (ret);
}
@@ -1499,8 +2309,11 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
struct fixup_entry *fe;
fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry));
- if (fe == NULL)
+ if (fe == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for a fixup");
return (NULL);
+ }
fe->next = a->fixup_list;
a->fixup_list = fe;
fe->fixup = 0;
@@ -1672,7 +2485,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
p = a->name;
while (*p != '\0' && alen) {
l = mbtowc(&wc, p, alen);
- if (l == -1) {
+ if (l == (size_t)-1) {
while (*p != '\0') {
if (*p == '\\')
*p = '/';
@@ -1887,6 +2700,8 @@ create_dir(struct archive_write_disk *a, char *path)
if (mkdir(path, mode) == 0) {
if (mode != mode_final) {
le = new_fixup(a, path);
+ if (le == NULL)
+ return (ARCHIVE_FATAL);
le->fixup |=TODO_MODE_BASE;
le->mode = mode_final;
}
@@ -1979,6 +2794,7 @@ set_time(int fd, int mode, const char *name,
* on fds and symlinks.
*/
struct timespec ts[2];
+ (void)mode; /* UNUSED */
ts[0].tv_sec = atime;
ts[0].tv_nsec = atime_nsec;
ts[1].tv_sec = mtime;
@@ -2036,6 +2852,11 @@ set_time(int fd, int mode, const char *name,
/*
* We don't know how to set the time on this platform.
*/
+ (void)fd; /* UNUSED */
+ (void)mode; /* UNUSED */
+ (void)name; /* UNUSED */
+ (void)atime_nsec; /* UNUSED */
+ (void)mtime_nsec; /* UNUSED */
return (ARCHIVE_WARN);
#endif
}
@@ -2068,7 +2889,7 @@ set_times(struct archive_write_disk *a,
time_t atime, long atime_nanos,
time_t birthtime, long birthtime_nanos,
time_t mtime, long mtime_nanos,
- time_t ctime, long ctime_nanos)
+ time_t cctime, long ctime_nanos)
{
/* Note: set_time doesn't use libarchive return conventions!
* It uses syscall conventions. So 0 here instead of ARCHIVE_OK. */
@@ -2083,9 +2904,12 @@ set_times(struct archive_write_disk *a,
if (a->user_uid == 0 &&
set_time_tru64(fd, mode, name,
atime, atime_nanos, mtime,
- mtime_nanos, ctime, ctime_nanos) == 0) {
+ mtime_nanos, cctime, ctime_nanos) == 0) {
return (ARCHIVE_OK);
}
+#else /* Tru64 */
+ (void)cctime; /* UNUSED */
+ (void)ctime_nanos; /* UNUSED */
#endif /* Tru64 */
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
@@ -2102,6 +2926,9 @@ set_times(struct archive_write_disk *a,
r1 = set_time(fd, mode, name,
atime, atime_nanos,
birthtime, birthtime_nanos);
+#else
+ (void)birthtime; /* UNUSED */
+ (void)birthtime_nanos; /* UNUSED */
#endif
r2 = set_time(fd, mode, name,
atime, atime_nanos,
@@ -2117,11 +2944,11 @@ set_times(struct archive_write_disk *a,
static int
set_times_from_entry(struct archive_write_disk *a)
{
- time_t atime, birthtime, mtime, ctime;
+ time_t atime, birthtime, mtime, cctime;
long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
/* Suitable defaults. */
- atime = birthtime = mtime = ctime = a->start_time;
+ atime = birthtime = mtime = cctime = a->start_time;
atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
/* If no time was provided, we're done. */
@@ -2145,7 +2972,7 @@ set_times_from_entry(struct archive_write_disk *a)
mtime_nsec = archive_entry_mtime_nsec(a->entry);
}
if (archive_entry_ctime_is_set(a->entry)) {
- ctime = archive_entry_ctime(a->entry);
+ cctime = archive_entry_ctime(a->entry);
ctime_nsec = archive_entry_ctime_nsec(a->entry);
}
@@ -2153,7 +2980,7 @@ set_times_from_entry(struct archive_write_disk *a)
atime, atime_nsec,
birthtime, birthtime_nsec,
mtime, mtime_nsec,
- ctime, ctime_nsec);
+ cctime, ctime_nsec);
}
static int
@@ -2312,6 +3139,8 @@ set_fflags(struct archive_write_disk *a)
*/
if ((critical_flags != 0) && (set & critical_flags)) {
le = current_fixup(a, a->name);
+ if (le == NULL)
+ return (ARCHIVE_FATAL);
le->fixup |= TODO_FFLAGS;
le->fflags_set = set;
/* Store the mode if it's not already there. */
@@ -2390,8 +3219,8 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
{
int ret;
int myfd = fd;
- unsigned long newflags, oldflags;
- unsigned long sf_mask = 0;
+ int newflags, oldflags;
+ int sf_mask = 0;
if (set == 0 && clear == 0)
return (ARCHIVE_OK);
@@ -2400,8 +3229,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
return (ARCHIVE_OK);
/* If we weren't given an fd, open it ourselves. */
- if (myfd < 0)
- myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY);
+ if (myfd < 0) {
+ myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(myfd);
+ }
if (myfd < 0)
return (ARCHIVE_OK);
@@ -2486,12 +3317,196 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname,
(void)metadata_size; /* UNUSED */
return (ARCHIVE_OK);
}
+
+static int
+fixup_appledouble(struct archive_write_disk *a, const char *pathname)
+{
+ (void)a; /* UNUSED */
+ (void)pathname; /* UNUSED */
+ return (ARCHIVE_OK);
+}
#else
/*
* On Mac OS, we use copyfile() to unpack the metadata and
* apply it to the target file.
*/
+
+#if defined(HAVE_SYS_XATTR_H)
+static int
+copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd)
+{
+ ssize_t xattr_size;
+ char *xattr_names = NULL, *xattr_val = NULL;
+ int ret = ARCHIVE_OK, xattr_i;
+
+ xattr_size = flistxattr(tmpfd, NULL, 0, 0);
+ if (xattr_size == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to read metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ xattr_names = malloc(xattr_size);
+ if (xattr_names == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for metadata(xattr)");
+ ret = ARCHIVE_FATAL;
+ goto exit_xattr;
+ }
+ xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0);
+ if (xattr_size == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to read metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ for (xattr_i = 0; xattr_i < xattr_size;
+ xattr_i += strlen(xattr_names + xattr_i) + 1) {
+ ssize_t s;
+ int f;
+
+ s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ xattr_val = realloc(xattr_val, s);
+ if (xattr_val == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Failed to get metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0);
+ if (f == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ }
+exit_xattr:
+ free(xattr_names);
+ free(xattr_val);
+ return (ret);
+}
+#endif
+
+static int
+copy_acls(struct archive_write_disk *a, int tmpfd, int dffd)
+{
+ acl_t acl, dfacl = NULL;
+ int acl_r, ret = ARCHIVE_OK;
+
+ acl = acl_get_fd(tmpfd);
+ if (acl == NULL) {
+ if (errno == ENOENT)
+ /* There are not any ACLs. */
+ return (ret);
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(acl)");
+ ret = ARCHIVE_WARN;
+ goto exit_acl;
+ }
+ dfacl = acl_dup(acl);
+ acl_r = acl_set_fd(dffd, dfacl);
+ if (acl_r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(acl)");
+ ret = ARCHIVE_WARN;
+ goto exit_acl;
+ }
+exit_acl:
+ if (acl)
+ acl_free(acl);
+ if (dfacl)
+ acl_free(dfacl);
+ return (ret);
+}
+
+static int
+create_tempdatafork(struct archive_write_disk *a, const char *pathname)
+{
+ struct archive_string tmpdatafork;
+ int tmpfd;
+
+ archive_string_init(&tmpdatafork);
+ archive_strcpy(&tmpdatafork, "tar.md.XXXXXX");
+ tmpfd = mkstemp(tmpdatafork.s);
+ if (tmpfd < 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to mkstemp");
+ archive_string_free(&tmpdatafork);
+ return (-1);
+ }
+ if (copyfile(pathname, tmpdatafork.s, 0,
+ COPYFILE_UNPACK | COPYFILE_NOFOLLOW
+ | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to restore metadata");
+ close(tmpfd);
+ tmpfd = -1;
+ }
+ unlink(tmpdatafork.s);
+ archive_string_free(&tmpdatafork);
+ return (tmpfd);
+}
+
+static int
+copy_metadata(struct archive_write_disk *a, const char *metadata,
+ const char *datafork, int datafork_compressed)
+{
+ int ret = ARCHIVE_OK;
+
+ if (datafork_compressed) {
+ int dffd, tmpfd;
+
+ tmpfd = create_tempdatafork(a, metadata);
+ if (tmpfd == -1)
+ return (ARCHIVE_WARN);
+
+ /*
+ * Do not open the data fork compressed by HFS+ compression
+ * with at least a writing mode(O_RDWR or O_WRONLY). it
+ * makes the data fork uncompressed.
+ */
+ dffd = open(datafork, 0);
+ if (dffd == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to open the data fork for metadata");
+ close(tmpfd);
+ return (ARCHIVE_WARN);
+ }
+
+#if defined(HAVE_SYS_XATTR_H)
+ ret = copy_xattrs(a, tmpfd, dffd);
+ if (ret == ARCHIVE_OK)
+#endif
+ ret = copy_acls(a, tmpfd, dffd);
+ close(tmpfd);
+ close(dffd);
+ } else {
+ if (copyfile(metadata, datafork, 0,
+ COPYFILE_UNPACK | COPYFILE_NOFOLLOW
+ | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to restore metadata");
+ ret = ARCHIVE_WARN;
+ }
+ }
+ return (ret);
+}
+
static int
set_mac_metadata(struct archive_write_disk *a, const char *pathname,
const void *metadata, size_t metadata_size)
@@ -2513,139 +3528,101 @@ set_mac_metadata(struct archive_write_disk *a, const char *pathname,
if (fd < 0) {
archive_set_error(&a->archive, errno,
"Failed to restore metadata");
+ archive_string_free(&tmp);
return (ARCHIVE_WARN);
}
written = write(fd, metadata, metadata_size);
close(fd);
- if (written != metadata_size
- || copyfile(tmp.s, pathname, 0,
- COPYFILE_UNPACK | COPYFILE_NOFOLLOW
- | COPYFILE_ACL | COPYFILE_XATTR)) {
+ if ((size_t)written != metadata_size) {
archive_set_error(&a->archive, errno,
"Failed to restore metadata");
ret = ARCHIVE_WARN;
+ } else {
+ int compressed;
+
+#if defined(UF_COMPRESSED)
+ if ((a->todo & TODO_HFS_COMPRESSION) != 0 &&
+ (ret = lazy_stat(a)) == ARCHIVE_OK)
+ compressed = a->st.st_flags & UF_COMPRESSED;
+ else
+#endif
+ compressed = 0;
+ ret = copy_metadata(a, tmp.s, pathname, compressed);
}
unlink(tmp.s);
+ archive_string_free(&tmp);
return (ret);
}
-#endif
-#ifndef HAVE_POSIX_ACL
-/* Default empty function body to satisfy mainline code. */
static int
-set_acls(struct archive_write_disk *a, int fd, const char *name,
- struct archive_acl *acl)
+fixup_appledouble(struct archive_write_disk *a, const char *pathname)
{
- (void)a; /* UNUSED */
- (void)fd; /* UNUSED */
- (void)name; /* UNUSED */
- (void)acl; /* UNUSED */
- return (ARCHIVE_OK);
-}
-
-#else
-
-/*
- * XXX TODO: What about ACL types other than ACCESS and DEFAULT?
- */
-static int
-set_acls(struct archive_write_disk *a, int fd, const char *name,
- struct archive_acl *abstract_acl)
-{
- int ret;
-
- ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS,
- ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
- if (ret != ARCHIVE_OK)
- return (ret);
- ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT,
- ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
- return (ret);
-}
-
-
-static int
-set_acl(struct archive_write_disk *a, int fd, const char *name,
- struct archive_acl *abstract_acl,
- acl_type_t acl_type, int ae_requested_type, const char *tname)
-{
- acl_t acl;
- acl_entry_t acl_entry;
- acl_permset_t acl_permset;
- int ret;
- int ae_type, ae_permset, ae_tag, ae_id;
- uid_t ae_uid;
- gid_t ae_gid;
- const char *ae_name;
- int entries;
+ char buff[8];
+ struct stat st;
+ const char *p;
+ struct archive_string datafork;
+ int fd = -1, ret = ARCHIVE_OK;
+
+ archive_string_init(&datafork);
+ /* Check if the current file name is a type of the resource
+ * fork file. */
+ p = strrchr(pathname, '/');
+ if (p == NULL)
+ p = pathname;
+ else
+ p++;
+ if (p[0] != '.' || p[1] != '_')
+ goto skip_appledouble;
- ret = ARCHIVE_OK;
- entries = archive_acl_reset(abstract_acl, ae_requested_type);
- if (entries == 0)
- return (ARCHIVE_OK);
- acl = acl_init(entries);
- while (archive_acl_next(&a->archive, abstract_acl,
- ae_requested_type, &ae_type, &ae_permset, &ae_tag, &ae_id,
- &ae_name) == ARCHIVE_OK) {
- acl_create_entry(&acl, &acl_entry);
-
- switch (ae_tag) {
- case ARCHIVE_ENTRY_ACL_USER:
- acl_set_tag_type(acl_entry, ACL_USER);
- ae_uid = archive_write_disk_uid(&a->archive,
- ae_name, ae_id);
- acl_set_qualifier(acl_entry, &ae_uid);
- break;
- case ARCHIVE_ENTRY_ACL_GROUP:
- acl_set_tag_type(acl_entry, ACL_GROUP);
- ae_gid = archive_write_disk_gid(&a->archive,
- ae_name, ae_id);
- acl_set_qualifier(acl_entry, &ae_gid);
- break;
- case ARCHIVE_ENTRY_ACL_USER_OBJ:
- acl_set_tag_type(acl_entry, ACL_USER_OBJ);
- break;
- case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
- acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
- break;
- case ARCHIVE_ENTRY_ACL_MASK:
- acl_set_tag_type(acl_entry, ACL_MASK);
- break;
- case ARCHIVE_ENTRY_ACL_OTHER:
- acl_set_tag_type(acl_entry, ACL_OTHER);
- break;
- default:
- /* XXX */
- break;
- }
+ /*
+ * Check if the data fork file exists.
+ *
+ * TODO: Check if this write disk object has handled it.
+ */
+ archive_strncpy(&datafork, pathname, p - pathname);
+ archive_strcat(&datafork, p + 2);
+ if (lstat(datafork.s, &st) == -1 ||
+ (st.st_mode & AE_IFMT) != AE_IFREG)
+ goto skip_appledouble;
- acl_get_permset(acl_entry, &acl_permset);
- acl_clear_perms(acl_permset);
- if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
- acl_add_perm(acl_permset, ACL_EXECUTE);
- if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
- acl_add_perm(acl_permset, ACL_WRITE);
- if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
- acl_add_perm(acl_permset, ACL_READ);
+ /*
+ * Check if the file is in the AppleDouble form.
+ */
+ fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
+ if (fd == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to open a restoring file");
+ ret = ARCHIVE_WARN;
+ goto skip_appledouble;
}
-
- /* Try restoring the ACL through 'fd' if we can. */
-#if HAVE_ACL_SET_FD
- if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
- ret = ARCHIVE_OK;
- else
+ if (read(fd, buff, 8) == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to read a restoring file");
+ close(fd);
+ ret = ARCHIVE_WARN;
+ goto skip_appledouble;
+ }
+ close(fd);
+ /* Check AppleDouble Magic Code. */
+ if (archive_be32dec(buff) != 0x00051607)
+ goto skip_appledouble;
+ /* Check AppleDouble Version. */
+ if (archive_be32dec(buff+4) != 0x00020000)
+ goto skip_appledouble;
+
+ ret = copy_metadata(a, pathname, datafork.s,
+#if defined(UF_COMPRESSED)
+ st.st_flags & UF_COMPRESSED);
#else
-#if HAVE_ACL_SET_FD_NP
- if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
- ret = ARCHIVE_OK;
- else
-#endif
+ 0);
#endif
- if (acl_set_file(name, acl_type, acl) != 0) {
- archive_set_error(&a->archive, errno, "Failed to set %s acl", tname);
- ret = ARCHIVE_WARN;
+ if (ret == ARCHIVE_OK) {
+ unlink(pathname);
+ ret = ARCHIVE_EOF;
}
- acl_free(acl);
+skip_appledouble:
+ archive_string_free(&datafork);
return (ret);
}
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h
index 707c0cf..d84e7e1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h
@@ -33,6 +33,11 @@
#ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
#define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
+#include "archive_acl_private.h"
+
struct archive_write_disk;
+int
+archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *);
+
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
index 5ee89a7..e79008e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_set_standard_lookup.c
@@ -122,6 +122,7 @@ lookup_gid(void *private_data, const char *gname, int64_t gid)
char _buffer[128];
size_t bufsize = 128;
char *buffer = _buffer;
+ char *allocated = NULL;
struct group grent, *result;
int r;
@@ -133,16 +134,15 @@ lookup_gid(void *private_data, const char *gname, int64_t gid)
if (r != ERANGE)
break;
bufsize *= 2;
- if (buffer != _buffer)
- free(buffer);
- buffer = malloc(bufsize);
- if (buffer == NULL)
+ free(allocated);
+ allocated = malloc(bufsize);
+ if (allocated == NULL)
break;
+ buffer = allocated;
}
if (result != NULL)
gid = result->gr_gid;
- if (buffer != _buffer)
- free(buffer);
+ free(allocated);
}
# else /* HAVE_GETGRNAM_R */
{
@@ -158,7 +158,7 @@ lookup_gid(void *private_data, const char *gname, int64_t gid)
#else
#error No way to perform gid lookups on this platform
#endif
- b->id = gid;
+ b->id = (gid_t)gid;
return (gid);
}
@@ -192,6 +192,7 @@ lookup_uid(void *private_data, const char *uname, int64_t uid)
char _buffer[128];
size_t bufsize = 128;
char *buffer = _buffer;
+ char *allocated = NULL;
struct passwd pwent, *result;
int r;
@@ -203,16 +204,15 @@ lookup_uid(void *private_data, const char *uname, int64_t uid)
if (r != ERANGE)
break;
bufsize *= 2;
- if (buffer != _buffer)
- free(buffer);
- buffer = malloc(bufsize);
- if (buffer == NULL)
+ free(allocated);
+ allocated = malloc(bufsize);
+ if (allocated == NULL)
break;
+ buffer = allocated;
}
if (result != NULL)
uid = result->pw_uid;
- if (buffer != _buffer)
- free(buffer);
+ free(allocated);
}
# else /* HAVE_GETPWNAM_R */
{
@@ -228,7 +228,7 @@ lookup_uid(void *private_data, const char *uname, int64_t uid)
#else
#error No way to look up uids on this platform
#endif
- b->id = uid;
+ b->id = (uid_t)uid;
return (uid);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
index 2dc2d92..0f0780a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2010 Tim Kientzle
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,9 +33,6 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
#ifdef HAVE_SYS_UTIME_H
#include <sys/utime.h>
#endif
@@ -48,13 +45,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
-#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
#include <winioctl.h>
/* TODO: Support Mac OS 'quarantine' feature. This is really just a
@@ -89,7 +82,7 @@ static BOOL SetFilePointerEx_perso(HANDLE hFile,
if(lpNewFilePointer) {
lpNewFilePointer->QuadPart = li.QuadPart;
}
- return li.LowPart != -1 || GetLastError() == NO_ERROR;
+ return li.LowPart != (DWORD)-1 || GetLastError() == NO_ERROR;
}
struct fixup_entry {
@@ -144,8 +137,8 @@ struct archive_write_disk {
struct fixup_entry *current_fixup;
int64_t user_uid;
int skip_file_set;
- dev_t skip_file_dev;
- ino_t skip_file_ino;
+ int64_t skip_file_dev;
+ int64_t skip_file_ino;
time_t start_time;
int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
@@ -214,26 +207,24 @@ struct archive_write_disk {
static int check_symlinks(struct archive_write_disk *);
static int create_filesystem_object(struct archive_write_disk *);
-static struct fixup_entry *current_fixup(struct archive_write_disk *, const wchar_t *pathname);
-#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
-static void edit_deep_directories(struct archive_write_disk *ad);
-#endif
+static struct fixup_entry *current_fixup(struct archive_write_disk *,
+ const wchar_t *pathname);
static int cleanup_pathname(struct archive_write_disk *);
static int create_dir(struct archive_write_disk *, wchar_t *);
static int create_parent_dir(struct archive_write_disk *, wchar_t *);
+static int la_chmod(const wchar_t *, mode_t);
static int older(BY_HANDLE_FILE_INFORMATION *, struct archive_entry *);
+static int permissive_name_w(struct archive_write_disk *);
static int restore_entry(struct archive_write_disk *);
-#ifdef HAVE_POSIX_ACL
-static int set_acl(struct archive_write_disk *, int fd, const char *, struct archive_acl *,
- acl_type_t, int archive_entry_acl_type, const char *tn);
-#endif
-static int set_acls(struct archive_write_disk *, HANDLE h, const wchar_t *, struct archive_acl *);
+static int set_acls(struct archive_write_disk *, HANDLE h,
+ const wchar_t *, struct archive_acl *);
static int set_xattrs(struct archive_write_disk *);
static int set_fflags(struct archive_write_disk *);
static int set_ownership(struct archive_write_disk *);
static int set_mode(struct archive_write_disk *, int mode);
-static int set_times(struct archive_write_disk *, HANDLE, int, const wchar_t *,
- time_t, long, time_t, long, time_t, long, time_t, long);
+static int set_times(struct archive_write_disk *, HANDLE, int,
+ const wchar_t *, time_t, long, time_t, long, time_t,
+ long, time_t, long);
static int set_times_from_entry(struct archive_write_disk *);
static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
static ssize_t write_data_block(struct archive_write_disk *,
@@ -243,11 +234,14 @@ static struct archive_vtable *archive_write_disk_vtable(void);
static int _archive_write_disk_close(struct archive *);
static int _archive_write_disk_free(struct archive *);
-static int _archive_write_disk_header(struct archive *, struct archive_entry *);
+static int _archive_write_disk_header(struct archive *,
+ struct archive_entry *);
static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
static int _archive_write_disk_finish_entry(struct archive *);
-static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t);
-static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t);
+static ssize_t _archive_write_disk_data(struct archive *, const void *,
+ size_t);
+static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
+ size_t, int64_t);
#define bhfi_dev(bhfi) ((bhfi)->dwVolumeSerialNumber)
/* Treat FileIndex as i-node. We should remove a sequence number
@@ -361,7 +355,7 @@ file_information(struct archive_write_disk *a, wchar_t *path,
* So we have to make the full-pathname in another way, which does not
* break "../" path string.
*/
-int
+static int
permissive_name_w(struct archive_write_disk *a)
{
wchar_t *wn, *wnp;
@@ -424,10 +418,12 @@ permissive_name_w(struct archive_write_disk *a)
wn = _wcsdup(wnp);
if (wn == NULL)
return (-1);
- archive_wstring_ensure(&(a->_name_data), 8 + wcslen(wn) + 1);
+ archive_wstring_ensure(&(a->_name_data),
+ 8 + wcslen(wn) + 1);
a->name = a->_name_data.s;
/* Prepend "\\?\UNC\" */
- archive_wstrncpy(&(a->_name_data), L"\\\\?\\UNC\\", 8);
+ archive_wstrncpy(&(a->_name_data),
+ L"\\\\?\\UNC\\", 8);
archive_wstrcat(&(a->_name_data), wn+2);
free(wn);
return (0);
@@ -457,7 +453,8 @@ permissive_name_w(struct archive_write_disk *a)
wn = _wcsdup(wnp);
if (wn == NULL)
return (-1);
- archive_wstring_ensure(&(a->_name_data), 4 + 2 + wcslen(wn) + 1);
+ archive_wstring_ensure(&(a->_name_data),
+ 4 + 2 + wcslen(wn) + 1);
a->name = a->_name_data.s;
/* Prepend "\\?\" and drive name. */
archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
@@ -484,7 +481,7 @@ permissive_name_w(struct archive_write_disk *a)
return (0);
}
-int
+static int
la_chmod(const wchar_t *path, mode_t mode)
{
DWORD attr;
@@ -610,7 +607,7 @@ lazy_stat(struct archive_write_disk *a)
/*
* XXX At this point, symlinks should not be hit, otherwise
- * XXX a race occured. Do we want to check explicitly for that?
+ * XXX a race occurred. Do we want to check explicitly for that?
*/
if (file_information(a, a->name, &a->st, NULL, 1) == 0) {
a->pst = &a->st;
@@ -917,6 +914,7 @@ archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
static ssize_t
write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
{
+ OVERLAPPED ol;
uint64_t start_size = size;
DWORD bytes_written = 0;
ssize_t block_size = 0, bytes_to_write;
@@ -968,26 +966,13 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
* truncate it to the block boundary. */
bytes_to_write = size;
if (a->offset + bytes_to_write > block_end)
- bytes_to_write = block_end - a->offset;
+ bytes_to_write = (DWORD)(block_end - a->offset);
}
- /* Seek if necessary to the specified offset. */
- if (a->offset != a->fd_offset) {
- LARGE_INTEGER distance;
- distance.QuadPart = a->offset;
- if (SetFilePointerEx_perso(a->fh, distance, NULL, FILE_BEGIN) == 0) {
- DWORD lasterr = GetLastError();
- if (lasterr == ERROR_ACCESS_DENIED)
- errno = EBADF;
- else
- la_dosmaperr(lasterr);
- archive_set_error(&a->archive, errno,
- "Seek failed");
- return (ARCHIVE_FATAL);
- }
- a->fd_offset = a->offset;
- }
+ memset(&ol, 0, sizeof(ol));
+ ol.Offset = (DWORD)(a->offset & 0xFFFFFFFF);
+ ol.OffsetHigh = (DWORD)(a->offset >> 32);
if (!WriteFile(a->fh, buff, (uint32_t)bytes_to_write,
- &bytes_written, NULL)) {
+ &bytes_written, &ol)) {
DWORD lasterr;
lasterr = GetLastError();
@@ -1004,7 +989,7 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
a->offset += bytes_written;
a->fd_offset = a->offset;
}
- return (start_size - size);
+ return ((ssize_t)(start_size - size));
}
static ssize_t
@@ -1062,48 +1047,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
/* Last write ended at exactly the filesize; we're done. */
/* Hopefully, this is the common case. */
} else {
- if (la_ftruncate(a->fh, a->filesize) == -1 &&
- a->filesize == 0) {
+ if (la_ftruncate(a->fh, a->filesize) == -1) {
archive_set_error(&a->archive, errno,
"File size could not be restored");
return (ARCHIVE_FAILED);
}
- /*
- * Not all platforms implement the XSI option to
- * extend files via ftruncate. Stat() the file again
- * to see what happened.
- */
- a->pst = NULL;
- if ((ret = lazy_stat(a)) != ARCHIVE_OK)
- return (ret);
- /* We can use lseek()/write() to extend the file if
- * ftruncate didn't work or isn't available. */
- if (bhfi_size(&(a->st)) < a->filesize) {
- const char nul = '\0';
- LARGE_INTEGER distance;
- distance.QuadPart = a->filesize - 1;
- if (!SetFilePointerEx_perso(a->fh, distance, NULL, FILE_BEGIN)) {
- DWORD lasterr = GetLastError();
- if (lasterr == ERROR_ACCESS_DENIED)
- errno = EBADF;
- else
- la_dosmaperr(lasterr);
- archive_set_error(&a->archive, errno,
- "Seek failed");
- return (ARCHIVE_FATAL);
- }
- if (!WriteFile(a->fh, &nul, 1, NULL, NULL)) {
- DWORD lasterr = GetLastError();
- if (lasterr == ERROR_ACCESS_DENIED)
- errno = EBADF;
- else
- la_dosmaperr(lasterr);
- archive_set_error(&a->archive, errno,
- "Write to restore size failed");
- return (ARCHIVE_FATAL);
- }
- a->pst = NULL;
- }
}
/* Restore metadata. */
@@ -1430,7 +1378,8 @@ restore_entry(struct archive_write_disk *a)
if (a->skip_file_set &&
bhfi_dev(&a->st) == a->skip_file_dev &&
bhfi_ino(&a->st) == a->skip_file_ino) {
- archive_set_error(&a->archive, 0, "Refusing to overwrite archive");
+ archive_set_error(&a->archive, 0,
+ "Refusing to overwrite archive");
return (ARCHIVE_FAILED);
}
@@ -1471,7 +1420,7 @@ restore_entry(struct archive_write_disk *a)
if (en) {
/* Everything failed; give up here. */
- archive_set_error(&a->archive, en, "Can't create '%s'",
+ archive_set_error(&a->archive, en, "Can't create '%ls'",
a->name);
return (ARCHIVE_FAILED);
}
@@ -1520,7 +1469,7 @@ create_filesystem_object(struct archive_write_disk *a)
*
* If the hardlink was successfully created and
* the archive doesn't have carry data for it,
- * consider it to be non-authoritive for meta data.
+ * consider it to be non-authoritative for meta data.
* This is consistent with GNU tar and BSD pax.
* If the hardlink does carry data, let the last
* archive entry decide ownership.
@@ -1562,7 +1511,7 @@ create_filesystem_object(struct archive_write_disk *a)
* that SUID, SGID, etc, require additional work to ensure
* security, so we never restore them at this point.
*/
- mode = final_mode & 0777 & a->user_umask;
+ mode = final_mode & 0777 & ~a->user_umask;
switch (a->mode & AE_IFMT) {
default:
@@ -1881,7 +1830,7 @@ check_symlinks(struct archive_write_disk *a)
*/
if (disk_unlink(a->name)) {
archive_set_error(&a->archive, errno,
- "Could not remove symlink %s",
+ "Could not remove symlink %ls",
a->name);
pn[0] = c;
return (ARCHIVE_FAILED);
@@ -1895,7 +1844,7 @@ check_symlinks(struct archive_write_disk *a)
*/
if (!S_ISLNK(a->mode)) {
archive_set_error(&a->archive, 0,
- "Removing symlink %s",
+ "Removing symlink %ls",
a->name);
}
/* Symlink gone. No more problem! */
@@ -1905,15 +1854,15 @@ check_symlinks(struct archive_write_disk *a)
/* User asked us to remove problems. */
if (disk_unlink(a->name) != 0) {
archive_set_error(&a->archive, 0,
- "Cannot remove intervening symlink %s",
- a->name);
+ "Cannot remove intervening "
+ "symlink %ls", a->name);
pn[0] = c;
return (ARCHIVE_FAILED);
}
a->pst = NULL;
} else {
archive_set_error(&a->archive, 0,
- "Cannot extract through symlink %s",
+ "Cannot extract through symlink %ls",
a->name);
pn[0] = c;
return (ARCHIVE_FAILED);
@@ -2184,19 +2133,20 @@ create_dir(struct archive_write_disk *a, wchar_t *path)
return (ARCHIVE_OK);
if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
archive_set_error(&a->archive, EEXIST,
- "Can't create directory '%s'", path);
+ "Can't create directory '%ls'", path);
return (ARCHIVE_FAILED);
}
if (disk_unlink(path) != 0) {
archive_set_error(&a->archive, errno,
- "Can't create directory '%s': "
+ "Can't create directory '%ls': "
"Conflicting file cannot be removed",
path);
return (ARCHIVE_FAILED);
}
} else if (errno != ENOENT && errno != ENOTDIR) {
/* Stat failed? */
- archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
+ archive_set_error(&a->archive, errno,
+ "Can't test directory '%ls'", path);
return (ARCHIVE_FAILED);
} else if (slash != NULL) {
*slash = '\0';
@@ -2245,10 +2195,11 @@ create_dir(struct archive_write_disk *a, wchar_t *path)
* don't add it to the fixup list here, as it's already been
* added.
*/
- if (file_information(a, path, &st, &st_mode, 0) == 0 && S_ISDIR(st_mode))
+ if (file_information(a, path, &st, &st_mode, 0) == 0 &&
+ S_ISDIR(st_mode))
return (ARCHIVE_OK);
- archive_set_error(&a->archive, errno, "Failed to create dir '%s'",
+ archive_set_error(&a->archive, errno, "Failed to create dir '%ls'",
path);
return (ARCHIVE_FAILED);
}
@@ -2277,7 +2228,7 @@ set_ownership(struct archive_write_disk *a)
}
archive_set_error(&a->archive, errno,
- "Can't set user=%jd/group=%jd for %s",
+ "Can't set user=%jd/group=%jd for %ls",
(intmax_t)a->uid, (intmax_t)a->gid, a->name);
return (ARCHIVE_WARN);
}
@@ -2288,7 +2239,7 @@ set_times(struct archive_write_disk *a,
time_t atime, long atime_nanos,
time_t birthtime, long birthtime_nanos,
time_t mtime, long mtime_nanos,
- time_t ctime, long ctime_nanos)
+ time_t ctime_sec, long ctime_nanos)
{
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
@@ -2299,7 +2250,7 @@ set_times(struct archive_write_disk *a,
FILETIME *pfbtime;
FILETIME fatime, fbtime, fmtime;
- (void)ctime; /* UNUSED */
+ (void)ctime_sec; /* UNUSED */
(void)ctime_nanos; /* UNUSED */
if (h != INVALID_HANDLE_VALUE) {
@@ -2350,11 +2301,11 @@ settimes_failed:
static int
set_times_from_entry(struct archive_write_disk *a)
{
- time_t atime, birthtime, mtime, ctime;
+ time_t atime, birthtime, mtime, ctime_sec;
long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
/* Suitable defaults. */
- atime = birthtime = mtime = ctime = a->start_time;
+ atime = birthtime = mtime = ctime_sec = a->start_time;
atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
/* If no time was provided, we're done. */
@@ -2376,7 +2327,7 @@ set_times_from_entry(struct archive_write_disk *a)
mtime_nsec = archive_entry_mtime_nsec(a->entry);
}
if (archive_entry_ctime_is_set(a->entry)) {
- ctime = archive_entry_ctime(a->entry);
+ ctime_sec = archive_entry_ctime(a->entry);
ctime_nsec = archive_entry_ctime_nsec(a->entry);
}
@@ -2384,7 +2335,7 @@ set_times_from_entry(struct archive_write_disk *a)
atime, atime_nsec,
birthtime, birthtime_nsec,
mtime, mtime_nsec,
- ctime, ctime_nsec);
+ ctime_sec, ctime_nsec);
}
static int
@@ -2507,7 +2458,7 @@ set_xattrs(struct archive_write_disk *a)
}
static void
-fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
+fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
{
ULARGE_INTEGER utc;
@@ -2516,11 +2467,11 @@ fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
/* milli seconds base */
- *time = (time_t)(utc.QuadPart / 10000000);
+ *t = (time_t)(utc.QuadPart / 10000000);
/* nano seconds base */
*ns = (long)(utc.QuadPart % 10000000) * 100;
} else {
- *time = 0;
+ *t = 0;
*ns = 0;
}
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_filter.3 b/Utilities/cmlibarchive/libarchive/archive_write_filter.3
index 00438d4..3ca248b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_filter.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_filter.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_FILTER 3
.Os
.Sh NAME
@@ -36,6 +36,8 @@
.Nm archive_write_add_filter_none ,
.Nm archive_write_add_filter_program ,
.Nm archive_write_add_filter_xz
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 b/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3
index 3add601..d881c80 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3
@@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_FINISH_ENTRY 3
.Os
.Sh NAME
.Nm archive_write_finish_entry
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_format.3 b/Utilities/cmlibarchive/libarchive/archive_write_format.3
index e12e7d8..dad2f7d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_format.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_format.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_FORMAT 3
.Os
.Sh NAME
@@ -35,6 +35,8 @@
.Nm archive_write_set_format_shar_dump ,
.Nm archive_write_set_format_ustar
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_free.3 b/Utilities/cmlibarchive/libarchive/archive_write_free.3
index 27efe18..1b2d071 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_free.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_free.3
@@ -24,17 +24,22 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_FREE 3
.Os
.Sh NAME
+.Nm archive_write_fail ,
.Nm archive_write_close ,
.Nm archive_write_finish ,
.Nm archive_write_free
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
+.Fn archive_write_fail "struct archive *"
+.Ft int
.Fn archive_write_close "struct archive *"
.Ft int
.Fn archive_write_finish "struct archive *"
@@ -42,6 +47,16 @@
.Fn archive_write_free "struct archive *"
.Sh DESCRIPTION
.Bl -tag -width indent
+.It Fn archive_write_fail
+Always returns
+.Cm ARCHIVE_FATAL .
+This marks the archive object as being unusable;
+after calling this function, the only call that can succeed is
+.Fn archive_write_free
+to release the resources.
+This can be used to speed recovery when the archive creation
+must be aborted.
+Note that the created archive is likely to be malformed in this case;
.It Fn archive_write_close
Complete the archive and invoke the close callback.
.It Fn archive_write_finish
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_header.3 b/Utilities/cmlibarchive/libarchive/archive_write_header.3
index 423b38e..4de58f3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_header.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_header.3
@@ -24,12 +24,14 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_HEADER 3
.Os
.Sh NAME
.Nm archive_write_header
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_new.3 b/Utilities/cmlibarchive/libarchive/archive_write_new.3
index d626ccb..f05d269 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_new.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_new.3
@@ -24,12 +24,14 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 23, 2011
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_NEW 3
.Os
.Sh NAME
.Nm archive_write_new
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open.3 b/Utilities/cmlibarchive/libarchive/archive_write_open.3
index 0d12cb3..4037248 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open.3
@@ -22,10 +22,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd March 23, 2011
-.Dt ARCHIVE_WRITE 3
+.Dd February 2, 2012
+.Dt ARCHIVE_WRITE_OPEN 3
.Os
.Sh NAME
.Nm archive_write_open ,
@@ -34,6 +34,8 @@
.Nm archive_write_open_filename ,
.Nm archive_write_open_memory
.Nd functions for creating archives
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c
index 8689866..196b770 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c
@@ -46,24 +46,25 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_filename.c 191165 200
#endif
#include "archive.h"
+#include "archive_private.h"
#include "archive_string.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
struct write_file_data {
int fd;
- char mbs_filename;
- union {
- char m[1];
- wchar_t w[1];
- } filename; /* Must be last! */
+ struct archive_mstring filename;
};
static int file_close(struct archive *, void *);
static int file_open(struct archive *, void *);
static ssize_t file_write(struct archive *, void *, const void *buff, size_t);
+static int open_filename(struct archive *, int, const void *);
int
archive_write_open_file(struct archive *a, const char *filename)
@@ -74,123 +75,122 @@ archive_write_open_file(struct archive *a, const char *filename)
int
archive_write_open_filename(struct archive *a, const char *filename)
{
- struct write_file_data *mine;
if (filename == NULL || filename[0] == '\0')
return (archive_write_open_fd(a, 1));
- mine = (struct write_file_data *)malloc(sizeof(*mine) + strlen(filename));
- if (mine == NULL) {
- archive_set_error(a, ENOMEM, "No memory");
- return (ARCHIVE_FATAL);
- }
- strcpy(mine->filename.m, filename);
- mine->mbs_filename = 1;
- mine->fd = -1;
- return (archive_write_open(a, mine,
- file_open, file_write, file_close));
+ return (open_filename(a, 1, filename));
}
int
archive_write_open_filename_w(struct archive *a, const wchar_t *filename)
{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- struct write_file_data *mine;
if (filename == NULL || filename[0] == L'\0')
return (archive_write_open_fd(a, 1));
- mine = malloc(sizeof(*mine) + wcslen(filename) * sizeof(wchar_t));
+ return (open_filename(a, 0, filename));
+}
+
+static int
+open_filename(struct archive *a, int mbs_fn, const void *filename)
+{
+ struct write_file_data *mine;
+ int r;
+
+ mine = (struct write_file_data *)calloc(1, sizeof(*mine));
if (mine == NULL) {
archive_set_error(a, ENOMEM, "No memory");
return (ARCHIVE_FATAL);
}
- wcscpy(mine->filename.w, filename);
- mine->mbs_filename = 0;
+ if (mbs_fn)
+ r = archive_mstring_copy_mbs(&mine->filename, filename);
+ else
+ r = archive_mstring_copy_wcs(&mine->filename, filename);
+ if (r < 0) {
+ if (errno == ENOMEM) {
+ archive_set_error(a, ENOMEM, "No memory");
+ return (ARCHIVE_FATAL);
+ }
+ if (mbs_fn)
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Can't convert '%s' to WCS",
+ (const char *)filename);
+ else
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Can't convert '%S' to MBS",
+ (const wchar_t *)filename);
+ return (ARCHIVE_FAILED);
+ }
mine->fd = -1;
return (archive_write_open(a, mine,
file_open, file_write, file_close));
-#else
- /*
- * POSIX system does not support a wchar_t interface for
- * open() system call, so we have to translate a wchar_t
- * filename to multi-byte one and use it.
- */
- struct archive_string fn;
- int r;
-
- if (filename == NULL || filename[0] == L'\0')
- return (archive_write_open_fd(a, 1));
-
- archive_string_init(&fn);
- if (archive_string_append_from_wcs(&fn, filename,
- wcslen(filename)) != 0) {
- archive_set_error(a, EINVAL,
- "Failed to convert a wide-character filename to"
- " a multi-byte filename");
- archive_string_free(&fn);
- return (ARCHIVE_FATAL);
- }
- r = archive_write_open_filename(a, fn.s);
- archive_string_free(&fn);
- return (r);
-#endif
}
-
static int
file_open(struct archive *a, void *client_data)
{
int flags;
struct write_file_data *mine;
struct stat st;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ wchar_t *fullpath;
+#endif
+ const wchar_t *wcs;
+ const char *mbs;
mine = (struct write_file_data *)client_data;
- flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY;
+ flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC;
/*
* Open the file.
*/
- if (mine->mbs_filename) {
- mine->fd = open(mine->filename.m, flags, 0666);
- if (mine->fd < 0) {
- archive_set_error(a, errno, "Failed to open '%s'",
- mine->filename.m);
- return (ARCHIVE_FATAL);
- }
-
- if (fstat(mine->fd, &st) != 0) {
- archive_set_error(a, errno, "Couldn't stat '%s'",
- mine->filename.m);
- return (ARCHIVE_FATAL);
- }
- } else {
+ mbs = NULL; wcs = NULL;
#if defined(_WIN32) && !defined(__CYGWIN__)
- mine->fd = _wopen(mine->filename.w, flags, 0666);
- if (mine->fd < 0 && errno == ENOENT) {
- wchar_t *fullpath;
- fullpath = __la_win_permissive_name_w(mine->filename.w);
- if (fullpath != NULL) {
- mine->fd = _wopen(fullpath, flags, 0666);
- free(fullpath);
- }
- }
- if (mine->fd < 0) {
- archive_set_error(a, errno, "Failed to open '%S'",
- mine->filename.w);
- return (ARCHIVE_FATAL);
- }
-
- if (fstat(mine->fd, &st) != 0) {
- archive_set_error(a, errno, "Couldn't stat '%S'",
- mine->filename.w);
- return (ARCHIVE_FATAL);
+ if (archive_mstring_get_wcs(a, &mine->filename, &wcs) != 0) {
+ if (errno == ENOMEM)
+ archive_set_error(a, errno, "No memory");
+ else {
+ archive_mstring_get_mbs(a, &mine->filename, &mbs);
+ archive_set_error(a, errno,
+ "Can't convert '%s' to WCS", mbs);
}
+ return (ARCHIVE_FATAL);
+ }
+ fullpath = __la_win_permissive_name_w(wcs);
+ if (fullpath != NULL) {
+ mine->fd = _wopen(fullpath, flags, 0666);
+ free(fullpath);
+ } else
+ mine->fd = _wopen(wcs, flags, 0666);
#else
- archive_set_error(a, ARCHIVE_ERRNO_MISC,
- "Unexpedted operation in archive_write_open_filename");
+ if (archive_mstring_get_mbs(a, &mine->filename, &mbs) != 0) {
+ if (errno == ENOMEM)
+ archive_set_error(a, errno, "No memory");
+ else {
+ archive_mstring_get_wcs(a, &mine->filename, &wcs);
+ archive_set_error(a, errno,
+ "Can't convert '%S' to MBS", wcs);
+ }
return (ARCHIVE_FATAL);
+ }
+ mine->fd = open(mbs, flags, 0666);
+ __archive_ensure_cloexec_flag(mine->fd);
#endif
+ if (mine->fd < 0) {
+ if (mbs != NULL)
+ archive_set_error(a, errno, "Failed to open '%s'", mbs);
+ else
+ archive_set_error(a, errno, "Failed to open '%S'", wcs);
+ return (ARCHIVE_FATAL);
+ }
+
+ if (fstat(mine->fd, &st) != 0) {
+ if (mbs != NULL)
+ archive_set_error(a, errno, "Couldn't stat '%s'", mbs);
+ else
+ archive_set_error(a, errno, "Couldn't stat '%S'", wcs);
+ return (ARCHIVE_FATAL);
}
/*
@@ -218,7 +218,8 @@ file_open(struct archive *a, void *client_data)
}
static ssize_t
-file_write(struct archive *a, void *client_data, const void *buff, size_t length)
+file_write(struct archive *a, void *client_data, const void *buff,
+ size_t length)
{
struct write_file_data *mine;
ssize_t bytesWritten;
@@ -243,6 +244,7 @@ file_close(struct archive *a, void *client_data)
(void)a; /* UNUSED */
close(mine->fd);
+ archive_mstring_clean(&mine->filename);
free(mine);
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_private.h b/Utilities/cmlibarchive/libarchive/archive_write_private.h
index 91284cf..e600d54 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_write_private.h
@@ -72,7 +72,7 @@ struct archive_write {
/* Dev/ino of the archive being written. */
int skip_file_set;
- dev_t skip_file_dev;
+ int64_t skip_file_dev;
int64_t skip_file_ino;
/* Utility: Pointer to a block of nulls. */
@@ -133,4 +133,13 @@ __archive_write_format_header_ustar(struct archive_write *, char buff[512],
struct archive_entry *, int tartype, int strict,
struct archive_string_conv *);
+struct archive_write_program_data;
+struct archive_write_program_data * __archive_write_program_allocate(void);
+int __archive_write_program_free(struct archive_write_program_data *);
+int __archive_write_program_open(struct archive_write_filter *,
+ struct archive_write_program_data *, const char *);
+int __archive_write_program_close(struct archive_write_filter *,
+ struct archive_write_program_data *);
+int __archive_write_program_write(struct archive_write_filter *,
+ struct archive_write_program_data *, const void *, size_t);
#endif
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
index b6589dd..4f1bc26 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -199,7 +199,7 @@ struct _7zip {
/*
* Compressed data buffer.
*/
- unsigned char wbuff[1024 * 64];
+ unsigned char wbuff[512 * 20 * 6];
size_t wbuff_remaining;
/*
@@ -405,7 +405,7 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
value[1] != '\0') {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
- "Illeagal value `%s'",
+ "Illegal value `%s'",
value);
return (ARCHIVE_FAILED);
}
@@ -413,7 +413,10 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
return (ARCHIVE_OK);
}
- return (ARCHIVE_FAILED);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -439,6 +442,14 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry)
file_free(file);
return (r);
}
+ if (file->size == 0 && file->dir) {
+ if (!__archive_rb_tree_insert_node(&(zip->rbtree),
+ (struct archive_rb_node *)file)) {
+ /* We have already had the same file. */
+ file_free(file);
+ return (ARCHIVE_OK);
+ }
+ }
if (file->flg & MTIME_IS_SET)
zip->total_number_time_defined[MTIME]++;
@@ -447,11 +458,6 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry)
if (file->flg & ATIME_IS_SET)
zip->total_number_time_defined[ATIME]++;
- if (file->size == 0 && file->dir) {
- if (!__archive_rb_tree_insert_node(&(zip->rbtree),
- (struct archive_rb_node *)file))
- file_free(file);
- }
zip->total_number_entry++;
zip->total_bytes_entry_name += file->name_len + 2;
if (file->size == 0) {
@@ -495,10 +501,10 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry)
if (archive_entry_filetype(entry) == AE_IFLNK) {
ssize_t bytes;
const void *p = (const void *)archive_entry_symlink(entry);
- bytes = compress_out(a, p, file->size, ARCHIVE_Z_RUN);
+ bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN);
if (bytes < 0)
return ((int)bytes);
- zip->entry_crc32 = crc32(zip->entry_crc32, p, bytes);
+ zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes);
zip->entry_bytes_remaining -= bytes;
}
@@ -512,7 +518,7 @@ static int
write_to_temp(struct archive_write *a, const void *buff, size_t s)
{
struct _7zip *zip;
- unsigned char *p;
+ const unsigned char *p;
ssize_t ws;
zip = (struct _7zip *)a->format_data;
@@ -530,7 +536,7 @@ write_to_temp(struct archive_write *a, const void *buff, size_t s)
}
}
- p = (unsigned char *)buff;
+ p = (const unsigned char *)buff;
while (s) {
ws = write(zip->temp_fd, p, s);
if (ws < 0) {
@@ -556,10 +562,11 @@ compress_out(struct archive_write *a, const void *buff, size_t s,
return (0);
if ((zip->crc32flg & PRECODE_CRC32) && s)
- zip->precode_crc32 = crc32(zip->precode_crc32, buff, s);
+ zip->precode_crc32 = crc32(zip->precode_crc32, buff,
+ (unsigned)s);
zip->stream.next_in = (const unsigned char *)buff;
zip->stream.avail_in = s;
- do {
+ for (;;) {
/* Compress file data. */
r = compression_code(&(a->archive), &(zip->stream), run);
if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
@@ -573,15 +580,19 @@ compress_out(struct archive_write *a, const void *buff, size_t s,
if (zip->crc32flg & ENCODED_CRC32)
zip->encoded_crc32 = crc32(zip->encoded_crc32,
zip->wbuff, sizeof(zip->wbuff));
+ if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF)
+ continue;
}
- } while (zip->stream.avail_in);
+ if (zip->stream.avail_in == 0)
+ break;
+ }
if (run == ARCHIVE_Z_FINISH) {
uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out;
- if (write_to_temp(a, zip->wbuff, bytes) != ARCHIVE_OK)
+ if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
if ((zip->crc32flg & ENCODED_CRC32) && bytes)
zip->encoded_crc32 = crc32(zip->encoded_crc32,
- zip->wbuff, bytes);
+ zip->wbuff, (unsigned)bytes);
}
return (s);
@@ -596,13 +607,13 @@ _7z_write_data(struct archive_write *a, const void *buff, size_t s)
zip = (struct _7zip *)a->format_data;
if (s > zip->entry_bytes_remaining)
- s = zip->entry_bytes_remaining;
+ s = (size_t)zip->entry_bytes_remaining;
if (s == 0 || zip->cur_file == NULL)
return (0);
bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN);
if (bytes < 0)
return (bytes);
- zip->entry_crc32 = crc32(zip->entry_crc32, buff, bytes);
+ zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes);
zip->entry_bytes_remaining -= bytes;
return (bytes);
}
@@ -619,12 +630,12 @@ _7z_finish_entry(struct archive_write *a)
return (ARCHIVE_OK);
while (zip->entry_bytes_remaining > 0) {
- s = zip->entry_bytes_remaining;
+ s = (size_t)zip->entry_bytes_remaining;
if (s > a->null_length)
s = a->null_length;
r = _7z_write_data(a, a->nulls, s);
if (r < 0)
- return (r);
+ return ((int)r);
}
zip->total_bytes_compressed += zip->stream.total_in;
zip->total_bytes_uncompressed += zip->stream.total_out;
@@ -727,8 +738,10 @@ _7z_close(struct archive_write *a)
zip->total_number_entry - zip->total_number_empty_entry;
/* Connect an empty file list. */
- *zip->file_list.last = zip->empty_list.first;
- zip->file_list.last = zip->empty_list.last;
+ if (zip->empty_list.first != NULL) {
+ *zip->file_list.last = zip->empty_list.first;
+ zip->file_list.last = zip->empty_list.last;
+ }
/* Connect a directory file list. */
ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) {
file_register(zip, (struct file *)n);
@@ -844,7 +857,7 @@ enc_uint64(struct archive_write *a, uint64_t val)
int i;
numdata[0] = 0;
- for (i = 1; i < sizeof(numdata); i++) {
+ for (i = 1; i < (int)sizeof(numdata); i++) {
if (val < mask) {
numdata[0] |= (uint8_t)val;
break;
@@ -854,7 +867,7 @@ enc_uint64(struct archive_write *a, uint64_t val)
numdata[0] |= mask;
mask >>= 1;
}
- return (compress_out(a, numdata, i, ARCHIVE_Z_RUN));
+ return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN));
}
static int
@@ -919,7 +932,7 @@ make_substreamsInfo(struct archive_write *a, struct coder *coders)
if (file->size == 0)
break;
archive_le32enc(crc, file->crc32);
- r = compress_out(a, crc, 4, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
}
@@ -943,7 +956,7 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
int i, r;
if (coders->codec == _7Z_COPY)
- numFolders = zip->total_number_nonempty_entry;
+ numFolders = (int)zip->total_number_nonempty_entry;
else
numFolders = 1;
@@ -1039,7 +1052,7 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
/* Write Codec ID. */
codec_size &= 0x0f;
- r = compress_out(a, &codec_buff[8-codec_size],
+ r = (int)compress_out(a, &codec_buff[8-codec_size],
codec_size, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
@@ -1051,7 +1064,7 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
return (r);
/* Write Codec properties. */
- r = compress_out(a, coders[i].props,
+ r = (int)compress_out(a, coders[i].props,
coders[i].prop_size, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
@@ -1097,7 +1110,7 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
if (r < 0)
return (r);
archive_le32enc(crc, header_crc);
- r = compress_out(a, crc, 4, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
}
@@ -1128,11 +1141,11 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
static uint64_t
-utcToFiletime(time_t time, long ns)
+utcToFiletime(time_t t, long ns)
{
uint64_t fileTime;
- fileTime = time;
+ fileTime = t;
fileTime *= 10000000;
fileTime += ns / 100;
fileTime += EPOC_TIME;
@@ -1146,7 +1159,7 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
struct _7zip *zip = (struct _7zip *)a->format_data;
struct file *file;
int r;
- uint8_t mask, byte;
+ uint8_t b, mask;
/*
* Make Time Bools.
@@ -1183,23 +1196,23 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
if (r < 0)
return (r);
- byte = 0;
+ b = 0;
mask = 0x80;
file = zip->file_list.first;
for (;file != NULL; file = file->next) {
if (file->flg & flg)
- byte |= mask;
+ b |= mask;
mask >>= 1;
if (mask == 0) {
- r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
mask = 0x80;
- byte = 0;
+ b = 0;
}
}
if (mask != 0x80) {
- r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
}
@@ -1220,7 +1233,7 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
continue;
archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
file->times[ti].time_ns));
- r = compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
}
@@ -1235,7 +1248,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
struct _7zip *zip = (struct _7zip *)a->format_data;
struct file *file;
int r;
- uint8_t mask, byte;
+ uint8_t b, mask;
/*
* Make FilesInfo.
@@ -1283,23 +1296,23 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
if (r < 0)
return (r);
- byte = 0;
+ b = 0;
mask = 0x80;
file = zip->file_list.first;
for (;file != NULL; file = file->next) {
if (file->size == 0)
- byte |= mask;
+ b |= mask;
mask >>= 1;
if (mask == 0) {
- r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
mask = 0x80;
- byte = 0;
+ b = 0;
}
}
if (mask != 0x80) {
- r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
}
@@ -1316,25 +1329,25 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
if (r < 0)
return (r);
- byte = 0;
+ b = 0;
mask = 0x80;
file = zip->file_list.first;
for (;file != NULL; file = file->next) {
if (file->size)
continue;
if (!file->dir)
- byte |= mask;
+ b |= mask;
mask >>= 1;
if (mask == 0) {
- r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
mask = 0x80;
- byte = 0;
+ b = 0;
}
}
if (mask != 0x80) {
- r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
}
@@ -1357,7 +1370,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
file = zip->file_list.first;
for (;file != NULL; file = file->next) {
- r = compress_out(a, file->utf16name, file->name_len+2,
+ r = (int)compress_out(a, file->utf16name, file->name_len+2,
ARCHIVE_Z_RUN);
if (r < 0)
return (r);
@@ -1413,7 +1426,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
attr |= 1;/* Read Only. */
attr |= ((uint32_t)file->mode) << 16;
archive_le32enc(&encattr, attr);
- r = compress_out(a, &encattr, 4, ARCHIVE_Z_RUN);
+ r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN);
if (r < 0)
return (r);
}
@@ -1449,8 +1462,8 @@ static int
file_cmp_node(const struct archive_rb_node *n1,
const struct archive_rb_node *n2)
{
- struct file *f1 = (struct file *)n1;
- struct file *f2 = (struct file *)n2;
+ const struct file *f1 = (const struct file *)n1;
+ const struct file *f2 = (const struct file *)n2;
if (f1->name_len == f2->name_len)
return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
@@ -1460,7 +1473,7 @@ file_cmp_node(const struct archive_rb_node *n1,
static int
file_cmp_key(const struct archive_rb_node *n, const void *key)
{
- struct file *f = (struct file *)n;
+ const struct file *f = (const struct file *)n;
return (f->name_len - *(const char *)key);
}
@@ -1487,6 +1500,7 @@ file_new(struct archive_write *a, struct archive_entry *entry,
if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) {
if (errno == ENOMEM) {
+ free(file);
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for UTF-16LE");
return (ARCHIVE_FATAL);
@@ -1498,6 +1512,7 @@ file_new(struct archive_write *a, struct archive_entry *entry,
}
file->utf16name = malloc(u16len + 2);
if (file->utf16name == NULL) {
+ free(file);
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Name");
return (ARCHIVE_FATAL);
@@ -1505,7 +1520,7 @@ file_new(struct archive_write *a, struct archive_entry *entry,
memcpy(file->utf16name, u16, u16len);
file->utf16name[u16len+0] = 0;
file->utf16name[u16len+1] = 0;
- file->name_len = u16len;
+ file->name_len = (unsigned)u16len;
file->mode = archive_entry_mode(entry);
if (archive_entry_filetype(entry) == AE_IFREG)
file->size = archive_entry_size(entry);
@@ -1585,7 +1600,8 @@ file_init_register_empty(struct _7zip *zip)
zip->empty_list.last = &(zip->empty_list.first);
}
-#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
+#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
+ !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
static int
compression_unsupported_encoder(struct archive *a,
struct la_zstream *lastrm, const char *name)
@@ -1669,11 +1685,11 @@ compression_init_encoder_deflate(struct archive *a,
* of ugly hackery to convert a const * pointer to
* a non-const pointer. */
strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
- strm->avail_in = lastrm->avail_in;
- strm->total_in = lastrm->total_in;
+ strm->avail_in = (uInt)lastrm->avail_in;
+ strm->total_in = (uLong)lastrm->total_in;
strm->next_out = lastrm->next_out;
- strm->avail_out = lastrm->avail_out;
- strm->total_out = lastrm->total_out;
+ strm->avail_out = (uInt)lastrm->avail_out;
+ strm->total_out = (uLong)lastrm->total_out;
if (deflateInit2(strm, level, Z_DEFLATED,
(withheader)?15:-15,
8, Z_DEFAULT_STRATEGY) != Z_OK) {
@@ -1702,11 +1718,11 @@ compression_code_deflate(struct archive *a,
* of ugly hackery to convert a const * pointer to
* a non-const pointer. */
strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
- strm->avail_in = lastrm->avail_in;
- strm->total_in = lastrm->total_in;
+ strm->avail_in = (uInt)lastrm->avail_in;
+ strm->total_in = (uLong)lastrm->total_in;
strm->next_out = lastrm->next_out;
- strm->avail_out = lastrm->avail_out;
- strm->total_out = lastrm->total_out;
+ strm->avail_out = (uInt)lastrm->avail_out;
+ strm->total_out = (uLong)lastrm->total_out;
r = deflate(strm,
(action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
lastrm->next_in = strm->next_in;
@@ -1908,6 +1924,7 @@ compression_init_encoder_lzma(struct archive *a,
if (level > 6)
level = 6;
if (lzma_lzma_preset(&lzma_opt, level)) {
+ free(strm);
lastrm->real_stream = NULL;
archive_set_error(a, ENOMEM,
"Internal error initializing compression library");
@@ -2177,6 +2194,8 @@ compression_code_ppmd(struct archive *a,
{
struct ppmd_stream *strm;
+ (void)a; /* UNUSED */
+
strm = (struct ppmd_stream *)lastrm->real_stream;
/* Copy encoded data if there are remaining bytes from previous call. */
@@ -2217,6 +2236,8 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
{
struct ppmd_stream *strm;
+ (void)a; /* UNUSED */
+
strm = (struct ppmd_stream *)lastrm->real_stream;
__archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc);
free(strm->buff);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
index 956b932..9f17564 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ar.c
@@ -165,7 +165,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry)
* Reject files with empty name.
*/
pathname = archive_entry_pathname(entry);
- if (*pathname == '\0') {
+ if (pathname == NULL || *pathname == '\0') {
archive_set_error(&a->archive, EINVAL,
"Invalid filename");
return (ARCHIVE_WARN);
@@ -366,7 +366,7 @@ archive_write_ar_data(struct archive_write *a, const void *buff, size_t s)
ar = (struct ar_w *)a->format_data;
if (s > ar->entry_bytes_remaining)
- s = ar->entry_bytes_remaining;
+ s = (size_t)ar->entry_bytes_remaining;
if (ar->is_strtab > 0) {
if (ar->has_strtab > 0) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c
index 9671f60..af3105e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c
@@ -56,8 +56,10 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "iso", archive_write_set_format_iso9660 },
{ "iso9660", archive_write_set_format_iso9660 },
{ "mtree", archive_write_set_format_mtree },
+ { "mtree-classic", archive_write_set_format_mtree_classic },
{ "newc", archive_write_set_format_cpio_newc },
{ "odc", archive_write_set_format_cpio },
+ { "oldtar", archive_write_set_format_v7tar },
{ "pax", archive_write_set_format_pax },
{ "paxr", archive_write_set_format_pax_restricted },
{ "posix", archive_write_set_format_pax },
@@ -65,6 +67,8 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "shar", archive_write_set_format_shar },
{ "shardump", archive_write_set_format_shar_dump },
{ "ustar", archive_write_set_format_ustar },
+ { "v7tar", archive_write_set_format_v7tar },
+ { "v7", archive_write_set_format_v7tar },
{ "xar", archive_write_set_format_xar },
{ "zip", archive_write_set_format_zip },
{ NULL, NULL }
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
index 92b9bfb..3526493 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -147,11 +148,13 @@ archive_write_cpio_options(struct archive_write *a, const char *key,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "%s: unknown keyword ``%s''", a->format_name, key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
/*
@@ -186,7 +189,7 @@ synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
/* Don't store a mapping if we don't need to. */
if (archive_entry_nlink(entry) < 2) {
- return ++cpio->ino_next;
+ return (int)(++cpio->ino_next);
}
/* Look up old ino; if we have it, this is a hardlink
@@ -197,7 +200,7 @@ synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
}
/* Assign a new index number. */
- ino_new = ++cpio->ino_next;
+ ino_new = (int)(++cpio->ino_next);
/* Ensure space for the new mapping. */
if (cpio->ino_list_size <= cpio->ino_list_next) {
@@ -278,18 +281,37 @@ write_header(struct archive_write *a, struct archive_entry *entry)
int64_t ino;
char h[76];
struct archive_string_conv *sconv;
+ struct archive_entry *entry_main;
size_t len;
cpio = (struct cpio *)a->format_data;
ret_final = ARCHIVE_OK;
sconv = get_sconv(a);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pahtname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ entry_main = __la_win_entry_in_posix_pathseparator(entry);
+ if (entry_main == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ return(ARCHIVE_FATAL);
+ }
+ if (entry != entry_main)
+ entry = entry_main;
+ else
+ entry_main = NULL;
+#else
+ entry_main = NULL;
+#endif
+
ret = archive_entry_pathname_l(entry, &path, &len, sconv);
if (ret != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Pathname");
- return (ARCHIVE_FATAL);
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s",
@@ -308,11 +330,13 @@ write_header(struct archive_write *a, struct archive_entry *entry)
if (ino < 0) {
archive_set_error(&a->archive, ENOMEM,
"No memory for ino translation table");
- return (ARCHIVE_FATAL);
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
} else if (ino > 0777777) {
archive_set_error(&a->archive, ERANGE,
"Too many files for this cpio format");
- return (ARCHIVE_FATAL);
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
}
format_octal(ino & 0777777, h + c_ino_offset, c_ino_size);
@@ -339,7 +363,8 @@ write_header(struct archive_write *a, struct archive_entry *entry)
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Linkname");
- return (ARCHIVE_FATAL);
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate linkname '%s' to %s",
@@ -356,25 +381,35 @@ write_header(struct archive_write *a, struct archive_entry *entry)
if (ret) {
archive_set_error(&a->archive, ERANGE,
"File is too large for cpio format.");
- return (ARCHIVE_FAILED);
+ ret_final = ARCHIVE_FAILED;
+ goto exit_write_header;
}
ret = __archive_write_output(a, h, sizeof(h));
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
ret = __archive_write_output(a, path, pathlength);
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
cpio->entry_bytes_remaining = archive_entry_size(entry);
/* Write the symlink now. */
if (p != NULL && *p != '\0') {
ret = __archive_write_output(a, p, strlen(p));
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
}
+exit_write_header:
+ if (entry_main)
+ archive_entry_free(entry_main);
return (ret_final);
}
@@ -386,7 +421,7 @@ archive_write_cpio_data(struct archive_write *a, const void *buff, size_t s)
cpio = (struct cpio *)a->format_data;
if (s > cpio->entry_bytes_remaining)
- s = cpio->entry_bytes_remaining;
+ s = (size_t)cpio->entry_bytes_remaining;
ret = __archive_write_output(a, buff, s);
cpio->entry_bytes_remaining -= s;
@@ -422,7 +457,7 @@ format_octal_recursive(int64_t v, char *p, int s)
if (s == 0)
return (v);
v = format_octal_recursive(v, p+1, s-1);
- *p = '0' + (v & 7);
+ *p = '0' + ((char)v & 7);
return (v >> 3);
}
@@ -460,5 +495,6 @@ archive_write_cpio_finish_entry(struct archive_write *a)
struct cpio *cpio;
cpio = (struct cpio *)a->format_data;
- return (__archive_write_nulls(a, cpio->entry_bytes_remaining));
+ return (__archive_write_nulls(a,
+ (size_t)cpio->entry_bytes_remaining));
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
index d06c391..a9bfa80 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2006 Rudolf Marek SYSGO s.r.o.
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -154,11 +155,13 @@ archive_write_newc_options(struct archive_write *a, const char *key,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "%s: unknown keyword ``%s''", a->format_name, key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static struct archive_string_conv *
@@ -220,6 +223,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
int pathlength, ret, ret_final;
char h[c_header_size];
struct archive_string_conv *sconv;
+ struct archive_entry *entry_main;
size_t len;
int pad;
@@ -227,12 +231,30 @@ write_header(struct archive_write *a, struct archive_entry *entry)
ret_final = ARCHIVE_OK;
sconv = get_sconv(a);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pahtname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ entry_main = __la_win_entry_in_posix_pathseparator(entry);
+ if (entry_main == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ return(ARCHIVE_FATAL);
+ }
+ if (entry != entry_main)
+ entry = entry_main;
+ else
+ entry_main = NULL;
+#else
+ entry_main = NULL;
+#endif
+
ret = archive_entry_pathname_l(entry, &path, &len, sconv);
if (ret != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Pathname");
- return (ARCHIVE_FATAL);
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s",
@@ -284,7 +306,8 @@ write_header(struct archive_write *a, struct archive_entry *entry)
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Likname");
- return (ARCHIVE_FATAL);
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate linkname '%s' to %s",
@@ -301,37 +324,51 @@ write_header(struct archive_write *a, struct archive_entry *entry)
if (ret) {
archive_set_error(&a->archive, ERANGE,
"File is too large for this format.");
- return (ARCHIVE_FAILED);
+ ret_final = ARCHIVE_FAILED;
+ goto exit_write_header;
}
ret = __archive_write_output(a, h, c_header_size);
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
/* Pad pathname to even length. */
ret = __archive_write_output(a, path, pathlength);
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
pad = PAD4(pathlength + c_header_size);
if (pad) {
ret = __archive_write_output(a, "\0\0\0", pad);
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
}
cpio->entry_bytes_remaining = archive_entry_size(entry);
- cpio->padding = PAD4(cpio->entry_bytes_remaining);
+ cpio->padding = (int)PAD4(cpio->entry_bytes_remaining);
/* Write the symlink now. */
if (p != NULL && *p != '\0') {
ret = __archive_write_output(a, p, strlen(p));
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
pad = PAD4(strlen(p));
ret = __archive_write_output(a, "\0\0\0", pad);
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ if (ret != ARCHIVE_OK) {
+ ret_final = ARCHIVE_FATAL;
+ goto exit_write_header;
+ }
}
+exit_write_header:
+ if (entry_main)
+ archive_entry_free(entry_main);
return (ret_final);
}
@@ -343,7 +380,7 @@ archive_write_newc_data(struct archive_write *a, const void *buff, size_t s)
cpio = (struct cpio *)a->format_data;
if (s > cpio->entry_bytes_remaining)
- s = cpio->entry_bytes_remaining;
+ s = (size_t)cpio->entry_bytes_remaining;
ret = __archive_write_output(a, buff, s);
cpio->entry_bytes_remaining -= s;
@@ -416,5 +453,6 @@ archive_write_newc_finish_entry(struct archive_write *a)
struct cpio *cpio;
cpio = (struct cpio *)a->format_data;
- return (__archive_write_nulls(a, cpio->entry_bytes_remaining + cpio->padding));
+ return (__archive_write_nulls(a,
+ (size_t)cpio->entry_bytes_remaining + cpio->padding));
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
index e091ed2..13942c1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* Author: Jonas Gastal <jgastal@profusion.mobi>
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
*
* All rights reserved.
*
@@ -177,7 +177,8 @@ archive_write_set_format_gnutar(struct archive *_a)
gnutar = (struct gnutar *)calloc(1, sizeof(*gnutar));
if (gnutar == NULL) {
- archive_set_error(&a->archive, ENOMEM, "Can't allocate gnutar data");
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate gnutar data");
return (ARCHIVE_FATAL);
}
a->format_data = gnutar;
@@ -213,11 +214,13 @@ archive_write_gnutar_options(struct archive_write *a, const char *key,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "%s: unknown keyword ``%s''", a->format_name, key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -244,8 +247,8 @@ archive_write_gnutar_finish_entry(struct archive_write *a)
int ret;
gnutar = (struct gnutar *)a->format_data;
- ret = __archive_write_nulls(a,
- gnutar->entry_bytes_remaining + gnutar->entry_padding);
+ ret = __archive_write_nulls(a, (size_t)
+ (gnutar->entry_bytes_remaining + gnutar->entry_padding));
gnutar->entry_bytes_remaining = gnutar->entry_padding = 0;
return (ret);
}
@@ -258,7 +261,7 @@ archive_write_gnutar_data(struct archive_write *a, const void *buff, size_t s)
gnutar = (struct gnutar *)a->format_data;
if (s > gnutar->entry_bytes_remaining)
- s = gnutar->entry_bytes_remaining;
+ s = (size_t)gnutar->entry_bytes_remaining;
ret = __archive_write_output(a, buff, s);
gnutar->entry_bytes_remaining -= s;
if (ret != ARCHIVE_OK)
@@ -275,6 +278,7 @@ archive_write_gnutar_header(struct archive_write *a,
int tartype;
struct gnutar *gnutar;
struct archive_string_conv *sconv;
+ struct archive_entry *entry_main;
gnutar = (struct gnutar *)a->format_data;
@@ -298,33 +302,95 @@ archive_write_gnutar_header(struct archive_write *a,
if (AE_IFDIR == archive_entry_filetype(entry)) {
const char *p;
- char *t;
+ size_t path_length;
/*
* Ensure a trailing '/'. Modify the entry so
* the client sees the change.
*/
- p = archive_entry_pathname(entry);
- if (p[strlen(p) - 1] != '/') {
- t = (char *)malloc(strlen(p) + 2);
- if (t == NULL) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ const wchar_t *wp;
+
+ wp = archive_entry_pathname_w(entry);
+ if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
+ struct archive_wstring ws;
+
+ archive_string_init(&ws);
+ path_length = wcslen(wp);
+ if (archive_wstring_ensure(&ws,
+ path_length + 2) == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ archive_wstring_free(&ws);
+ return(ARCHIVE_FATAL);
+ }
+ /* Should we keep '\' ? */
+ if (wp[path_length -1] == L'\\')
+ path_length--;
+ archive_wstrncpy(&ws, wp, path_length);
+ archive_wstrappend_wchar(&ws, L'/');
+ archive_entry_copy_pathname_w(entry, ws.s);
+ archive_wstring_free(&ws);
+ p = NULL;
+ } else
+#endif
+ p = archive_entry_pathname(entry);
+ /*
+ * On Windows, this is a backup operation just in
+ * case getting WCS failed. On POSIX, this is a
+ * normal operation.
+ */
+ if (p != NULL && p[strlen(p) - 1] != '/') {
+ struct archive_string as;
+
+ archive_string_init(&as);
+ path_length = strlen(p);
+ if (archive_string_ensure(&as,
+ path_length + 2) == NULL) {
archive_set_error(&a->archive, ENOMEM,
- "Can't allocate gnutar data");
+ "Can't allocate ustar data");
+ archive_string_free(&as);
return(ARCHIVE_FATAL);
}
- strcpy(t, p);
- strcat(t, "/");
- archive_entry_copy_pathname(entry, t);
- free(t);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* NOTE: This might break the pathname
+ * if the current code page is CP932 and
+ * the pathname includes a character '\'
+ * as a part of its multibyte pathname. */
+ if (p[strlen(p) -1] == '\\')
+ path_length--;
+ else
+#endif
+ archive_strncpy(&as, p, path_length);
+ archive_strappend_char(&as, '/');
+ archive_entry_copy_pathname(entry, as.s);
+ archive_string_free(&as);
}
}
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pahtname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ entry_main = __la_win_entry_in_posix_pathseparator(entry);
+ if (entry_main == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ return(ARCHIVE_FATAL);
+ }
+ if (entry != entry_main)
+ entry = entry_main;
+ else
+ entry_main = NULL;
+#else
+ entry_main = NULL;
+#endif
r = archive_entry_pathname_l(entry, &(gnutar->pathname),
&(gnutar->pathname_length), sconv);
if (r != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Pathame");
- return (ARCHIVE_FATAL);
+ ret = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s",
@@ -338,7 +404,8 @@ archive_write_gnutar_header(struct archive_write *a,
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Uname");
- return (ARCHIVE_FATAL);
+ ret = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@@ -353,7 +420,8 @@ archive_write_gnutar_header(struct archive_write *a,
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Gname");
- return (ARCHIVE_FATAL);
+ ret = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@@ -370,7 +438,8 @@ archive_write_gnutar_header(struct archive_write *a,
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Linkname");
- return (ARCHIVE_FATAL);
+ ret = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@@ -386,7 +455,8 @@ archive_write_gnutar_header(struct archive_write *a,
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Linkname");
- return (ARCHIVE_FATAL);
+ ret = ARCHIVE_FATAL;
+ goto exit_write_header;
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@@ -400,7 +470,7 @@ archive_write_gnutar_header(struct archive_write *a,
size_t todo = gnutar->linkname_length;
struct archive_entry *temp = archive_entry_new2(&a->archive);
- /* Uname/gname here don't really matter since noone reads them;
+ /* Uname/gname here don't really matter since no one reads them;
* these are the values that GNU tar happens to use on FreeBSD. */
archive_entry_set_uname(temp, "root");
archive_entry_set_gname(temp, "wheel");
@@ -409,18 +479,18 @@ archive_write_gnutar_header(struct archive_write *a,
archive_entry_set_size(temp, gnutar->linkname_length + 1);
ret = archive_format_gnutar_header(a, buff, temp, 'K');
if (ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
ret = __archive_write_output(a, buff, 512);
if(ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
archive_entry_free(temp);
/* Write as many 512 bytes blocks as needed to write full name. */
ret = __archive_write_output(a, gnutar->linkname, todo);
if(ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)todo));
if (ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
}
/* If pathname is longer than 100 chars we need to add an 'L' header. */
@@ -429,7 +499,7 @@ archive_write_gnutar_header(struct archive_write *a,
size_t todo = gnutar->pathname_length;
struct archive_entry *temp = archive_entry_new2(&a->archive);
- /* Uname/gname here don't really matter since noone reads them;
+ /* Uname/gname here don't really matter since no one reads them;
* these are the values that GNU tar happens to use on FreeBSD. */
archive_entry_set_uname(temp, "root");
archive_entry_set_gname(temp, "wheel");
@@ -438,18 +508,18 @@ archive_write_gnutar_header(struct archive_write *a,
archive_entry_set_size(temp, gnutar->pathname_length + 1);
ret = archive_format_gnutar_header(a, buff, temp, 'L');
if (ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
ret = __archive_write_output(a, buff, 512);
if(ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
archive_entry_free(temp);
/* Write as many 512 bytes blocks as needed to write full name. */
ret = __archive_write_output(a, pathname, todo);
if(ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)todo));
if (ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
}
if (archive_entry_hardlink(entry) != NULL) {
@@ -466,28 +536,35 @@ archive_write_gnutar_header(struct archive_write *a,
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"tar format cannot archive socket");
- return (ARCHIVE_FAILED);
+ ret = ARCHIVE_FAILED;
+ goto exit_write_header;
default:
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"tar format cannot archive this (mode=0%lo)",
(unsigned long)archive_entry_mode(entry));
- return (ARCHIVE_FAILED);
+ ret = ARCHIVE_FAILED;
+ goto exit_write_header;
}
ret = archive_format_gnutar_header(a, buff, entry, tartype);
if (ret < ARCHIVE_WARN)
- return (ret);
+ goto exit_write_header;
if (ret2 < ret)
ret = ret2;
ret2 = __archive_write_output(a, buff, 512);
- if (ret2 < ARCHIVE_WARN)
- return (ret2);
+ if (ret2 < ARCHIVE_WARN) {
+ ret = ret2;
+ goto exit_write_header;
+ }
if (ret2 < ret)
ret = ret2;
gnutar->entry_bytes_remaining = archive_entry_size(entry);
gnutar->entry_padding = 0x1ff & (-(int64_t)gnutar->entry_bytes_remaining);
+exit_write_header:
+ if (entry_main)
+ archive_entry_free(entry_main);
return (ret);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
index 0b9aaf9..e722625 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2009-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2009-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -994,7 +994,7 @@ static void isoent_remove_child(struct isoent *, struct isoent *);
static void isoent_setup_directory_location(struct iso9660 *,
int, struct vdd *);
static void isoent_setup_file_location(struct iso9660 *, int);
-static int get_path_component(char *, int, const char *);
+static int get_path_component(char *, size_t, const char *);
static int isoent_tree(struct archive_write *, struct isoent **);
static struct isoent *isoent_find_child(struct isoent *, const char *);
static struct isoent *isoent_find_entry(struct isoent *, const char *);
@@ -1507,6 +1507,11 @@ iso9660_options(struct archive_write *a, const char *key, const char *value)
break;
}
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+
invalid_value:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid value for option ``%s''", key);
@@ -1693,7 +1698,7 @@ wb_write_padding_to_temp(struct archive_write *a, int64_t csize)
size_t ns;
int ret;
- ns = csize % LOGICAL_BLOCK_SIZE;
+ ns = (size_t)(csize % LOGICAL_BLOCK_SIZE);
if (ns != 0)
ret = write_null(a, LOGICAL_BLOCK_SIZE - ns);
else
@@ -1720,8 +1725,8 @@ write_iso9660_data(struct archive_write *a, const void *buff, size_t s)
struct content *con;
size_t ts;
- ts = MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE -
- iso9660->cur_file->cur_content->size;
+ ts = (size_t)(MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE -
+ iso9660->cur_file->cur_content->size);
if (iso9660->zisofs.detect_magic)
zisofs_detect_magic(a, buff, ts);
@@ -1741,9 +1746,9 @@ write_iso9660_data(struct archive_write *a, const void *buff, size_t s)
return (ARCHIVE_FATAL);
/* Compute the logical block number. */
- iso9660->cur_file->cur_content->blocks =
- (iso9660->cur_file->cur_content->size
- + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS;
+ iso9660->cur_file->cur_content->blocks = (int)
+ ((iso9660->cur_file->cur_content->size
+ + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
/*
* Make next extent.
@@ -1791,7 +1796,7 @@ iso9660_write_data(struct archive_write *a, const void *buff, size_t s)
if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG)
return (0);
if (s > iso9660->bytes_remaining)
- s = iso9660->bytes_remaining;
+ s = (size_t)iso9660->bytes_remaining;
if (s == 0)
return (0);
@@ -1833,9 +1838,9 @@ iso9660_finish_entry(struct archive_write *a)
return (ARCHIVE_FATAL);
/* Compute the logical block number. */
- iso9660->cur_file->cur_content->blocks =
- (iso9660->cur_file->cur_content->size
- + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS;
+ iso9660->cur_file->cur_content->blocks = (int)
+ ((iso9660->cur_file->cur_content->size
+ + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
/* Add the current file to data file list. */
isofile_add_data_file(iso9660, iso9660->cur_file);
@@ -1852,7 +1857,7 @@ iso9660_close(struct archive_write *a)
iso9660 = a->format_data;
/*
- * Write remaining data out to the temprary file.
+ * Write remaining data out to the temporary file.
*/
if (wb_remaining(a) > 0) {
ret = wb_write_out(a);
@@ -1881,7 +1886,7 @@ iso9660_close(struct archive_write *a)
ret = zisofs_rewind_boot_file(a);
if (ret < 0)
return (ret);
- /* Write remaining data out to the temprary file. */
+ /* Write remaining data out to the temporary file. */
if (wb_remaining(a) > 0) {
ret = wb_write_out(a);
if (ret < 0)
@@ -2239,7 +2244,7 @@ set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s,
onepad = 0;
if (vdc == VDC_UCS2) {
struct iso9660 *iso9660 = a->format_data;
- if (archive_strncpy_in_locale(&iso9660->utf16be, s, strlen(s),
+ if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s),
iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for UTF-16BE");
@@ -2542,7 +2547,7 @@ set_date_time(unsigned char *p, time_t t)
set_digit(p+10, 2, tm.tm_min);
set_digit(p+12, 2, tm.tm_sec);
set_digit(p+14, 2, 0);
- set_num_712(p+16, get_gmoffset(&tm)/(60*15));
+ set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15)));
}
static void
@@ -2564,7 +2569,7 @@ set_time_915(unsigned char *p, time_t t)
set_num_711(p+3, tm.tm_hour);
set_num_711(p+4, tm.tm_min);
set_num_711(p+5, tm.tm_sec);
- set_num_712(p+6, get_gmoffset(&tm)/(60*15));
+ set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15)));
}
@@ -2884,7 +2889,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
if (nmmax > 0xff)
nmmax = 0xff;
while (nmlen + 5 > nmmax) {
- length = nmmax;
+ length = (int)nmmax;
if (bp != NULL) {
bp[3] = length;
bp[5] = 0x01;/* Alternate Name continues
@@ -2907,7 +2912,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
bp[4] = 1; /* version */
}
}
- length = 5 + nmlen;
+ length = 5 + (int)nmlen;
if (bp != NULL) {
bp[3] = length;
bp[5] = 0;
@@ -2936,8 +2941,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
bp = extra_next_record(&ctl, length);
if (bp != NULL) {
mode_t mode;
- uid_t uid;
- gid_t gid;
+ int64_t uid;
+ int64_t gid;
mode = archive_entry_mode(file->entry);
uid = archive_entry_uid(file->entry);
@@ -2970,8 +2975,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
/* file links (stat.st_nlink) */
set_num_733(bp+13,
archive_entry_nlink(file->entry));
- set_num_733(bp+21, uid);
- set_num_733(bp+29, gid);
+ set_num_733(bp+21, (uint32_t)uid);
+ set_num_733(bp+29, (uint32_t)gid);
/* File Serial Number */
if (pxent->dir)
set_num_733(bp+37, pxent->dir_location);
@@ -3352,8 +3357,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
bp[3] = length;
bp[4] = 1; /* version */
dev = (uint64_t)archive_entry_rdev(file->entry);
- set_num_733(bp + 5, dev >> 32);
- set_num_733(bp + 13, dev & 0xFFFFFFFF);
+ set_num_733(bp + 5, (uint32_t)(dev >> 32));
+ set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF));
bp += length;
}
extra_tell_used_size(&ctl, length);
@@ -3487,7 +3492,7 @@ set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
set_num_733(bp+11,
xisoent->dir_block * LOGICAL_BLOCK_SIZE);
else
- set_num_733(bp+11, file->cur_content->size);
+ set_num_733(bp+11, (uint32_t)file->cur_content->size);
/* Recording Date and Time */
/* NOTE:
* If a file type is symbolic link, you are seeing this
@@ -3506,7 +3511,7 @@ set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
/* Volume Sequence Number */
set_num_723(bp+29, iso9660->volume_sequence_number);
/* Length of File Identifier */
- set_num_711(bp+33, fi_len);
+ set_num_711(bp+33, (unsigned char)fi_len);
/* File Identifier */
switch (t) {
case DIR_REC_VD:
@@ -3537,20 +3542,20 @@ set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
if (t == DIR_REC_VD) {
if (p != NULL)
/* Length of Directory Record */
- set_num_711(p, dr_len);
+ set_num_711(p, (unsigned char)dr_len);
else
- isoent->dr_len.vd = dr_len;
- return (dr_len);
+ isoent->dr_len.vd = (int)dr_len;
+ return ((int)dr_len);
}
/* Rockridge */
if (iso9660->opt.rr && vdd_type != VDD_JOLIET)
- dr_len = set_directory_record_rr(bp, dr_len,
+ dr_len = set_directory_record_rr(bp, (int)dr_len,
isoent, iso9660, t);
if (p != NULL)
/* Length of Directory Record */
- set_num_711(p, dr_len);
+ set_num_711(p, (unsigned char)dr_len);
else {
/*
* Save the size which is needed to write this
@@ -3563,15 +3568,15 @@ set_directory_record(unsigned char *p, size_t n, struct isoent *isoent,
* in switch .... */
break;
case DIR_REC_SELF:
- isoent->dr_len.self = dr_len; break;
+ isoent->dr_len.self = (int)dr_len; break;
case DIR_REC_PARENT:
- isoent->dr_len.parent = dr_len; break;
+ isoent->dr_len.parent = (int)dr_len; break;
case DIR_REC_NORMAL:
- isoent->dr_len.normal = dr_len; break;
+ isoent->dr_len.normal = (int)dr_len; break;
}
}
- return (dr_len);
+ return ((int)dr_len);
}
/*
@@ -3664,7 +3669,7 @@ wb_set_offset(struct archive_write *a, int64_t off)
iso9660->wbuff_tail = iso9660->wbuff_offset + used;
if (iso9660->wbuff_offset < iso9660->wbuff_written) {
if (used > 0 &&
- write_to_temp(a, iso9660->wbuff, used) != ARCHIVE_OK)
+ write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
iso9660->wbuff_offset = iso9660->wbuff_written;
lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET);
@@ -3683,13 +3688,13 @@ wb_set_offset(struct archive_write *a, int64_t off)
iso9660->wbuff_offset = off;
iso9660->wbuff_remaining = sizeof(iso9660->wbuff);
} else if (off <= iso9660->wbuff_tail) {
- iso9660->wbuff_remaining =
- sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset);
+ iso9660->wbuff_remaining = (size_t)
+ (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset));
} else {
ext_bytes = off - iso9660->wbuff_tail;
- iso9660->wbuff_remaining = sizeof(iso9660->wbuff)
- - (iso9660->wbuff_tail - iso9660->wbuff_offset);
- while (ext_bytes >= iso9660->wbuff_remaining) {
+ iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff)
+ - (iso9660->wbuff_tail - iso9660->wbuff_offset));
+ while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) {
if (write_null(a, (size_t)iso9660->wbuff_remaining)
!= ARCHIVE_OK)
return (ARCHIVE_FATAL);
@@ -4250,7 +4255,7 @@ _write_path_table(struct archive_write *a, int type_m, int depth,
bp = wb -1;
}
/* Length of Directory Identifier */
- set_num_711(bp+1, len);
+ set_num_711(bp+1, (unsigned char)len);
/* Extended Attribute Record Length */
set_num_711(bp+2, 0);
/* Location of Extent */
@@ -4273,7 +4278,7 @@ _write_path_table(struct archive_write *a, int type_m, int depth,
bp[9+len] = 0;
len++;
}
- wsize += 8 + len;
+ wsize += 8 + (int)len;
bp += 8 + len;
}
if ((bp + 1) > wb) {
@@ -4508,8 +4513,7 @@ write_file_descriptors(struct archive_write *a)
/* Write the boot file contents. */
if (iso9660->el_torito.boot != NULL) {
- struct isofile *file = iso9660->el_torito.boot->file;
-
+ file = iso9660->el_torito.boot->file;
blocks = file->content.blocks;
offset = file->content.offset_of_temp;
if (offset != 0) {
@@ -4810,13 +4814,19 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
struct archive_wstring ws;
if (wp != NULL) {
+ int r;
archive_string_init(&ws);
archive_wstrcpy(&ws, wp);
cleanup_backslash_2(ws.s);
archive_string_empty(&(file->parentdir));
- archive_string_append_from_wcs(&(file->parentdir),
+ r = archive_string_append_from_wcs(&(file->parentdir),
ws.s, ws.length);
archive_wstring_free(&ws);
+ if (r < 0 && errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
}
}
#endif
@@ -4919,14 +4929,20 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
struct archive_wstring ws;
if (wp != NULL) {
+ int r;
archive_string_init(&ws);
archive_wstrcpy(&ws, wp);
cleanup_backslash_2(ws.s);
archive_string_empty(&(file->symlink));
- archive_string_append_from_wcs(
+ r = archive_string_append_from_wcs(
&(file->symlink),
ws.s, ws.length);
archive_wstring_free(&ws);
+ if (r < 0 && errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
}
}
#endif
@@ -5422,8 +5438,8 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location)
iso9660->total_file_block = 0;
if ((isoent = iso9660->el_torito.catalog) != NULL) {
isoent->file->content.location = location;
- block = (archive_entry_size(isoent->file->entry) +
- LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS;
+ block = (int)((archive_entry_size(isoent->file->entry) +
+ LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS);
location += block;
iso9660->total_file_block += block;
}
@@ -5431,8 +5447,9 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location)
isoent->file->content.location = location;
size = fd_boot_image_size(iso9660->el_torito.media_type);
if (size == 0)
- size = archive_entry_size(isoent->file->entry);
- block = (size + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS;
+ size = (size_t)archive_entry_size(isoent->file->entry);
+ block = ((int)size + LOGICAL_BLOCK_SIZE -1)
+ >> LOGICAL_BLOCK_BITS;
location += block;
iso9660->total_file_block += block;
isoent->file->content.blocks = block;
@@ -5493,10 +5510,10 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location)
}
static int
-get_path_component(char *name, int n, const char *fn)
+get_path_component(char *name, size_t n, const char *fn)
{
char *p;
- int l;
+ size_t l;
p = strchr(fn, '/');
if (p == NULL) {
@@ -5509,7 +5526,7 @@ get_path_component(char *name, int n, const char *fn)
memcpy(name, fn, l);
name[l] = '\0';
- return (l);
+ return ((int)l);
}
/*
@@ -5802,17 +5819,18 @@ idr_ensure_poolsize(struct archive_write *a, struct idr *idr,
{
if (idr->pool_size < cnt) {
+ void *p;
const int bk = (1 << 7) - 1;
int psize;
psize = (cnt + bk) & ~bk;
- idr->idrent_pool = realloc(idr->idrent_pool,
- sizeof(struct idrent) * psize);
- if (idr->idrent_pool == NULL) {
+ p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize);
+ if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
return (ARCHIVE_FATAL);
}
+ idr->idrent_pool = (struct idrent *)p;
idr->pool_size = psize;
}
return (ARCHIVE_OK);
@@ -6000,7 +6018,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
char *dot, *xdot;
int ext_off, noff, weight;
- l = np->file->basename.length;
+ l = (int)np->file->basename.length;
p = malloc(l+31+2+1);
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
@@ -6064,7 +6082,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
ext_off = l;
} else {
*dot = '.';
- ext_off = dot - p;
+ ext_off = (int)(dot - p);
if (iso9660->opt.iso_level == 1) {
if (dot - p <= 8) {
@@ -6091,11 +6109,11 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
ext_off = dnmax;
}
} else if (l > ffmax) {
- int extlen = strlen(dot);
+ int extlen = (int)strlen(dot);
int xdoff;
if (xdot != NULL)
- xdoff = xdot - p;
+ xdoff = (int)(xdot - p);
else
xdoff = 0;
@@ -6132,7 +6150,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
}
/* Save an offset of a file name extension to sort files. */
np->ext_off = ext_off;
- np->ext_len = strlen(&p[ext_off]);
+ np->ext_len = (int)strlen(&p[ext_off]);
np->id_len = l = ext_off + np->ext_len;
/* Make an offset of the number which is used to be set
@@ -6249,30 +6267,35 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
p += 2;
lt -= 2;
}
- ext_off = dot - (unsigned char *)np->identifier;
+ ext_off = (int)(dot - (unsigned char *)np->identifier);
np->ext_off = ext_off;
- np->ext_len = l - ext_off;
- np->id_len = l;
+ np->ext_len = (int)l - ext_off;
+ np->id_len = (int)l;
/*
* Get a length of MBS of a full-pathname.
*/
if ((int)np->file->basename_utf16.length > ffmax) {
- archive_strncpy_in_locale(&iso9660->mbs,
+ if (archive_strncpy_l(&iso9660->mbs,
(const char *)np->identifier, l,
- iso9660->sconv_from_utf16be);
- np->mb_len = iso9660->mbs.length;
+ iso9660->sconv_from_utf16be) != 0 &&
+ errno == ENOMEM) {
+ archive_set_error(&a->archive, errno,
+ "No memory");
+ return (ARCHIVE_FATAL);
+ }
+ np->mb_len = (int)iso9660->mbs.length;
if (np->mb_len != (int)np->file->basename.length)
weight = np->mb_len;
} else
- np->mb_len = np->file->basename.length;
+ np->mb_len = (int)np->file->basename.length;
/* If a length of full-pathname is longer than 240 bytes,
* it violates Joliet extensions regulation. */
if (parent_len + np->mb_len > 240) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"The regulation of Joliet extensions;"
- " A lenght of a full-pathname of `%s' is "
+ " A length of a full-pathname of `%s' is "
"longer than 240 bytes, (p=%d, b=%d)",
archive_entry_pathname(np->file->entry),
(int)parent_len, (int)np->mb_len);
@@ -6280,7 +6303,7 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
}
/* Make an offset of the number which is used to be set
- * hexadecimal number to avoid duplicate identififier. */
+ * hexadecimal number to avoid duplicate identifier. */
if ((int)l == ffmax)
noff = ext_off - 6;
else if ((int)l == ffmax-2)
@@ -6300,7 +6323,7 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent,
}
/*
- * This comparing rule is acording to ISO9660 Standard 9.3
+ * This comparing rule is according to ISO9660 Standard 9.3
*/
static int
isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2)
@@ -6360,7 +6383,7 @@ isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2)
if (0x20 != *s2++)
return (0x20
- *(const unsigned char *)(s2 - 1));
- } else if (p1->ext_len < p2->ext_len) {
+ } else if (p1->ext_len > p2->ext_len) {
s1 += l;
l = p1->ext_len - p2->ext_len;
while (l--)
@@ -6448,7 +6471,7 @@ isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2)
while (l--)
if (0 != *s2++)
return (- *(const unsigned char *)(s2 - 1));
- } else if (p1->ext_len < p2->ext_len) {
+ } else if (p1->ext_len > p2->ext_len) {
s1 += l;
l = p1->ext_len - p2->ext_len;
while (l--)
@@ -6514,8 +6537,7 @@ isoent_traverse_tree(struct archive_write *a, struct vdd* vdd)
struct idr idr;
int depth;
int r;
- int (*genid)(struct archive_write *a, struct isoent *isoent,
- struct idr *idr);
+ int (*genid)(struct archive_write *, struct isoent *, struct idr *);
idr_init(iso9660, vdd, &idr);
np = vdd->rootent;
@@ -6896,12 +6918,22 @@ isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd,
switch (vdd->vdd_type) {
case VDD_PRIMARY:
case VDD_ENHANCED:
+#ifdef __COMPAR_FN_T
+ qsort(enttbl, pt->cnt, sizeof(struct isoent *),
+ (__compar_fn_t)_compare_path_table);
+#else
qsort(enttbl, pt->cnt, sizeof(struct isoent *),
_compare_path_table);
+#endif
break;
case VDD_JOLIET:
+#ifdef __COMPAR_FN_T
+ qsort(enttbl, pt->cnt, sizeof(struct isoent *),
+ (__compar_fn_t)_compare_path_table_joliet);
+#else
qsort(enttbl, pt->cnt, sizeof(struct isoent *),
_compare_path_table_joliet);
+#endif
break;
}
for (i = 0; i < pt->cnt; i++)
@@ -7284,7 +7316,7 @@ setup_boot_information(struct archive_write *a)
size_t rsize;
ssize_t i, rs;
- if (size > sizeof(buff))
+ if (size > (int64_t)sizeof(buff))
rsize = sizeof(buff);
else
rsize = (size_t)size;
@@ -7370,7 +7402,7 @@ zisofs_init(struct archive_write *a, struct isofile *file)
struct iso9660 *iso9660 = a->format_data;
#ifdef HAVE_ZLIB_H
uint64_t tsize;
- size_t ceil, bpsize;
+ size_t _ceil, bpsize;
int r;
#endif
@@ -7405,12 +7437,13 @@ zisofs_init(struct archive_write *a, struct isofile *file)
/* Mark file->zisofs to create RRIP 'ZF' Use Entry. */
file->zisofs.header_size = ZF_HEADER_SIZE >> 2;
file->zisofs.log2_bs = ZF_LOG2_BS;
- file->zisofs.uncompressed_size = archive_entry_size(file->entry);
+ file->zisofs.uncompressed_size =
+ (uint32_t)archive_entry_size(file->entry);
/* Calculate a size of Block Pointers of zisofs. */
- ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1)
+ _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1)
>> file->zisofs.log2_bs;
- iso9660->zisofs.block_pointers_cnt = ceil + 1;
+ iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1;
iso9660->zisofs.block_pointers_idx = 0;
/* Ensure a buffer size used for Block Pointers */
@@ -7433,13 +7466,14 @@ zisofs_init(struct archive_write *a, struct isofile *file)
* file.
*/
tsize = ZF_HEADER_SIZE + bpsize;
- if (write_null(a, tsize) != ARCHIVE_OK)
+ if (write_null(a, (size_t)tsize) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
/*
* Initialize some variables to make zisofs.
*/
- archive_le32enc(&(iso9660->zisofs.block_pointers[0]), tsize);
+ archive_le32enc(&(iso9660->zisofs.block_pointers[0]),
+ (uint32_t)tsize);
iso9660->zisofs.remaining = file->zisofs.uncompressed_size;
iso9660->zisofs.making = 1;
iso9660->zisofs.allzero = 1;
@@ -7461,14 +7495,14 @@ zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
uint32_t uncompressed_size;
unsigned char header_size;
unsigned char log2_bs;
- size_t ceil, doff;
+ size_t _ceil, doff;
uint32_t bst, bed;
int magic_max;
int64_t entry_size;
entry_size = archive_entry_size(file->entry);
- if (sizeof(iso9660->zisofs.magic_buffer) > entry_size)
- magic_max = entry_size;
+ if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size)
+ magic_max = (int)entry_size;
else
magic_max = sizeof(iso9660->zisofs.magic_buffer);
@@ -7485,7 +7519,7 @@ zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
l = s;
memcpy(iso9660->zisofs.magic_buffer
+ iso9660->zisofs.magic_cnt, buff, l);
- iso9660->zisofs.magic_cnt += l;
+ iso9660->zisofs.magic_cnt += (int)l;
if (iso9660->zisofs.magic_cnt < magic_max)
return;
}
@@ -7509,16 +7543,16 @@ zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
return;/* Invalid or not supported header. */
/* Calculate a size of Block Pointers of zisofs. */
- ceil = (uncompressed_size +
+ _ceil = (uncompressed_size +
(ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs;
- doff = (ceil + 1) * 4 + 16;
- if (entry_size < doff)
+ doff = (_ceil + 1) * 4 + 16;
+ if (entry_size < (int64_t)doff)
return;/* Invalid data. */
/* Check every Block Pointer has valid value. */
p = magic_buff + 16;
endp = magic_buff + magic_max;
- while (ceil && p + 8 <= endp) {
+ while (_ceil && p + 8 <= endp) {
bst = archive_le32dec(p);
if (bst != doff)
return;/* Invalid data. */
@@ -7527,7 +7561,7 @@ zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s)
if (bed < bst || bed > entry_size)
return;/* Invalid data. */
doff += bed - bst;
- ceil--;
+ _ceil--;
}
file->zisofs.uncompressed_size = uncompressed_size;
@@ -7555,7 +7589,7 @@ zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
zstrm = &(iso9660->zisofs.stream);
zstrm->next_out = wb_buffptr(a);
- zstrm->avail_out = wb_remaining(a);
+ zstrm->avail_out = (uInt)wb_remaining(a);
b = (const unsigned char *)buff;
do {
avail = ZF_BLOCK_SIZE - zstrm->total_in;
@@ -7569,7 +7603,7 @@ zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
flush = Z_FINISH;
zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b;
- zstrm->avail_in = avail;
+ zstrm->avail_in = (uInt)avail;
/*
* Check if current data block are all zero.
@@ -7625,7 +7659,7 @@ zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
iso9660->zisofs.total_size += csize;
iso9660->cur_file->cur_content->size += csize;
zstrm->next_out = wb_buffptr(a);
- zstrm->avail_out = wb_remaining(a);
+ zstrm->avail_out = (uInt)wb_remaining(a);
break;
default:
archive_set_error(&a->archive,
@@ -7644,7 +7678,7 @@ zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s)
iso9660->zisofs.block_pointers_idx ++;
archive_le32enc(&(iso9660->zisofs.block_pointers[
iso9660->zisofs.block_pointers_idx]),
- iso9660->zisofs.total_size);
+ (uint32_t)iso9660->zisofs.total_size);
r = zisofs_init_zstream(a);
if (r != ARCHIVE_OK)
return (ARCHIVE_FATAL);
@@ -7770,13 +7804,13 @@ zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs,
const unsigned char *p, size_t bytes)
{
size_t avail = bytes;
- size_t ceil, xsize;
+ size_t _ceil, xsize;
/* Allocate block pointers buffer. */
- ceil = (zisofs->pz_uncompressed_size +
+ _ceil = (size_t)((zisofs->pz_uncompressed_size +
(((int64_t)1) << zisofs->pz_log2_bs) - 1)
- >> zisofs->pz_log2_bs;
- xsize = (ceil + 1) * 4;
+ >> zisofs->pz_log2_bs);
+ xsize = (_ceil + 1) * 4;
if (zisofs->block_pointers == NULL) {
size_t alloc = ((xsize >> 10) + 1) << 10;
zisofs->block_pointers = malloc(alloc);
@@ -7789,7 +7823,7 @@ zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs,
zisofs->block_pointers_size = xsize;
/* Allocate uncompressed data buffer. */
- zisofs->uncompressed_buffer_size = 1UL << zisofs->pz_log2_bs;
+ zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs;
/*
* Read the file header, and check the magic code of zisofs.
@@ -7859,7 +7893,7 @@ zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
return (rs);
if (!zisofs->initialized) {
/* We need more data. */
- zisofs->pz_offset += bytes;
+ zisofs->pz_offset += (uint32_t)bytes;
return (bytes);
}
avail = rs;
@@ -7942,9 +7976,9 @@ zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
if (avail > zisofs->block_avail)
zisofs->stream.avail_in = zisofs->block_avail;
else
- zisofs->stream.avail_in = avail;
+ zisofs->stream.avail_in = (uInt)avail;
zisofs->stream.next_out = wb_buffptr(a);
- zisofs->stream.avail_out = wb_remaining(a);
+ zisofs->stream.avail_out = (uInt)wb_remaining(a);
r = inflate(&zisofs->stream, 0);
switch (r) {
@@ -7957,12 +7991,12 @@ zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs,
return (ARCHIVE_FATAL);
}
avail -= zisofs->stream.next_in - p;
- zisofs->block_avail -= zisofs->stream.next_in - p;
+ zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out);
if (r < 0)
return (r);
}
- zisofs->pz_offset += bytes;
+ zisofs->pz_offset += (uint32_t)bytes;
return (bytes - avail);
}
@@ -7996,7 +8030,7 @@ zisofs_rewind_boot_file(struct archive_write *a)
fd = iso9660->temp_fd;
new_offset = wb_offset(a);
read_offset = file->content.offset_of_temp;
- remaining = file->content.size;
+ remaining = (size_t)file->content.size;
if (remaining > 1024 * 32)
rbuff_size = 1024 * 32;
else
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
index 3802a25..9c0613c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 2009,2011 Michihiro NAKAJIMA
* Copyright (c) 2008 Joerg Sonnenberger
+ * Copyright (c) 2009-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171
#include "archive_crypto_private.h"
#include "archive_entry.h"
#include "archive_private.h"
+#include "archive_rb.h"
+#include "archive_string.h"
#include "archive_write_private.h"
#define INDENTNAMELEN 15
@@ -45,27 +47,39 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171
#define SET_KEYS \
(F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME)
-struct mtree_entry {
- struct mtree_entry *next;
+struct attr_counter {
+ struct attr_counter *prev;
+ struct attr_counter *next;
+ struct mtree_entry *m_entry;
+ int count;
+};
- char *pathname;
- char *symlink;
- unsigned int nlink;
- mode_t filetype;
- mode_t mode;
- int64_t uid;
- int64_t gid;
- char *uname;
- char *gname;
- char *fflags_text;
- unsigned long fflags_set;
- unsigned long fflags_clear;
- time_t mtime;
- long mtime_nsec;
- dev_t rdevmajor;
- dev_t rdevminor;
- int64_t size;
+struct att_counter_set {
+ struct attr_counter *uid_list;
+ struct attr_counter *gid_list;
+ struct attr_counter *mode_list;
+ struct attr_counter *flags_list;
+};
+
+struct mtree_chain {
+ struct mtree_entry *first;
+ struct mtree_entry **last;
+};
+
+/*
+ * The Data only for a directory file.
+ */
+struct dir_info {
+ struct archive_rb_tree rbtree;
+ struct mtree_chain children;
+ struct mtree_entry *chnext;
+ int virtual;
+};
+/*
+ * The Data only for a regular file.
+ */
+struct reg_info {
int compute_sum;
uint32_t crc;
#ifdef ARCHIVE_HAS_MD5
@@ -88,23 +102,51 @@ struct mtree_entry {
#endif
};
-struct attr_counter {
- struct attr_counter *prev;
- struct attr_counter *next;
- int count;
- struct mtree_entry *m_entry;
+struct mtree_entry {
+ struct archive_rb_node rbnode;
+ struct mtree_entry *next;
+ struct mtree_entry *parent;
+ struct dir_info *dir_info;
+ struct reg_info *reg_info;
+
+ struct archive_string parentdir;
+ struct archive_string basename;
+ struct archive_string pathname;
+ struct archive_string symlink;
+ struct archive_string uname;
+ struct archive_string gname;
+ struct archive_string fflags_text;
+ unsigned int nlink;
+ mode_t filetype;
+ mode_t mode;
+ int64_t size;
+ int64_t uid;
+ int64_t gid;
+ time_t mtime;
+ long mtime_nsec;
+ unsigned long fflags_set;
+ unsigned long fflags_clear;
+ dev_t rdevmajor;
+ dev_t rdevminor;
};
struct mtree_writer {
struct mtree_entry *mtree_entry;
+ struct mtree_entry *root;
+ struct mtree_entry *cur_dirent;
+ struct archive_string cur_dirstr;
+ struct mtree_chain file_list;
+
struct archive_string ebuf;
struct archive_string buf;
int first;
uint64_t entry_bytes_remaining;
+
+ /*
+ * Set global value.
+ */
struct {
- int output;
- int processed;
- struct archive_string parent;
+ int processing;
mode_t type;
int keys;
int64_t uid;
@@ -112,14 +154,11 @@ struct mtree_writer {
mode_t mode;
unsigned long fflags_set;
unsigned long fflags_clear;
-
- struct attr_counter *uid_list;
- struct attr_counter *gid_list;
- struct attr_counter *mode_list;
- struct attr_counter *flags_list;
- struct mtree_entry *me_first;
- struct mtree_entry **me_last;
} set;
+ struct att_counter_set acs;
+ int classic;
+ int depth;
+
/* check sum */
int compute_sum;
uint32_t crc;
@@ -173,27 +212,51 @@ struct mtree_writer {
#define F_SHA512 0x02000000 /* SHA-512 digest */
/* Options */
- int dironly; /* if the dironly is 1, ignore everything except
- * directory type files. like mtree(8) -d option.
- */
- int indent; /* if the indent is 1, indent writing data. */
+ int dironly; /* If it is set, ignore all files except
+ * directory files, like mtree(8) -d option. */
+ int indent; /* If it is set, indent output data. */
+ int output_global_set; /* If it is set, use /set keyword to set
+ * global values. When generating mtree
+ * classic format, it is set by default. */
};
#define DEFAULT_KEYS (F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\
| F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\
| F_UNAME)
+#define attr_counter_set_reset attr_counter_set_free
-static struct attr_counter * new_attr_count(struct mtree_entry *,
- struct attr_counter *);
-static void free_attr_count(struct attr_counter **);
-static int inc_attr_count(struct attr_counter **, struct attr_counter *,
+static void attr_counter_free(struct attr_counter **);
+static int attr_counter_inc(struct attr_counter **, struct attr_counter *,
struct attr_counter *, struct mtree_entry *);
-static int collect_set_values(struct mtree_writer *, struct mtree_entry *);
-static int get_keys(struct mtree_writer *, struct mtree_entry *);
+static struct attr_counter * attr_counter_new(struct mtree_entry *,
+ struct attr_counter *);
+static int attr_counter_set_collect(struct mtree_writer *,
+ struct mtree_entry *);
+static void attr_counter_set_free(struct mtree_writer *);
+static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *);
+static int mtree_entry_add_child_tail(struct mtree_entry *,
+ struct mtree_entry *);
+static int mtree_entry_create_virtual_dir(struct archive_write *, const char *,
+ struct mtree_entry **);
+static int mtree_entry_cmp_node(const struct archive_rb_node *,
+ const struct archive_rb_node *);
+static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *);
+static int mtree_entry_exchange_same_entry(struct archive_write *,
+ struct mtree_entry *, struct mtree_entry *);
+static void mtree_entry_free(struct mtree_entry *);
+static int mtree_entry_new(struct archive_write *, struct archive_entry *,
+ struct mtree_entry **);
+static void mtree_entry_register_free(struct mtree_writer *);
+static void mtree_entry_register_init(struct mtree_writer *);
+static int mtree_entry_setup_filenames(struct archive_write *,
+ struct mtree_entry *, struct archive_entry *);
+static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **);
static void sum_init(struct mtree_writer *);
static void sum_update(struct mtree_writer *, const void *, size_t);
-static void sum_final(struct mtree_writer *, struct mtree_entry *);
-static void sum_write(struct archive_string *, struct mtree_entry *);
+static void sum_final(struct mtree_writer *, struct reg_info *);
+static void sum_write(struct archive_string *, struct reg_info *);
+static int write_mtree_entry(struct archive_write *, struct mtree_entry *);
+static int write_dot_dot_entry(struct archive_write *, struct mtree_entry *);
#define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
static const uint32_t crctab[] = {
@@ -251,26 +314,30 @@ static const uint32_t crctab[] = {
0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};
-static int
-mtree_safe_char(char c)
-{
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
- return 1;
- if (c >= '0' && c <= '9')
- return 1;
- if (c == 35 || c == 61 || c == 92)
- return 0; /* #, = and \ are always quoted */
-
- if (c >= 33 && c <= 47) /* !"$%&'()*+,-./ */
- return 1;
- if (c >= 58 && c <= 64) /* :;<>?@ */
- return 1;
- if (c >= 91 && c <= 96) /* []^_` */
- return 1;
- if (c >= 123 && c <= 126) /* {|}~ */
- return 1;
- return 0;
-}
+static const unsigned char safe_char[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
+ /* !"$%&'()*+,-./ EXCLUSION:0x20( ) 0x23(#) */
+ 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
+ /* 0123456789:;<>? EXCLUSION:0x3d(=) */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */
+ /* @ABCDEFGHIJKLMNO */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
+ /* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\) */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */
+ /* `abcdefghijklmno */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
+ /* pqrstuvwxyz{|}~ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
+};
static void
mtree_quote(struct archive_string *s, const char *str)
@@ -280,7 +347,7 @@ mtree_quote(struct archive_string *s, const char *str)
unsigned char c;
for (start = str; *str != '\0'; ++str) {
- if (mtree_safe_char(*str))
+ if (safe_char[*(const unsigned char *)str])
continue;
if (start != str)
archive_strncat(s, start, str - start);
@@ -303,9 +370,19 @@ mtree_quote(struct archive_string *s, const char *str)
static void
mtree_indent(struct mtree_writer *mtree)
{
- int i, fn;
+ int i, fn, nd, pd;
const char *r, *s, *x;
+ if (mtree->classic) {
+ if (mtree->indent) {
+ nd = 0;
+ pd = mtree->depth * 4;
+ } else {
+ nd = mtree->depth?4:0;
+ pd = 0;
+ }
+ } else
+ nd = pd = 0;
fn = 1;
s = r = mtree->ebuf.s;
x = NULL;
@@ -314,37 +391,46 @@ mtree_indent(struct mtree_writer *mtree)
while ((r = strchr(r, ' ')) != NULL) {
if (fn) {
fn = 0;
+ for (i = 0; i < nd + pd; i++)
+ archive_strappend_char(&mtree->buf, ' ');
archive_strncat(&mtree->buf, s, r - s);
- if (r -s > INDENTNAMELEN) {
+ if (nd + (r -s) > INDENTNAMELEN) {
archive_strncat(&mtree->buf, " \\\n", 3);
- for (i = 0; i < (INDENTNAMELEN + 1); i++)
+ for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
archive_strappend_char(&mtree->buf, ' ');
} else {
- for (i = r -s; i < (INDENTNAMELEN + 1); i++)
+ for (i = (int)(r -s + nd);
+ i < (INDENTNAMELEN + 1); i++)
archive_strappend_char(&mtree->buf, ' ');
}
s = ++r;
x = NULL;
continue;
}
- if (r - s <= MAXLINELEN - 3 - INDENTNAMELEN)
+ if (pd + (r - s) <= MAXLINELEN - 3 - INDENTNAMELEN)
x = r++;
else {
if (x == NULL)
x = r;
archive_strncat(&mtree->buf, s, x - s);
archive_strncat(&mtree->buf, " \\\n", 3);
- for (i = 0; i < (INDENTNAMELEN + 1); i++)
+ for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
archive_strappend_char(&mtree->buf, ' ');
s = r = ++x;
x = NULL;
}
}
- if (x != NULL && strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) {
+ if (fn) {
+ for (i = 0; i < nd + pd; i++)
+ archive_strappend_char(&mtree->buf, ' ');
+ archive_strcat(&mtree->buf, s);
+ s += strlen(s);
+ }
+ if (x != NULL && pd + strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) {
/* Last keyword is longer. */
archive_strncat(&mtree->buf, s, x - s);
archive_strncat(&mtree->buf, " \\\n", 3);
- for (i = 0; i < (INDENTNAMELEN + 1); i++)
+ for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
archive_strappend_char(&mtree->buf, ' ');
s = ++x;
}
@@ -352,163 +438,70 @@ mtree_indent(struct mtree_writer *mtree)
archive_string_empty(&mtree->ebuf);
}
-#if !defined(_WIN32) || defined(__CYGWIN__)
-static size_t
-dir_len(struct mtree_entry *me)
-{
- const char *path, *r;
-
- path = me->pathname;
- r = strrchr(path, '/');
- if (r == NULL)
- return (0);
- /* Include a separator size */
- return (r - path + 1);
-}
-
-#else /* _WIN32 && !__CYGWIN__ */
-/*
- * Note: We should use wide-character for findng '\' character,
- * a directory separator on Windows, because some character-set have
- * been using the '\' character for a part of its multibyte character
- * code.
- */
-static size_t
-dir_len(struct mtree_entry *me)
-{
- wchar_t wc;
- const char *path;
- const char *p, *rp;
- size_t al, l, size;
-
- path = me->pathname;
- al = l = -1;
- for (p = path; *p != '\0'; ++p) {
- if (*p == '\\')
- al = l = p - path;
- else if (*p == '/')
- al = p - path;
- }
- if (l == -1)
- goto alen;
- size = p - path;
- rp = p = path;
- while (*p != '\0') {
- l = mbtowc(&wc, p, size);
- if (l == -1)
- goto alen;
- if (l == 1 && (wc == L'/' || wc == L'\\'))
- rp = p;
- p += l;
- size -= l;
- }
- return (rp - path + 1);
-alen:
- if (al == -1)
- return (0);
- return (al + 1);
-}
-#endif /* _WIN32 && !__CYGWIN__ */
-
-/*
- * Test if a parent directory of the current entry is changed.
- */
-static int
-parent_dir_changed(struct archive_string *dir, struct mtree_entry *me)
-{
- const char *path;
- size_t l;
-
- l = dir_len(me);
- path = me->pathname;
- if (archive_strlen(dir) > 0) {
- if (l == 0) {
- archive_string_empty(dir);
- return (1);
- }
- if (strncmp(dir->s, path, l) == 0)
- return (0); /* The parent directory is the same. */
- } else if (l == 0)
- return (0); /* The parent directory is the same. */
- archive_strncpy(dir, path, l);
- return (1);
-}
-
/*
* Write /set keyword.
* Set most used value of uid,gid,mode and fflags, which are
- * collected by collect_set_values() function.
+ * collected by attr_counter_set_collect() function.
*/
static void
write_global(struct mtree_writer *mtree)
{
struct archive_string setstr;
struct archive_string unsetstr;
- const char *name;
+ struct att_counter_set *acs;
int keys, oldkeys, effkeys;
- struct attr_counter *ac;
archive_string_init(&setstr);
archive_string_init(&unsetstr);
keys = mtree->keys & SET_KEYS;
oldkeys = mtree->set.keys;
effkeys = keys;
- if (mtree->set.processed) {
+ acs = &mtree->acs;
+ if (mtree->set.processing) {
/*
* Check if the global data needs updating.
*/
effkeys &= ~F_TYPE;
- if (oldkeys & (F_UNAME | F_UID)) {
- ac = mtree->set.uid_list;
- do {
- if (mtree->set.uid == ac->m_entry->uid) {
- effkeys &= ~(F_UNAME | F_UID);
- break;
- }
- if (ac->next != NULL &&
- ac->next->count == ac->count)
- continue;
- } while (0);
+ if (acs->uid_list == NULL)
+ effkeys &= ~(F_UNAME | F_UID);
+ else if (oldkeys & (F_UNAME | F_UID)) {
+ if (acs->uid_list->count < 2 ||
+ mtree->set.uid == acs->uid_list->m_entry->uid)
+ effkeys &= ~(F_UNAME | F_UID);
}
- if (oldkeys & (F_GNAME | F_GID)) {
- ac = mtree->set.gid_list;
- do {
- if (mtree->set.gid == ac->m_entry->gid) {
- effkeys &= ~(F_GNAME | F_GID);
- break;
- }
- if (ac->next != NULL &&
- ac->next->count == ac->count)
- continue;
- } while (0);
+ if (acs->gid_list == NULL)
+ effkeys &= ~(F_GNAME | F_GID);
+ else if (oldkeys & (F_GNAME | F_GID)) {
+ if (acs->gid_list->count < 2 ||
+ mtree->set.gid == acs->gid_list->m_entry->gid)
+ effkeys &= ~(F_GNAME | F_GID);
}
- if (oldkeys & F_MODE) {
- ac = mtree->set.mode_list;
- do {
- if (mtree->set.mode == ac->m_entry->mode) {
- effkeys &= ~F_MODE;
- break;
- }
- if (ac->next != NULL &&
- ac->next->count == ac->count)
- continue;
- } while (0);
+ if (acs->mode_list == NULL)
+ effkeys &= ~F_MODE;
+ else if (oldkeys & F_MODE) {
+ if (acs->mode_list->count < 2 ||
+ mtree->set.mode == acs->mode_list->m_entry->mode)
+ effkeys &= ~F_MODE;
}
- if ((oldkeys & F_FLAGS) != 0) {
- ac = mtree->set.flags_list;
- do {
- if (ac->m_entry->fflags_set ==
- mtree->set.fflags_set &&
- ac->m_entry->fflags_clear ==
- mtree->set.fflags_clear) {
- effkeys &= ~F_FLAGS;
- break;
- }
- if (ac->next != NULL &&
- ac->next->count == ac->count)
- continue;
- } while (0);
+ if (acs->flags_list == NULL)
+ effkeys &= ~F_FLAGS;
+ else if ((oldkeys & F_FLAGS) != 0) {
+ if (acs->flags_list->count < 2 ||
+ (acs->flags_list->m_entry->fflags_set ==
+ mtree->set.fflags_set &&
+ acs->flags_list->m_entry->fflags_clear ==
+ mtree->set.fflags_clear))
+ effkeys &= ~F_FLAGS;
}
+ } else {
+ if (acs->uid_list == NULL)
+ keys &= ~(F_UNAME | F_UID);
+ if (acs->gid_list == NULL)
+ keys &= ~(F_GNAME | F_GID);
+ if (acs->mode_list == NULL)
+ keys &= ~F_MODE;
+ if (acs->flags_list == NULL)
+ keys &= ~F_FLAGS;
}
if ((keys & effkeys & F_TYPE) != 0) {
if (mtree->dironly) {
@@ -520,10 +513,9 @@ write_global(struct mtree_writer *mtree)
}
}
if ((keys & effkeys & F_UNAME) != 0) {
- name = mtree->set.uid_list->m_entry->uname;
- if (name != NULL) {
+ if (archive_strlen(&(acs->uid_list->m_entry->uname)) > 0) {
archive_strcat(&setstr, " uname=");
- mtree_quote(&setstr, name);
+ mtree_quote(&setstr, acs->uid_list->m_entry->uname.s);
} else {
keys &= ~F_UNAME;
if ((oldkeys & F_UNAME) != 0)
@@ -531,15 +523,14 @@ write_global(struct mtree_writer *mtree)
}
}
if ((keys & effkeys & F_UID) != 0) {
- mtree->set.uid = mtree->set.uid_list->m_entry->uid;
+ mtree->set.uid = acs->uid_list->m_entry->uid;
archive_string_sprintf(&setstr, " uid=%jd",
(intmax_t)mtree->set.uid);
}
if ((keys & effkeys & F_GNAME) != 0) {
- name = mtree->set.gid_list->m_entry->gname;
- if (name != NULL) {
+ if (archive_strlen(&(acs->gid_list->m_entry->gname)) > 0) {
archive_strcat(&setstr, " gname=");
- mtree_quote(&setstr, name);
+ mtree_quote(&setstr, acs->gid_list->m_entry->gname.s);
} else {
keys &= ~F_GNAME;
if ((oldkeys & F_GNAME) != 0)
@@ -547,24 +538,25 @@ write_global(struct mtree_writer *mtree)
}
}
if ((keys & effkeys & F_GID) != 0) {
- mtree->set.gid = mtree->set.gid_list->m_entry->gid;
+ mtree->set.gid = acs->gid_list->m_entry->gid;
archive_string_sprintf(&setstr, " gid=%jd",
(intmax_t)mtree->set.gid);
}
if ((keys & effkeys & F_MODE) != 0) {
- mtree->set.mode = mtree->set.mode_list->m_entry->mode;
+ mtree->set.mode = acs->mode_list->m_entry->mode;
archive_string_sprintf(&setstr, " mode=%o",
(unsigned int)mtree->set.mode);
}
if ((keys & effkeys & F_FLAGS) != 0) {
- name = mtree->set.flags_list->m_entry->fflags_text;
- if (name != NULL) {
+ if (archive_strlen(
+ &(acs->flags_list->m_entry->fflags_text)) > 0) {
archive_strcat(&setstr, " flags=");
- mtree_quote(&setstr, name);
+ mtree_quote(&setstr,
+ acs->flags_list->m_entry->fflags_text.s);
mtree->set.fflags_set =
- mtree->set.flags_list->m_entry->fflags_set;
+ acs->flags_list->m_entry->fflags_set;
mtree->set.fflags_clear =
- mtree->set.flags_list->m_entry->fflags_clear;
+ acs->flags_list->m_entry->fflags_clear;
} else {
keys &= ~F_FLAGS;
if ((oldkeys & F_FLAGS) != 0)
@@ -578,16 +570,11 @@ write_global(struct mtree_writer *mtree)
archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s);
archive_string_free(&setstr);
mtree->set.keys = keys;
- mtree->set.processed = 1;
-
- free_attr_count(&mtree->set.uid_list);
- free_attr_count(&mtree->set.gid_list);
- free_attr_count(&mtree->set.mode_list);
- free_attr_count(&mtree->set.flags_list);
+ mtree->set.processing = 1;
}
static struct attr_counter *
-new_attr_count(struct mtree_entry *me, struct attr_counter *prev)
+attr_counter_new(struct mtree_entry *me, struct attr_counter *prev)
{
struct attr_counter *ac;
@@ -602,7 +589,7 @@ new_attr_count(struct mtree_entry *me, struct attr_counter *prev)
}
static void
-free_attr_count(struct attr_counter **top)
+attr_counter_free(struct attr_counter **top)
{
struct attr_counter *ac, *tac;
@@ -618,7 +605,7 @@ free_attr_count(struct attr_counter **top)
}
static int
-inc_attr_count(struct attr_counter **top, struct attr_counter *ac,
+attr_counter_inc(struct attr_counter **top, struct attr_counter *ac,
struct attr_counter *last, struct mtree_entry *me)
{
struct attr_counter *pac;
@@ -647,7 +634,7 @@ inc_attr_count(struct attr_counter **top, struct attr_counter *ac,
ac->next->prev = ac;
}
} else {
- ac = new_attr_count(me, last);
+ ac = attr_counter_new(me, last);
if (ac == NULL)
return (-1);
last->next = ac;
@@ -655,93 +642,99 @@ inc_attr_count(struct attr_counter **top, struct attr_counter *ac,
return (0);
}
+/*
+ * Tabulate uid,gid,mode and fflags of a entry in order to be used for /set.
+ */
static int
-collect_set_values(struct mtree_writer *mtree, struct mtree_entry *me)
+attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
{
- int keys = mtree->keys;
struct attr_counter *ac, *last;
+ struct att_counter_set *acs = &mtree->acs;
+ int keys = mtree->keys;
if (keys & (F_UNAME | F_UID)) {
- if (mtree->set.uid_list == NULL) {
- mtree->set.uid_list = new_attr_count(me, NULL);
- if (mtree->set.uid_list == NULL)
+ if (acs->uid_list == NULL) {
+ acs->uid_list = attr_counter_new(me, NULL);
+ if (acs->uid_list == NULL)
return (-1);
} else {
last = NULL;
- for (ac = mtree->set.uid_list; ac; ac = ac->next) {
+ for (ac = acs->uid_list; ac; ac = ac->next) {
if (ac->m_entry->uid == me->uid)
break;
last = ac;
}
- if (inc_attr_count(
- &mtree->set.uid_list, ac, last, me) < 0)
+ if (attr_counter_inc(&acs->uid_list, ac, last, me) < 0)
return (-1);
}
}
if (keys & (F_GNAME | F_GID)) {
- if (mtree->set.gid_list == NULL) {
- mtree->set.gid_list = new_attr_count(me, NULL);
- if (mtree->set.gid_list == NULL)
+ if (acs->gid_list == NULL) {
+ acs->gid_list = attr_counter_new(me, NULL);
+ if (acs->gid_list == NULL)
return (-1);
} else {
last = NULL;
- for (ac = mtree->set.gid_list; ac; ac = ac->next) {
+ for (ac = acs->gid_list; ac; ac = ac->next) {
if (ac->m_entry->gid == me->gid)
break;
last = ac;
}
- if (inc_attr_count(
- &mtree->set.gid_list, ac, last, me) < 0)
+ if (attr_counter_inc(&acs->gid_list, ac, last, me) < 0)
return (-1);
}
}
if (keys & F_MODE) {
- if (mtree->set.mode_list == NULL) {
- mtree->set.mode_list = new_attr_count(me, NULL);
- if (mtree->set.mode_list == NULL)
+ if (acs->mode_list == NULL) {
+ acs->mode_list = attr_counter_new(me, NULL);
+ if (acs->mode_list == NULL)
return (-1);
} else {
last = NULL;
- for (ac = mtree->set.mode_list; ac; ac = ac->next) {
+ for (ac = acs->mode_list; ac; ac = ac->next) {
if (ac->m_entry->mode == me->mode)
break;
last = ac;
}
- if (inc_attr_count(
- &mtree->set.mode_list, ac, last, me) < 0)
+ if (attr_counter_inc(&acs->mode_list, ac, last, me) < 0)
return (-1);
}
}
if (keys & F_FLAGS) {
- if (mtree->set.flags_list == NULL) {
- mtree->set.flags_list = new_attr_count(me, NULL);
- if (mtree->set.flags_list == NULL)
+ if (acs->flags_list == NULL) {
+ acs->flags_list = attr_counter_new(me, NULL);
+ if (acs->flags_list == NULL)
return (-1);
} else {
last = NULL;
- for (ac = mtree->set.flags_list; ac; ac = ac->next) {
+ for (ac = acs->flags_list; ac; ac = ac->next) {
if (ac->m_entry->fflags_set == me->fflags_set &&
- ac->m_entry->fflags_clear == me->fflags_clear)
+ ac->m_entry->fflags_clear ==
+ me->fflags_clear)
break;
last = ac;
}
- if (inc_attr_count(
- &mtree->set.flags_list, ac, last, me) < 0)
+ if (attr_counter_inc(&acs->flags_list, ac, last, me) < 0)
return (-1);
}
}
- /*
- * Save a entry.
- */
- me->next = NULL;
- *mtree->set.me_last = me;
- mtree->set.me_last = &me->next;
return (0);
}
+static void
+attr_counter_set_free(struct mtree_writer *mtree)
+{
+ struct att_counter_set *acs = &mtree->acs;
+
+ attr_counter_free(&acs->uid_list);
+ attr_counter_free(&acs->gid_list);
+ attr_counter_free(&acs->mode_list);
+ attr_counter_free(&acs->flags_list);
+}
+
static int
-get_keys(struct mtree_writer *mtree, struct mtree_entry *me)
+get_global_set_keys(struct mtree_writer *mtree, struct mtree_entry *me)
{
int keys;
@@ -788,56 +781,92 @@ get_keys(struct mtree_writer *mtree, struct mtree_entry *me)
return (keys);
}
-static struct mtree_entry *
-new_mtree_entry(struct archive_entry *entry)
+static int
+mtree_entry_new(struct archive_write *a, struct archive_entry *entry,
+ struct mtree_entry **m_entry)
{
struct mtree_entry *me;
const char *s;
+ int r;
+ static const struct archive_rb_tree_ops rb_ops = {
+ mtree_entry_cmp_node, mtree_entry_cmp_key
+ };
me = calloc(1, sizeof(*me));
- if (me == NULL)
- return (NULL);
- me->pathname = strdup(archive_entry_pathname(entry));
+ if (me == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for a mtree entry");
+ *m_entry = NULL;
+ return (ARCHIVE_FATAL);
+ }
+
+ r = mtree_entry_setup_filenames(a, me, entry);
+ if (r < ARCHIVE_WARN) {
+ mtree_entry_free(me);
+ *m_entry = NULL;
+ return (r);
+ }
+
if ((s = archive_entry_symlink(entry)) != NULL)
- me->symlink = strdup(s);
- else
- me->symlink = NULL;
+ archive_strcpy(&me->symlink, s);
me->nlink = archive_entry_nlink(entry);
me->filetype = archive_entry_filetype(entry);
me->mode = archive_entry_mode(entry) & 07777;
me->uid = archive_entry_uid(entry);
me->gid = archive_entry_gid(entry);
if ((s = archive_entry_uname(entry)) != NULL)
- me->uname = strdup(s);
- else
- me->uname = NULL;
+ archive_strcpy(&me->uname, s);
if ((s = archive_entry_gname(entry)) != NULL)
- me->gname = strdup(s);
- else
- me->gname = NULL;
+ archive_strcpy(&me->gname, s);
if ((s = archive_entry_fflags_text(entry)) != NULL)
- me->fflags_text = strdup(s);
- else
- me->fflags_text = NULL;
+ archive_strcpy(&me->fflags_text, s);
archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear);
me->mtime = archive_entry_mtime(entry);
me->mtime_nsec = archive_entry_mtime_nsec(entry);
me->rdevmajor = archive_entry_rdevmajor(entry);
me->rdevminor = archive_entry_rdevminor(entry);
me->size = archive_entry_size(entry);
- me->compute_sum = 0;
+ if (me->filetype == AE_IFDIR) {
+ me->dir_info = calloc(1, sizeof(*me->dir_info));
+ if (me->dir_info == NULL) {
+ mtree_entry_free(me);
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for a mtree entry");
+ *m_entry = NULL;
+ return (ARCHIVE_FATAL);
+ }
+ __archive_rb_tree_init(&me->dir_info->rbtree, &rb_ops);
+ me->dir_info->children.first = NULL;
+ me->dir_info->children.last = &(me->dir_info->children.first);
+ me->dir_info->chnext = NULL;
+ } else if (me->filetype == AE_IFREG) {
+ me->reg_info = calloc(1, sizeof(*me->reg_info));
+ if (me->reg_info == NULL) {
+ mtree_entry_free(me);
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for a mtree entry");
+ *m_entry = NULL;
+ return (ARCHIVE_FATAL);
+ }
+ me->reg_info->compute_sum = 0;
+ }
- return (me);
+ *m_entry = me;
+ return (ARCHIVE_OK);
}
static void
-free_mtree_entry(struct mtree_entry *me)
+mtree_entry_free(struct mtree_entry *me)
{
- free(me->pathname);
- free(me->symlink);
- free(me->uname);
- free(me->gname);
- free(me->fflags_text);
+ archive_string_free(&me->parentdir);
+ archive_string_free(&me->basename);
+ archive_string_free(&me->pathname);
+ archive_string_free(&me->symlink);
+ archive_string_free(&me->uname);
+ archive_string_free(&me->gname);
+ archive_string_free(&me->fflags_text);
+ free(me->dir_info);
+ free(me->reg_info);
free(me);
}
@@ -846,66 +875,100 @@ archive_write_mtree_header(struct archive_write *a,
struct archive_entry *entry)
{
struct mtree_writer *mtree= a->format_data;
+ struct mtree_entry *mtree_entry;
+ int r, r2;
if (mtree->first) {
mtree->first = 0;
archive_strcat(&mtree->buf, "#mtree\n");
if ((mtree->keys & SET_KEYS) == 0)
- mtree->set.output = 0;/* Disalbed. */
+ mtree->output_global_set = 0;/* Disalbed. */
}
mtree->entry_bytes_remaining = archive_entry_size(entry);
+
+ /* While directory only mode, we do not handle non directory files. */
if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR)
return (ARCHIVE_OK);
- mtree->mtree_entry = new_mtree_entry(entry);
- if (mtree->mtree_entry == NULL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate mtree entry");
- return (ARCHIVE_FATAL);
+ r2 = mtree_entry_new(a, entry, &mtree_entry);
+ if (r2 < ARCHIVE_WARN)
+ return (r2);
+ r = mtree_entry_tree_add(a, &mtree_entry);
+ if (r < ARCHIVE_WARN) {
+ mtree_entry_free(mtree_entry);
+ return (r);
}
+ mtree->mtree_entry = mtree_entry;
- mtree->compute_sum = 0;
-
- /* If current file is not a regular file, we do not have to
- * compute the sum of its content. */
- if (archive_entry_filetype(entry) != AE_IFREG)
- return (ARCHIVE_OK);
-
- /* Initialize a bunch of sum check context. */
- sum_init(mtree);
+ /* If the current file is a regular file, we have to
+ * compute the sum of its content.
+ * Initialize a bunch of sum check context. */
+ if (mtree_entry->reg_info)
+ sum_init(mtree);
- return (ARCHIVE_OK);
+ return (r2);
}
static int
-write_entry(struct archive_write *a, struct mtree_entry *me)
+write_mtree_entry(struct archive_write *a, struct mtree_entry *me)
{
struct mtree_writer *mtree = a->format_data;
struct archive_string *str;
int keys, ret;
+ if (me->dir_info) {
+ if (mtree->classic) {
+ /*
+ * Output a comment line to describe the full
+ * pathname of the entry as mtree utility does
+ * while generating classic format.
+ */
+ if (!mtree->dironly)
+ archive_strappend_char(&mtree->buf, '\n');
+ if (me->parentdir.s)
+ archive_string_sprintf(&mtree->buf,
+ "# %s/%s\n",
+ me->parentdir.s, me->basename.s);
+ else
+ archive_string_sprintf(&mtree->buf,
+ "# %s\n",
+ me->basename.s);
+ }
+ if (mtree->output_global_set)
+ write_global(mtree);
+ }
archive_string_empty(&mtree->ebuf);
- str = (mtree->indent)? &mtree->ebuf : &mtree->buf;
- mtree_quote(str, me->pathname);
- keys = get_keys(mtree, me);
+ str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf;
+
+ if (!mtree->classic && me->parentdir.s) {
+ /*
+ * If generating format is not classic one(v1), output
+ * a full pathname.
+ */
+ mtree_quote(str, me->parentdir.s);
+ archive_strappend_char(str, '/');
+ }
+ mtree_quote(str, me->basename.s);
+
+ keys = get_global_set_keys(mtree, me);
if ((keys & F_NLINK) != 0 &&
me->nlink != 1 && me->filetype != AE_IFDIR)
archive_string_sprintf(str, " nlink=%u", me->nlink);
- if ((keys & F_GNAME) != 0 && me->gname != NULL) {
+ if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) {
archive_strcat(str, " gname=");
- mtree_quote(str, me->gname);
+ mtree_quote(str, me->gname.s);
}
- if ((keys & F_UNAME) != 0 && me->uname != NULL) {
+ if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) {
archive_strcat(str, " uname=");
- mtree_quote(str, me->uname);
+ mtree_quote(str, me->uname.s);
}
if ((keys & F_FLAGS) != 0) {
- if (me->fflags_text != NULL) {
+ if (archive_strlen(&me->fflags_text) > 0) {
archive_strcat(str, " flags=");
- mtree_quote(str, me->fflags_text);
- } else if (mtree->set.processed &&
+ mtree_quote(str, me->fflags_text.s);
+ } else if (mtree->set.processing &&
(mtree->set.keys & F_FLAGS) != 0)
/* Overwrite the global parameter. */
archive_strcat(str, " flags=none");
@@ -926,7 +989,7 @@ write_entry(struct archive_write *a, struct mtree_entry *me)
archive_strcat(str, " type=link");
if ((keys & F_SLINK) != 0) {
archive_strcat(str, " link=");
- mtree_quote(str, me->symlink);
+ mtree_quote(str, me->symlink.s);
}
break;
case AE_IFSOCK:
@@ -972,15 +1035,48 @@ write_entry(struct archive_write *a, struct mtree_entry *me)
}
/* Write a bunch of sum. */
- if (me->filetype == AE_IFREG)
- sum_write(str, me);
+ if (me->reg_info)
+ sum_write(str, me->reg_info);
+
+ archive_strappend_char(str, '\n');
+ if (mtree->indent || mtree->classic)
+ mtree_indent(mtree);
+
+ if (mtree->buf.length > 32768) {
+ ret = __archive_write_output(
+ a, mtree->buf.s, mtree->buf.length);
+ archive_string_empty(&mtree->buf);
+ } else
+ ret = ARCHIVE_OK;
+ return (ret);
+}
- archive_strcat(str, "\n");
- if (mtree->indent)
+static int
+write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n)
+{
+ struct mtree_writer *mtree = a->format_data;
+ int ret;
+
+ if (n->parentdir.s) {
+ if (mtree->indent) {
+ int i, pd = mtree->depth * 4;
+ for (i = 0; i < pd; i++)
+ archive_strappend_char(&mtree->buf, ' ');
+ }
+ archive_string_sprintf(&mtree->buf, "# %s/%s\n",
+ n->parentdir.s, n->basename.s);
+ }
+
+ if (mtree->indent) {
+ archive_string_empty(&mtree->ebuf);
+ archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4);
mtree_indent(mtree);
+ } else
+ archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4);
if (mtree->buf.length > 32768) {
- ret = __archive_write_output(a, mtree->buf.s, mtree->buf.length);
+ ret = __archive_write_output(
+ a, mtree->buf.s, mtree->buf.length);
archive_string_empty(&mtree->buf);
} else
ret = ARCHIVE_OK;
@@ -988,29 +1084,106 @@ write_entry(struct archive_write *a, struct mtree_entry *me)
}
/*
- * Write mtree entries saved at collect_set_values() function.
+ * Write mtree entries saved at attr_counter_set_collect() function.
*/
static int
-write_mtree_entries(struct archive_write *a)
+write_mtree_entry_tree(struct archive_write *a)
{
struct mtree_writer *mtree = a->format_data;
- struct mtree_entry *me, *tme;
+ struct mtree_entry *np = mtree->root;
+ struct archive_rb_node *n;
int ret;
- for (me = mtree->set.me_first; me; me = me->next) {
- ret = write_entry(a, me);
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
- }
+ do {
+ if (mtree->output_global_set) {
+ /*
+ * Collect attribute infomation to know which value
+ * is frequently used among the children.
+ */
+ attr_counter_set_reset(mtree);
+ ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
+ struct mtree_entry *e = (struct mtree_entry *)n;
+ if (attr_counter_set_collect(mtree, e) < 0) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ }
+ if (!np->dir_info->virtual || mtree->classic) {
+ ret = write_mtree_entry(a, np);
+ if (ret != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ } else {
+ /* Whenever output_global_set is enabled
+ * output global value(/set keywords)
+ * even if the directory entry is not allowd
+ * to be written because the global values
+ * can be used for the children. */
+ if (mtree->output_global_set)
+ write_global(mtree);
+ }
+ /*
+ * Output the attribute of all files except directory files.
+ */
+ mtree->depth++;
+ ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
+ struct mtree_entry *e = (struct mtree_entry *)n;
+
+ if (e->dir_info)
+ mtree_entry_add_child_tail(np, e);
+ else {
+ ret = write_mtree_entry(a, e);
+ if (ret != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ }
+ }
+ mtree->depth--;
+
+ if (np->dir_info->children.first != NULL) {
+ /*
+ * Descend the tree.
+ */
+ np = np->dir_info->children.first;
+ if (mtree->indent)
+ mtree->depth++;
+ continue;
+ } else if (mtree->classic) {
+ /*
+ * While printing mtree classic, if there are not
+ * any directory files(except "." and "..") in the
+ * directory, output two dots ".." as returning
+ * the parent directory.
+ */
+ ret = write_dot_dot_entry(a, np);
+ if (ret != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ }
+
+ while (np != np->parent) {
+ if (np->dir_info->chnext == NULL) {
+ /*
+ * Ascend the tree; go back to the parent.
+ */
+ if (mtree->indent)
+ mtree->depth--;
+ if (mtree->classic) {
+ ret = write_dot_dot_entry(a,
+ np->parent);
+ if (ret != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ }
+ np = np->parent;
+ } else {
+ /*
+ * Switch to next mtree entry in the directory.
+ */
+ np = np->dir_info->chnext;
+ break;
+ }
+ }
+ } while (np != np->parent);
- me = mtree->set.me_first;
- while (me != NULL) {
- tme = me->next;
- free_mtree_entry(me);
- me = tme;
- }
- mtree->set.me_first = NULL;
- mtree->set.me_last = &mtree->set.me_first;
return (ARCHIVE_OK);
}
@@ -1019,40 +1192,15 @@ archive_write_mtree_finish_entry(struct archive_write *a)
{
struct mtree_writer *mtree = a->format_data;
struct mtree_entry *me;
- int ret;
if ((me = mtree->mtree_entry) == NULL)
return (ARCHIVE_OK);
mtree->mtree_entry = NULL;
- if (me->filetype == AE_IFREG)
- sum_final(mtree, me);
+ if (me->reg_info)
+ sum_final(mtree, me->reg_info);
- if (mtree->set.output) {
- if (!mtree->dironly) {
- if (archive_strlen(&mtree->set.parent) == 0)
- parent_dir_changed(&mtree->set.parent, me);
- if (parent_dir_changed(&mtree->set.parent, me)) {
- /* Write /set keyword */
- write_global(mtree);
- /* Write entries saved by
- * collect_set_values() function. */
- ret = write_mtree_entries(a);
- if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
- }
- }
- /* Tabulate uid,gid,mode and fflags of a entry
- * in order to be used for /set. and, at this time
- * we do not write a entry. */
- collect_set_values(mtree, me);
- return (ARCHIVE_OK);
- } else {
- /* Write the current entry and free it. */
- ret = write_entry(a, me);
- free_mtree_entry(me);
- }
- return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL);
+ return (ARCHIVE_OK);
}
static int
@@ -1061,9 +1209,8 @@ archive_write_mtree_close(struct archive_write *a)
struct mtree_writer *mtree= a->format_data;
int ret;
- if (mtree->set.output && mtree->set.me_first != NULL) {
- write_global(mtree);
- ret = write_mtree_entries(a);
+ if (mtree->root != NULL) {
+ ret = write_mtree_entry_tree(a);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
}
@@ -1079,7 +1226,7 @@ archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
struct mtree_writer *mtree= a->format_data;
if (n > mtree->entry_bytes_remaining)
- n = mtree->entry_bytes_remaining;
+ n = (size_t)mtree->entry_bytes_remaining;
mtree->entry_bytes_remaining -= n;
/* We don't need to compute a regular file sum */
@@ -1096,25 +1243,16 @@ static int
archive_write_mtree_free(struct archive_write *a)
{
struct mtree_writer *mtree= a->format_data;
- struct mtree_entry *me, *tme;
if (mtree == NULL)
return (ARCHIVE_OK);
/* Make sure we dot not leave any entries. */
- me = mtree->set.me_first;
- while (me != NULL) {
- tme = me->next;
- free_mtree_entry(me);
- me = tme;
- }
+ mtree_entry_register_free(mtree);
+ archive_string_free(&mtree->cur_dirstr);
archive_string_free(&mtree->ebuf);
archive_string_free(&mtree->buf);
- archive_string_free(&mtree->set.parent);
- free_attr_count(&mtree->set.uid_list);
- free_attr_count(&mtree->set.gid_list);
- free_attr_count(&mtree->set.mode_list);
- free_attr_count(&mtree->set.flags_list);
+ attr_counter_set_free(mtree);
free(mtree);
a->format_data = NULL;
return (ARCHIVE_OK);
@@ -1209,7 +1347,7 @@ archive_write_mtree_options(struct archive_write *a, const char *key,
else if (strcmp(key, "uname") == 0)
keybit = F_UNAME;
else if (strcmp(key, "use-set") == 0) {
- mtree->set.output = (value != NULL)? 1: 0;
+ mtree->output_global_set = (value != NULL)? 1: 0;
return (ARCHIVE_OK);
}
break;
@@ -1222,17 +1360,19 @@ archive_write_mtree_options(struct archive_write *a, const char *key,
return (ARCHIVE_OK);
}
- return (ARCHIVE_FAILED);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
-int
-archive_write_set_format_mtree(struct archive *_a)
+static int
+archive_write_set_format_mtree_default(struct archive *_a, const char *fn)
{
struct archive_write *a = (struct archive_write *)_a;
struct mtree_writer *mtree;
- archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
- ARCHIVE_STATE_NEW, "archive_write_set_format_mtree");
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn);
if (a->format_free != NULL)
(a->format_free)(a);
@@ -1246,14 +1386,12 @@ archive_write_set_format_mtree(struct archive *_a)
mtree->mtree_entry = NULL;
mtree->first = 1;
memset(&(mtree->set), 0, sizeof(mtree->set));
- archive_string_init(&mtree->set.parent);
mtree->keys = DEFAULT_KEYS;
mtree->dironly = 0;
mtree->indent = 0;
archive_string_init(&mtree->ebuf);
archive_string_init(&mtree->buf);
- mtree->set.me_first = NULL;
- mtree->set.me_last = &mtree->set.me_first;
+ mtree_entry_register_init(mtree);
a->format_data = mtree;
a->format_free = archive_write_mtree_free;
a->format_name = "mtree";
@@ -1268,9 +1406,41 @@ archive_write_set_format_mtree(struct archive *_a)
return (ARCHIVE_OK);
}
+int
+archive_write_set_format_mtree(struct archive *_a)
+{
+ return archive_write_set_format_mtree_default(_a,
+ "archive_write_set_format_mtree");
+}
+
+int
+archive_write_set_format_mtree_classic(struct archive *_a)
+{
+ int r;
+
+ r = archive_write_set_format_mtree_default(_a,
+ "archive_write_set_format_mtree_classic");
+ if (r == ARCHIVE_OK) {
+ struct archive_write *a = (struct archive_write *)_a;
+ struct mtree_writer *mtree;
+
+ mtree = (struct mtree_writer *)a->format_data;
+
+ /* Set to output a mtree archive in classic format. */
+ mtree->classic = 1;
+ /* Basically, mtree classic format uses '/set' global
+ * value. */
+ mtree->output_global_set = 1;
+ }
+ return (r);
+}
+
static void
sum_init(struct mtree_writer *mtree)
{
+
+ mtree->compute_sum = 0;
+
if (mtree->keys & F_CKSUM) {
mtree->compute_sum |= F_CKSUM;
mtree->crc = 0;
@@ -1367,7 +1537,7 @@ sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
}
static void
-sum_final(struct mtree_writer *mtree, struct mtree_entry *me)
+sum_final(struct mtree_writer *mtree, struct reg_info *reg)
{
if (mtree->compute_sum & F_CKSUM) {
@@ -1375,34 +1545,34 @@ sum_final(struct mtree_writer *mtree, struct mtree_entry *me)
/* Include the length of the file. */
for (len = mtree->crc_len; len != 0; len >>= 8)
COMPUTE_CRC(mtree->crc, len & 0xff);
- me->crc = ~mtree->crc;
+ reg->crc = ~mtree->crc;
}
#ifdef ARCHIVE_HAS_MD5
if (mtree->compute_sum & F_MD5)
- archive_md5_final(&mtree->md5ctx, me->buf_md5);
+ archive_md5_final(&mtree->md5ctx, reg->buf_md5);
#endif
#ifdef ARCHIVE_HAS_RMD160
if (mtree->compute_sum & F_RMD160)
- archive_rmd160_final(&mtree->rmd160ctx, me->buf_rmd160);
+ archive_rmd160_final(&mtree->rmd160ctx, reg->buf_rmd160);
#endif
#ifdef ARCHIVE_HAS_SHA1
if (mtree->compute_sum & F_SHA1)
- archive_sha1_final(&mtree->sha1ctx, me->buf_sha1);
+ archive_sha1_final(&mtree->sha1ctx, reg->buf_sha1);
#endif
#ifdef ARCHIVE_HAS_SHA256
if (mtree->compute_sum & F_SHA256)
- archive_sha256_final(&mtree->sha256ctx, me->buf_sha256);
+ archive_sha256_final(&mtree->sha256ctx, reg->buf_sha256);
#endif
#ifdef ARCHIVE_HAS_SHA384
if (mtree->compute_sum & F_SHA384)
- archive_sha384_final(&mtree->sha384ctx, me->buf_sha384);
+ archive_sha384_final(&mtree->sha384ctx, reg->buf_sha384);
#endif
#ifdef ARCHIVE_HAS_SHA512
if (mtree->compute_sum & F_SHA512)
- archive_sha512_final(&mtree->sha512ctx, me->buf_sha512);
+ archive_sha512_final(&mtree->sha512ctx, reg->buf_sha512);
#endif
/* Save what types of sum are computed. */
- me->compute_sum = mtree->compute_sum;
+ reg->compute_sum = mtree->compute_sum;
}
#if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
@@ -1422,47 +1592,612 @@ strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
#endif
static void
-sum_write(struct archive_string *str, struct mtree_entry *me)
+sum_write(struct archive_string *str, struct reg_info *reg)
{
- if (me->compute_sum & F_CKSUM) {
+ if (reg->compute_sum & F_CKSUM) {
archive_string_sprintf(str, " cksum=%ju",
- (uintmax_t)me->crc);
+ (uintmax_t)reg->crc);
}
#ifdef ARCHIVE_HAS_MD5
- if (me->compute_sum & F_MD5) {
+ if (reg->compute_sum & F_MD5) {
archive_strcat(str, " md5digest=");
- strappend_bin(str, me->buf_md5, sizeof(me->buf_md5));
+ strappend_bin(str, reg->buf_md5, sizeof(reg->buf_md5));
}
#endif
#ifdef ARCHIVE_HAS_RMD160
- if (me->compute_sum & F_RMD160) {
+ if (reg->compute_sum & F_RMD160) {
archive_strcat(str, " rmd160digest=");
- strappend_bin(str, me->buf_rmd160, sizeof(me->buf_rmd160));
+ strappend_bin(str, reg->buf_rmd160, sizeof(reg->buf_rmd160));
}
#endif
#ifdef ARCHIVE_HAS_SHA1
- if (me->compute_sum & F_SHA1) {
+ if (reg->compute_sum & F_SHA1) {
archive_strcat(str, " sha1digest=");
- strappend_bin(str, me->buf_sha1, sizeof(me->buf_sha1));
+ strappend_bin(str, reg->buf_sha1, sizeof(reg->buf_sha1));
}
#endif
#ifdef ARCHIVE_HAS_SHA256
- if (me->compute_sum & F_SHA256) {
+ if (reg->compute_sum & F_SHA256) {
archive_strcat(str, " sha256digest=");
- strappend_bin(str, me->buf_sha256, sizeof(me->buf_sha256));
+ strappend_bin(str, reg->buf_sha256, sizeof(reg->buf_sha256));
}
#endif
#ifdef ARCHIVE_HAS_SHA384
- if (me->compute_sum & F_SHA384) {
+ if (reg->compute_sum & F_SHA384) {
archive_strcat(str, " sha384digest=");
- strappend_bin(str, me->buf_sha384, sizeof(me->buf_sha384));
+ strappend_bin(str, reg->buf_sha384, sizeof(reg->buf_sha384));
}
#endif
#ifdef ARCHIVE_HAS_SHA512
- if (me->compute_sum & F_SHA512) {
+ if (reg->compute_sum & F_SHA512) {
archive_strcat(str, " sha512digest=");
- strappend_bin(str, me->buf_sha512, sizeof(me->buf_sha512));
+ strappend_bin(str, reg->buf_sha512, sizeof(reg->buf_sha512));
+ }
+#endif
+}
+
+static int
+mtree_entry_cmp_node(const struct archive_rb_node *n1,
+ const struct archive_rb_node *n2)
+{
+ const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
+ const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
+
+ return (strcmp(e2->basename.s, e1->basename.s));
+}
+
+static int
+mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key)
+{
+ const struct mtree_entry *e = (const struct mtree_entry *)n;
+
+ return (strcmp((const char *)key, e->basename.s));
+}
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+static int
+cleanup_backslash_1(char *p)
+{
+ int mb, dos;
+
+ mb = dos = 0;
+ while (*p) {
+ if (*(unsigned char *)p > 127)
+ mb = 1;
+ if (*p == '\\') {
+ /* If we have not met any multi-byte characters,
+ * we can replace '\' with '/'. */
+ if (!mb)
+ *p = '/';
+ dos = 1;
+ }
+ p++;
+ }
+ if (!mb || !dos)
+ return (0);
+ return (-1);
+}
+
+static void
+cleanup_backslash_2(wchar_t *p)
+{
+
+ /* Convert a path-separator from '\' to '/' */
+ while (*p != L'\0') {
+ if (*p == L'\\')
+ *p = L'/';
+ p++;
+ }
+}
+#endif
+
+/*
+ * Generate a parent directory name and a base name from a pathname.
+ */
+static int
+mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
+ struct archive_entry *entry)
+{
+ const char *pathname;
+ char *p, *dirname, *slash;
+ size_t len;
+ int ret = ARCHIVE_OK;
+
+ archive_strcpy(&file->pathname, archive_entry_pathname(entry));
+#if defined(_WIN32) || defined(__CYGWIN__)
+ /*
+ * Convert a path-separator from '\' to '/'
+ */
+ if (cleanup_backslash_1(file->pathname.s) != 0) {
+ const wchar_t *wp = archive_entry_pathname_w(entry);
+ struct archive_wstring ws;
+
+ if (wp != NULL) {
+ int r;
+ archive_string_init(&ws);
+ archive_wstrcpy(&ws, wp);
+ cleanup_backslash_2(ws.s);
+ archive_string_empty(&(file->pathname));
+ r = archive_string_append_from_wcs(&(file->pathname),
+ ws.s, ws.length);
+ archive_wstring_free(&ws);
+ if (r < 0 && errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+ }
+ }
+#else
+ (void)a; /* UNUSED */
+#endif
+ pathname = file->pathname.s;
+ if (strcmp(pathname, ".") == 0) {
+ archive_strcpy(&file->basename, ".");
+ return (ARCHIVE_OK);
+ }
+
+ archive_strcpy(&(file->parentdir), pathname);
+
+ len = file->parentdir.length;
+ p = dirname = file->parentdir.s;
+
+ /*
+ * Remove leading '/' and '../' elements
+ */
+ while (*p) {
+ if (p[0] == '/') {
+ p++;
+ len--;
+ } else if (p[0] != '.')
+ break;
+ else if (p[1] == '.' && p[2] == '/') {
+ p += 3;
+ len -= 3;
+ } else
+ break;
+ }
+ if (p != dirname) {
+ memmove(dirname, p, len+1);
+ p = dirname;
+ }
+ /*
+ * Remove "/","/." and "/.." elements from tail.
+ */
+ while (len > 0) {
+ size_t ll = len;
+
+ if (len > 0 && p[len-1] == '/') {
+ p[len-1] = '\0';
+ len--;
+ }
+ if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
+ p[len-2] = '\0';
+ len -= 2;
+ }
+ if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
+ p[len-1] == '.') {
+ p[len-3] = '\0';
+ len -= 3;
+ }
+ if (ll == len)
+ break;
+ }
+ while (*p) {
+ if (p[0] == '/') {
+ if (p[1] == '/')
+ /* Convert '//' --> '/' */
+ strcpy(p, p+1);
+ else if (p[1] == '.' && p[2] == '/')
+ /* Convert '/./' --> '/' */
+ strcpy(p, p+2);
+ else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
+ /* Convert 'dir/dir1/../dir2/'
+ * --> 'dir/dir2/'
+ */
+ char *rp = p -1;
+ while (rp >= dirname) {
+ if (*rp == '/')
+ break;
+ --rp;
+ }
+ if (rp > dirname) {
+ strcpy(rp, p+3);
+ p = rp;
+ } else {
+ strcpy(dirname, p+4);
+ p = dirname;
+ }
+ } else
+ p++;
+ } else
+ p++;
+ }
+ p = dirname;
+ len = strlen(p);
+
+ /*
+ * Add "./" prefiex.
+ * NOTE: If the pathname does not have a path separator, we have
+ * to add "./" to the head of the pathename because mtree reader
+ * will suppose that it is v1(a.k.a classic) mtree format and
+ * change the directory unexpectedly and so it will make a wrong
+ * path.
+ */
+ if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) {
+ struct archive_string as;
+ archive_string_init(&as);
+ archive_strcpy(&as, "./");
+ archive_strncat(&as, p, len);
+ archive_string_empty(&file->parentdir);
+ archive_string_concat(&file->parentdir, &as);
+ archive_string_free(&as);
+ p = file->parentdir.s;
+ len = archive_strlen(&file->parentdir);
+ }
+
+ /*
+ * Find out the position which points the last position of
+ * path separator('/').
+ */
+ slash = NULL;
+ for (; *p != '\0'; p++) {
+ if (*p == '/')
+ slash = p;
+ }
+ if (slash == NULL) {
+ /* The pathname doesn't have a parent directory. */
+ file->parentdir.length = len;
+ archive_string_copy(&(file->basename), &(file->parentdir));
+ archive_string_empty(&(file->parentdir));
+ *file->parentdir.s = '\0';
+ return (ret);
+ }
+
+ /* Make a basename from dirname and slash */
+ *slash = '\0';
+ file->parentdir.length = slash - dirname;
+ archive_strcpy(&(file->basename), slash + 1);
+ return (ret);
+}
+
+static int
+mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname,
+ struct mtree_entry **m_entry)
+{
+ struct archive_entry *entry;
+ struct mtree_entry *file;
+ int r;
+
+ entry = archive_entry_new();
+ if (entry == NULL) {
+ *m_entry = NULL;
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory");
+ return (ARCHIVE_FATAL);
}
+ archive_entry_copy_pathname(entry, pathname);
+ archive_entry_set_mode(entry, AE_IFDIR | 0755);
+ archive_entry_set_mtime(entry, time(NULL), 0);
+
+ r = mtree_entry_new(a, entry, &file);
+ archive_entry_free(entry);
+ if (r < ARCHIVE_WARN) {
+ *m_entry = NULL;
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory");
+ return (ARCHIVE_FATAL);
+ }
+
+ file->dir_info->virtual = 1;
+
+ *m_entry = file;
+ return (ARCHIVE_OK);
+}
+
+static void
+mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file)
+{
+ file->next = NULL;
+ *mtree->file_list.last = file;
+ mtree->file_list.last = &(file->next);
+}
+
+static void
+mtree_entry_register_init(struct mtree_writer *mtree)
+{
+ mtree->file_list.first = NULL;
+ mtree->file_list.last = &(mtree->file_list.first);
+}
+
+static void
+mtree_entry_register_free(struct mtree_writer *mtree)
+{
+ struct mtree_entry *file, *file_next;
+
+ file = mtree->file_list.first;
+ while (file != NULL) {
+ file_next = file->next;
+ mtree_entry_free(file);
+ file = file_next;
+ }
+}
+
+static int
+mtree_entry_add_child_tail(struct mtree_entry *parent,
+ struct mtree_entry *child)
+{
+ child->dir_info->chnext = NULL;
+ *parent->dir_info->children.last = child;
+ parent->dir_info->children.last = &(child->dir_info->chnext);
+ return (1);
+}
+
+/*
+ * Find a entry from a parent entry with the name.
+ */
+static struct mtree_entry *
+mtree_entry_find_child(struct mtree_entry *parent, const char *child_name)
+{
+ struct mtree_entry *np;
+
+ if (parent == NULL)
+ return (NULL);
+ np = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &(parent->dir_info->rbtree), child_name);
+ return (np);
+}
+
+static int
+get_path_component(char *name, size_t n, const char *fn)
+{
+ char *p;
+ size_t l;
+
+ p = strchr(fn, '/');
+ if (p == NULL) {
+ if ((l = strlen(fn)) == 0)
+ return (0);
+ } else
+ l = p - fn;
+ if (l > n -1)
+ return (-1);
+ memcpy(name, fn, l);
+ name[l] = '\0';
+
+ return ((int)l);
+}
+
+/*
+ * Add a new entry into the tree.
+ */
+static int
+mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ char name[_MAX_FNAME];/* Included null terminator size. */
+#elif defined(NAME_MAX) && NAME_MAX >= 255
+ char name[NAME_MAX+1];
+#else
+ char name[256];
#endif
+ struct mtree_writer *mtree = (struct mtree_writer *)a->format_data;
+ struct mtree_entry *dent, *file, *np;
+ const char *fn, *p;
+ int l, r;
+
+ file = *filep;
+ if (file->parentdir.length == 0 && file->basename.length == 1 &&
+ file->basename.s[0] == '.') {
+ file->parent = file;
+ if (mtree->root != NULL) {
+ np = mtree->root;
+ goto same_entry;
+ }
+ mtree->root = file;
+ mtree_entry_register_add(mtree, file);
+ return (ARCHIVE_OK);
+ }
+
+ if (file->parentdir.length == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Internal programing error "
+ "in generating canonical name for %s",
+ file->pathname.s);
+ return (ARCHIVE_FAILED);
+ }
+
+ fn = p = file->parentdir.s;
+
+ /*
+ * If the path of the parent directory of `file' entry is
+ * the same as the path of `cur_dirent', add `file' entry to
+ * `cur_dirent'.
+ */
+ if (archive_strlen(&(mtree->cur_dirstr))
+ == archive_strlen(&(file->parentdir)) &&
+ strcmp(mtree->cur_dirstr.s, fn) == 0) {
+ if (!__archive_rb_tree_insert_node(
+ &(mtree->cur_dirent->dir_info->rbtree),
+ (struct archive_rb_node *)file)) {
+ /* There is the same name in the tree. */
+ np = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &(mtree->cur_dirent->dir_info->rbtree),
+ file->basename.s);
+ goto same_entry;
+ }
+ file->parent = mtree->cur_dirent;
+ mtree_entry_register_add(mtree, file);
+ return (ARCHIVE_OK);
+ }
+
+ dent = mtree->root;
+ for (;;) {
+ l = get_path_component(name, sizeof(name), fn);
+ if (l == 0) {
+ np = NULL;
+ break;
+ }
+ if (l < 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "A name buffer is too small");
+ return (ARCHIVE_FATAL);
+ }
+ if (l == 1 && name[0] == '.' && dent != NULL &&
+ dent == mtree->root) {
+ fn += l;
+ if (fn[0] == '/')
+ fn++;
+ continue;
+ }
+
+ np = mtree_entry_find_child(dent, name);
+ if (np == NULL || fn[0] == '\0')
+ break;
+
+ /* Find next sub directory. */
+ if (!np->dir_info) {
+ /* NOT Directory! */
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "`%s' is not directory, we cannot insert `%s' ",
+ np->pathname.s, file->pathname.s);
+ return (ARCHIVE_FAILED);
+ }
+ fn += l;
+ if (fn[0] == '/')
+ fn++;
+ dent = np;
+ }
+ if (np == NULL) {
+ /*
+ * Create virtual parent directories.
+ */
+ while (fn[0] != '\0') {
+ struct mtree_entry *vp;
+ struct archive_string as;
+
+ archive_string_init(&as);
+ archive_strncat(&as, p, fn - p + l);
+ if (as.s[as.length-1] == '/') {
+ as.s[as.length-1] = '\0';
+ as.length--;
+ }
+ r = mtree_entry_create_virtual_dir(a, as.s, &vp);
+ archive_string_free(&as);
+ if (r < ARCHIVE_WARN)
+ return (r);
+
+ if (strcmp(vp->pathname.s, ".") == 0) {
+ vp->parent = vp;
+ mtree->root = vp;
+ } else {
+ __archive_rb_tree_insert_node(
+ &(dent->dir_info->rbtree),
+ (struct archive_rb_node *)vp);
+ vp->parent = dent;
+ }
+ mtree_entry_register_add(mtree, vp);
+ np = vp;
+
+ fn += l;
+ if (fn[0] == '/')
+ fn++;
+ l = get_path_component(name, sizeof(name), fn);
+ if (l < 0) {
+ archive_string_free(&as);
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "A name buffer is too small");
+ return (ARCHIVE_FATAL);
+ }
+ dent = np;
+ }
+
+ /* Found out the parent directory where `file' can be
+ * inserted. */
+ mtree->cur_dirent = dent;
+ archive_string_empty(&(mtree->cur_dirstr));
+ archive_string_ensure(&(mtree->cur_dirstr),
+ archive_strlen(&(dent->parentdir)) +
+ archive_strlen(&(dent->basename)) + 2);
+ if (archive_strlen(&(dent->parentdir)) +
+ archive_strlen(&(dent->basename)) == 0)
+ mtree->cur_dirstr.s[0] = 0;
+ else {
+ if (archive_strlen(&(dent->parentdir)) > 0) {
+ archive_string_copy(&(mtree->cur_dirstr),
+ &(dent->parentdir));
+ archive_strappend_char(
+ &(mtree->cur_dirstr), '/');
+ }
+ archive_string_concat(&(mtree->cur_dirstr),
+ &(dent->basename));
+ }
+
+ if (!__archive_rb_tree_insert_node(
+ &(dent->dir_info->rbtree),
+ (struct archive_rb_node *)file)) {
+ np = (struct mtree_entry *)__archive_rb_tree_find_node(
+ &(dent->dir_info->rbtree), file->basename.s);
+ goto same_entry;
+ }
+ file->parent = dent;
+ mtree_entry_register_add(mtree, file);
+ return (ARCHIVE_OK);
+ }
+
+same_entry:
+ /*
+ * We have already has the entry the filename of which is
+ * the same.
+ */
+ r = mtree_entry_exchange_same_entry(a, np, file);
+ if (r < ARCHIVE_WARN)
+ return (r);
+ if (np->dir_info)
+ np->dir_info->virtual = 0;
+ *filep = np;
+ mtree_entry_free(file);
+ return (ARCHIVE_WARN);
+}
+
+static int
+mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
+ struct mtree_entry *file)
+{
+
+ if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Found duplicate entries `%s' and its file type is "
+ "different",
+ np->pathname.s);
+ return (ARCHIVE_FAILED);
+ }
+
+ /* Update the existent mtree entry's attributes by the new one's. */
+ archive_string_empty(&np->symlink);
+ archive_string_concat(&np->symlink, &file->symlink);
+ archive_string_empty(&np->uname);
+ archive_string_concat(&np->uname, &file->uname);
+ archive_string_empty(&np->gname);
+ archive_string_concat(&np->gname, &file->gname);
+ archive_string_empty(&np->fflags_text);
+ archive_string_concat(&np->fflags_text, &file->fflags_text);
+ np->nlink = file->nlink;
+ np->filetype = file->filetype;
+ np->mode = file->mode;
+ np->size = file->size;
+ np->uid = file->uid;
+ np->gid = file->gid;
+ np->fflags_set = file->fflags_set;
+ np->fflags_clear = file->fflags_clear;
+ np->mtime = file->mtime;
+ np->mtime_nsec = file->mtime_nsec;
+ np->rdevmajor = file->rdevmajor;
+ np->rdevminor = file->rdevminor;
+
+ return (ARCHIVE_WARN);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
index 8affb2c..687f8e4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2010-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -187,11 +187,13 @@ archive_write_pax_options(struct archive_write *a, const char *key,
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"pax: invalid charset name");
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "pax: unknown keyword ``%s''", key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
/*
@@ -332,8 +334,7 @@ archive_write_pax_header_xattrs(struct archive_write *a,
url_encoded_name = url_encode(name);
if (url_encoded_name != NULL) {
/* Convert narrow-character to UTF-8. */
- r = archive_strcpy_in_locale(
- &(pax->l_url_encoded_name),
+ r = archive_strcpy_l(&(pax->l_url_encoded_name),
url_encoded_name, pax->sconv_utf8);
free(url_encoded_name); /* Done with this. */
if (r == 0)
@@ -463,7 +464,6 @@ archive_write_pax_header(struct archive_write *a,
{
struct archive_entry *entry_main;
const char *p;
- char *t;
const char *suffix;
int need_extension, r, ret;
int sparse_count;
@@ -541,24 +541,73 @@ archive_write_pax_header(struct archive_write *a,
case AE_IFREG:
break;
case AE_IFDIR:
+ {
/*
* Ensure a trailing '/'. Modify the original
* entry so the client sees the change.
*/
- p = archive_entry_pathname(entry_original);
- if (p[strlen(p) - 1] != '/') {
- t = (char *)malloc(strlen(p) + 2);
- if (t == NULL) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ const wchar_t *wp;
+
+ wp = archive_entry_pathname_w(entry_original);
+ if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
+ struct archive_wstring ws;
+
+ archive_string_init(&ws);
+ path_length = wcslen(wp);
+ if (archive_wstring_ensure(&ws,
+ path_length + 2) == NULL) {
archive_set_error(&a->archive, ENOMEM,
- "Can't allocate pax data");
+ "Can't allocate pax data");
+ archive_wstring_free(&ws);
return(ARCHIVE_FATAL);
}
- strcpy(t, p);
- strcat(t, "/");
- archive_entry_copy_pathname(entry_original, t);
- free(t);
+ /* Should we keep '\' ? */
+ if (wp[path_length -1] == L'\\')
+ path_length--;
+ archive_wstrncpy(&ws, wp, path_length);
+ archive_wstrappend_wchar(&ws, L'/');
+ archive_entry_copy_pathname_w(
+ entry_original, ws.s);
+ archive_wstring_free(&ws);
+ p = NULL;
+ } else
+#endif
+ p = archive_entry_pathname(entry_original);
+ /*
+ * On Windows, this is a backup operation just in
+ * case getting WCS failed. On POSIX, this is a
+ * normal operation.
+ */
+ if (p != NULL && p[strlen(p) - 1] != '/') {
+ struct archive_string as;
+
+ archive_string_init(&as);
+ path_length = strlen(p);
+ if (archive_string_ensure(&as,
+ path_length + 2) == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate pax data");
+ archive_string_free(&as);
+ return(ARCHIVE_FATAL);
+ }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* NOTE: This might break the pathname
+ * if the current code page is CP932 and
+ * the pathname includes a character '\'
+ * as a part of its multibyte pathname. */
+ if (p[strlen(p) -1] == '\\')
+ path_length--;
+ else
+#endif
+ archive_strncpy(&as, p, path_length);
+ archive_strappend_char(&as, '/');
+ archive_entry_copy_pathname(
+ entry_original, as.s);
+ archive_string_free(&as);
}
break;
+ }
case AE_IFSOCK:
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@@ -576,7 +625,7 @@ archive_write_pax_header(struct archive_write *a,
/*
* If Mac OS metadata blob is here, recurse to write that
- * as a separate entry. This is realy a pretty poor design:
+ * as a separate entry. This is really a pretty poor design:
* In particular, it doubles the overhead for long filenames.
* TODO: Help Apple folks design something better and figure
* out how to transition from this legacy format.
@@ -598,8 +647,10 @@ archive_write_pax_header(struct archive_write *a,
oname = archive_entry_pathname(entry_original);
name_length = strlen(oname);
name = malloc(name_length + 3);
- if (name == NULL) {
+ if (name == NULL || extra == NULL) {
/* XXX error message */
+ archive_entry_free(extra);
+ free(name);
return (ARCHIVE_FAILED);
}
strcpy(name, oname);
@@ -638,11 +689,13 @@ archive_write_pax_header(struct archive_write *a,
/* Recurse to write the special copyfile entry. */
r = archive_write_pax_header(a, extra);
+ archive_entry_free(extra);
if (r < ARCHIVE_WARN)
return (r);
if (r < ret)
ret = r;
- r = archive_write_pax_data(a, mac_metadata, mac_metadata_size);
+ r = (int)archive_write_pax_data(a, mac_metadata,
+ mac_metadata_size);
if (r < ARCHIVE_WARN)
return (r);
if (r < ret)
@@ -655,7 +708,20 @@ archive_write_pax_header(struct archive_write *a,
}
/* Copy entry so we can modify it as needed. */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pahtname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ entry_main = __la_win_entry_in_posix_pathseparator(entry_original);
+ if (entry_main == entry_original)
+ entry_main = archive_entry_clone(entry_original);
+#else
entry_main = archive_entry_clone(entry_original);
+#endif
+ if (entry_main == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate pax data");
+ return(ARCHIVE_FATAL);
+ }
archive_string_empty(&(pax->pax_header)); /* Blank our work area. */
archive_string_empty(&(pax->sparse_map));
sparse_total = 0;
@@ -1261,7 +1327,7 @@ archive_write_pax_header(struct archive_write *a,
return (ARCHIVE_FATAL);
}
/* Pad out the end of the entry. */
- r = __archive_write_nulls(a, pax->entry_padding);
+ r = __archive_write_nulls(a, (size_t)pax->entry_padding);
if (r != ARCHIVE_OK) {
/* If a write fails, we're pretty much toast. */
return (ARCHIVE_FATAL);
@@ -1439,7 +1505,7 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length,
*
* Joerg Schilling has argued that this is unnecessary because, in
* practice, if the pax extended attributes get extracted as regular
- * files, noone is going to bother reading those attributes to
+ * files, no one is going to bother reading those attributes to
* manually restore them. Based on this, 'star' uses
* /tmp/PaxHeader/'basename' as the ustar header name. This is a
* tempting argument, in part because it's simpler than the SUSv3
@@ -1596,13 +1662,14 @@ archive_write_pax_finish_entry(struct archive_write *a)
if (remaining == 0) {
while (pax->sparse_list) {
struct sparse_block *sb;
- remaining += pax->sparse_list->remaining;
+ if (!pax->sparse_list->is_hole)
+ remaining += pax->sparse_list->remaining;
sb = pax->sparse_list->next;
free(pax->sparse_list);
pax->sparse_list = sb;
}
}
- ret = __archive_write_nulls(a, remaining + pax->entry_padding);
+ ret = __archive_write_nulls(a, (size_t)(remaining + pax->entry_padding));
pax->entry_bytes_remaining = pax->entry_padding = 0;
return (ret);
}
@@ -1647,9 +1714,9 @@ archive_write_pax_data(struct archive_write *a, const void *buff, size_t s)
return (total);
p = ((const unsigned char *)buff) + total;
- ws = s;
+ ws = s - total;
if (ws > pax->sparse_list->remaining)
- ws = pax->sparse_list->remaining;
+ ws = (size_t)pax->sparse_list->remaining;
if (pax->sparse_list->is_hole) {
/* Current block is hole thus we do not write
@@ -1799,7 +1866,7 @@ _sparse_list_add_block(struct pax *pax, int64_t offset, int64_t length,
sb->is_hole = is_hole;
sb->offset = offset;
sb->remaining = length;
- if (pax->sparse_list == NULL)
+ if (pax->sparse_list == NULL || pax->sparse_tail == NULL)
pax->sparse_list = pax->sparse_tail = sb;
else {
pax->sparse_tail->next = sb;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
index 4b96ac2..484ab34 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_ustar.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -224,11 +224,13 @@ archive_write_ustar_options(struct archive_write *a, const char *key,
else
ret = ARCHIVE_FATAL;
}
- } else
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "%s: unknown keyword ``%s''", a->format_name, key);
+ return (ret);
+ }
- return (ret);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -237,6 +239,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
char buff[512];
int ret, ret2;
struct ustar *ustar;
+ struct archive_entry *entry_main;
struct archive_string_conv *sconv;
ustar = (struct ustar *)a->format_data;
@@ -267,37 +270,106 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
if (AE_IFDIR == archive_entry_filetype(entry)) {
const char *p;
- char *t;
+ size_t path_length;
/*
* Ensure a trailing '/'. Modify the entry so
* the client sees the change.
*/
- p = archive_entry_pathname(entry);
- if (p[strlen(p) - 1] != '/') {
- t = (char *)malloc(strlen(p) + 2);
- if (t == NULL) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ const wchar_t *wp;
+
+ wp = archive_entry_pathname_w(entry);
+ if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
+ struct archive_wstring ws;
+
+ archive_string_init(&ws);
+ path_length = wcslen(wp);
+ if (archive_wstring_ensure(&ws,
+ path_length + 2) == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ archive_wstring_free(&ws);
+ return(ARCHIVE_FATAL);
+ }
+ /* Should we keep '\' ? */
+ if (wp[path_length -1] == L'\\')
+ path_length--;
+ archive_wstrncpy(&ws, wp, path_length);
+ archive_wstrappend_wchar(&ws, L'/');
+ archive_entry_copy_pathname_w(entry, ws.s);
+ archive_wstring_free(&ws);
+ p = NULL;
+ } else
+#endif
+ p = archive_entry_pathname(entry);
+ /*
+ * On Windows, this is a backup operation just in
+ * case getting WCS failed. On POSIX, this is a
+ * normal operation.
+ */
+ if (p != NULL && p[strlen(p) - 1] != '/') {
+ struct archive_string as;
+
+ archive_string_init(&as);
+ path_length = strlen(p);
+ if (archive_string_ensure(&as,
+ path_length + 2) == NULL) {
archive_set_error(&a->archive, ENOMEM,
- "Can't allocate ustar data");
+ "Can't allocate ustar data");
+ archive_string_free(&as);
return(ARCHIVE_FATAL);
}
- strcpy(t, p);
- strcat(t, "/");
- archive_entry_copy_pathname(entry, t);
- free(t);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* NOTE: This might break the pathname
+ * if the current code page is CP932 and
+ * the pathname includes a character '\'
+ * as a part of its multibyte pathname. */
+ if (p[strlen(p) -1] == '\\')
+ path_length--;
+ else
+#endif
+ archive_strncpy(&as, p, path_length);
+ archive_strappend_char(&as, '/');
+ archive_entry_copy_pathname(entry, as.s);
+ archive_string_free(&as);
}
}
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pahtname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ entry_main = __la_win_entry_in_posix_pathseparator(entry);
+ if (entry_main == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate ustar data");
+ return(ARCHIVE_FATAL);
+ }
+ if (entry != entry_main)
+ entry = entry_main;
+ else
+ entry_main = NULL;
+#else
+ entry_main = NULL;
+#endif
ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1, sconv);
- if (ret < ARCHIVE_WARN)
+ if (ret < ARCHIVE_WARN) {
+ if (entry_main)
+ archive_entry_free(entry_main);
return (ret);
+ }
ret2 = __archive_write_output(a, buff, 512);
- if (ret2 < ARCHIVE_WARN)
+ if (ret2 < ARCHIVE_WARN) {
+ if (entry_main)
+ archive_entry_free(entry_main);
return (ret2);
+ }
if (ret2 < ret)
ret = ret2;
ustar->entry_bytes_remaining = archive_entry_size(entry);
ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining);
+ if (entry_main)
+ archive_entry_free(entry_main);
return (ret);
}
@@ -670,7 +742,7 @@ archive_write_ustar_finish_entry(struct archive_write *a)
ustar = (struct ustar *)a->format_data;
ret = __archive_write_nulls(a,
- ustar->entry_bytes_remaining + ustar->entry_padding);
+ (size_t)(ustar->entry_bytes_remaining + ustar->entry_padding));
ustar->entry_bytes_remaining = ustar->entry_padding = 0;
return (ret);
}
@@ -683,7 +755,7 @@ archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
ustar = (struct ustar *)a->format_data;
if (s > ustar->entry_bytes_remaining)
- s = ustar->entry_bytes_remaining;
+ s = (size_t)ustar->entry_bytes_remaining;
ret = __archive_write_output(a, buff, s);
ustar->entry_bytes_remaining -= s;
if (ret != ARCHIVE_OK)
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c
new file mode 100644
index 0000000..17efbaf
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_v7tar.c
@@ -0,0 +1,661 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_entry_locale.h"
+#include "archive_private.h"
+#include "archive_write_private.h"
+
+struct v7tar {
+ uint64_t entry_bytes_remaining;
+ uint64_t entry_padding;
+
+ struct archive_string_conv *opt_sconv;
+ struct archive_string_conv *sconv_default;
+ int init_default_conversion;
+};
+
+/*
+ * Define structure of POSIX 'v7tar' tar header.
+ */
+#define V7TAR_name_offset 0
+#define V7TAR_name_size 100
+#define V7TAR_mode_offset 100
+#define V7TAR_mode_size 6
+#define V7TAR_mode_max_size 8
+#define V7TAR_uid_offset 108
+#define V7TAR_uid_size 6
+#define V7TAR_uid_max_size 8
+#define V7TAR_gid_offset 116
+#define V7TAR_gid_size 6
+#define V7TAR_gid_max_size 8
+#define V7TAR_size_offset 124
+#define V7TAR_size_size 11
+#define V7TAR_size_max_size 12
+#define V7TAR_mtime_offset 136
+#define V7TAR_mtime_size 11
+#define V7TAR_mtime_max_size 12
+#define V7TAR_checksum_offset 148
+#define V7TAR_checksum_size 8
+#define V7TAR_typeflag_offset 156
+#define V7TAR_typeflag_size 1
+#define V7TAR_linkname_offset 157
+#define V7TAR_linkname_size 100
+#define V7TAR_padding_offset 257
+#define V7TAR_padding_size 255
+
+/*
+ * A filled-in copy of the header for initialization.
+ */
+static const char template_header[] = {
+ /* name: 100 bytes */
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,
+ /* Mode, space-null termination: 8 bytes */
+ '0','0','0','0','0','0', ' ','\0',
+ /* uid, space-null termination: 8 bytes */
+ '0','0','0','0','0','0', ' ','\0',
+ /* gid, space-null termination: 8 bytes */
+ '0','0','0','0','0','0', ' ','\0',
+ /* size, space termation: 12 bytes */
+ '0','0','0','0','0','0','0','0','0','0','0', ' ',
+ /* mtime, space termation: 12 bytes */
+ '0','0','0','0','0','0','0','0','0','0','0', ' ',
+ /* Initial checksum value: 8 spaces */
+ ' ',' ',' ',' ',' ',' ',' ',' ',
+ /* Typeflag: 1 byte */
+ 0,
+ /* Linkname: 100 bytes */
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,
+ /* Padding: 255 bytes */
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0
+};
+
+static ssize_t archive_write_v7tar_data(struct archive_write *a, const void *buff,
+ size_t s);
+static int archive_write_v7tar_free(struct archive_write *);
+static int archive_write_v7tar_close(struct archive_write *);
+static int archive_write_v7tar_finish_entry(struct archive_write *);
+static int archive_write_v7tar_header(struct archive_write *,
+ struct archive_entry *entry);
+static int archive_write_v7tar_options(struct archive_write *,
+ const char *, const char *);
+static int format_256(int64_t, char *, int);
+static int format_number(int64_t, char *, int size, int max, int strict);
+static int format_octal(int64_t, char *, int);
+static int format_header_v7tar(struct archive_write *, char h[512],
+ struct archive_entry *, int, struct archive_string_conv *);
+
+/*
+ * Set output format to 'v7tar' format.
+ */
+int
+archive_write_set_format_v7tar(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct v7tar *v7tar;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_write_set_format_v7tar");
+
+ /* If someone else was already registered, unregister them. */
+ if (a->format_free != NULL)
+ (a->format_free)(a);
+
+ /* Basic internal sanity test. */
+ if (sizeof(template_header) != 512) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Internal: template_header wrong size: %zu should be 512",
+ sizeof(template_header));
+ return (ARCHIVE_FATAL);
+ }
+
+ v7tar = (struct v7tar *)malloc(sizeof(*v7tar));
+ if (v7tar == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate v7tar data");
+ return (ARCHIVE_FATAL);
+ }
+ memset(v7tar, 0, sizeof(*v7tar));
+ a->format_data = v7tar;
+ a->format_name = "tar (non-POSIX)";
+ a->format_options = archive_write_v7tar_options;
+ a->format_write_header = archive_write_v7tar_header;
+ a->format_write_data = archive_write_v7tar_data;
+ a->format_close = archive_write_v7tar_close;
+ a->format_free = archive_write_v7tar_free;
+ a->format_finish_entry = archive_write_v7tar_finish_entry;
+ a->archive.archive_format = ARCHIVE_FORMAT_TAR;
+ a->archive.archive_format_name = "tar (non-POSIX)";
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_v7tar_options(struct archive_write *a, const char *key,
+ const char *val)
+{
+ struct v7tar *v7tar = (struct v7tar *)a->format_data;
+ int ret = ARCHIVE_FAILED;
+
+ if (strcmp(key, "hdrcharset") == 0) {
+ if (val == NULL || val[0] == 0)
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "%s: hdrcharset option needs a character-set name",
+ a->format_name);
+ else {
+ v7tar->opt_sconv = archive_string_conversion_to_charset(
+ &a->archive, val, 0);
+ if (v7tar->opt_sconv != NULL)
+ ret = ARCHIVE_OK;
+ else
+ ret = ARCHIVE_FATAL;
+ }
+ return (ret);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+static int
+archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
+{
+ char buff[512];
+ int ret, ret2;
+ struct v7tar *v7tar;
+ struct archive_entry *entry_main;
+ struct archive_string_conv *sconv;
+
+ v7tar = (struct v7tar *)a->format_data;
+
+ /* Setup default string conversion. */
+ if (v7tar->opt_sconv == NULL) {
+ if (!v7tar->init_default_conversion) {
+ v7tar->sconv_default =
+ archive_string_default_conversion_for_write(
+ &(a->archive));
+ v7tar->init_default_conversion = 1;
+ }
+ sconv = v7tar->sconv_default;
+ } else
+ sconv = v7tar->opt_sconv;
+
+ /* Sanity check. */
+ if (archive_entry_pathname(entry) == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Can't record entry in tar file without pathname");
+ return (ARCHIVE_FAILED);
+ }
+
+ /* Only regular files (not hardlinks) have data. */
+ if (archive_entry_hardlink(entry) != NULL ||
+ archive_entry_symlink(entry) != NULL ||
+ !(archive_entry_filetype(entry) == AE_IFREG))
+ archive_entry_set_size(entry, 0);
+
+ if (AE_IFDIR == archive_entry_filetype(entry)) {
+ const char *p;
+ size_t path_length;
+ /*
+ * Ensure a trailing '/'. Modify the entry so
+ * the client sees the change.
+ */
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ const wchar_t *wp;
+
+ wp = archive_entry_pathname_w(entry);
+ if (wp != NULL && wp[wcslen(wp) -1] != L'/') {
+ struct archive_wstring ws;
+
+ archive_string_init(&ws);
+ path_length = wcslen(wp);
+ if (archive_wstring_ensure(&ws,
+ path_length + 2) == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate v7tar data");
+ archive_wstring_free(&ws);
+ return(ARCHIVE_FATAL);
+ }
+ /* Should we keep '\' ? */
+ if (wp[path_length -1] == L'\\')
+ path_length--;
+ archive_wstrncpy(&ws, wp, path_length);
+ archive_wstrappend_wchar(&ws, L'/');
+ archive_entry_copy_pathname_w(entry, ws.s);
+ archive_wstring_free(&ws);
+ p = NULL;
+ } else
+#endif
+ p = archive_entry_pathname(entry);
+ /*
+ * On Windows, this is a backup operation just in
+ * case getting WCS failed. On POSIX, this is a
+ * normal operation.
+ */
+ if (p != NULL && p[strlen(p) - 1] != '/') {
+ struct archive_string as;
+
+ archive_string_init(&as);
+ path_length = strlen(p);
+ if (archive_string_ensure(&as,
+ path_length + 2) == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate v7tar data");
+ archive_string_free(&as);
+ return(ARCHIVE_FATAL);
+ }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* NOTE: This might break the pathname
+ * if the current code page is CP932 and
+ * the pathname includes a character '\'
+ * as a part of its multibyte pathname. */
+ if (p[strlen(p) -1] == '\\')
+ path_length--;
+ else
+#endif
+ archive_strncpy(&as, p, path_length);
+ archive_strappend_char(&as, '/');
+ archive_entry_copy_pathname(entry, as.s);
+ archive_string_free(&as);
+ }
+ }
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pahtname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ entry_main = __la_win_entry_in_posix_pathseparator(entry);
+ if (entry_main == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate v7tar data");
+ return(ARCHIVE_FATAL);
+ }
+ if (entry != entry_main)
+ entry = entry_main;
+ else
+ entry_main = NULL;
+#else
+ entry_main = NULL;
+#endif
+ ret = format_header_v7tar(a, buff, entry, 1, sconv);
+ if (ret < ARCHIVE_WARN) {
+ if (entry_main)
+ archive_entry_free(entry_main);
+ return (ret);
+ }
+ ret2 = __archive_write_output(a, buff, 512);
+ if (ret2 < ARCHIVE_WARN) {
+ if (entry_main)
+ archive_entry_free(entry_main);
+ return (ret2);
+ }
+ if (ret2 < ret)
+ ret = ret2;
+
+ v7tar->entry_bytes_remaining = archive_entry_size(entry);
+ v7tar->entry_padding = 0x1ff & (-(int64_t)v7tar->entry_bytes_remaining);
+ if (entry_main)
+ archive_entry_free(entry_main);
+ return (ret);
+}
+
+/*
+ * Format a basic 512-byte "v7tar" header.
+ *
+ * Returns -1 if format failed (due to field overflow).
+ * Note that this always formats as much of the header as possible.
+ * If "strict" is set to zero, it will extend numeric fields as
+ * necessary (overwriting terminators or using base-256 extensions).
+ *
+ */
+static int
+format_header_v7tar(struct archive_write *a, char h[512],
+ struct archive_entry *entry, int strict,
+ struct archive_string_conv *sconv)
+{
+ unsigned int checksum;
+ int i, r, ret;
+ size_t copy_length;
+ const char *p, *pp;
+ int mytartype;
+
+ ret = 0;
+ mytartype = -1;
+ /*
+ * The "template header" already includes the "v7tar"
+ * signature, various end-of-field markers and other required
+ * elements.
+ */
+ memcpy(h, &template_header, 512);
+
+ /*
+ * Because the block is already null-filled, and strings
+ * are allowed to exactly fill their destination (without null),
+ * I use memcpy(dest, src, strlen()) here a lot to copy strings.
+ */
+ r = archive_entry_pathname_l(entry, &pp, &copy_length, sconv);
+ if (r != 0) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Pathname");
+ return (ARCHIVE_FATAL);
+ }
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't translate pathname '%s' to %s",
+ pp, archive_string_conversion_charset_name(sconv));
+ ret = ARCHIVE_WARN;
+ }
+ if (strict && copy_length < V7TAR_name_size)
+ memcpy(h + V7TAR_name_offset, pp, copy_length);
+ else if (!strict && copy_length <= V7TAR_name_size)
+ memcpy(h + V7TAR_name_offset, pp, copy_length);
+ else {
+ /* Prefix is too long. */
+ archive_set_error(&a->archive, ENAMETOOLONG,
+ "Pathname too long");
+ ret = ARCHIVE_FAILED;
+ }
+
+ r = archive_entry_hardlink_l(entry, &p, &copy_length, sconv);
+ if (r != 0) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Linkname");
+ return (ARCHIVE_FATAL);
+ }
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't translate linkname '%s' to %s",
+ p, archive_string_conversion_charset_name(sconv));
+ ret = ARCHIVE_WARN;
+ }
+ if (copy_length > 0)
+ mytartype = '1';
+ else {
+ r = archive_entry_symlink_l(entry, &p, &copy_length, sconv);
+ if (r != 0) {
+ if (errno == ENOMEM) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Linkname");
+ return (ARCHIVE_FATAL);
+ }
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't translate linkname '%s' to %s",
+ p, archive_string_conversion_charset_name(sconv));
+ ret = ARCHIVE_WARN;
+ }
+ }
+ if (copy_length > 0) {
+ if (copy_length >= V7TAR_linkname_size) {
+ archive_set_error(&a->archive, ENAMETOOLONG,
+ "Link contents too long");
+ ret = ARCHIVE_FAILED;
+ copy_length = V7TAR_linkname_size;
+ }
+ memcpy(h + V7TAR_linkname_offset, p, copy_length);
+ }
+
+ if (format_number(archive_entry_mode(entry) & 07777,
+ h + V7TAR_mode_offset, V7TAR_mode_size,
+ V7TAR_mode_max_size, strict)) {
+ archive_set_error(&a->archive, ERANGE,
+ "Numeric mode too large");
+ ret = ARCHIVE_FAILED;
+ }
+
+ if (format_number(archive_entry_uid(entry),
+ h + V7TAR_uid_offset, V7TAR_uid_size, V7TAR_uid_max_size, strict)) {
+ archive_set_error(&a->archive, ERANGE,
+ "Numeric user ID too large");
+ ret = ARCHIVE_FAILED;
+ }
+
+ if (format_number(archive_entry_gid(entry),
+ h + V7TAR_gid_offset, V7TAR_gid_size, V7TAR_gid_max_size, strict)) {
+ archive_set_error(&a->archive, ERANGE,
+ "Numeric group ID too large");
+ ret = ARCHIVE_FAILED;
+ }
+
+ if (format_number(archive_entry_size(entry),
+ h + V7TAR_size_offset, V7TAR_size_size,
+ V7TAR_size_max_size, strict)) {
+ archive_set_error(&a->archive, ERANGE,
+ "File size out of range");
+ ret = ARCHIVE_FAILED;
+ }
+
+ if (format_number(archive_entry_mtime(entry),
+ h + V7TAR_mtime_offset, V7TAR_mtime_size,
+ V7TAR_mtime_max_size, strict)) {
+ archive_set_error(&a->archive, ERANGE,
+ "File modification time too large");
+ ret = ARCHIVE_FAILED;
+ }
+
+ if (mytartype >= 0) {
+ h[V7TAR_typeflag_offset] = mytartype;
+ } else {
+ switch (archive_entry_filetype(entry)) {
+ case AE_IFREG: case AE_IFDIR:
+ break;
+ case AE_IFLNK:
+ h[V7TAR_typeflag_offset] = '2';
+ break;
+ case AE_IFCHR:
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "tar format cannot archive character device");
+ return (ARCHIVE_FAILED);
+ case AE_IFBLK:
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "tar format cannot archive block device");
+ return (ARCHIVE_FAILED);
+ case AE_IFIFO:
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "tar format cannot archive fifo");
+ return (ARCHIVE_FAILED);
+ case AE_IFSOCK:
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "tar format cannot archive socket");
+ return (ARCHIVE_FAILED);
+ default:
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "tar format cannot archive this (mode=0%lo)",
+ (unsigned long)archive_entry_mode(entry));
+ ret = ARCHIVE_FAILED;
+ }
+ }
+
+ checksum = 0;
+ for (i = 0; i < 512; i++)
+ checksum += 255 & (unsigned int)h[i];
+ format_octal(checksum, h + V7TAR_checksum_offset, 6);
+ /* Can't be pre-set in the template. */
+ h[V7TAR_checksum_offset + 6] = '\0';
+ return (ret);
+}
+
+/*
+ * Format a number into a field, with some intelligence.
+ */
+static int
+format_number(int64_t v, char *p, int s, int maxsize, int strict)
+{
+ int64_t limit;
+
+ limit = ((int64_t)1 << (s*3));
+
+ /* "Strict" only permits octal values with proper termination. */
+ if (strict)
+ return (format_octal(v, p, s));
+
+ /*
+ * In non-strict mode, we allow the number to overwrite one or
+ * more bytes of the field termination. Even old tar
+ * implementations should be able to handle this with no
+ * problem.
+ */
+ if (v >= 0) {
+ while (s <= maxsize) {
+ if (v < limit)
+ return (format_octal(v, p, s));
+ s++;
+ limit <<= 3;
+ }
+ }
+
+ /* Base-256 can handle any number, positive or negative. */
+ return (format_256(v, p, maxsize));
+}
+
+/*
+ * Format a number into the specified field using base-256.
+ */
+static int
+format_256(int64_t v, char *p, int s)
+{
+ p += s;
+ while (s-- > 0) {
+ *--p = (char)(v & 0xff);
+ v >>= 8;
+ }
+ *p |= 0x80; /* Set the base-256 marker bit. */
+ return (0);
+}
+
+/*
+ * Format a number into the specified field.
+ */
+static int
+format_octal(int64_t v, char *p, int s)
+{
+ int len;
+
+ len = s;
+
+ /* Octal values can't be negative, so use 0. */
+ if (v < 0) {
+ while (len-- > 0)
+ *p++ = '0';
+ return (-1);
+ }
+
+ p += s; /* Start at the end and work backwards. */
+ while (s-- > 0) {
+ *--p = (char)('0' + (v & 7));
+ v >>= 3;
+ }
+
+ if (v == 0)
+ return (0);
+
+ /* If it overflowed, fill field with max value. */
+ while (len-- > 0)
+ *p++ = '7';
+
+ return (-1);
+}
+
+static int
+archive_write_v7tar_close(struct archive_write *a)
+{
+ return (__archive_write_nulls(a, 512*2));
+}
+
+static int
+archive_write_v7tar_free(struct archive_write *a)
+{
+ struct v7tar *v7tar;
+
+ v7tar = (struct v7tar *)a->format_data;
+ free(v7tar);
+ a->format_data = NULL;
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_v7tar_finish_entry(struct archive_write *a)
+{
+ struct v7tar *v7tar;
+ int ret;
+
+ v7tar = (struct v7tar *)a->format_data;
+ ret = __archive_write_nulls(a,
+ (size_t)(v7tar->entry_bytes_remaining + v7tar->entry_padding));
+ v7tar->entry_bytes_remaining = v7tar->entry_padding = 0;
+ return (ret);
+}
+
+static ssize_t
+archive_write_v7tar_data(struct archive_write *a, const void *buff, size_t s)
+{
+ struct v7tar *v7tar;
+ int ret;
+
+ v7tar = (struct v7tar *)a->format_data;
+ if (s > v7tar->entry_bytes_remaining)
+ s = (size_t)v7tar->entry_bytes_remaining;
+ ret = __archive_write_output(a, buff, s);
+ v7tar->entry_bytes_remaining -= s;
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ return (s);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
index 4515157..a4ce7ee 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2010-2011 Michihiro NAKAJIMA
+ * Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -97,6 +97,8 @@ archive_write_set_format_xar(struct archive *_a)
/*#define DEBUG_PRINT_TOC 1 */
+#define BAD_CAST_CONST (const xmlChar *)
+
#define HEADER_MAGIC 0x78617221
#define HEADER_SIZE 28
#define HEADER_VERSION 1
@@ -468,7 +470,7 @@ xar_options(struct archive_write *a, const char *key, const char *value)
value[1] != '\0') {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
- "Illeagal value `%s'",
+ "Illegal value `%s'",
value);
return (ARCHIVE_FAILED);
}
@@ -492,7 +494,10 @@ xar_options(struct archive_write *a, const char *key, const char *value)
return (ARCHIVE_OK);
}
- return (ARCHIVE_FAILED);
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
}
static int
@@ -621,11 +626,11 @@ static int
write_to_temp(struct archive_write *a, const void *buff, size_t s)
{
struct xar *xar;
- unsigned char *p;
+ const unsigned char *p;
ssize_t ws;
xar = (struct xar *)a->format_data;
- p = (unsigned char *)buff;
+ p = (const unsigned char *)buff;
while (s) {
ws = write(xar->temp_fd, p, s);
if (ws < 0) {
@@ -651,7 +656,7 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s)
xar = (struct xar *)a->format_data;
if (s > xar->bytes_remaining)
- s = xar->bytes_remaining;
+ s = (size_t)xar->bytes_remaining;
if (s == 0 || xar->cur_file == NULL)
return (0);
if (xar->cur_file->data.compression == NONE) {
@@ -676,7 +681,7 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s)
}
#if !defined(_WIN32) || defined(__CYGWIN__)
if (xar->bytes_remaining ==
- archive_entry_size(xar->cur_file->entry)) {
+ (uint64_t)archive_entry_size(xar->cur_file->entry)) {
/*
* Get the path of a shell script if so.
*/
@@ -732,7 +737,7 @@ xar_finish_entry(struct archive_write *a)
return (ARCHIVE_OK);
while (xar->bytes_remaining > 0) {
- s = xar->bytes_remaining;
+ s = (size_t)xar->bytes_remaining;
if (s > a->null_length)
s = a->null_length;
w = xar_write_data(a, a->nulls, s);
@@ -756,7 +761,7 @@ xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
{
int r;
- r = xmlTextWriterStartElement(writer, BAD_CAST(key));
+ r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
if (r < 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -765,7 +770,7 @@ xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
}
if (attrkey != NULL && attrvalue != NULL) {
r = xmlTextWriterWriteAttribute(writer,
- BAD_CAST(attrkey), BAD_CAST(attrvalue));
+ BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue));
if (r < 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -774,7 +779,7 @@ xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
}
}
if (value != NULL) {
- r = xmlTextWriterWriteString(writer, BAD_CAST(value));
+ r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
if (r < 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -801,7 +806,7 @@ xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
if (value == NULL)
return (ARCHIVE_OK);
- r = xmlTextWriterStartElement(writer, BAD_CAST(key));
+ r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
if (r < 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -809,7 +814,7 @@ xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
return (ARCHIVE_FATAL);
}
if (value != NULL) {
- r = xmlTextWriterWriteString(writer, BAD_CAST(value));
+ r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
if (r < 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -1062,7 +1067,7 @@ make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
} while (p != NULL);
if (n > 0) {
- r = xmlTextWriterStartElement(writer, BAD_CAST(element));
+ r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element));
if (r < 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -1557,7 +1562,7 @@ make_toc(struct archive_write *a)
goto exit_toc;
}
r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"),
- BAD_CAST(getalgname(xar->opt_toc_sumalg)));
+ BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg)));
if (r < 0) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@@ -1865,8 +1870,8 @@ static int
file_cmp_node(const struct archive_rb_node *n1,
const struct archive_rb_node *n2)
{
- struct file *f1 = (struct file *)n1;
- struct file *f2 = (struct file *)n2;
+ const struct file *f1 = (const struct file *)n1;
+ const struct file *f2 = (const struct file *)n2;
return (strcmp(f1->basename.s, f2->basename.s));
}
@@ -1874,7 +1879,7 @@ file_cmp_node(const struct archive_rb_node *n1,
static int
file_cmp_key(const struct archive_rb_node *n, const void *key)
{
- struct file *f = (struct file *)n;
+ const struct file *f = (const struct file *)n;
return (strcmp(f->basename.s, (const char *)key));
}
@@ -1938,6 +1943,8 @@ file_create_virtual_dir(struct archive_write *a, struct xar *xar,
{
struct file *file;
+ (void)xar; /* UNUSED */
+
file = file_new(a, NULL);
if (file == NULL)
return (NULL);
@@ -2464,8 +2471,8 @@ static int
file_hd_cmp_node(const struct archive_rb_node *n1,
const struct archive_rb_node *n2)
{
- struct hardlink *h1 = (struct hardlink *)n1;
- struct hardlink *h2 = (struct hardlink *)n2;
+ const struct hardlink *h1 = (const struct hardlink *)n1;
+ const struct hardlink *h2 = (const struct hardlink *)n2;
return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
archive_entry_pathname(h2->file_list.first->entry)));
@@ -2474,7 +2481,7 @@ file_hd_cmp_node(const struct archive_rb_node *n1,
static int
file_hd_cmp_key(const struct archive_rb_node *n, const void *key)
{
- struct hardlink *h = (struct hardlink *)n;
+ const struct hardlink *h = (const struct hardlink *)n;
return (strcmp(archive_entry_pathname(h->file_list.first->entry),
(const char *)key));
@@ -2589,10 +2596,10 @@ compression_init_encoder_gzip(struct archive *a,
* a non-const pointer. */
strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
strm->avail_in = lastrm->avail_in;
- strm->total_in = lastrm->total_in;
+ strm->total_in = (uLong)lastrm->total_in;
strm->next_out = lastrm->next_out;
strm->avail_out = lastrm->avail_out;
- strm->total_out = lastrm->total_out;
+ strm->total_out = (uLong)lastrm->total_out;
if (deflateInit2(strm, level, Z_DEFLATED,
(withheader)?15:-15,
8, Z_DEFAULT_STRATEGY) != Z_OK) {
@@ -2622,10 +2629,10 @@ compression_code_gzip(struct archive *a,
* a non-const pointer. */
strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
strm->avail_in = lastrm->avail_in;
- strm->total_in = lastrm->total_in;
+ strm->total_in = (uLong)lastrm->total_in;
strm->next_out = lastrm->next_out;
strm->avail_out = lastrm->avail_out;
- strm->total_out = lastrm->total_out;
+ strm->total_out = (uLong)lastrm->total_out;
r = deflate(strm,
(action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
lastrm->next_in = strm->next_in;
@@ -2861,6 +2868,7 @@ compression_init_encoder_xz(struct archive *a,
if (level > 6)
level = 6;
if (lzma_lzma_preset(&lzma_opt, level)) {
+ free(strm);
lastrm->real_stream = NULL;
archive_set_error(a, ENOMEM,
"Internal error initializing compression library");
@@ -3082,8 +3090,10 @@ save_xattrs(struct archive_write *a, struct file *file)
checksum_update(&(xar->a_sumwrk), value, size);
checksum_final(&(xar->a_sumwrk), &(heap->a_sum));
if (write_to_temp(a, value, size)
- != ARCHIVE_OK)
+ != ARCHIVE_OK) {
+ free(heap);
return (ARCHIVE_FATAL);
+ }
heap->length = size;
/* Add heap to the tail of file->xattr. */
heap->next = NULL;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
index 11fbd45..5a9f114 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2008 Anselm Strauss
* Copyright (c) 2009 Joerg Sonnenberger
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -109,69 +109,75 @@ static unsigned int dos_time(const time_t);
static size_t path_length(struct archive_entry *);
static int write_path(struct archive_entry *, struct archive_write *);
-struct zip_local_file_header {
- char signature[4];
- char version[2];
- char flags[2];
- char compression[2];
- char timedate[4];
- char crc32[4];
- char compressed_size[4];
- char uncompressed_size[4];
- char filename_length[2];
- char extra_length[2];
-};
-
-struct zip_file_header {
- char signature[4];
- char version_by[2];
- char version_extract[2];
- char flags[2];
- char compression[2];
- char timedate[4];
- char crc32[4];
- char compressed_size[4];
- char uncompressed_size[4];
- char filename_length[2];
- char extra_length[2];
- char comment_length[2];
- char disk_number[2];
- char attributes_internal[2];
- char attributes_external[4];
- char offset[4];
-};
-
-struct zip_data_descriptor {
- char signature[4]; /* Not mandatory, but recommended by specification. */
- char crc32[4];
- char compressed_size[4];
- char uncompressed_size[4];
-};
-
-struct zip_extra_data_local {
- char time_id[2];
- char time_size[2];
- char time_flag[1];
- char mtime[4];
- char atime[4];
- char ctime[4];
- char unix_id[2];
- char unix_size[2];
- char unix_version;
- char unix_uid_size;
- char unix_uid[4];
- char unix_gid_size;
- char unix_gid[4];
-};
-
-struct zip_extra_data_central {
- char time_id[2];
- char time_size[2];
- char time_flag[1];
- char mtime[4];
- char unix_id[2];
- char unix_size[2];
-};
+#define LOCAL_FILE_HEADER_SIGNATURE 0
+#define LOCAL_FILE_HEADER_VERSION 4
+#define LOCAL_FILE_HEADER_FLAGS 6
+#define LOCAL_FILE_HEADER_COMPRESSION 8
+#define LOCAL_FILE_HEADER_TIMEDATE 10
+#define LOCAL_FILE_HEADER_CRC32 14
+#define LOCAL_FILE_HEADER_COMPRESSED_SIZE 18
+#define LOCAL_FILE_HEADER_UNCOMPRESSED_SIZE 22
+#define LOCAL_FILE_HEADER_FILENAME_LENGTH 26
+#define LOCAL_FILE_HEADER_EXTRA_LENGTH 28
+#define SIZE_LOCAL_FILE_HEADER 30
+
+#define FILE_HEADER_SIGNATURE 0
+#define FILE_HEADER_VERSION_BY 4
+#define FILE_HEADER_VERSION_EXTRACT 6
+#define FILE_HEADER_FLAGS 8
+#define FILE_HEADER_COMPRESSION 10
+#define FILE_HEADER_TIMEDATE 12
+#define FILE_HEADER_CRC32 16
+#define FILE_HEADER_COMPRESSED_SIZE 20
+#define FILE_HEADER_UNCOMPRESSED_SIZE 24
+#define FILE_HEADER_FILENAME_LENGTH 28
+#define FILE_HEADER_EXTRA_LENGTH 30
+#define FILE_HEADER_COMMENT_LENGTH 32
+#define FILE_HEADER_DISK_NUMBER 34
+#define FILE_HEADER_ATTRIBUTES_INTERNAL 36
+#define FILE_HEADER_ATTRIBUTES_EXTERNAL 38
+#define FILE_HEADER_OFFSET 42
+#define SIZE_FILE_HEADER 46
+
+ /* Not mandatory, but recommended by specification. */
+#define DATA_DESCRIPTOR_SIGNATURE 0
+#define DATA_DESCRIPTOR_CRC32 4
+#define DATA_DESCRIPTOR_COMPRESSED_SIZE 8
+#define DATA_DESCRIPTOR_UNCOMPRESSED_SIZE 12
+#define SIZE_DATA_DESCRIPTOR 16
+
+#define EXTRA_DATA_LOCAL_TIME_ID 0
+#define EXTRA_DATA_LOCAL_TIME_SIZE 2
+#define EXTRA_DATA_LOCAL_TIME_FLAG 4
+#define EXTRA_DATA_LOCAL_MTIME 5
+#define EXTRA_DATA_LOCAL_ATIME 9
+#define EXTRA_DATA_LOCAL_CTIME 13
+#define EXTRA_DATA_LOCAL_UNIX_ID 17
+#define EXTRA_DATA_LOCAL_UNIX_SIZE 19
+#define EXTRA_DATA_LOCAL_UNIX_VERSION 21
+#define EXTRA_DATA_LOCAL_UNIX_UID_SIZE 22
+#define EXTRA_DATA_LOCAL_UNIX_UID 23
+#define EXTRA_DATA_LOCAL_UNIX_GID_SIZE 27
+#define EXTRA_DATA_LOCAL_UNIX_GID 28
+#define SIZE_EXTRA_DATA_LOCAL 32
+
+#define EXTRA_DATA_CENTRAL_TIME_ID 0
+#define EXTRA_DATA_CENTRAL_TIME_SIZE 2
+#define EXTRA_DATA_CENTRAL_TIME_FLAG 4
+#define EXTRA_DATA_CENTRAL_MTIME 5
+#define EXTRA_DATA_CENTRAL_UNIX_ID 9
+#define EXTRA_DATA_CENTRAL_UNIX_SIZE 11
+#define SIZE_EXTRA_DATA_CENTRAL 13
+
+#define CENTRAL_DIRECTORY_END_SIGNATURE 0
+#define CENTRAL_DIRECTORY_END_DISK 4
+#define CENTRAL_DIRECTORY_END_START_DISK 6
+#define CENTRAL_DIRECTORY_END_ENTRIES_DISK 8
+#define CENTRAL_DIRECTORY_END_ENTRIES 10
+#define CENTRAL_DIRECTORY_END_SIZE 12
+#define CENTRAL_DIRECTORY_END_OFFSET 16
+#define CENTRAL_DIRECTORY_END_COMMENT_LENGTH 20
+#define SIZE_CENTRAL_DIRECTORY_END 22
struct zip_file_header_link {
struct zip_file_header_link *next;
@@ -184,7 +190,7 @@ struct zip_file_header_link {
};
struct zip {
- struct zip_data_descriptor data_descriptor;
+ uint8_t data_descriptor[SIZE_DATA_DESCRIPTOR];
struct zip_file_header_link *central_directory;
struct zip_file_header_link *central_directory_end;
int64_t offset;
@@ -203,17 +209,6 @@ struct zip {
#endif
};
-struct zip_central_directory_end {
- char signature[4];
- char disk[2];
- char start_disk[2];
- char entries_disk[2];
- char entries[2];
- char size[4];
- char offset[4];
- char comment_length[2];
-};
-
static int
archive_write_zip_options(struct archive_write *a, const char *key,
const char *val)
@@ -238,6 +233,7 @@ archive_write_zip_options(struct archive_write *a, const char *key,
zip->compression = COMPRESSION_STORE;
ret = ARCHIVE_OK;
}
+ return (ret);
} else if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -251,9 +247,61 @@ archive_write_zip_options(struct archive_write *a, const char *key,
else
ret = ARCHIVE_FATAL;
}
- } else
+ return (ret);
+ }
+
+ /* Note: The "warn" return is just to inform the options
+ * supervisor that we didn't handle it. It will generate
+ * a suitable error if no one used this option. */
+ return (ARCHIVE_WARN);
+}
+
+int
+archive_write_zip_set_compression_deflate(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ int ret = ARCHIVE_FAILED;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER,
+ "archive_write_zip_set_compression_deflate");
+ if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Can only use archive_write_zip_set_compression_deflate"
+ " with zip format");
+ ret = ARCHIVE_FATAL;
+ } else {
+#ifdef HAVE_ZLIB_H
+ struct zip *zip = a->format_data;
+ zip->compression = COMPRESSION_DEFLATE;
+ ret = ARCHIVE_OK;
+#else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "%s: unknown keyword ``%s''", a->format_name, key);
+ "deflate compression not supported");
+#endif
+ }
+ return (ret);
+}
+
+int
+archive_write_zip_set_compression_store(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct zip *zip = a->format_data;
+ int ret = ARCHIVE_FAILED;
+
+ archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
+ ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER,
+ "archive_write_zip_set_compression_deflate");
+ if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Can only use archive_write_zip_set_compression_store"
+ " with zip format");
+ ret = ARCHIVE_FATAL;
+ } else {
+ zip->compression = COMPRESSION_STORE;
+ ret = ARCHIVE_OK;
+ }
return (ret);
}
@@ -287,6 +335,7 @@ archive_write_set_format_zip(struct archive *_a)
zip->len_buf = 65536;
zip->buf = malloc(zip->len_buf);
if (zip->buf == NULL) {
+ free(zip);
archive_set_error(&a->archive, ENOMEM,
"Can't allocate compression buffer");
return (ARCHIVE_FATAL);
@@ -306,7 +355,7 @@ archive_write_set_format_zip(struct archive *_a)
a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
a->archive.archive_format_name = "ZIP";
- archive_le32enc(&zip->data_descriptor.signature,
+ archive_le32enc(&zip->data_descriptor[DATA_DESCRIPTOR_SIGNATURE],
ZIP_SIGNATURE_DATA_DESCRIPTOR);
return (ARCHIVE_OK);
@@ -328,9 +377,9 @@ static int
archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
{
struct zip *zip;
- struct zip_local_file_header h;
- struct zip_extra_data_local e;
- struct zip_data_descriptor *d;
+ uint8_t h[SIZE_LOCAL_FILE_HEADER];
+ uint8_t e[SIZE_EXTRA_DATA_LOCAL];
+ uint8_t *d;
struct zip_file_header_link *l;
struct archive_string_conv *sconv;
int ret, ret2 = ARCHIVE_OK;
@@ -343,7 +392,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Filetype not supported");
return ARCHIVE_FAILED;
- };
+ };
/* Directory entries should have a size of 0. */
if (type == AE_IFDIR)
@@ -370,7 +419,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
#endif
}
}
- d = &zip->data_descriptor;
+ d = zip->data_descriptor;
size = archive_entry_size(entry);
zip->remaining_data_bytes = size;
@@ -381,7 +430,21 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
"Can't allocate zip header data");
return (ARCHIVE_FATAL);
}
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ /* Make sure the path separators in pahtname, hardlink and symlink
+ * are all slash '/', not the Windows path separator '\'. */
+ l->entry = __la_win_entry_in_posix_pathseparator(entry);
+ if (l->entry == entry)
+ l->entry = archive_entry_clone(entry);
+#else
l->entry = archive_entry_clone(entry);
+#endif
+ if (l->entry == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate zip header data");
+ free(l);
+ return (ARCHIVE_FATAL);
+ }
l->flags = zip->flags;
if (zip->opt_sconv != NULL)
sconv = zip->opt_sconv;
@@ -393,21 +456,47 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
if (archive_entry_pathname_l(entry, &p, &len, sconv) != 0) {
if (errno == ENOMEM) {
+ archive_entry_free(l->entry);
+ free(l);
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Pathname");
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
- "Can't translate pathname '%s' to %s",
+ "Can't translate Pathname '%s' to %s",
archive_entry_pathname(entry),
archive_string_conversion_charset_name(sconv));
ret2 = ARCHIVE_WARN;
}
if (len > 0)
archive_entry_set_pathname(l->entry, p);
+
+ /*
+ * Although there is no character-set regulation for Symlink,
+ * it is suitable to convert a character-set of Symlinke to
+ * what those of the Pathname has been converted to.
+ */
+ if (type == AE_IFLNK) {
+ if (archive_entry_symlink_l(entry, &p, &len, sconv)) {
+ if (errno == ENOMEM) {
+ archive_entry_free(l->entry);
+ free(l);
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory "
+ " for Symlink");
+ return (ARCHIVE_FATAL);
+ }
+ /*
+ * Even if the strng conversion failed,
+ * we should not report the error since
+ * thre is no regulation for.
+ */
+ } else if (len > 0)
+ archive_entry_set_symlink(l->entry, p);
+ }
}
- /* If all character of a filename is ASCII, Reset UTF-8 Name flag. */
+ /* If all characters in a filename are ASCII, Reset UTF-8 Name flag. */
if ((l->flags & ZIP_FLAGS_UTF8_NAME) != 0 &&
is_all_ascii(archive_entry_pathname(l->entry)))
l->flags &= ~ZIP_FLAGS_UTF8_NAME;
@@ -440,13 +529,16 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
* directory. */
l->offset = zip->written_bytes;
- memset(&h, 0, sizeof(h));
- archive_le32enc(&h.signature, ZIP_SIGNATURE_LOCAL_FILE_HEADER);
- archive_le16enc(&h.version, ZIP_VERSION_EXTRACT);
- archive_le16enc(&h.flags, l->flags);
- archive_le16enc(&h.compression, l->compression);
- archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(entry)));
- archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry));
+ memset(h, 0, sizeof(h));
+ archive_le32enc(&h[LOCAL_FILE_HEADER_SIGNATURE],
+ ZIP_SIGNATURE_LOCAL_FILE_HEADER);
+ archive_le16enc(&h[LOCAL_FILE_HEADER_VERSION], ZIP_VERSION_EXTRACT);
+ archive_le16enc(&h[LOCAL_FILE_HEADER_FLAGS], l->flags);
+ archive_le16enc(&h[LOCAL_FILE_HEADER_COMPRESSION], l->compression);
+ archive_le32enc(&h[LOCAL_FILE_HEADER_TIMEDATE],
+ dos_time(archive_entry_mtime(entry)));
+ archive_le16enc(&h[LOCAL_FILE_HEADER_FILENAME_LENGTH],
+ (uint16_t)path_length(l->entry));
switch (l->compression) {
case COMPRESSION_STORE:
@@ -454,18 +546,21 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
* specification says to set to zero when using data
* descriptors. Otherwise the end of the data for an
* entry is rather difficult to find. */
- archive_le32enc(&h.compressed_size, size);
- archive_le32enc(&h.uncompressed_size, size);
+ archive_le32enc(&h[LOCAL_FILE_HEADER_COMPRESSED_SIZE],
+ (uint32_t)size);
+ archive_le32enc(&h[LOCAL_FILE_HEADER_UNCOMPRESSED_SIZE],
+ (uint32_t)size);
break;
#ifdef HAVE_ZLIB_H
case COMPRESSION_DEFLATE:
- archive_le32enc(&h.uncompressed_size, size);
+ archive_le32enc(&h[LOCAL_FILE_HEADER_UNCOMPRESSED_SIZE],
+ (uint32_t)size);
zip->stream.zalloc = Z_NULL;
zip->stream.zfree = Z_NULL;
zip->stream.opaque = Z_NULL;
zip->stream.next_out = zip->buf;
- zip->stream.avail_out = zip->len_buf;
+ zip->stream.avail_out = (uInt)zip->len_buf;
if (deflateInit2(&zip->stream, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
archive_set_error(&a->archive, ENOMEM,
@@ -477,28 +572,33 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
}
/* Formatting extra data. */
- archive_le16enc(&h.extra_length, sizeof(e));
- archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP);
- archive_le16enc(&e.time_size, sizeof(e.time_flag) +
- sizeof(e.mtime) + sizeof(e.atime) + sizeof(e.ctime));
- e.time_flag[0] = 0x07;
- archive_le32enc(&e.mtime, archive_entry_mtime(entry));
- archive_le32enc(&e.atime, archive_entry_atime(entry));
- archive_le32enc(&e.ctime, archive_entry_ctime(entry));
-
- archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX);
- archive_le16enc(&e.unix_size, sizeof(e.unix_version) +
- sizeof(e.unix_uid_size) + sizeof(e.unix_uid) +
- sizeof(e.unix_gid_size) + sizeof(e.unix_gid));
- e.unix_version = 1;
- e.unix_uid_size = 4;
- archive_le32enc(&e.unix_uid, archive_entry_uid(entry));
- e.unix_gid_size = 4;
- archive_le32enc(&e.unix_gid, archive_entry_gid(entry));
-
- archive_le32enc(&d->uncompressed_size, size);
-
- ret = __archive_write_output(a, &h, sizeof(h));
+ archive_le16enc(&h[LOCAL_FILE_HEADER_EXTRA_LENGTH], sizeof(e));
+ archive_le16enc(&e[EXTRA_DATA_LOCAL_TIME_ID],
+ ZIP_SIGNATURE_EXTRA_TIMESTAMP);
+ archive_le16enc(&e[EXTRA_DATA_LOCAL_TIME_SIZE], 1 + 4 * 3);
+ e[EXTRA_DATA_LOCAL_TIME_FLAG] = 0x07;
+ archive_le32enc(&e[EXTRA_DATA_LOCAL_MTIME],
+ (uint32_t)archive_entry_mtime(entry));
+ archive_le32enc(&e[EXTRA_DATA_LOCAL_ATIME],
+ (uint32_t)archive_entry_atime(entry));
+ archive_le32enc(&e[EXTRA_DATA_LOCAL_CTIME],
+ (uint32_t)archive_entry_ctime(entry));
+
+ archive_le16enc(&e[EXTRA_DATA_LOCAL_UNIX_ID],
+ ZIP_SIGNATURE_EXTRA_NEW_UNIX);
+ archive_le16enc(&e[EXTRA_DATA_LOCAL_UNIX_SIZE], 1 + (1 + 4) * 2);
+ e[EXTRA_DATA_LOCAL_UNIX_VERSION] = 1;
+ e[EXTRA_DATA_LOCAL_UNIX_UID_SIZE] = 4;
+ archive_le32enc(&e[EXTRA_DATA_LOCAL_UNIX_UID],
+ (uint32_t)archive_entry_uid(entry));
+ e[EXTRA_DATA_LOCAL_UNIX_GID_SIZE] = 4;
+ archive_le32enc(&e[EXTRA_DATA_LOCAL_UNIX_GID],
+ (uint32_t)archive_entry_gid(entry));
+
+ archive_le32enc(&d[DATA_DESCRIPTOR_UNCOMPRESSED_SIZE],
+ (uint32_t)size);
+
+ ret = __archive_write_output(a, h, sizeof(h));
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
zip->written_bytes += sizeof(h);
@@ -508,7 +608,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
return (ARCHIVE_FATAL);
zip->written_bytes += ret;
- ret = __archive_write_output(a, &e, sizeof(e));
+ ret = __archive_write_output(a, e, sizeof(e));
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
zip->written_bytes += sizeof(e);
@@ -517,11 +617,11 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
const unsigned char *p;
p = (const unsigned char *)archive_entry_symlink(l->entry);
- ret = __archive_write_output(a, p, size);
+ ret = __archive_write_output(a, p, (size_t)size);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
zip->written_bytes += size;
- l->crc32 = crc32(l->crc32, p, size);
+ l->crc32 = crc32(l->crc32, p, (unsigned)size);
}
if (ret2 != ARCHIVE_OK)
@@ -548,12 +648,12 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
zip->written_bytes += s;
zip->remaining_data_bytes -= s;
l->compressed_size += s;
- l->crc32 = crc32(l->crc32, buff, s);
+ l->crc32 = crc32(l->crc32, buff, (unsigned)s);
return (s);
#if HAVE_ZLIB_H
case COMPRESSION_DEFLATE:
zip->stream.next_in = (unsigned char*)(uintptr_t)buff;
- zip->stream.avail_in = s;
+ zip->stream.avail_in = (uInt)s;
do {
ret = deflate(&zip->stream, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR)
@@ -566,12 +666,12 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
l->compressed_size += zip->len_buf;
zip->written_bytes += zip->len_buf;
zip->stream.next_out = zip->buf;
- zip->stream.avail_out = zip->len_buf;
+ zip->stream.avail_out = (uInt)zip->len_buf;
}
} while (zip->stream.avail_in != 0);
zip->remaining_data_bytes -= s;
/* If we have it, use zlib's fast crc32() */
- l->crc32 = crc32(l->crc32, buff, s);
+ l->crc32 = crc32(l->crc32, buff, (uInt)s);
return (s);
#endif
@@ -588,7 +688,7 @@ archive_write_zip_finish_entry(struct archive_write *a)
/* Write the data descripter after file data has been written. */
int ret;
struct zip *zip = a->format_data;
- struct zip_data_descriptor *d = &zip->data_descriptor;
+ uint8_t *d = zip->data_descriptor;
struct zip_file_header_link *l = zip->central_directory_end;
#if HAVE_ZLIB_H
size_t reminder;
@@ -612,19 +712,20 @@ archive_write_zip_finish_entry(struct archive_write *a)
zip->stream.next_out = zip->buf;
if (zip->stream.avail_out != 0)
break;
- zip->stream.avail_out = zip->len_buf;
+ zip->stream.avail_out = (uInt)zip->len_buf;
}
deflateEnd(&zip->stream);
break;
#endif
}
- archive_le32enc(&d->crc32, l->crc32);
- archive_le32enc(&d->compressed_size, l->compressed_size);
- ret = __archive_write_output(a, d, sizeof(*d));
+ archive_le32enc(&d[DATA_DESCRIPTOR_CRC32], l->crc32);
+ archive_le32enc(&d[DATA_DESCRIPTOR_COMPRESSED_SIZE],
+ (uint32_t)l->compressed_size);
+ ret = __archive_write_output(a, d, SIZE_DATA_DESCRIPTOR);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- zip->written_bytes += sizeof(*d);
+ zip->written_bytes += SIZE_DATA_DESCRIPTOR;
return (ARCHIVE_OK);
}
@@ -633,9 +734,9 @@ archive_write_zip_close(struct archive_write *a)
{
struct zip *zip;
struct zip_file_header_link *l;
- struct zip_file_header h;
- struct zip_central_directory_end end;
- struct zip_extra_data_central e;
+ uint8_t h[SIZE_FILE_HEADER];
+ uint8_t end[SIZE_CENTRAL_DIRECTORY_END];
+ uint8_t e[SIZE_EXTRA_DATA_CENTRAL];
int64_t offset_start, offset_end;
int entries;
int ret;
@@ -652,10 +753,10 @@ archive_write_zip_close(struct archive_write *a)
* - disk_number
* - attributes_internal
*/
- memset(&h, 0, sizeof(h));
- archive_le32enc(&h.signature, ZIP_SIGNATURE_FILE_HEADER);
- archive_le16enc(&h.version_by, ZIP_VERSION_BY);
- archive_le16enc(&h.version_extract, ZIP_VERSION_EXTRACT);
+ memset(h, 0, sizeof(h));
+ archive_le32enc(&h[FILE_HEADER_SIGNATURE], ZIP_SIGNATURE_FILE_HEADER);
+ archive_le16enc(&h[FILE_HEADER_VERSION_BY], ZIP_VERSION_BY);
+ archive_le16enc(&h[FILE_HEADER_VERSION_EXTRACT], ZIP_VERSION_EXTRACT);
entries = 0;
offset_start = zip->written_bytes;
@@ -663,31 +764,34 @@ archive_write_zip_close(struct archive_write *a)
/* Formatting individual header fields per entry and
* writing each entry. */
while (l != NULL) {
- archive_le16enc(&h.flags, l->flags);
- archive_le16enc(&h.compression, l->compression);
- archive_le32enc(&h.timedate,
+ archive_le16enc(&h[FILE_HEADER_FLAGS], l->flags);
+ archive_le16enc(&h[FILE_HEADER_COMPRESSION], l->compression);
+ archive_le32enc(&h[FILE_HEADER_TIMEDATE],
dos_time(archive_entry_mtime(l->entry)));
- archive_le32enc(&h.crc32, l->crc32);
- archive_le32enc(&h.compressed_size, l->compressed_size);
- archive_le32enc(&h.uncompressed_size,
- archive_entry_size(l->entry));
- archive_le16enc(&h.filename_length,
+ archive_le32enc(&h[FILE_HEADER_CRC32], l->crc32);
+ archive_le32enc(&h[FILE_HEADER_COMPRESSED_SIZE],
+ (uint32_t)l->compressed_size);
+ archive_le32enc(&h[FILE_HEADER_UNCOMPRESSED_SIZE],
+ (uint32_t)archive_entry_size(l->entry));
+ archive_le16enc(&h[FILE_HEADER_FILENAME_LENGTH],
(uint16_t)path_length(l->entry));
- archive_le16enc(&h.extra_length, sizeof(e));
- archive_le16enc(&h.attributes_external[2],
+ archive_le16enc(&h[FILE_HEADER_EXTRA_LENGTH], sizeof(e));
+ archive_le16enc(&h[FILE_HEADER_ATTRIBUTES_EXTERNAL+2],
archive_entry_mode(l->entry));
- archive_le32enc(&h.offset, l->offset);
+ archive_le32enc(&h[FILE_HEADER_OFFSET], (uint32_t)l->offset);
/* Formatting extra data. */
- archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP);
- archive_le16enc(&e.time_size,
- sizeof(e.mtime) + sizeof(e.time_flag));
- e.time_flag[0] = 0x07;
- archive_le32enc(&e.mtime, archive_entry_mtime(l->entry));
- archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX);
- archive_le16enc(&e.unix_size, 0x0000);
-
- ret = __archive_write_output(a, &h, sizeof(h));
+ archive_le16enc(&e[EXTRA_DATA_CENTRAL_TIME_ID],
+ ZIP_SIGNATURE_EXTRA_TIMESTAMP);
+ archive_le16enc(&e[EXTRA_DATA_CENTRAL_TIME_SIZE], 1 + 4);
+ e[EXTRA_DATA_CENTRAL_TIME_FLAG] = 0x07;
+ archive_le32enc(&e[EXTRA_DATA_CENTRAL_MTIME],
+ (uint32_t)archive_entry_mtime(l->entry));
+ archive_le16enc(&e[EXTRA_DATA_CENTRAL_UNIX_ID],
+ ZIP_SIGNATURE_EXTRA_NEW_UNIX);
+ archive_le16enc(&e[EXTRA_DATA_CENTRAL_UNIX_SIZE], 0x0000);
+
+ ret = __archive_write_output(a, h, sizeof(h));
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
zip->written_bytes += sizeof(h);
@@ -697,7 +801,7 @@ archive_write_zip_close(struct archive_write *a)
return (ARCHIVE_FATAL);
zip->written_bytes += ret;
- ret = __archive_write_output(a, &e, sizeof(e));
+ ret = __archive_write_output(a, e, sizeof(e));
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
zip->written_bytes += sizeof(e);
@@ -708,15 +812,18 @@ archive_write_zip_close(struct archive_write *a)
offset_end = zip->written_bytes;
/* Formatting end of central directory. */
- memset(&end, 0, sizeof(end));
- archive_le32enc(&end.signature, ZIP_SIGNATURE_CENTRAL_DIRECTORY_END);
- archive_le16enc(&end.entries_disk, entries);
- archive_le16enc(&end.entries, entries);
- archive_le32enc(&end.size, offset_end - offset_start);
- archive_le32enc(&end.offset, offset_start);
+ memset(end, 0, sizeof(end));
+ archive_le32enc(&end[CENTRAL_DIRECTORY_END_SIGNATURE],
+ ZIP_SIGNATURE_CENTRAL_DIRECTORY_END);
+ archive_le16enc(&end[CENTRAL_DIRECTORY_END_ENTRIES_DISK], entries);
+ archive_le16enc(&end[CENTRAL_DIRECTORY_END_ENTRIES], entries);
+ archive_le32enc(&end[CENTRAL_DIRECTORY_END_SIZE],
+ (uint32_t)(offset_end - offset_start));
+ archive_le32enc(&end[CENTRAL_DIRECTORY_END_OFFSET],
+ (uint32_t)offset_start);
/* Writing end of central directory. */
- ret = __archive_write_output(a, &end, sizeof(end));
+ ret = __archive_write_output(a, end, sizeof(end));
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
zip->written_bytes += sizeof(end);
@@ -784,7 +891,10 @@ path_length(struct archive_entry *entry)
type = archive_entry_filetype(entry);
path = archive_entry_pathname(entry);
- if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) {
+ if (path == NULL)
+ return (0);
+ if (type == AE_IFDIR &&
+ (path[0] == '\0' || path[strlen(path) - 1] != '/')) {
return strlen(path) + 1;
} else {
return strlen(path);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_options.3 b/Utilities/cmlibarchive/libarchive/archive_write_set_options.3
index 9a8ea3d..9d60515 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_options.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_options.3
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd Feb 27, 2010
+.Dd February 2, 2012
.Dt ARCHIVE_WRITE_OPTIONS 3
.Os
.Sh NAME
@@ -33,8 +33,8 @@
.Nm archive_write_set_option ,
.Nm archive_write_set_options
.Nd functions controlling options for reading archives
-.Sh SYNOPSIS
-.\"
+.Sh LIBRARY
+Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.Ft int
.Fo archive_write_set_filter_option
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_options.c b/Utilities/cmlibarchive/libarchive/archive_write_set_options.c
index a8c2d23..962309a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_options.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_options.c
@@ -78,11 +78,13 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
struct archive_write *a = (struct archive_write *)_a;
if (a->format_name == NULL)
- return (ARCHIVE_FAILED);
+ return (m == NULL)?ARCHIVE_FAILED:ARCHIVE_WARN - 1;
+ /* If the format name didn't match, return a special code for
+ * _archive_set_option[s]. */
if (m != NULL && strcmp(m, a->format_name) != 0)
- return (ARCHIVE_FAILED);
+ return (ARCHIVE_WARN - 1);
if (a->format_options == NULL)
- return (ARCHIVE_FAILED);
+ return (ARCHIVE_WARN);
return a->format_options(a, o, v);
}
@@ -92,7 +94,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
{
struct archive_write *a = (struct archive_write *)_a;
struct archive_write_filter *filter;
- int r, rv = ARCHIVE_FAILED;
+ int r, rv = ARCHIVE_WARN;
for (filter = a->filter_first; filter != NULL; filter = filter->next_filter) {
if (filter->options == NULL)
@@ -111,6 +113,10 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
if (r == ARCHIVE_OK)
rv = ARCHIVE_OK;
}
+ /* If the filter name didn't match, return a special code for
+ * _archive_set_option[s]. */
+ if (rv == ARCHIVE_WARN && m != NULL)
+ rv = ARCHIVE_WARN - 1;
return (rv);
}
diff --git a/Utilities/cmlibarchive/libarchive/cpio.5 b/Utilities/cmlibarchive/libarchive/cpio.5
index 13a4445..1a2886f 100644
--- a/Utilities/cmlibarchive/libarchive/cpio.5
+++ b/Utilities/cmlibarchive/libarchive/cpio.5
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libarchive/cpio.5,v 1.2 2008/05/26 17:00:23 kientzle Exp $
+.\" $FreeBSD$
.\"
-.Dd October 5, 2007
+.Dd December 23, 2011
.Dt CPIO 5
.Os
.Sh NAME
diff --git a/Utilities/cmlibarchive/libarchive/filter_fork.h b/Utilities/cmlibarchive/libarchive/filter_fork.h
index 453d032..a28272b 100644
--- a/Utilities/cmlibarchive/libarchive/filter_fork.h
+++ b/Utilities/cmlibarchive/libarchive/filter_fork.h
@@ -33,7 +33,7 @@
#define FILTER_FORK_H
pid_t
-__archive_create_child(const char *path, int *child_stdin, int *child_stdout);
+__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout);
void
__archive_check_child(int in, int out);
diff --git a/Utilities/cmlibarchive/libarchive/filter_fork.c b/Utilities/cmlibarchive/libarchive/filter_fork_posix.c
index d160524..02dbd4b 100644
--- a/Utilities/cmlibarchive/libarchive/filter_fork.c
+++ b/Utilities/cmlibarchive/libarchive/filter_fork_posix.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Joerg Sonnenberger
+ * Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,10 +28,19 @@
/* This capability is only available on POSIX systems. */
#if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \
- (defined(HAVE_FORK) || defined(HAVE_VFORK))
+ (defined(HAVE_FORK) || defined(HAVE_VFORK) || defined(HAVE_POSIX_SPAWNP))
__FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00Z kientzle $");
+#if defined(HAVE_SYS_TYPES_H)
+# include <sys/types.h>
+#endif
+#ifdef HAVE_ERRNO_H
+# include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H))
# if defined(HAVE_POLL_H)
# include <poll.h>
@@ -47,17 +57,37 @@ __FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
+#ifdef HAVE_SPAWN_H
+# include <spawn.h>
+#endif
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
+#include "archive.h"
+#include "archive_cmdline_private.h"
+
#include "filter_fork.h"
pid_t
-__archive_create_child(const char *path, int *child_stdin, int *child_stdout)
+__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
{
pid_t child;
int stdin_pipe[2], stdout_pipe[2], tmp;
+#if HAVE_POSIX_SPAWNP
+ posix_spawn_file_actions_t actions;
+ int r;
+#endif
+ struct archive_cmdline *cmdline;
+
+ cmdline = __archive_cmdline_allocate();
+ if (cmdline == NULL)
+ goto state_allocated;
+ if (__archive_cmdline_parse(cmdline, cmd) != ARCHIVE_OK)
+ goto state_allocated;
if (pipe(stdin_pipe) == -1)
goto state_allocated;
@@ -76,14 +106,53 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
stdout_pipe[1] = tmp;
}
+#if HAVE_POSIX_SPAWNP
+
+ r = posix_spawn_file_actions_init(&actions);
+ if (r != 0) {
+ errno = r;
+ goto stdout_opened;
+ }
+ r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[1]);
+ if (r != 0)
+ goto actions_inited;
+ r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[0]);
+ if (r != 0)
+ goto actions_inited;
+ /* Setup for stdin. */
+ r = posix_spawn_file_actions_adddup2(&actions, stdin_pipe[0], 0);
+ if (r != 0)
+ goto actions_inited;
+ if (stdin_pipe[0] != 0 /* stdin */) {
+ r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[0]);
+ if (r != 0)
+ goto actions_inited;
+ }
+ /* Setup for stdout. */
+ r = posix_spawn_file_actions_adddup2(&actions, stdout_pipe[1], 1);
+ if (r != 0)
+ goto actions_inited;
+ if (stdout_pipe[1] != 1 /* stdout */) {
+ r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[1]);
+ if (r != 0)
+ goto actions_inited;
+ }
+ r = posix_spawnp(&child, cmdline->path, &actions, NULL,
+ cmdline->argv, NULL);
+ if (r != 0)
+ goto actions_inited;
+ posix_spawn_file_actions_destroy(&actions);
+
+#else /* HAVE_POSIX_SPAWNP */
+
#if HAVE_VFORK
- switch ((child = vfork())) {
+ child = vfork();
#else
- switch ((child = fork())) {
+ child = fork();
#endif
- case -1:
+ if (child == -1)
goto stdout_opened;
- case 0:
+ if (child == 0) {
close(stdin_pipe[1]);
close(stdout_pipe[0]);
if (dup2(stdin_pipe[0], 0 /* stdin */) == -1)
@@ -94,20 +163,27 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
_exit(254);
if (stdout_pipe[1] != 1 /* stdout */)
close(stdout_pipe[1]);
- execlp(path, path, (char *)NULL);
+ execvp(cmdline->path, cmdline->argv);
_exit(254);
- default:
- close(stdin_pipe[0]);
- close(stdout_pipe[1]);
-
- *child_stdin = stdin_pipe[1];
- fcntl(*child_stdin, F_SETFL, O_NONBLOCK);
- *child_stdout = stdout_pipe[0];
- fcntl(*child_stdout, F_SETFL, O_NONBLOCK);
}
+#endif /* HAVE_POSIX_SPAWNP */
+
+ close(stdin_pipe[0]);
+ close(stdout_pipe[1]);
+
+ *child_stdin = stdin_pipe[1];
+ fcntl(*child_stdin, F_SETFL, O_NONBLOCK);
+ *child_stdout = stdout_pipe[0];
+ fcntl(*child_stdout, F_SETFL, O_NONBLOCK);
+ __archive_cmdline_free(cmdline);
return child;
+#if HAVE_POSIX_SPAWNP
+actions_inited:
+ errno = r;
+ posix_spawn_file_actions_destroy(&actions);
+#endif
stdout_opened:
close(stdout_pipe[0]);
close(stdout_pipe[1]);
@@ -115,6 +191,7 @@ stdin_opened:
close(stdin_pipe[0]);
close(stdin_pipe[1]);
state_allocated:
+ __archive_cmdline_free(cmdline);
return -1;
}
diff --git a/Utilities/cmlibarchive/libarchive/filter_fork_windows.c b/Utilities/cmlibarchive/libarchive/filter_fork_windows.c
index 272e56c..fa59cc9 100644
--- a/Utilities/cmlibarchive/libarchive/filter_fork_windows.c
+++ b/Utilities/cmlibarchive/libarchive/filter_fork_windows.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2009 Michihiro NAKAJIMA
+ * Copyright (c) 2009-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,17 +26,100 @@
#include "archive_platform.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
+#include "archive_cmdline_private.h"
+#include "archive_string.h"
#include "filter_fork.h"
pid_t
-__archive_create_child(const char *path, int *child_stdin, int *child_stdout)
+__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
{
HANDLE childStdout[2], childStdin[2],childStderr;
SECURITY_ATTRIBUTES secAtts;
STARTUPINFO staInfo;
PROCESS_INFORMATION childInfo;
- char cmd[MAX_PATH];
+ struct archive_string cmdline;
+ struct archive_string fullpath;
+ struct archive_cmdline *acmd;
+ char *arg0, *ext;
+ int i, l;
+ DWORD fl, fl_old;
+
+ childStdout[0] = childStdout[1] = INVALID_HANDLE_VALUE;
+ childStdin[0] = childStdin[1] = INVALID_HANDLE_VALUE;
+ childStderr = INVALID_HANDLE_VALUE;
+ archive_string_init(&cmdline);
+ archive_string_init(&fullpath);
+
+ acmd = __archive_cmdline_allocate();
+ if (acmd == NULL)
+ goto fail;
+ if (__archive_cmdline_parse(acmd, cmd) != ARCHIVE_OK)
+ goto fail;
+
+ /*
+ * Search the full path of 'path'.
+ * NOTE: This does not need if we give CreateProcessA 'path' as
+ * a part of the cmdline and give CreateProcessA NULL as first
+ * parameter, but I do not like that way.
+ */
+ ext = strrchr(acmd->path, '.');
+ if (ext == NULL || strlen(ext) > 4)
+ /* 'path' does not have a proper extension, so we have to
+ * give SearchPath() ".exe" as the extension. */
+ ext = ".exe";
+ else
+ ext = NULL;/* 'path' has an extension. */
+
+ fl = MAX_PATH;
+ do {
+ if (archive_string_ensure(&fullpath, fl) == NULL)
+ goto fail;
+ fl_old = fl;
+ fl = SearchPathA(NULL, acmd->path, ext, fl, fullpath.s,
+ &arg0);
+ } while (fl != 0 && fl > fl_old);
+ if (fl == 0)
+ goto fail;
+
+ /*
+ * Make a command line.
+ */
+ for (l = 0, i = 0; acmd->argv[i] != NULL; i++) {
+ if (i == 0)
+ continue;
+ l += (int)strlen(acmd->argv[i]) + 1;
+ }
+ if (archive_string_ensure(&cmdline, l + 1) == NULL)
+ goto fail;
+ for (i = 0; acmd->argv[i] != NULL; i++) {
+ if (i == 0) {
+ const char *p, *sp;
+
+ if ((p = strchr(acmd->argv[i], '/')) != NULL ||
+ (p = strchr(acmd->argv[i], '\\')) != NULL)
+ p++;
+ else
+ p = acmd->argv[i];
+ if ((sp = strchr(p, ' ')) != NULL)
+ archive_strappend_char(&cmdline, '"');
+ archive_strcat(&cmdline, p);
+ if (sp != NULL)
+ archive_strappend_char(&cmdline, '"');
+ } else {
+ archive_strappend_char(&cmdline, ' ');
+ archive_strcat(&cmdline, acmd->argv[i]);
+ }
+ }
+ if (i <= 1) {
+ const char *sp;
+
+ if ((sp = strchr(arg0, ' ')) != NULL)
+ archive_strappend_char(&cmdline, '"');
+ archive_strcat(&cmdline, arg0);
+ if (sp != NULL)
+ archive_strappend_char(&cmdline, '"');
+ }
secAtts.nLength = sizeof(SECURITY_ATTRIBUTES);
secAtts.bInheritHandle = TRUE;
@@ -44,33 +127,15 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
if (CreatePipe(&childStdout[0], &childStdout[1], &secAtts, 0) == 0)
goto fail;
if (!SetHandleInformation(childStdout[0], HANDLE_FLAG_INHERIT, 0))
- {
- CloseHandle(childStdout[0]);
- CloseHandle(childStdout[1]);
goto fail;
- }
- if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) {
- CloseHandle(childStdout[0]);
- CloseHandle(childStdout[1]);
+ if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0)
goto fail;
- }
if (!SetHandleInformation(childStdin[1], HANDLE_FLAG_INHERIT, 0))
- {
- CloseHandle(childStdout[0]);
- CloseHandle(childStdout[1]);
- CloseHandle(childStdin[0]);
- CloseHandle(childStdin[1]);
goto fail;
- }
if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE),
GetCurrentProcess(), &childStderr, 0, TRUE,
- DUPLICATE_SAME_ACCESS) == 0) {
- CloseHandle(childStdout[0]);
- CloseHandle(childStdout[1]);
- CloseHandle(childStdin[0]);
- CloseHandle(childStdin[1]);
+ DUPLICATE_SAME_ACCESS) == 0)
goto fail;
- }
memset(&staInfo, 0, sizeof(staInfo));
staInfo.cb = sizeof(staInfo);
@@ -79,17 +144,9 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
staInfo.hStdInput = childStdin[0];
staInfo.wShowWindow = SW_HIDE;
staInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
- strncpy(cmd, path, sizeof(cmd)-1);
- cmd[sizeof(cmd)-1] = '\0';
- if (CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL,
- &staInfo, &childInfo) == 0) {
- CloseHandle(childStdout[0]);
- CloseHandle(childStdout[1]);
- CloseHandle(childStdin[0]);
- CloseHandle(childStdin[1]);
- CloseHandle(childStderr);
+ if (CreateProcessA(fullpath.s, cmdline.s, NULL, NULL, TRUE, 0,
+ NULL, NULL, &staInfo, &childInfo) == 0)
goto fail;
- }
WaitForInputIdle(childInfo.hProcess, INFINITE);
CloseHandle(childInfo.hProcess);
CloseHandle(childInfo.hThread);
@@ -100,17 +157,33 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
CloseHandle(childStdout[1]);
CloseHandle(childStdin[0]);
+ archive_string_free(&cmdline);
+ archive_string_free(&fullpath);
+ __archive_cmdline_free(acmd);
return (childInfo.dwProcessId);
fail:
+ if (childStdout[0] != INVALID_HANDLE_VALUE)
+ CloseHandle(childStdout[0]);
+ if (childStdout[1] != INVALID_HANDLE_VALUE)
+ CloseHandle(childStdout[1]);
+ if (childStdin[0] != INVALID_HANDLE_VALUE)
+ CloseHandle(childStdin[0]);
+ if (childStdin[1] != INVALID_HANDLE_VALUE)
+ CloseHandle(childStdin[1]);
+ if (childStderr != INVALID_HANDLE_VALUE)
+ CloseHandle(childStderr);
+ archive_string_free(&cmdline);
+ archive_string_free(&fullpath);
+ __archive_cmdline_free(acmd);
return (-1);
}
void
__archive_check_child(int in, int out)
{
- (void)in; /* UNSED */
- (void)out; /* UNSED */
+ (void)in; /* UNUSED */
+ (void)out; /* UNUSED */
Sleep(100);
}
diff --git a/Utilities/cmlibarchive/libarchive/libarchive-formats.5 b/Utilities/cmlibarchive/libarchive/libarchive-formats.5
index d223bf8..4a709b3 100644
--- a/Utilities/cmlibarchive/libarchive/libarchive-formats.5
+++ b/Utilities/cmlibarchive/libarchive/libarchive-formats.5
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/libarchive-formats.5 201077 2009-12-28 01:50:23Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd December 27, 2009
+.Dd March 18, 2012
.Dt LIBARCHIVE-FORMATS 5
.Os
.Sh NAME
@@ -51,11 +51,11 @@ functions to enable all supported formats.
The
.Xr libarchive 3
library can read most tar archives.
-However, it only writes POSIX-standard
+It can write POSIX-standard
.Dq ustar
and
.Dq pax interchange
-formats.
+formats and a subset of the legacy GNU tar format.
.Pp
All tar formats store each entry in one or more 512-byte records.
The first record is used for file metadata, including filename,
@@ -70,13 +70,18 @@ subsequent entries.
.It Cm gnutar
The
.Xr libarchive 3
-library can read GNU-format tar archives.
+library can read most GNU-format tar archives.
It currently supports the most popular GNU extensions, including
modern long filename and linkname support, as well as atime and ctime data.
The libarchive library does not support multi-volume
archives, nor the old GNU long filename format.
It can read GNU sparse file entries, including the new POSIX-based
-formats, but cannot write GNU sparse file entries.
+formats.
+.Pp
+The
+.Xr libarchive 3
+library can write GNU tar format, including long filename
+and linkname support, as well as atime and ctime data.
.It Cm pax
The
.Xr libarchive 3
@@ -98,6 +103,14 @@ archiver and a few LIBARCHIVE keys.
The libarchive library can read most of the SCHILY keys
and most of the GNU keys introduced by GNU tar.
It silently ignores any keywords that it does not understand.
+.Pp
+The pax interchange format converts filenames to Unicode
+and stores them using the UTF-8 encoding.
+Prior to libarchive 3.0, libarchive erroneously assumed
+that the system wide-character routines natively supported
+Unicode.
+This caused it to mis-handle non-ASCII filenames on systems
+that did not satisfy this assumption.
.It Cm restricted pax
The libarchive library can also write pax archives in which it
attempts to suppress the extended attributes entry whenever
@@ -135,6 +148,8 @@ security information cannot be stored.
Archive entries are limited to 8 gigabytes in size.
.El
Note that the pax interchange format has none of these restrictions.
+The ustar format is old and widely supported.
+It is recommended when compatibility is the primary concern.
.El
.Pp
The libarchive library also reads a variety of commonly-used extensions to
@@ -268,19 +283,68 @@ If both extensions are present, the Joliet extensions will be
used and the Rockridge extensions will be ignored.
In particular, this can create problems with hardlinks and symlinks,
which are supported by Rockridge but not by Joliet.
+.Pp
+Libarchive reads ISO9660 images using a streaming strategy.
+This allows it to read compressed images directly
+(decompressing on the fly) and allows it to read images
+directly from network sockets, pipes, and other non-seekable
+data sources.
+This strategy works well for optimized ISO9660 images created
+by many popular programs.
+Such programs collect all directory information at the beginning
+of the ISO9660 image so it can be read from a physical disk
+with a minimum of seeking.
+However, not all ISO9660 images can be read in this fashion.
+.Pp
+Libarchive can also write ISO9660 images.
+Such images are fully optimized with the directory information
+preceding all file data.
+This is done by storing all file data to a temporary file
+while collecting directory information in memory.
+When the image is finished, libarchive writes out the
+directory structure followed by the file data.
+The location used for the temporary file can be changed
+by the usual environment variables.
.Ss Zip format
Libarchive can read and write zip format archives that have
uncompressed entries and entries compressed with the
.Dq deflate
algorithm.
-Older zip compression algorithms are not supported.
-It can extract jar archives, archives that use Zip64 extensions and many
+Other zip compression algorithms are not supported.
+It can extract jar archives, archives that use Zip64 extensions and
self-extracting zip archives.
-Libarchive reads Zip archives as they are being streamed,
-which allows it to read archives of arbitrary size.
-It currently does not use the central directory; this
-limits libarchive's ability to support some self-extracting
-archives and ones that have been modified in certain ways.
+Libarchive can use either of two different strategies for
+reading Zip archives:
+a streaming strategy which is fast and can handle extremely
+large archives, and a seeking strategy which can correctly
+process self-extracting Zip archives and archives with
+deleted members or other in-place modifications.
+.Pp
+The streaming reader processes Zip archives as they are read.
+It can read archives of arbitrary size from tape or
+network sockets, and can decode Zip archives that have
+been separately compressed or encoded.
+However, self-extracting Zip archives and archives with
+certain types of modifications cannot be correctly
+handled.
+Such archives require that the reader first process the
+Central Directory, which is ordinarily located
+at the end of a Zip archive and is thus inaccessible
+to the streaming reader.
+If the program using libarchive has enabled seek support, then
+libarchive will use this to processes the central directory first.
+.Pp
+In particular, the seeking reader must be used to
+correctly handle self-extracting archives.
+Such archives consist of a program followed by a regular
+Zip archive.
+The streaming reader cannot parse the initial program
+portion, but the seeking reader starts by reading the
+Central Directory from the end of the archive.
+Similarly, Zip archives that have been modified in-place
+can have deleted entries or other garbage data that
+can only be accurately detected by first reading the
+Central Directory.
.Ss Archive (library) file format
The Unix archive format (commonly created by the
.Xr ar 1
@@ -315,7 +379,7 @@ of a file hierarchy in which each line specifies the name of a file and
provides specific metadata about that file.
Libarchive can read all of the keywords supported by both
the NetBSD and FreeBSD versions of
-.Xr mtree 1 ,
+.Xr mtree 8 ,
although many of the keywords cannot currently be stored in an
.Tn archive_entry
object.
@@ -342,12 +406,18 @@ using libarchive.
If it cannot locate and open the file on disk, libarchive
will return an error for any attempt to read the entry
body.
+.Ss LHA
+XXX Information about libarchive's LHA support XXX
+.Ss CAB
+XXX Information about libarchive's CAB support XXX
+.Ss XAR
+XXX Information about libarchive's XAR support XXX
.Ss RAR
-libarchive has limited support to read files in RAR format. Currently,
-libarchive can read single RAR files in RARv3 format which have been either
-created uncompressed, or compressed using any of the compression methods
-supported by the RARv3 format. libarchive can also extract RAR files which have
-been created as self-extracting RAR files.
+Libarchive has limited support for reading RAR format archives.
+Currently, libarchive can read RARv3 format archives
+which have been either created uncompressed, or compressed using
+any of the compression methods supported by the RARv3 format.
+Libarchive can also read self-extracting RAR archives.
.Sh SEE ALSO
.Xr ar 1 ,
.Xr cpio 1 ,
diff --git a/Utilities/cmlibarchive/libarchive/libarchive.3 b/Utilities/cmlibarchive/libarchive/libarchive.3
index d655404..3a9a841 100644
--- a/Utilities/cmlibarchive/libarchive/libarchive.3
+++ b/Utilities/cmlibarchive/libarchive/libarchive.3
@@ -22,16 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libarchive/libarchive.3,v 1.11 2007/01/09 08:05:56 kientzle Exp $
+.\" $FreeBSD$
.\"
-.Dd February 6, 2010
+.Dd March 18, 2012
.Dt LIBARCHIVE 3
.Os
.Sh NAME
.Nm libarchive
.Nd functions for reading and writing streaming archives
-.Sh LIBRARY
-.Lb libarchive
.Sh OVERVIEW
The
.Nm
@@ -66,15 +64,33 @@ most common cpio archive formats,
.It
ISO9660 CD images (including RockRidge and Joliet extensions),
.It
-Zip archives.
+Zip archives,
+.It
+ar archives (including GNU/SysV and BSD extensions),
+.It
+Microsoft CAB archives,
+.It
+LHA archives,
+.It
+mtree file tree descriptions,
+.It
+RAR archives,
+.It
+XAR archives.
.El
The library automatically detects archives compressed with
.Xr gzip 1 ,
.Xr bzip2 1 ,
.Xr xz 1 ,
+.Xr lzip 1 ,
or
.Xr compress 1
and decompresses them transparently.
+It can similarly detect and decode archives processed with
+.Xr uuencode 1
+or which have an
+.Xr rpm 1
+header.
.Pp
When writing an archive, you can specify the compression
to be used and the format to use.
@@ -93,7 +109,17 @@ POSIX octet-oriented cpio archives,
.It
Zip archive,
.It
-two different variants of shar archives.
+two different variants of shar archives,
+.It
+ISO9660 CD images,
+.It
+7-Zip archives,
+.It
+ar archives,
+.It
+mtree file tree descriptions,
+.It
+XAR archives.
.El
Pax interchange format is an extension of the tar archive format that
eliminates essentially all of the limitations of historic tar formats
@@ -145,9 +171,21 @@ operations.
.Sh READING ENTRIES FROM DISK
The
.Xr archive_read_disk 3
-provides some support for populating
+supports for populating
.Xr archive_entry 3
objects from information in the filesystem.
+This includes the information accessible from the
+.Xr stat 2
+system call as well as ACLs, extended attributes,
+and other metadata.
+The
+.Xr archive_read_disk 3
+API also supports iterating over directory trees,
+which allows directories of files to be read using
+an API compatible with
+the
+.Xr archive_read 3
+API.
.Sh DESCRIPTION
Detailed descriptions of each function are provided by the
corresponding manual pages.
@@ -227,7 +265,7 @@ library first appeared in
.An -nosplit
The
.Nm libarchive
-library was written by
+library was originally written by
.An Tim Kientzle Aq kientzle@acm.org .
.Sh BUGS
Some archive formats support information that is not supported by
@@ -244,13 +282,8 @@ is supported by all formats.
For example, cpio formats do not support nanosecond timestamps;
old tar formats do not support large device numbers.
.Pp
-The
-.Xr archive_read_disk 3
-API should support iterating over filesystems;
-that would make it possible to share code among
-disk-to-archive, archive-to-archive, archive-to-disk,
-and disk-to-disk operations.
-Currently, it only supports reading the
-information for a single file.
-(Which is still quite useful, as it hides a lot
-of system-specific details.)
+The ISO9660 reader cannot yet read all ISO9660 images;
+it should learn how to seek.
+.Pp
+The AR writer requires the client program to use
+two passes, unlike all other libarchive writers.
diff --git a/Utilities/cmlibarchive/libarchive/libarchive_changes.3 b/Utilities/cmlibarchive/libarchive/libarchive_changes.3
index 6ee6af2..bacd6e1 100644
--- a/Utilities/cmlibarchive/libarchive/libarchive_changes.3
+++ b/Utilities/cmlibarchive/libarchive/libarchive_changes.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 27, 2011
+.Dd December 23, 2011
.Dt LIBARCHIVE_CHANGES 3
.Os
.Sh NAME
diff --git a/Utilities/cmlibarchive/libarchive/libarchive_internals.3 b/Utilities/cmlibarchive/libarchive/libarchive_internals.3
index 776f4c3..4aa09f9 100644
--- a/Utilities/cmlibarchive/libarchive/libarchive_internals.3
+++ b/Utilities/cmlibarchive/libarchive/libarchive_internals.3
@@ -22,10 +22,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/lib/libarchive/libarchive_internals.3,v 1.2 2007/12/30 04:58:22 kientzle Exp $
+.\" $FreeBSD$
.\"
-.Dd April 16, 2007
-.Dt LIBARCHIVE 3
+.Dd January 26, 2011
+.Dt LIBARCHIVE_INTERNALS 3
.Os
.Sh NAME
.Nm libarchive_internals
diff --git a/Utilities/cmlibarchive/libarchive/mtree.5 b/Utilities/cmlibarchive/libarchive/mtree.5
index b6637d6..983fff7 100644
--- a/Utilities/cmlibarchive/libarchive/mtree.5
+++ b/Utilities/cmlibarchive/libarchive/mtree.5
@@ -28,7 +28,7 @@
.\" From: @(#)mtree.8 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd August 20, 2007
+.Dd May 6, 2008
.Dt MTREE 5
.Os
.Sh NAME
diff --git a/Utilities/cmlibarchive/libarchive/tar.5 b/Utilities/cmlibarchive/libarchive/tar.5
index 65875bd..688bb92 100644
--- a/Utilities/cmlibarchive/libarchive/tar.5
+++ b/Utilities/cmlibarchive/libarchive/tar.5
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libarchive/tar.5 201077 2009-12-28 01:50:23Z kientzle $
+.\" $FreeBSD$
.\"
-.Dd December 27, 2009
+.Dd December 23, 2011
.Dt TAR 5
.Os
.Sh NAME
diff --git a/bootstrap b/bootstrap
index 281c3d0..afb66e5 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1525,14 +1525,6 @@ set (CMAKE_MAN_DIR "'"${cmake_man_dir}"'" CACHE PATH "Install location for man p
set (CMAKE_DATA_DIR "'"${cmake_data_dir}"'" CACHE PATH "Install location for data (relative to prefix)." FORCE)
' > "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
-# Suppress -isysroot if user-provided flags already have it.
-if echo "${cmake_c_flags}" | grep isysroot >/dev/null 2>&1 &&
- echo "${cmake_cxx_flags}" | grep isysroot >/dev/null 2>&1; then
- echo '
-set(CMAKE_OSX_SYSROOT "" CACHE PATH "" FORCE)
-' >> "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
-fi
-
# Add configuration settings given as command-line options.
if [ "x${cmake_bootstrap_qt_gui}" != "x" ]; then
echo '