From: <man...@us...> - 2014-09-23 07:11:58
|
Revision: 4303 http://sourceforge.net/p/modplug/code/4303 Author: manxorist Date: 2014-09-23 07:11:50 +0000 (Tue, 23 Sep 2014) Log Message: ----------- [Var] lhasa: Update to git commit ab4ae51c0b6eb3b291f9c54f4a7d2e6d883bdca4 (2014-07-12). This adds support for the "lhx" compression variant. Modified Paths: -------------- trunk/OpenMPT/build/gen/lhasa.vcproj trunk/OpenMPT/build/gen/lhasa.vcxproj trunk/OpenMPT/build/gen/lhasa.vcxproj.filters trunk/OpenMPT/include/lhasa/NEWS trunk/OpenMPT/include/lhasa/OpenMPT.txt trunk/OpenMPT/include/lhasa/TODO trunk/OpenMPT/include/lhasa/configure.ac trunk/OpenMPT/include/lhasa/lib/Makefile.am trunk/OpenMPT/include/lhasa/lib/lh_new_decoder.c trunk/OpenMPT/include/lhasa/lib/lha_arch.h trunk/OpenMPT/include/lhasa/lib/lha_arch_unix.c trunk/OpenMPT/include/lhasa/lib/lha_arch_win32.c trunk/OpenMPT/include/lhasa/lib/lha_decoder.c trunk/OpenMPT/include/lhasa/lib/lha_input_stream.c trunk/OpenMPT/include/lhasa/lib/pm1_decoder.c trunk/OpenMPT/include/lhasa/pkg/win32/GNUmakefile trunk/OpenMPT/include/lhasa/pkg/win32/README trunk/OpenMPT/include/lhasa/src/args.txt trunk/OpenMPT/include/lhasa/src/extract.c trunk/OpenMPT/include/lhasa/src/extract.h trunk/OpenMPT/include/lhasa/src/main.c trunk/OpenMPT/include/premake4.lua Added Paths: ----------- trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c Modified: trunk/OpenMPT/build/gen/lhasa.vcproj =================================================================== --- trunk/OpenMPT/build/gen/lhasa.vcproj 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/build/gen/lhasa.vcproj 2014-09-23 07:11:50 UTC (rev 4303) @@ -585,6 +585,10 @@ > </File> <File + RelativePath="..\..\include\lhasa\lib\lhx_decoder.c" + > + </File> + <File RelativePath="..\..\include\lhasa\lib\lz5_decoder.c" > </File> Modified: trunk/OpenMPT/build/gen/lhasa.vcxproj =================================================================== --- trunk/OpenMPT/build/gen/lhasa.vcxproj 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/build/gen/lhasa.vcxproj 2014-09-23 07:11:50 UTC (rev 4303) @@ -330,6 +330,8 @@ </ClCompile> <ClCompile Include="..\..\include\lhasa\lib\lha_reader.c"> </ClCompile> + <ClCompile Include="..\..\include\lhasa\lib\lhx_decoder.c"> + </ClCompile> <ClCompile Include="..\..\include\lhasa\lib\lz5_decoder.c"> </ClCompile> <ClCompile Include="..\..\include\lhasa\lib\lzs_decoder.c"> Modified: trunk/OpenMPT/build/gen/lhasa.vcxproj.filters =================================================================== --- trunk/OpenMPT/build/gen/lhasa.vcxproj.filters 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/build/gen/lhasa.vcxproj.filters 2014-09-23 07:11:50 UTC (rev 4303) @@ -2,16 +2,16 @@ <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="include"> - <UniqueIdentifier>{A6F4B617-6322-F44E-A3F2-588A54F34CE3}</UniqueIdentifier> + <UniqueIdentifier>{5347F1AC-E81E-434A-80CF-594FD46C8AEB}</UniqueIdentifier> </Filter> <Filter Include="include\lhasa"> - <UniqueIdentifier>{CFC29837-5222-D84F-9D05-846E8F3C7DA0}</UniqueIdentifier> + <UniqueIdentifier>{2AA988BF-BBA8-5B47-BB82-345545624965}</UniqueIdentifier> </Filter> <Filter Include="include\lhasa\lib"> - <UniqueIdentifier>{5AEAA659-17AE-2C48-805E-72AA72560879}</UniqueIdentifier> + <UniqueIdentifier>{DCDB0AF6-FE6D-244E-BADF-36BCF126672E}</UniqueIdentifier> </Filter> <Filter Include="include\lhasa\lib\public"> - <UniqueIdentifier>{FAABDB2D-4E8E-B34A-9D32-B4EA00080BA7}</UniqueIdentifier> + <UniqueIdentifier>{1EFC59C9-1EE9-6F41-880B-EEC67B9934E4}</UniqueIdentifier> </Filter> </ItemGroup> <ItemGroup> @@ -101,6 +101,9 @@ <ClCompile Include="..\..\include\lhasa\lib\lha_reader.c"> <Filter>include\lhasa\lib</Filter> </ClCompile> + <ClCompile Include="..\..\include\lhasa\lib\lhx_decoder.c"> + <Filter>include\lhasa\lib</Filter> + </ClCompile> <ClCompile Include="..\..\include\lhasa\lib\lz5_decoder.c"> <Filter>include\lhasa\lib</Filter> </ClCompile> Modified: trunk/OpenMPT/include/lhasa/NEWS =================================================================== --- trunk/OpenMPT/include/lhasa/NEWS 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/NEWS 2014-09-23 07:11:50 UTC (rev 4303) @@ -1,4 +1,16 @@ +v0.2.0 (2013-08-04): + * Decompression of archives using the -lhx- file format supported by + unlha32.dll is now supported (thanks Multi for the patch). + * The -p (print to stdout) command line option is now supported. + * The test suite should now run correctly on Windows. + + Bugs fixed: + * Bug where archives read from pipes (eg. stdin) were not extracted + beyond the first file in the archive. + * Output when using the -w (extract directory) option now correctly + matches the output of Unix lha. + v0.1.0 (2013-03-16): * There are now test archives for OS-9 and OS-9/68k (OSK) and a Modified: trunk/OpenMPT/include/lhasa/OpenMPT.txt =================================================================== --- trunk/OpenMPT/include/lhasa/OpenMPT.txt 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/OpenMPT.txt 2014-09-23 07:11:50 UTC (rev 4303) @@ -1,4 +1,5 @@ -lhasa LHA decompression library from https://github.com/fragglet/lhasa commit 13b44ac7859aad2f2b4fa76600c186f9f7f98c63 as of 2013-06-16. -No local changes made. +lhasa LHA decompression library from https://github.com/fragglet/lhasa commit ab4ae51c0b6eb3b291f9c54f4a7d2e6d883bdca4 as of 2014-07-12. +The test directory is not included in the OpenMPT repository. +No further local changes have been made. For building, premake4 is used to generate Visual Studio project files. See ../premake4.lua for details. Modified: trunk/OpenMPT/include/lhasa/TODO =================================================================== --- trunk/OpenMPT/include/lhasa/TODO 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/TODO 2014-09-23 07:11:50 UTC (rev 4303) @@ -12,7 +12,7 @@ * Decompressors for obscure algorithms: * -lh2-, -lh3- (experimental LHA?) * LHark -lh7- (modified -lh5-) - * -lx1-, -lhx- (unlha32 obscure/experimental?) + * -lx1- (unlha32 obscure/experimental?) Command line tool: * Create/update/modify archives. Modified: trunk/OpenMPT/include/lhasa/configure.ac =================================================================== --- trunk/OpenMPT/include/lhasa/configure.ac 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/configure.ac 2014-09-23 07:11:50 UTC (rev 4303) @@ -1,4 +1,4 @@ -AC_INIT(Lhasa, 0.1.0, fr...@gm..., lhasa) +AC_INIT(Lhasa, 0.2.0, fr...@gm..., lhasa) AC_CONFIG_AUX_DIR(autotools) AM_INIT_AUTOMAKE([no-define]) Modified: trunk/OpenMPT/include/lhasa/lib/Makefile.am =================================================================== --- trunk/OpenMPT/include/lhasa/lib/Makefile.am 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/Makefile.am 2014-09-23 07:11:50 UTC (rev 4303) @@ -26,6 +26,7 @@ lh5_decoder.c \ lh6_decoder.c \ lh7_decoder.c \ + lhx_decoder.c \ lz5_decoder.c \ lzs_decoder.c \ pm1_decoder.c \ Modified: trunk/OpenMPT/include/lhasa/lib/lh_new_decoder.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lh_new_decoder.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lh_new_decoder.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -60,7 +60,7 @@ // Number of possible codes in the "temporary table" used to encode the // codes table. -#define MAX_TEMP_CODES 19 +#define MAX_TEMP_CODES 20 typedef struct { // Input bit stream. Modified: trunk/OpenMPT/include/lhasa/lib/lha_arch.h =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_arch.h 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_arch.h 2014-09-23 07:11:50 UTC (rev 4303) @@ -144,15 +144,6 @@ LHAFileType lha_arch_exists(char *filename); /** - * Change to the specified directory. - * - * @param path Path to change to. - * @return Non-zero for success. - */ - -int lha_arch_chdir(char *path); - -/** * Create a symbolic link. * * If a file already exists at the location of the link to be created, it is Modified: trunk/OpenMPT/include/lhasa/lib/lha_arch_unix.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_arch_unix.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_arch_unix.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -163,11 +163,6 @@ } } -int lha_arch_chdir(char *path) -{ - return chdir(path) == 0; -} - int lha_arch_symlink(char *path, char *target) { unlink(path); Modified: trunk/OpenMPT/include/lhasa/lib/lha_arch_win32.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_arch_win32.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_arch_win32.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -194,11 +194,6 @@ return LHA_FILE_NONE; } -int lha_arch_chdir(char *path) -{ - return SetCurrentDirectoryA(path) != 0; -} - int lha_arch_symlink(char *path, char *target) { // No-op. Modified: trunk/OpenMPT/include/lhasa/lib/lha_decoder.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_decoder.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_decoder.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -38,6 +38,7 @@ extern LHADecoderType lha_lh5_decoder; extern LHADecoderType lha_lh6_decoder; extern LHADecoderType lha_lh7_decoder; +extern LHADecoderType lha_lhx_decoder; // PMarc compression algorithms: extern LHADecoderType lha_pm1_decoder; @@ -56,6 +57,7 @@ { "-lh5-", &lha_lh5_decoder }, { "-lh6-", &lha_lh6_decoder }, { "-lh7-", &lha_lh7_decoder }, + { "-lhx-", &lha_lhx_decoder }, { "-pm0-", &lha_null_decoder }, { "-pm1-", &lha_pm1_decoder }, { "-pm2-", &lha_pm2_decoder }, Modified: trunk/OpenMPT/include/lhasa/lib/lha_input_stream.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lha_input_stream.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/lha_input_stream.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -328,6 +328,16 @@ { int result; + // If this is an unseekable stream of some kind, always use the + // fallback behavior, as at least this is guaranteed to work. + // This is to work around problems on Windows, where fseek() can + // seek half-way on a stream and *then* fail, leaving us in an + // unworkable situation. + + if (ftell(handle) < 0) { + return file_source_skip_fallback(handle, bytes); + } + result = fseek(handle, (long) bytes, SEEK_CUR); if (result < 0) { Added: trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c (rev 0) +++ trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -0,0 +1,45 @@ +/* + +Copyright (c) 2011, 2012, 2013, Simon Howard + +Permission to use, copy, modify, and/or distribute this software +for any purpose with or without fee is hereby granted, provided +that the above copyright notice and this permission notice appear +in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + */ + +// +// Decoder for the -lhx- algorithm. Provided by Multi. +// +// -lhx- is Unlha32.dll's original extension. Some unique archivers +// support it. +// + +// 128 KiB history ring buffer: +// -lhx-'s maximum dictionary size is 2^19. 2x ring buffer is required. + +#define HISTORY_BITS 20 /* 2^20 = 1048576. */ + +// Number of bits to encode HISTORY_BITS: + +#define OFFSET_BITS 5 + +// Name of the variable for the encoder: + +#define DECODER_NAME lha_lhx_decoder + +// The actual algorithm code is contained in lh_new_decoder.c, which +// acts as a template for -lh4-, -lh5-, -lh6-, -lh7- and -lhx-. + +#include "lh_new_decoder.c" + Property changes on: trunk/OpenMPT/include/lhasa/lib/lhx_decoder.c ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/x-csrc \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Modified: trunk/OpenMPT/include/lhasa/lib/pm1_decoder.c =================================================================== --- trunk/OpenMPT/include/lhasa/lib/pm1_decoder.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/lib/pm1_decoder.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -73,6 +73,12 @@ // History linked list, for adaptively encoding byte values. HistoryLinkedList history_list; + + // Callback to read more compressed data from the input (see + // read_callback_wrapper below). + + LHADecoderCallback callback; + void *callback_data; } LHAPM1Decoder; // Table used to decode distance into history buffer to copy data. @@ -166,15 +172,42 @@ { 0x00 }, // -- special entry: 0, no tree }; +// Wrapper function invoked to read more data from the input. This mostly just +// calls the real function that does the read. However, when the end of file +// is reached, instead of returning zero, the buffer is filled with zero bytes +// instead. There seem to be archive files that actually depend on this +// ability to read "beyond" the length of the compressed data. + +static size_t read_callback_wrapper(void *buf, size_t buf_len, void *user_data) +{ + LHAPM1Decoder *decoder = user_data; + size_t result; + + result = decoder->callback(buf, buf_len, decoder->callback_data); + + if (result == 0) { + memset(buf, 0, buf_len); + result = buf_len; + } + + return result; +} + static int lha_pm1_init(void *data, LHADecoderCallback callback, - void *callback_data) + void *callback_data) { LHAPM1Decoder *decoder = data; memset(decoder, 0, sizeof(LHAPM1Decoder)); + // Unlike other decoders, the bitstream code must call the wrapper + // function above to read data. + + decoder->callback = callback; + decoder->callback_data = callback_data; + bit_stream_reader_init(&decoder->bit_stream_reader, - callback, callback_data); + read_callback_wrapper, decoder); decoder->output_stream_pos = 0; decoder->byte_decode_tree = NULL; @@ -663,10 +696,6 @@ command_type = read_bit(&decoder->bit_stream_reader); - if (command_type < 0) { - return 0; - } - if (command_type == 0) { return read_copy_command(decoder, buf); } else { Modified: trunk/OpenMPT/include/lhasa/pkg/win32/GNUmakefile =================================================================== --- trunk/OpenMPT/include/lhasa/pkg/win32/GNUmakefile 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/pkg/win32/GNUmakefile 2014-09-23 07:11:50 UTC (rev 4303) @@ -3,7 +3,7 @@ TOPLEVEL=../.. -EXE_FILES=$(TOPLEVEL)/src/.libs/lha.exe +EXE_FILES=$(TOPLEVEL)/src/lha.exe ZIP=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-win32.zip Modified: trunk/OpenMPT/include/lhasa/pkg/win32/README =================================================================== --- trunk/OpenMPT/include/lhasa/pkg/win32/README 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/pkg/win32/README 2014-09-23 07:11:50 UTC (rev 4303) @@ -2,3 +2,8 @@ Makefile to build Windows packages. Requires zip and unix2dos cygwin packages to be installed. +The configure script should be run with the right options to disable +shared libraries: + + ./configure --disable-shared --enable-static + Modified: trunk/OpenMPT/include/lhasa/src/args.txt =================================================================== --- trunk/OpenMPT/include/lhasa/src/args.txt 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/src/args.txt 2014-09-23 07:11:50 UTC (rev 4303) @@ -7,6 +7,7 @@ e/x - Extract l/v - List (normal / verbose mode) t - Test CRC + p - Print files to STDOUT Options - flags following the mode character. Options are accepted even if they are inappropriate for the mode, eg. "lha lf". @@ -23,6 +24,9 @@ in test mode, behavior is similar to extract mode, but level 2 behavior is similar to level 0. + in print mode, at quiet level 2 the filename is not + printed before the file contents. + all quiet modes imply 'f', disabling overwrite without confirmation. @@ -49,6 +53,9 @@ Also applies to test mode - the output filename of the tested file does not include the directory. + In print mode, the path is not printed in the header + before each file. + v - Verbose mode, prints extra information. in list mode, verbose mode splits the filename onto a Modified: trunk/OpenMPT/include/lhasa/src/extract.c =================================================================== --- trunk/OpenMPT/include/lhasa/src/extract.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/src/extract.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -53,6 +53,10 @@ len = 0; + if (options->extract_path != NULL) { + len += strlen(options->extract_path) + 1; + } + if (options->use_path && header->path != NULL) { len += strlen(header->path); } @@ -70,30 +74,38 @@ result[0] = '\0'; - if (options->use_path && header->path != NULL) { - strcat(result, header->path); + if (options->extract_path != NULL) { + strcat(result, options->extract_path); + strcat(result, "/"); } - if (header->filename != NULL) { - strcat(result, header->filename); + // Add path. If it is an absolute path (contains a leading '/') + // then skip over the leading '/' to make it a relative path. + // This prevents the possibility of a security threat with a + // malicious archive that might try to write to arbitrary + // filesystem locations. + // It also removes the double '/' when using the -w option. + + if (options->use_path && header->path != NULL) { + p = header->path; + while (*p == '/') { + ++p; + } + strcat(result, p); } - // If the header contains leading '/' characters, it is an - // absolute path (eg. /etc/passwd). Strip these leading - // characters to always generate a relative path, otherwise - // it can be a security risk - extracting an archive might - // overwrite arbitrary files on the filesystem. + // The filename header field might conceivably try to include + // a path separator as well, so skip over any leading '/' + // here too. - p = result; - - while (*p == '/') { - ++p; + if (header->filename != NULL) { + p = header->filename; + while (*p == '/') { + ++p; + } + strcat(result, p); } - if (p > result) { - memmove(result, p, strlen(p) + 1); - } - return result; } @@ -163,6 +175,14 @@ fflush(stdout); } +// Print a line to stdout describing a symlink. + +static void print_symlink_line(char *src, char *dest) +{ + safe_printf("Symbolic Link %s -> %s", src, dest); + printf("\n"); +} + // Perform CRC check of an archived file. static int test_archived_file_crc(LHAReader *reader, @@ -254,63 +274,58 @@ return 1; } -// Given a file header, create its parent directories as necessary. -// If include_final is zero, the final directory in the path is not -// created. +// Given a filename, create its parent directories as necessary. -static int make_parent_directories(char *orig_path, int include_final) +static int make_parent_directories(char *orig_path) { int result; char *p; char *path; - char saved = 0; result = 1; + + // Duplicate the path and strip off any trailing '/'s: + path = strdup(orig_path); + if (path == NULL) { + exit(-1); + } + + p = path + strlen(path) - 1; + + while (p >= path && *p == '/') { + *p = '\0'; + --p; + } + // Iterate through the string, finding each path separator. At // each place, temporarily chop off the end of the path to get // each parent directory in turn. - p = path; + for (p = path; *p == '/'; ++p); - do { + for (;;) { p = strchr(p, '/'); - // Terminate string after the path separator. - - if (p != NULL) { - saved = *(p + 1); - *(p + 1) = '\0'; + if (p == NULL) { + break; } - // Check if this parent directory exists and create it; - // however, don't create the final directory in the path - // if include_final is false. This is used for handling - // directories, where we should only create missing - // parent directories - not the directory itself. - // eg. for: - // - // -lhd- subdir/subdir2/ - // - // Only create subdir/ - subdir/subdir2/ is created - // by the call to lha_reader_extract. + *p = '\0'; - if (include_final || strcmp(orig_path, path) != 0) { - if (!check_parent_directory(path)) { - result = 0; - break; - } + // Check if this parent directory exists and create it: + + if (!check_parent_directory(path)) { + result = 0; + break; } - // Restore character that was after the path separator - // and advance to the next path. + // Restore path separator and advance to the next path. - if (p != NULL) { - *(p + 1) = saved; - ++p; - } - } while (p != NULL); + *p = '/'; + ++p; + } free(path); @@ -413,7 +428,6 @@ LHAOptions *options) { ProgressCallbackData progress; - char *path; char *filename; int success; int is_dir, is_symlink; @@ -423,30 +437,6 @@ is_dir = !strcmp(header->compress_method, LHA_COMPRESS_TYPE_DIR) && !is_symlink; - // Print appropriate message and stop if we are performing a dry run. - // The message if we have an existing file is weird, but this is just - // accurately duplicating what the Unix LHA tool says. - // The symlink handling is particularly odd - they are treated as - // directories (a bleed-through of the way in which symlinks are - // stored). - - if (options->dry_run) { - if (is_dir) { - safe_printf("EXTRACT %s (directory)", filename); - } else if (header->symlink_target != NULL) { - safe_printf("EXTRACT %s|%s (directory)", - filename, header->symlink_target); - } else if (file_exists(filename)) { - safe_printf("EXTRACT %s but file is exist.", filename); - } else { - safe_printf("EXTRACT %s", filename); - } - printf("\n"); - - free(filename); - return 1; - } - // If a file already exists with this name, confirm overwrite. if (!is_dir && !is_symlink && file_exists(filename) @@ -467,17 +457,9 @@ // Create parent directories for file: - if (options->use_path && header->path != NULL) { - path = header->path; - - while (path[0] == '/') { - ++path; - } - - if (*path != '\0' && !make_parent_directories(path, !is_dir)) { - free(filename); - return 0; - } + if (!make_parent_directories(filename)) { + free(filename); + return 0; } progress.invoked = 0; @@ -499,9 +481,7 @@ printf("\n"); } } else if (is_symlink) { - safe_printf("Symbolic Link %s -> %s", filename, - header->symlink_target); - printf("\n"); + print_symlink_line(filename, header->symlink_target); } fflush(stdout); @@ -541,29 +521,65 @@ return result; } -// lha -e / -x +// lha -en / -xn / -pn: +// Simulate extracting an archive file, but just print the operations +// that would have been performed to stdout. -int extract_archive(LHAFilter *filter, LHAOptions *options) +static int extract_archive_dry_run(LHAFilter *filter, LHAOptions *options) { + char *filename; int result; - // Change directory before extract? (-w option). + result = 1; - if (options->extract_path != NULL) { - if (!make_parent_directories(options->extract_path, 1)) { - fprintf(stderr, - "Failed to create extract directory: %s.\n", - options->extract_path); - exit(-1); + for (;;) { + LHAFileHeader *header; + + header = lha_filter_next_file(filter); + + if (header == NULL) { + break; } - if (!lha_arch_chdir(options->extract_path)) { - fprintf(stderr, "Failed to change directory to %s.\n", - options->extract_path); - exit(-1); + filename = file_full_path(header, options); + + // Every line begins the same - "EXTRACT filename..." + + safe_printf("EXTRACT %s", filename); + + // After the filename we might print something extra. + // The message if we have an existing file is weird, but this + // is just accurately duplicating what the Unix LHA tool says. + // The symlink handling is particularly odd - they are treated + // as directories (a bleed-through of the way in which + // symlinks are stored). + + if (header->symlink_target != NULL) { + safe_printf("|%s (directory)", header->symlink_target); + } else if (!strcmp(header->compress_method, + LHA_COMPRESS_TYPE_DIR)) { + safe_printf(" (directory)"); + } else if (file_exists(filename)) { + safe_printf(" but file is exist."); } + printf("\n"); + + free(filename); } + return result; +} + +// lha -e / -x + +int extract_archive(LHAFilter *filter, LHAOptions *options) +{ + int result; + + if (options->dry_run) { + return extract_archive_dry_run(filter, options); + } + result = 1; for (;;) { @@ -583,3 +599,78 @@ return result; } +// Dump contents of the current file from the specified reader to stdout. + +static int print_archived_file(LHAReader *reader) +{ + char buf[512]; + size_t bytes; + + for (;;) { + bytes = lha_reader_read(reader, buf, sizeof(buf)); + if (bytes <= 0) { + break; + } + + if (fwrite(buf, 1, bytes, stdout) < bytes) { + return 0; + } + } + + return 1; +} + +// lha -p + +int print_archive(LHAFilter *filter, LHAOptions *options) +{ + LHAFileHeader *header; + int is_normal_file; + char *full_path; + + // As a weird quirk of Unix LHA, lha -pn is equivalent to lha -en: + + if (options->dry_run) { + return extract_archive_dry_run(filter, options); + } + + for (;;) { + header = lha_filter_next_file(filter); + + if (header == NULL) { + break; + } + + is_normal_file = strcmp(header->compress_method, + LHA_COMPRESS_TYPE_DIR) != 0; + + // Print "header" before the file containing the filename. + // For normal files this is a three line separator. + // Symlinks get shown in the same way as during extract. + // Directories are ignored. + + if (options->quiet < 2) { + full_path = file_full_path(header, options); + + if (header->symlink_target != NULL) { + print_symlink_line(full_path, + header->symlink_target); + } else if (is_normal_file) { + printf("::::::::\n"); + safe_printf("%s", full_path); + printf("\n::::::::\n"); + } + + free(full_path); + } + + // If this is a normal file, dump the contents to stdout. + + if (is_normal_file && !print_archived_file(filter->reader)) { + return 0; + } + } + + return 1; +} + Modified: trunk/OpenMPT/include/lhasa/src/extract.h =================================================================== --- trunk/OpenMPT/include/lhasa/src/extract.h 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/src/extract.h 2014-09-23 07:11:50 UTC (rev 4303) @@ -26,6 +26,7 @@ int test_file_crc(LHAFilter *filter, LHAOptions *options); int extract_archive(LHAFilter *filter, LHAOptions *options); +int print_archive(LHAFilter *filter, LHAOptions *options); #endif /* #ifndef LHASA_EXTRACT_H */ Modified: trunk/OpenMPT/include/lhasa/src/main.c =================================================================== --- trunk/OpenMPT/include/lhasa/src/main.c 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/lhasa/src/main.c 2014-09-23 07:11:50 UTC (rev 4303) @@ -35,7 +35,8 @@ MODE_LIST, MODE_LIST_VERBOSE, MODE_CRC_CHECK, - MODE_EXTRACT + MODE_EXTRACT, + MODE_PRINT } ProgramMode; static void help_page(char *progname) @@ -44,13 +45,13 @@ PACKAGE_NAME " v" PACKAGE_VERSION " command line LHA tool " "- Copyright (C) 2011,2012 Simon Howard\n" "usage: %s [-]{lvtxe[q{num}][finv]}[w=<dir>] archive_file [file...]\n" - "commands: options:\n" - " l,v List / Verbose List f Force overwrite (no prompt)\n" - " t Test file CRC in archive i Ignore directory path\n" - " x,e Extract from archive n Perform dry run\n" - " q{num} Quiet mode\n" - " v Verbose\n" - " w=<dir> Specify extract directory\n" + "commands: options:\n" + " l,v List / Verbose List f Force overwrite (no prompt)\n" + " t Test file CRC in archive i Ignore directory path\n" + " x,e Extract from archive n Perform dry run\n" + " p Print to stdout from archive q{num} Quiet mode\n" + " v Verbose\n" + " w=<dir> Specify extract directory\n" , progname); exit(-1); @@ -101,6 +102,10 @@ result = extract_archive(&filter, options); break; + case MODE_PRINT: + result = print_archive(&filter, options); + break; + case MODE_UNKNOWN: break; } @@ -138,6 +143,8 @@ case 'e': case 'x': return MODE_EXTRACT; + case 'p': + return MODE_PRINT; default: return MODE_UNKNOWN; } Modified: trunk/OpenMPT/include/premake4.lua =================================================================== --- trunk/OpenMPT/include/premake4.lua 2014-09-23 06:13:10 UTC (rev 4302) +++ trunk/OpenMPT/include/premake4.lua 2014-09-23 07:11:50 UTC (rev 4303) @@ -249,6 +249,7 @@ "../include/lhasa/lib/lha_file_header.c", "../include/lhasa/lib/lha_input_stream.c", "../include/lhasa/lib/lha_reader.c", + "../include/lhasa/lib/lhx_decoder.c", "../include/lhasa/lib/lz5_decoder.c", "../include/lhasa/lib/lzs_decoder.c", "../include/lhasa/lib/macbinary.c", This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |