From 7d36a275870c0f13175bff792bc241216dade2e2 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 7 Nov 2015 15:26:21 +0100 Subject: Merging upstream version 1.2. Signed-off-by: Daniel Baumann --- ChangeLog | 13 ++++++--- INSTALL | 4 +-- Makefile.in | 10 +++---- NEWS | 16 ++--------- README | 10 +++---- configure | 14 +++++----- doc/pdlzip.1 | 10 ++++--- main.c | 64 +++++++++++++++++++------------------------ pdlzip.h | 79 +++++++++++++++++++++++++++--------------------------- testsuite/check.sh | 16 ++++++++--- 10 files changed, 116 insertions(+), 120 deletions(-) diff --git a/ChangeLog b/ChangeLog index a489100..286b061 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-01-05 Antonio Diaz Diaz + + * Version 1.2 released. + * Code cleanup. Minor fixes. + 2010-08-19 Antonio Diaz Diaz * Version 1.1 released. @@ -6,7 +11,7 @@ reduced to extend range of use towards gzip. Lower numbers now compress less but faster. (-1 now takes 43% less time for only 20% larger compressed size). - * Code has been converted to "C89 + long long" from C99. + * Code has been converted to `C89 + long long' from C99. 2010-04-05 Antonio Diaz Diaz @@ -15,8 +20,8 @@ * Using LZMA SDK 9.10 (public domain) from Igor Pavlov. -Copyright (C) 2010 Antonio Diaz Diaz. +Copyright (C) 2010, 2011 Antonio Diaz Diaz. This file is a collection of facts, and thus it is not copyrightable, -but just in case, I give you unlimited permission to copy, distribute -and modify it. +but just in case, you have unlimited permission to copy, distribute and +modify it. diff --git a/INSTALL b/INSTALL index 6695e25..a9ca16e 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Requirements ------------ You will need a C compiler. -I use gcc 4.3.4 and 3.3.6, but the code should compile with any +I use gcc 4.3.5 and 3.3.6, but the code should compile with any standards compliant compiler. Gcc is available at http://gcc.gnu.org. @@ -50,7 +50,7 @@ After running `configure', you can run `make' and `make install' as explained above. -Copyright (C) 2010 Antonio Diaz Diaz. +Copyright (C) 2010, 2011 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. diff --git a/Makefile.in b/Makefile.in index 724badf..be09e82 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,10 +17,10 @@ objs = 7zFile.o 7zStream.o Alloc.o LzFind.o LzmaDec.o LzmaEnc.o \ all : $(progname) $(progname) : $(objs) - $(CC) $(LDFLAGS) -o $(progname) $(objs) + $(CC) $(LDFLAGS) -o $@ $^ $(progname)_profiled : $(objs) - $(CC) $(LDFLAGS) -pg -o $(progname)_profiled $(objs) + $(CC) $(LDFLAGS) -pg -o $@ $^ main.o : main.c $(CC) $(CPPFLAGS) $(CFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< @@ -49,14 +49,14 @@ $(VPATH)/doc/$(pkgname).info : $(VPATH)/doc/$(pkgname).texinfo man : $(VPATH)/doc/$(progname).1 $(VPATH)/doc/$(progname).1 : $(progname) - help2man -n 'data compressor based on the LZMA algorithm' \ - -o $(VPATH)/doc/$(progname).1 --no-info ./$(progname) + help2man -n 'reduces the size of files' \ + -o $@ --no-info ./$(progname) Makefile : $(VPATH)/configure $(VPATH)/Makefile.in ./config.status check : all - @$(VPATH)/testsuite/check.sh $(VPATH)/testsuite + @$(VPATH)/testsuite/check.sh $(VPATH)/testsuite $(pkgversion) install : all install-man if [ ! -d "$(DESTDIR)$(bindir)" ] ; then $(INSTALL_DIR) "$(DESTDIR)$(bindir)" ; fi diff --git a/NEWS b/NEWS index f6d4638..814471c 100644 --- a/NEWS +++ b/NEWS @@ -1,15 +1,3 @@ -Changes in version 1.1: +Changes in version 1.2: -Support for decompression of lzma-alone (.lzma) files has been added. - -Match length limit set by options -1 to -8 has been reduced to extend -range of use towards gzip. Lower numbers now compress less but faster. -(-1 now takes 43% less time for only 20% larger compressed size). - -(Note that the bidimensional parameter space of LZMA can't be mapped to -a linear scale optimal for all files. If your files are large, very -repetitive, etc, you may need to use the --match-length and ---dictionary-size options directly to achieve optimal performance). - -Code has been converted to "C89 + long long". A C99 compiler is no more -needed. +Code cleanup. Minor fixes. diff --git a/README b/README index 0b6427d..f3679e9 100644 --- a/README +++ b/README @@ -9,18 +9,18 @@ and data archiving. Pdlzip is also able to decompress legacy lzma-alone (.lzma) files. Pdlzip is a public domain version of the lzip data compressor, intended -for those who can't (or do not want) distribute GPL licensed Free -Software. Pdlzip is written in C. +for those who can't distribute GPL licensed Free Software. Pdlzip is +written in C. Pdlzip uses public domain compression code from the LZMA SDK written by Igor Pavlov. -Copyright (C) 2010 Antonio Diaz Diaz. +Copyright (C) 2010, 2011 Antonio Diaz Diaz. This file is free documentation: you have unlimited permission to copy, distribute and modify it. The file Makefile.in is a data file used by configure to produce the -Makefile. It has the same copyright owner and permissions that this -file. +Makefile. It has the same copyright owner and permissions that configure +itself. diff --git a/configure b/configure index 7d572f9..22353ed 100755 --- a/configure +++ b/configure @@ -1,16 +1,16 @@ #! /bin/sh -# configure script for Pdlzip - A data compressor based on the LZMA algorithm -# Copyright (C) 2010 Antonio Diaz Diaz. +# configure script for Pdlzip - Data compressor based on the LZMA algorithm +# Copyright (C) 2010, 2011 Antonio Diaz Diaz. # # This configure script is free software: you have unlimited permission # to copy, distribute and modify it. # -# Date of this version: 2010-08-19 +# Date of this version: 2011-01-05 args= no_create= pkgname=pdlzip -pkgversion=1.1 +pkgversion=1.2 progname=pdlzip srctrigger=pdlzip.h @@ -80,7 +80,7 @@ while [ -n "$1" ] ; do bindir=`echo ${optarg} | sed -e 's,/$,,'` ;; --datadir* | --da*) datadir=`echo ${optarg} | sed -e 's,/$,,'` ;; - --infodir* | --in*) + --infodir* | --inf*) infodir=`echo ${optarg} | sed -e 's,/$,,'` ;; --mandir* | --ma*) mandir=`echo ${optarg} | sed -e 's,/$,,'` ;; @@ -166,8 +166,8 @@ echo "CFLAGS = ${CFLAGS}" echo "LDFLAGS = ${LDFLAGS}" rm -f Makefile cat > Makefile << EOF -# Makefile for Pdlzip - A data compressor based on the LZMA algorithm -# Copyright (C) 2010 Antonio Diaz Diaz. +# Makefile for Pdlzip - Data compressor based on the LZMA algorithm +# Copyright (C) 2010, 2011 Antonio Diaz Diaz. # This file was generated automatically by configure. Do not edit. # # This Makefile is free software: you have unlimited permission diff --git a/doc/pdlzip.1 b/doc/pdlzip.1 index 4809683..22b298d 100644 --- a/doc/pdlzip.1 +++ b/doc/pdlzip.1 @@ -1,13 +1,13 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1. -.TH PDLZIP "1" "August 2010" "Pdlzip 1.1" "User Commands" +.TH PDLZIP "1" "January 2011" "Pdlzip 1.2" "User Commands" .SH NAME -Pdlzip \- data compressor based on the LZMA algorithm +Pdlzip \- reduces the size of files .SH SYNOPSIS .B pdlzip [\fIoptions\fR] [\fIfile\fR] .SH DESCRIPTION Pdlzip \- A "public domain" version of the lzip data compressor -able to decompress legacy lzma\-alone (.lzma) files. +also able to decompress legacy lzma\-alone (.lzma) files. .SH OPTIONS .TP \fB\-h\fR, \fB\-\-help\fR @@ -52,8 +52,10 @@ Numbers may be followed by a multiplier: k = kB = 10^3 = 1000, Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc... .SH "REPORTING BUGS" Report bugs to lzip\-bug@nongnu.org +.br +Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html .SH COPYRIGHT -Copyright \(co 2010 Antonio Diaz Diaz. +Copyright \(co 2011 Antonio Diaz Diaz. Public Domain 2009 Igor Pavlov. .br This is free software: you are free to change and redistribute it. diff --git a/main.c b/main.c index b5e35df..3a75453 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,6 @@ -/* Pdlzip - A data compressor based on the LZMA algorithm +/* Pdlzip - Data compressor based on the LZMA algorithm 2009-08-14 : Igor Pavlov : Public domain - Copyright (C) 2010 Antonio Diaz Diaz. + Copyright (C) 2010, 2011 Antonio Diaz Diaz. This program is free software: you have unlimited permission to copy, distribute and modify it. @@ -48,10 +48,10 @@ static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } static void SzFree(void *p, void *address) { p = p; MyFree(address); } static ISzAlloc g_Alloc = { SzAlloc, SzFree }; +const char * const Program_name = "Pdlzip"; +const char * const program_name = "pdlzip"; +const char * const program_year = "2011"; const char * invocation_name = 0; -const char * const Program_name = "Pdlzip"; -const char * const program_name = "pdlzip"; -const char * const program_year = "2010"; struct { const char * from; const char * to; } const known_extensions[] = { @@ -66,7 +66,7 @@ struct Lzma_options int match_len_limit; /* 5..273 */ }; -enum Mode { m_compress = 0, m_decompress, m_test }; +enum Mode { m_compress, m_decompress, m_test }; char * output_filename = 0; @@ -82,7 +82,7 @@ inline void * resize_buffer( void * buf, const int min_size ) static void show_help() { printf( "%s - A \"public domain\" version of the lzip data compressor\n", Program_name ); - printf( "able to decompress legacy lzma-alone (.lzma) files.\n" ); + printf( "also able to decompress legacy lzma-alone (.lzma) files.\n" ); printf( "\nUsage: %s [options] [file]\n", invocation_name ); printf( "\nOptions:\n" ); printf( " -h, --help display this help and exit\n" ); @@ -104,7 +104,7 @@ static void show_help() printf( "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" ); printf( "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" ); printf( "\nReport bugs to lzip-bug@nongnu.org\n" ); -/* printf( "Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html\n" ); */ + printf( "Pdlzip home page: http://www.nongnu.org/lzip/pdlzip.html\n" ); } @@ -118,34 +118,24 @@ static void show_version() } -static const char * format_num( long long num, long long limit, - const int set_prefix ) +static const char * format_num( long long num ) { - const char * const si_prefix[8] = - { "k", "M", "G", "T", "P", "E", "Z", "Y" }; - const char * const binary_prefix[8] = + const char * const prefix[8] = { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; - static bool si = false; - static char buf[16]; - - if( set_prefix ) si = ( set_prefix > 0 ); - { - const int factor = ( si ) ? 1000 : 1024; - const char * const *prefix = ( si ) ? si_prefix : binary_prefix; + enum { buf_size = 16, factor = 1024 }; + static char buf[buf_size]; const char *p = ""; int i; - limit = max( 999LL, min( 999999LL, limit ) ); - for( i = 0; i < 8 && ( llabs( num ) > limit || + for( i = 0; i < 8 && ( llabs( num ) > 9999 || ( llabs( num ) >= factor && num % factor == 0 ) ); ++i ) { num /= factor; p = prefix[i]; } - snprintf( buf, sizeof buf, "%lld %s", num, p ); - } + snprintf( buf, buf_size, "%lld %s", num, p ); return buf; } -static long long getnum( const char * const ptr, const int bs, +static long long getnum( const char * const ptr, const long long llimit, const long long ulimit ) { long long result; @@ -167,9 +157,6 @@ static long long getnum( const char * const ptr, const int bs, switch( tail[0] ) { case ' ': break; - case 'b': if( bs > 0 ) { factor = bs; exponent = 1; } - else bad_multiplier = true; - break; case 'Y': exponent = 8; break; case 'Z': exponent = 7; break; case 'E': exponent = 6; break; @@ -211,7 +198,7 @@ static int get_dict_size( const char * const arg ) if( bits >= min_dictionary_bits && bits <= max_dictionary_bits && *tail == 0 ) return ( 1 << bits ); - return getnum( arg, 0, min_dictionary_size, max_dictionary_size ); + return getnum( arg, min_dictionary_size, max_dictionary_size ); } @@ -297,7 +284,7 @@ static int lzma_Decode2( UInt64 unpackSize, CLzmaDec *state, { show_error( "Data error.", 0, false ); return 1; } if( verbosity >= 2 ) fprintf( stderr, "lzma-alone, dictionary size %7sB. ", - format_num( state->prop.dicSize, 9999, 0 ) ); + format_num( state->prop.dicSize ) ); if( verbosity >= 3 ) fprintf( stderr, "uncompressed size %9lld, compressed size %8lld. ", total_out, total_in ); @@ -365,7 +352,8 @@ static int Decode2( CLzmaDec *state, ISeqOutStream *outStream, error = true; if( verbosity >= 0 ) fprintf( stderr, "trailer truncated at trailer position %u;" - " some checks may fail.\n", (unsigned int)(*inSize - *inPos) ); + " some checks may fail.\n", + (unsigned int)(*inSize - *inPos) ); for( i = *inSize - *inPos; i < trailer_size; ++i ) inBuf[*inPos+i] = 0; } @@ -474,7 +462,7 @@ static int Decode( ISeqOutStream *outStream, ISeqInStream *inStream, if( verbosity >= 2 ) fprintf( stderr, "version %d, dictionary size %7sB. ", Fh_version( header ), - format_num( Fh_get_dictionary_size( header ), 9999, 0 ) ); + format_num( Fh_get_dictionary_size( header ) ) ); props[0] = 93; /* (45 * 2) + (9 * 0) + 3 */ ds = Fh_get_dictionary_size( header ); @@ -549,14 +537,16 @@ void show_error( const char * const msg, const int errcode, const bool help ) fprintf( stderr, "\n" ); } if( help && invocation_name && invocation_name[0] ) - fprintf( stderr, "Try `%s --help' for more information.\n", invocation_name ); + fprintf( stderr, "Try `%s --help' for more information.\n", + invocation_name ); } } void internal_error( const char * const msg ) { - fprintf( stderr, "%s: internal error: %s.\n", program_name, msg ); + if( verbosity >= 0 ) + fprintf( stderr, "%s: internal error: %s.\n", program_name, msg ); exit( 3 ); } @@ -618,7 +608,7 @@ int main( const int argc, const char * const argv[] ) to the corresponding LZMA compression modes. */ const struct Lzma_options option_mapping[] = { - { 1 << 16, 5 }, /* -0 */ + { 1 << 20, 5 }, /* -0 */ { 1 << 20, 5 }, /* -1 */ { 3 << 19, 6 }, /* -2 */ { 1 << 21, 8 }, /* -3 */ @@ -697,7 +687,7 @@ int main( const int argc, const char * const argv[] ) case 'h': show_help(); return 0; case 'k': keep_input_files = true; break; case 'm': encoder_options.match_len_limit = - getnum( arg, 0, min_match_len_limit, max_match_len ); break; + getnum( arg, min_match_len_limit, max_match_len ); break; case 'q': verbosity = -1; break; case 's': encoder_options.dictionary_size = get_dict_size( arg ); break; @@ -707,7 +697,7 @@ int main( const int argc, const char * const argv[] ) case 'V': show_version(); return 0; default : internal_error( "uncaught option" ); } - } + } /* end process options */ if( ap_arguments( &parser ) > argind && strcmp( ap_argument( &parser, argind ), "-" ) ) diff --git a/pdlzip.h b/pdlzip.h index 077ea9b..a54ef76 100644 --- a/pdlzip.h +++ b/pdlzip.h @@ -1,5 +1,5 @@ -/* Pdlzip - A data compressor based on the LZMA algorithm - Copyright (C) 2010 Antonio Diaz Diaz. +/* Pdlzip - Data compressor based on the LZMA algorithm + Copyright (C) 2010, 2011 Antonio Diaz Diaz. This program is free software: you have unlimited permission to copy, distribute and modify it. @@ -69,6 +69,15 @@ static inline void CRC32_update_buf( uint32_t * crc, const uint8_t * const buffe } +static inline int real_bits( const int value ) + { + int bits = 0, i, mask; + for( i = 1, mask = 1; mask > 0; ++i, mask <<= 1 ) + if( value & mask ) bits = i; + return bits; + } + + static const uint8_t magic_string[4] = { 'L', 'Z', 'I', 'P' }; typedef uint8_t File_header[6]; /* 0-3 magic bytes */ @@ -76,52 +85,44 @@ typedef uint8_t File_header[6]; /* 0-3 magic bytes */ /* 5 coded_dict_size */ enum { Fh_size = 6 }; -static inline void Fh_set_magic( File_header header ) +static inline void Fh_set_magic( File_header data ) { - memcpy( header, magic_string, 4 ); - header[4] = 1; + memcpy( data, magic_string, 4 ); + data[4] = 1; } -static inline bool Fh_verify_magic( const File_header header ) +static inline bool Fh_verify_magic( const File_header data ) { - return ( memcmp( header, magic_string, 4 ) == 0 ); + return ( memcmp( data, magic_string, 4 ) == 0 ); } -static inline uint8_t Fh_version( const File_header header ) - { return header[4]; } +static inline uint8_t Fh_version( const File_header data ) + { return data[4]; } -static inline bool Fh_verify_version( const File_header header ) - { return ( header[4] <= 1 ); } - -static inline int Fh_real_bits( const int value ) - { - int bits = 0, i, mask; - for( i = 1, mask = 1; mask > 0; ++i, mask <<= 1 ) - if( value & mask ) bits = i; - return bits; - } +static inline bool Fh_verify_version( const File_header data ) + { return ( data[4] <= 1 ); } -static inline int Fh_get_dictionary_size( const File_header header ) +static inline int Fh_get_dictionary_size( const File_header data ) { - int sz = ( 1 << ( header[5] & 0x1F ) ); + int sz = ( 1 << ( data[5] & 0x1F ) ); if( sz > min_dictionary_size && sz <= max_dictionary_size ) - sz -= ( sz / 16 ) * ( ( header[5] >> 5 ) & 0x07 ); + sz -= ( sz / 16 ) * ( ( data[5] >> 5 ) & 0x07 ); return sz; } -static inline bool Fh_set_dictionary_size( File_header header, const int sz ) +static inline bool Fh_set_dictionary_size( File_header data, const int sz ) { if( sz >= min_dictionary_size && sz <= max_dictionary_size ) { - header[5] = Fh_real_bits( sz - 1 ); + data[5] = real_bits( sz - 1 ); if( sz > min_dictionary_size ) { - const int base_size = 1 << header[5]; + const int base_size = 1 << data[5]; const int wedge = base_size / 16; int i; for( i = 7; i >= 1; --i ) if( base_size - ( i * wedge ) >= sz ) - { header[5] |= ( i << 5 ); break; } + { data[5] |= ( i << 5 ); break; } } return true; } @@ -139,51 +140,51 @@ enum { Ft_size = 20 }; static inline int Ft_versioned_size( const int version ) { return ( ( version >= 1 ) ? 20 : 12 ); } -static inline uint32_t Ft_get_data_crc( const File_trailer trailer ) +static inline uint32_t Ft_get_data_crc( const File_trailer data ) { uint32_t tmp = 0; int i; - for( i = 3; i >= 0; --i ) { tmp <<= 8; tmp += trailer[i]; } + for( i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Ft_set_data_crc( File_trailer trailer, uint32_t crc ) +static inline void Ft_set_data_crc( File_trailer data, uint32_t crc ) { int i; - for( i = 0; i <= 3; ++i ) { trailer[i] = (uint8_t)crc; crc >>= 8; } + for( i = 0; i <= 3; ++i ) { data[i] = (uint8_t)crc; crc >>= 8; } } -static inline long long Ft_get_data_size( const File_trailer trailer ) +static inline long long Ft_get_data_size( const File_trailer data ) { long long tmp = 0; int i; - for( i = 11; i >= 4; --i ) { tmp <<= 8; tmp += trailer[i]; } + for( i = 11; i >= 4; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Ft_set_data_size( File_trailer trailer, long long sz ) +static inline void Ft_set_data_size( File_trailer data, long long sz ) { int i; - for( i = 4; i <= 11; ++i ) { trailer[i] = (uint8_t)sz; sz >>= 8; } + for( i = 4; i <= 11; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } -static inline long long Ft_get_member_size( const File_trailer trailer ) +static inline long long Ft_get_member_size( const File_trailer data ) { long long tmp = 0; int i; - for( i = 19; i >= 12; --i ) { tmp <<= 8; tmp += trailer[i]; } + for( i = 19; i >= 12; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } -static inline void Ft_set_member_size( File_trailer trailer, long long sz ) +static inline void Ft_set_member_size( File_trailer data, long long sz ) { int i; - for( i = 12; i <= 19; ++i ) { trailer[i] = (uint8_t)sz; sz >>= 8; } + for( i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } +/* defined in main.c */ extern int verbosity; -void cleanup_and_fail( const int retval ); void show_error( const char * const msg, const int errcode, const bool help ); void internal_error( const char * const msg ); diff --git a/testsuite/check.sh b/testsuite/check.sh index c619507..635a404 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -1,6 +1,6 @@ #! /bin/sh -# check script for Pdlzip - A data compressor based on the LZMA algorithm -# Copyright (C) 2010 Antonio Diaz Diaz. +# check script for Pdlzip - Data compressor based on the LZMA algorithm +# Copyright (C) 2010, 2011 Antonio Diaz Diaz. # # This script is free software: you have unlimited permission # to copy, distribute and modify it. @@ -19,18 +19,23 @@ fi if [ -d tmp ] ; then rm -rf tmp ; fi mkdir tmp -printf "testing pdlzip..." +printf "testing pdlzip-%s..." "$2" cd "${objdir}"/tmp cat "${testdir}"/test.txt > in || framework_failure fail=0 "${LZIP}" -t "${testdir}"/test.lz || fail=1 +printf . "${LZIP}" -cd "${testdir}"/test.lz > copy || fail=1 cmp in copy || fail=1 +printf . + "${LZIP}" -t "${testdir}"/test.lzma || fail=1 +printf . "${LZIP}" -cd "${testdir}"/test.lzma > copy || fail=1 cmp in copy || fail=1 +printf . for i in s4Ki 0 1 2 3 4 5 6 7 8s16 9s16 ; do "${LZIP}" -k -$i in || fail=1 @@ -56,6 +61,11 @@ for i in s4Ki 0 1 2 3 4 5 6 7 8s16 9s16 ; do printf . done +"${LZIP}" -$i < in > anyothername || fail=1 +"${LZIP}" -dq anyothername || fail=1 +cmp in anyothername.out || fail=1 +printf . + echo if [ ${fail} = 0 ] ; then echo "tests completed successfully." -- cgit v1.2.3