123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270 |
- diff -urdN busybox-1.29.1.old/archival/Config.src busybox-1.29.1.new/archival/Config.src
- --- busybox-1.29.1.old/archival/Config.src 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/archival/Config.src 2018-07-17 00:03:25.000000000 +0200
- @@ -21,6 +21,10 @@
- bool "Make tar, rpm, modprobe etc understand .gz data"
- default y
-
- +config FEATURE_SEAMLESS_LZ
- + bool "Make tar, rpm, modprobe etc understand .lz data"
- + default y
- +
- config FEATURE_SEAMLESS_Z
- bool "Make tar, rpm, modprobe etc understand .Z data"
- default n # it is ancient
- diff -urdN busybox-1.29.1.old/archival/bbunzip.c busybox-1.29.1.new/archival/bbunzip.c
- --- busybox-1.29.1.old/archival/bbunzip.c 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/archival/bbunzip.c 2018-07-19 12:53:03.000000000 +0200
- @@ -194,18 +194,31 @@
-
- #if ENABLE_UNCOMPRESS \
- || ENABLE_FEATURE_BZIP2_DECOMPRESS \
- + || ENABLE_FEATURE_LZIP_DECOMPRESS \
- || ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA \
- || ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ
- static
- char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext)
- {
- char *extension = strrchr(filename, '.');
- - if (!extension || strcmp(extension + 1, expected_ext) != 0) {
- +
- + if (!extension)
- + return NULL;
- +
- + if (strcmp(extension + 1, expected_ext) == 0) {
- + *extension = '\0';
- + } else if (extension[1] == 't' && strlen(expected_ext) >= 2 &&
- + strcmp(extension + 2, expected_ext) == 0) {
- + filename = xstrdup(filename);
- + extension = strrchr(filename, '.');
- + extension[2] = 'a';
- + extension[3] = 'r';
- + extension[4] = '\0';
- + } else {
- /* Mimic GNU gunzip - "real" bunzip2 tries to */
- /* unpack file anyway, to file.out */
- return NULL;
- }
- - *extension = '\0';
- return filename;
- }
- #endif
- @@ -449,6 +462,38 @@
- }
- #endif
-
- +
- +//config:config LUNZIP
- +//config: bool "lunzip"
- +//config: default y
- +//config: select FEATURE_LZIP_DECOMPRESS
- +//config: help
- +//config: lunzip is used to decompress archives created by lzip.
- +//config: You can use the '-t' option to test the integrity of
- +//config: an archive, without decompressing it.
- +
- +//applet:IF_LUNZIP(APPLET(lunzip, BB_DIR_USR_BIN, BB_SUID_DROP))
- +//kbuild:lib-$(CONFIG_LUNZIP) += bbunzip.o
- +
- +//usage:#define lunzip_trivial_usage
- +//usage: "[-cft] [FILE]..."
- +//usage:#define lunzip_full_usage "\n\n"
- +//usage: "Decompress FILEs (or stdin)\n"
- +//usage: "\n -c Write to stdout"
- +//usage: "\n -f Force"
- +//usage: "\n -k Keep input files"
- +//usage: "\n -t Test file integrity"
- +#if ENABLE_FEATURE_LZIP_DECOMPRESS
- +int lunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
- +int lunzip_main(int argc UNUSED_PARAM, char **argv)
- +{
- + getopt32(argv, BBUNPK_OPTSTR "dt");
- + argv += optind;
- +
- + return bbunpack(argv, unpack_lz_stream, make_new_name_generic, "lz");
- +}
- +#endif
- +
-
- /*
- * Small lzma deflate implementation.
- diff -urdN busybox-1.29.1.old/archival/dpkg.c busybox-1.29.1.new/archival/dpkg.c
- --- busybox-1.29.1.old/archival/dpkg.c 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/archival/dpkg.c 2018-07-17 00:03:25.000000000 +0200
- @@ -1482,6 +1482,9 @@
- #if ENABLE_FEATURE_SEAMLESS_XZ
- llist_add_to(&(ar_handle->accept), (char*)"control.tar.xz");
- #endif
- +#if ENABLE_FEATURE_SEAMLESS_LZ
- + llist_add_to(&(ar_handle->accept), (char*)"control.tar.lz");
- +#endif
-
- /* Assign the tar handle as a subarchive of the ar handle */
- ar_handle->dpkg__sub_archive = tar_handle;
- @@ -1509,6 +1512,9 @@
- #if ENABLE_FEATURE_SEAMLESS_XZ
- llist_add_to(&(ar_handle->accept), (char*)"data.tar.xz");
- #endif
- +#if ENABLE_FEATURE_SEAMLESS_LZ
- + llist_add_to(&(ar_handle->accept), (char*)"data.tar.lz");
- +#endif
-
- /* Assign the tar handle as a subarchive of the ar handle */
- ar_handle->dpkg__sub_archive = tar_handle;
- diff -urdN busybox-1.29.1.old/archival/dpkg_deb.c busybox-1.29.1.new/archival/dpkg_deb.c
- --- busybox-1.29.1.old/archival/dpkg_deb.c 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/archival/dpkg_deb.c 2018-07-17 00:03:25.000000000 +0200
- @@ -69,6 +69,10 @@
- llist_add_to(&ar_archive->accept, (char*)"data.tar.bz2");
- llist_add_to(&control_tar_llist, (char*)"control.tar.bz2");
- #endif
- +#if ENABLE_FEATURE_SEAMLESS_LZ
- + llist_add_to(&ar_archive->accept, (char*)"data.tar.lz");
- + llist_add_to(&control_tar_llist, (char*)"control.tar.lz");
- +#endif
- #if ENABLE_FEATURE_SEAMLESS_LZMA
- llist_add_to(&ar_archive->accept, (char*)"data.tar.lzma");
- llist_add_to(&control_tar_llist, (char*)"control.tar.lzma");
- diff -urdN busybox-1.29.1.old/archival/libarchive/Kbuild.src busybox-1.29.1.new/archival/libarchive/Kbuild.src
- --- busybox-1.29.1.old/archival/libarchive/Kbuild.src 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/archival/libarchive/Kbuild.src 2018-07-19 13:03:34.000000000 +0200
- @@ -37,6 +37,7 @@
- get_header_tar.o \
- get_header_tar_gz.o \
- get_header_tar_bz2.o \
- + get_header_tar_lz.o \
- get_header_tar_lzma.o \
- get_header_tar_xz.o \
-
- @@ -56,6 +57,8 @@
- # 'bzip2 -d', bunzip2 or bzcat selects FEATURE_BZIP2_DECOMPRESS
- lib-$(CONFIG_FEATURE_BZIP2_DECOMPRESS) += open_transformer.o decompress_bunzip2.o
- lib-$(CONFIG_FEATURE_UNZIP_BZIP2) += open_transformer.o decompress_bunzip2.o
- +# 'lzip -d' or lunzip select FEATURE_LZIP_DECOMPRESS
- +lib-$(CONFIG_FEATURE_LZIP_DECOMPRESS) += open_transformer.o decompress_lunzip.o
- lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o
- lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o
- lib-$(CONFIG_LZMA) += open_transformer.o decompress_unlzma.o
- @@ -72,6 +75,7 @@
- lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o
- lib-$(CONFIG_GZIP) += open_transformer.o
- lib-$(CONFIG_BZIP2) += open_transformer.o
- +lib-$(CONFIG_LZIP) += open_transformer.o
- lib-$(CONFIG_LZOP) += open_transformer.o
- lib-$(CONFIG_MAN) += open_transformer.o
- lib-$(CONFIG_SETFONT) += open_transformer.o
- @@ -87,6 +91,7 @@
- lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o
- lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_gunzip.o
- lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o
- +lib-$(CONFIG_FEATURE_SEAMLESS_LZ) += open_transformer.o decompress_lunzip.o
- lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o
- lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o
- lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o
- diff -urdN busybox-1.29.1.old/archival/libarchive/decompress_lunzip.c busybox-1.29.1.new/archival/libarchive/decompress_lunzip.c
- --- busybox-1.29.1.old/archival/libarchive/decompress_lunzip.c 1970-01-01 01:00:00.000000000 +0100
- +++ busybox-1.29.1.new/archival/libarchive/decompress_lunzip.c 2018-07-18 12:26:07.000000000 +0200
- @@ -0,0 +1,497 @@
- +/*
- + * lunzip implementation for busybox
- + *
- + * Copyright (C) 2012-2018 Antonio Diaz Diaz.
- + *
- + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- + */
- +
- +#include "libbb.h"
- +#include "bb_archive.h"
- +#include "lzip.h"
- +
- +/* Some functions have been marked with __always_inline because xz does
- + it, giving the impression that unxz is much faster than lunzip. */
- +#ifndef __always_inline
- +# ifdef __GNUC__
- +# define __always_inline \
- + inline __attribute__((__always_inline__))
- +# else
- +# define __always_inline inline
- +# endif
- +#endif
- +
- +
- +enum { rd_buffer_size = 16384 };
- +
- +struct Range_decoder {
- + unsigned long long partial_member_pos;
- + uint8_t *buffer; /* input buffer */
- + int pos; /* current pos in buffer */
- + int stream_pos; /* when reached, a new block must be read */
- + uint32_t code;
- + uint32_t range;
- + int infd; /* input file descriptor */
- + bool at_stream_end;
- +};
- +
- +
- +static bool Rd_read_block(struct Range_decoder * const rdec)
- +{
- + if (!rdec->at_stream_end) {
- + rdec->stream_pos =
- + full_read(rdec->infd, rdec->buffer, rd_buffer_size);
- + rdec->at_stream_end = (rdec->stream_pos < rd_buffer_size);
- + rdec->partial_member_pos += rdec->pos;
- + rdec->pos = 0;
- + }
- + return rdec->pos < rdec->stream_pos;
- +}
- +
- +
- +static bool Rd_init(struct Range_decoder * const rdec, const int ifd,
- + const bool magic_skipped)
- +{
- + rdec->partial_member_pos = (magic_skipped ? 4 : 0);
- + rdec->buffer = (uint8_t *) malloc(rd_buffer_size);
- + if (!rdec->buffer) return false;
- + rdec->pos = 0;
- + rdec->stream_pos = 0;
- + rdec->code = 0;
- + rdec->range = 0xFFFFFFFFU;
- + rdec->infd = ifd;
- + rdec->at_stream_end = false;
- + return true;
- +}
- +
- +static __always_inline bool Rd_finished(struct Range_decoder * const rdec)
- +{
- + return rdec->pos >= rdec->stream_pos && !Rd_read_block(rdec);
- +}
- +
- +static inline unsigned long long
- +Rd_member_position(const struct Range_decoder * const rdec)
- +{
- + return rdec->partial_member_pos + rdec->pos;
- +}
- +
- +static inline void Rd_reset_member_position(struct Range_decoder * const rdec)
- +{
- + rdec->partial_member_pos = 0; rdec->partial_member_pos -= rdec->pos;
- +}
- +
- +static __always_inline uint8_t Rd_get_byte(struct Range_decoder * const rdec)
- +{
- + /* 0xFF avoids decoder error if member is truncated at EOS marker */
- + if (Rd_finished(rdec)) return 0xFF;
- + return rdec->buffer[rdec->pos++];
- +}
- +
- +static void Rd_load(struct Range_decoder * const rdec)
- +{
- + int i;
- + rdec->code = 0;
- + for (i = 0; i < 5; ++i)
- + rdec->code = (rdec->code << 8) | Rd_get_byte(rdec);
- + rdec->range = 0xFFFFFFFFU;
- +}
- +
- +static __always_inline void Rd_normalize(struct Range_decoder * const rdec)
- +{
- + if (rdec->range <= 0x00FFFFFFU) {
- + rdec->range <<= 8;
- + rdec->code = (rdec->code << 8) | Rd_get_byte(rdec);
- + }
- +}
- +
- +static unsigned Rd_decode(struct Range_decoder * const rdec,
- + const int num_bits)
- +{
- + unsigned symbol = 0;
- + int i;
- + for (i = num_bits; i > 0; --i) {
- + bool bit;
- + Rd_normalize(rdec);
- + rdec->range >>= 1;
- + /* symbol <<= 1; */
- + /* if(rdec->code >= rdec->range) { rdec->code -= rdec->range; symbol |= 1; } */
- + bit = (rdec->code >= rdec->range);
- + symbol = (symbol << 1) + bit;
- + rdec->code -= rdec->range & (0U - bit);
- + }
- + return symbol;
- +}
- +
- +static __always_inline unsigned Rd_decode_bit(struct Range_decoder * const rdec,
- + Bit_model * const probability)
- +{
- + uint32_t bound;
- + Rd_normalize(rdec);
- + bound = (rdec->range >> bit_model_total_bits) * *probability;
- + if (rdec->code < bound) {
- + rdec->range = bound;
- + *probability += (bit_model_total - *probability) >> bit_model_move_bits;
- + return 0;
- + } else {
- + rdec->range -= bound;
- + rdec->code -= bound;
- + *probability -= *probability >> bit_model_move_bits;
- + return 1;
- + }
- +}
- +
- +static __always_inline unsigned Rd_decode_tree(struct Range_decoder * const rdec,
- + Bit_model bm[], const int num_bits)
- +{
- + unsigned symbol = 1;
- + int i;
- + for (i = num_bits; i > 0; --i)
- + symbol = (symbol << 1) | Rd_decode_bit(rdec, &bm[symbol]);
- + return symbol - (1 << num_bits);
- +}
- +
- +static __always_inline unsigned Rd_decode_tree_reversed(struct Range_decoder * const rdec,
- + Bit_model bm[], const int num_bits)
- +{
- + unsigned model = 1;
- + unsigned symbol = 0;
- + int i;
- + for (i = 0; i < num_bits; ++i) {
- + const unsigned bit = Rd_decode_bit(rdec, &bm[model]);
- + model = (model << 1) + bit;
- + symbol |= (bit << i);
- + }
- + return symbol;
- +}
- +
- +static unsigned Rd_decode_matched(struct Range_decoder * const rdec,
- + Bit_model bm[], unsigned match_byte)
- +{
- + unsigned symbol = 1;
- + unsigned mask = 0x100;
- + while(true) {
- + const unsigned match_bit = (match_byte <<= 1) & mask;
- + const unsigned bit = Rd_decode_bit(rdec, &bm[symbol+match_bit+mask]);
- + symbol = (symbol << 1) + bit;
- + if (symbol >= 0x100) return symbol & 0xFF;
- + mask &= ~(match_bit ^ (bit << 8)); /* if( match_bit != bit ) mask = 0; */
- + }
- +}
- +
- +static __always_inline unsigned Rd_decode_len(struct Range_decoder * const rdec,
- + struct Len_model * const lm,
- + const int pos_state)
- +{
- + if (Rd_decode_bit(rdec, &lm->choice1) == 0)
- + return Rd_decode_tree(rdec, lm->bm_low[pos_state], len_low_bits);
- + if (Rd_decode_bit(rdec, &lm->choice2) == 0)
- + return len_low_symbols +
- + Rd_decode_tree(rdec, lm->bm_mid[pos_state], len_mid_bits);
- + return len_low_symbols + len_mid_symbols +
- + Rd_decode_tree(rdec, lm->bm_high, len_high_bits);
- +}
- +
- +
- +struct LZ_decoder {
- + unsigned long long partial_data_pos;
- + struct Range_decoder *rdec;
- + unsigned dictionary_size;
- + uint8_t *buffer; /* output buffer */
- + unsigned pos; /* current pos in buffer */
- + unsigned stream_pos; /* first byte not yet written to file */
- + uint32_t crc;
- + int outfd; /* output file descriptor */
- + bool pos_wrapped;
- + bool write_error;
- +};
- +
- +static void LZd_flush_data(struct LZ_decoder * const d)
- +{
- + if (d->pos > d->stream_pos) {
- + const int size = d->pos - d->stream_pos;
- + d->crc = crc32_block_endian0(d->crc, d->buffer + d->stream_pos,
- + size, global_crc32_table);
- + if (d->outfd >= 0 && full_write(d->outfd,
- + d->buffer + d->stream_pos, size) != size)
- + d->write_error = true;
- + if (d->pos >= d->dictionary_size) {
- + d->partial_data_pos += d->pos;
- + d->pos = 0;
- + d->pos_wrapped = true;
- + }
- + d->stream_pos = d->pos;
- + }
- +}
- +
- +static __always_inline uint8_t LZd_peek_prev(const struct LZ_decoder * const d)
- +{
- + const unsigned i = ((d->pos > 0) ? d->pos : d->dictionary_size) - 1;
- + return d->buffer[i];
- +}
- +
- +static __always_inline uint8_t LZd_peek(const struct LZ_decoder * const d,
- + const unsigned distance)
- +{
- + unsigned i = d->pos - distance - 1;
- + if (d->pos <= distance) i += d->dictionary_size;
- + return d->buffer[i];
- +}
- +
- +static __always_inline void LZd_put_byte(struct LZ_decoder * const d,
- + const uint8_t b)
- +{
- + d->buffer[d->pos] = b;
- + if (++d->pos >= d->dictionary_size) LZd_flush_data(d);
- +}
- +
- +static void LZd_copy_block(struct LZ_decoder * const d,
- + const unsigned distance, unsigned len)
- +{
- + unsigned i = d->pos - distance - 1;
- + bool fast;
- + if (d->pos <= distance) {
- + i += d->dictionary_size;
- + fast = (len <= d->dictionary_size - i && len <= i - d->pos);
- + }
- + else
- + fast = (len < d->dictionary_size - d->pos && len <= d->pos - i);
- + if( fast ) { /* no wrap, no overlap */
- + memcpy(d->buffer + d->pos, d->buffer + i, len);
- + d->pos += len;
- + } else for (; len > 0; --len) {
- + d->buffer[d->pos] = d->buffer[i];
- + if (++d->pos >= d->dictionary_size) LZd_flush_data(d);
- + if (++i >= d->dictionary_size) i = 0;
- + }
- +}
- +
- +static bool LZd_init(struct LZ_decoder * const d,
- + struct Range_decoder * const rde,
- + const unsigned dict_size, const int ofd)
- +{
- + d->partial_data_pos = 0;
- + d->rdec = rde;
- + d->dictionary_size = dict_size;
- + d->buffer = (uint8_t *) malloc(d->dictionary_size);
- + if (!d->buffer) return false;
- + d->pos = 0;
- + d->stream_pos = 0;
- + d->crc = 0xFFFFFFFFU;
- + d->outfd = ofd;
- + d->pos_wrapped = false;
- + d->write_error = false;
- + d->buffer[d->dictionary_size - 1] = 0; /* prev_byte of first byte */
- + return true;
- +}
- +
- +static inline uint32_t LZd_crc(const struct LZ_decoder * const d)
- +{
- + return d->crc ^ 0xFFFFFFFFU;
- +}
- +
- +static __always_inline unsigned long long
- +LZd_data_position(const struct LZ_decoder * const d)
- +{
- + return d->partial_data_pos + d->pos;
- +}
- +
- +
- +static bool LZd_verify_trailer(struct LZ_decoder * const d)
- +{
- + Lzip_trailer trailer;
- + int i = 0;
- + while (i < Lt_size)
- + trailer[i++] = Rd_get_byte(d->rdec);
- +
- + return (Lt_get_data_crc(trailer) == LZd_crc(d) &&
- + Lt_get_data_size(trailer) == LZd_data_position(d) &&
- + Lt_get_member_size(trailer) == Rd_member_position(d->rdec));
- +}
- +
- +
- +/* Return value: -1 = write error, 0 = OK, 1 = data error. */
- +static int LZd_decode_member(struct LZ_decoder * const d)
- +{
- + struct Range_decoder * const rdec = d->rdec;
- + Bit_model bm_literal[1 << literal_context_bits][0x300];
- + Bit_model bm_match[states][pos_states];
- + Bit_model bm_rep[states];
- + Bit_model bm_rep0[states];
- + Bit_model bm_rep1[states];
- + Bit_model bm_rep2[states];
- + Bit_model bm_len[states][pos_states];
- + Bit_model bm_dis_slot[len_states][1 << dis_slot_bits];
- + Bit_model bm_dis[modeled_distances-end_dis_model+1];
- + Bit_model bm_align[dis_align_size];
- + struct Len_model match_len_model;
- + struct Len_model rep_len_model;
- + unsigned rep0 = 0; /* rep[0-3] latest four distances */
- + unsigned rep1 = 0; /* used for efficient coding of */
- + unsigned rep2 = 0; /* repeated distances */
- + unsigned rep3 = 0;
- + State state = 0;
- +
- + Bm_array_init(bm_literal[0], (1 << literal_context_bits) * 0x300);
- + Bm_array_init(bm_match[0], states * pos_states);
- + Bm_array_init(bm_rep, states);
- + Bm_array_init(bm_rep0, states);
- + Bm_array_init(bm_rep1, states);
- + Bm_array_init(bm_rep2, states);
- + Bm_array_init(bm_len[0], states * pos_states);
- + Bm_array_init(bm_dis_slot[0], len_states * (1 << dis_slot_bits));
- + Bm_array_init(bm_dis, modeled_distances - end_dis_model + 1);
- + Bm_array_init(bm_align, dis_align_size);
- + Lm_init(&match_len_model);
- + Lm_init(&rep_len_model);
- +
- + Rd_load(rdec);
- + while (!Rd_finished(rdec)) {
- + int len;
- + const int pos_state = LZd_data_position(d) & pos_state_mask;
- + if (Rd_decode_bit(rdec, &bm_match[state][pos_state]) == 0) {
- + /* literal byte */
- + Bit_model * const bm = bm_literal[get_lit_state(LZd_peek_prev(d))];
- + if (St_is_char(state)) {
- + state -= (state < 4) ? state : 3;
- + LZd_put_byte(d, Rd_decode_tree(rdec, bm, 8));
- + } else {
- + state -= (state < 10) ? 3 : 6;
- + LZd_put_byte(d, Rd_decode_matched(rdec, bm, LZd_peek(d, rep0)));
- + }
- + continue;
- + }
- + /* match or repeated match */
- + if (Rd_decode_bit(rdec, &bm_rep[state]) != 0) {
- + if (Rd_decode_bit(rdec, &bm_rep0[state]) == 0) {
- + if (Rd_decode_bit(rdec, &bm_len[state][pos_state]) == 0) {
- + state = St_set_short_rep(state);
- + LZd_put_byte(d, LZd_peek(d, rep0));
- + continue;
- + }
- + } else {
- + unsigned distance;
- + if (Rd_decode_bit(rdec, &bm_rep1[state]) == 0)
- + distance = rep1;
- + else {
- + if (Rd_decode_bit(rdec, &bm_rep2[state]) == 0)
- + distance = rep2;
- + else {
- + distance = rep3;
- + rep3 = rep2;
- + }
- + rep2 = rep1;
- + }
- + rep1 = rep0;
- + rep0 = distance;
- + }
- + state = St_set_rep(state);
- + len = min_match_len + Rd_decode_len(rdec, &rep_len_model, pos_state);
- + } else { /* match */
- + unsigned distance;
- + len = min_match_len + Rd_decode_len(rdec, &match_len_model, pos_state);
- + distance = Rd_decode_tree(rdec, bm_dis_slot[get_len_state(len)], 6);
- + if (distance >= start_dis_model) {
- + const unsigned dis_slot = distance;
- + const int direct_bits = (dis_slot >> 1) - 1;
- + distance = (2 | (dis_slot & 1)) << direct_bits;
- + if (dis_slot < end_dis_model)
- + distance += Rd_decode_tree_reversed(rdec,
- + bm_dis + (distance - dis_slot), direct_bits);
- + else {
- + distance +=
- + Rd_decode(rdec, direct_bits - dis_align_bits) << dis_align_bits;
- + distance += Rd_decode_tree_reversed(rdec, bm_align, dis_align_bits);
- + if (distance == 0xFFFFFFFFU) { /* marker found */
- + Rd_normalize(rdec);
- + LZd_flush_data(d);
- + if (d->write_error) return -1;
- + if (len == min_match_len && /* End Of Stream marker */
- + LZd_verify_trailer(d))
- + return 0;
- + if (len == min_match_len + 1) { /* Sync Flush marker */
- + Rd_load(rdec);
- + continue;
- + }
- + return 1;
- + }
- + }
- + }
- + rep3 = rep2; rep2 = rep1; rep1 = rep0; rep0 = distance;
- + state = St_set_match(state);
- + if (rep0 >= d->dictionary_size ||
- + (rep0 >= d->pos && !d->pos_wrapped)) {
- + LZd_flush_data(d);
- + return 1;
- + }
- + }
- + LZd_copy_block(d, rep0, len);
- + }
- + LZd_flush_data(d);
- + return 1;
- +}
- +
- +
- +IF_DESKTOP(long long) int FAST_FUNC
- +unpack_lz_stream(transformer_state_t *xstate)
- +{
- + IF_DESKTOP(long long) int total = 0;
- + struct Range_decoder rdec;
- + bool first_member;
- + const bool magic_skipped = (xstate->signature_skipped != 0);
- +
- + if (!global_crc32_table)
- + global_crc32_new_table_le();
- +
- + if (!Rd_init(&rdec, xstate->src_fd, magic_skipped))
- + return -1;
- +
- + for (first_member = true;; first_member = false) {
- + int tmp = 0;
- + Lzip_header header;
- + struct LZ_decoder decoder;
- +
- + if (first_member && magic_skipped) {
- + Lh_set_magic(header);
- + tmp = 4;
- + } else {
- + Rd_reset_member_position(&rdec);
- + }
- + while (tmp < Lh_size)
- + header[tmp++] = Rd_get_byte(&rdec);
- + if (Rd_finished(&rdec)) { /* End Of File */
- + if (first_member) {
- + bb_error_msg(bb_msg_read_error);
- + total = -1;
- + }
- + break;
- + }
- + tmp = Lh_get_dictionary_size(header);
- + if (!Lh_verify_magic(header) || tmp < min_dictionary_size ||
- + tmp > max_dictionary_size) {
- + if (!first_member)
- + break; /* trailing garbage */
- + bb_error_msg("invalid magic");
- + total = -1;
- + break;
- + }
- +
- + if (!LZd_init(&decoder, &rdec, tmp, xstate->dst_fd)) {
- + bb_error_msg(bb_msg_memory_exhausted);
- + total = -1;
- + break;
- + }
- + tmp = LZd_decode_member(&decoder);
- + IF_DESKTOP(total += Rd_member_position(&rdec);)
- + free(decoder.buffer);
- + if (tmp != 0) {
- + if (tmp < 0)
- + bb_perror_msg(bb_msg_write_error);
- + else
- + bb_error_msg("corrupted data");
- + total = -1;
- + break;
- + }
- + }
- + free(rdec.buffer);
- + return total;
- +}
- diff -urdN busybox-1.29.1.old/archival/libarchive/filter_accept_list_reassign.c busybox-1.29.1.new/archival/libarchive/filter_accept_list_reassign.c
- --- busybox-1.29.1.old/archival/libarchive/filter_accept_list_reassign.c 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/archival/libarchive/filter_accept_list_reassign.c 2018-07-17 00:03:25.000000000 +0200
- @@ -43,6 +43,12 @@
- archive_handle->dpkg__action_data_subarchive = get_header_tar_bz2;
- return EXIT_SUCCESS;
- }
- + if (ENABLE_FEATURE_SEAMLESS_LZ
- + && strcmp(name_ptr, "lz") == 0
- + ) {
- + archive_handle->dpkg__action_data_subarchive = get_header_tar_lz;
- + return EXIT_SUCCESS;
- + }
- if (ENABLE_FEATURE_SEAMLESS_LZMA
- && strcmp(name_ptr, "lzma") == 0
- ) {
- diff -urdN busybox-1.29.1.old/archival/libarchive/get_header_tar_lz.c busybox-1.29.1.new/archival/libarchive/get_header_tar_lz.c
- --- busybox-1.29.1.old/archival/libarchive/get_header_tar_lz.c 1970-01-01 01:00:00.000000000 +0100
- +++ busybox-1.29.1.new/archival/libarchive/get_header_tar_lz.c 2018-07-19 20:26:44.000000000 +0200
- @@ -0,0 +1,20 @@
- +/* vi: set sw=4 ts=4: */
- +/*
- + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- + */
- +#include "libbb.h"
- +#include "bb_archive.h"
- +
- +char FAST_FUNC get_header_tar_lz(archive_handle_t *archive_handle)
- +{
- + /* Can't lseek over pipes */
- + archive_handle->seek = seek_by_read;
- +
- + fork_transformer_with_sig(archive_handle->src_fd, unpack_lz_stream, "lunzip");
- + archive_handle->offset = 0;
- + while (get_header_tar(archive_handle) == EXIT_SUCCESS)
- + continue;
- +
- + /* Can only do one file at a time */
- + return EXIT_FAILURE;
- +}
- diff -urdN busybox-1.29.1.old/archival/libarchive/lzip.h busybox-1.29.1.new/archival/libarchive/lzip.h
- --- busybox-1.29.1.old/archival/libarchive/lzip.h 1970-01-01 01:00:00.000000000 +0100
- +++ busybox-1.29.1.new/archival/libarchive/lzip.h 2018-07-17 14:06:36.000000000 +0200
- @@ -0,0 +1,249 @@
- +/* Lzip - LZMA lossless data compressor
- + Copyright (C) 2008-2018 Antonio Diaz Diaz.
- +
- + This program is free software: you can redistribute it and/or modify
- + it under the terms of the GNU General Public License as published by
- + the Free Software Foundation, either version 2 of the License, or
- + (at your option) any later version.
- +
- + This program is distributed in the hope that it will be useful,
- + but WITHOUT ANY WARRANTY; without even the implied warranty of
- + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + GNU General Public License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with this program. If not, see <http://www.gnu.org/licenses/>.
- +*/
- +
- +typedef int State;
- +
- +enum { states = 12 };
- +
- +static inline bool St_is_char(const State st) { return st < 7; }
- +
- +static inline State St_set_char(const State st)
- +{
- + static const State next[states] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
- + return next[st];
- +}
- +
- +static inline State St_set_match(const State st)
- +{
- + return ((st < 7) ? 7 : 10);
- +}
- +
- +static inline State St_set_rep(const State st)
- +{
- + return ((st < 7) ? 8 : 11);
- +}
- +
- +static inline State St_set_short_rep(const State st)
- +{
- + return ((st < 7) ? 9 : 11);
- +}
- +
- +
- +enum {
- + min_dictionary_bits = 12,
- + min_dictionary_size = 1 << min_dictionary_bits, /* >= modeled_distances */
- + max_dictionary_bits = 29,
- + max_dictionary_size = 1 << max_dictionary_bits,
- + literal_context_bits = 3,
- + pos_state_bits = 2,
- + pos_states = 1 << pos_state_bits,
- + pos_state_mask = pos_states - 1,
- +
- + len_states = 4,
- + dis_slot_bits = 6,
- + start_dis_model = 4,
- + end_dis_model = 14,
- + modeled_distances = 1 << (end_dis_model / 2), /* 128 */
- + dis_align_bits = 4,
- + dis_align_size = 1 << dis_align_bits,
- +
- + len_low_bits = 3,
- + len_mid_bits = 3,
- + len_high_bits = 8,
- + len_low_symbols = 1 << len_low_bits,
- + len_mid_symbols = 1 << len_mid_bits,
- + len_high_symbols = 1 << len_high_bits,
- + max_len_symbols = len_low_symbols + len_mid_symbols + len_high_symbols,
- +
- + min_match_len = 2, /* must be 2 */
- + max_match_len = min_match_len + max_len_symbols - 1, /* 273 */
- + min_match_len_limit = 5,
- +
- + lz_num_models =
- + ((1 << literal_context_bits) * 0x300) +
- + (2 * states * pos_states) +
- + (4 * states) +
- + (len_states * (1 << dis_slot_bits)) +
- + (modeled_distances - end_dis_model + 1) +
- + dis_align_size,
- +};
- +
- +static inline int get_len_state(const int len)
- +{
- + return MIN(len - min_match_len, len_states - 1);
- +}
- +
- +static inline int get_lit_state(const uint8_t prev_byte)
- +{
- + return (prev_byte >> (8 - literal_context_bits));
- +}
- +
- +
- +enum { bit_model_move_bits = 5,
- + bit_model_total_bits = 11,
- + bit_model_total = 1 << bit_model_total_bits
- +};
- +
- +typedef int Bit_model;
- +
- +static inline void Bm_init(Bit_model * const probability)
- +{
- + *probability = bit_model_total / 2;
- +}
- +
- +static inline void Bm_array_init(Bit_model bm[], const int size)
- +{
- + int i;
- + for (i = 0; i < size; ++i)
- + Bm_init(&bm[i]);
- +}
- +
- +struct Len_model {
- + Bit_model choice1;
- + Bit_model choice2;
- + Bit_model bm_low[pos_states][len_low_symbols];
- + Bit_model bm_mid[pos_states][len_mid_symbols];
- + Bit_model bm_high[len_high_symbols];
- +};
- +
- +static inline void Lm_init(struct Len_model * const lm)
- +{
- + Bm_init(&lm->choice1);
- + Bm_init(&lm->choice2);
- + Bm_array_init(lm->bm_low[0], pos_states * len_low_symbols);
- + Bm_array_init(lm->bm_mid[0], pos_states * len_mid_symbols);
- + Bm_array_init(lm->bm_high, len_high_symbols);
- +}
- +
- +
- +static inline int real_bits(unsigned value)
- +{
- + int bits = 0;
- + while(value > 0) { value >>= 1; ++bits; }
- + return bits;
- +}
- +
- +
- +static const uint8_t lzip_magic[4] = { 0x4C, 0x5A, 0x49, 0x50 }; /* "LZIP" */
- +
- +typedef uint8_t Lzip_header[6]; /* 0-3 magic bytes */
- + /* 4 version */
- + /* 5 coded_dict_size */
- +enum { Lh_size = 6 };
- +
- +static inline void Lh_set_magic(Lzip_header data)
- +{
- + memcpy(data, lzip_magic, 4);
- + data[4] = 1;
- +}
- +
- +static inline bool Lh_verify_magic(const Lzip_header data)
- +{
- + return (memcmp(data, lzip_magic, 4) == 0 && data[4] == 1);
- +}
- +
- +static inline unsigned Lh_get_dictionary_size(const Lzip_header data)
- +{
- + unsigned sz = (1 << (data[5] & 0x1F));
- + if (sz > min_dictionary_size)
- + sz -= (sz / 16) * ((data[5] >> 5) & 7);
- + return sz;
- +}
- +
- +static inline bool Lh_set_dictionary_size(Lzip_header data, const unsigned sz)
- +{
- + if (sz < min_dictionary_size || sz > max_dictionary_size) return false;
- + data[5] = real_bits(sz - 1);
- + if (sz > min_dictionary_size) {
- + const unsigned base_size = 1 << data[5];
- + const unsigned fraction = base_size / 16;
- + unsigned i;
- + for (i = 7; i >= 1; --i)
- + if (base_size - (i * fraction) >= sz) {
- + data[5] |= (i << 5);
- + break;
- + }
- + }
- + return true;
- +}
- +
- +
- +typedef uint8_t Lzip_trailer[20];
- + /* 0-3 CRC32 of the uncompressed data */
- + /* 4-11 size of the uncompressed data */
- + /* 12-19 member size including header and trailer */
- +enum { Lt_size = 20 };
- +
- +static inline unsigned Lt_get_data_crc(const Lzip_trailer data)
- +{
- + unsigned tmp = 0;
- + int i;
- + for (i = 3; i >= 0; --i) {
- + tmp <<= 8;
- + tmp += data[i];
- + }
- + return tmp;
- +}
- +
- +static inline void Lt_set_data_crc(Lzip_trailer data, unsigned crc)
- +{
- + int i;
- + for (i = 0; i <= 3; ++i) {
- + data[i] = (uint8_t)crc;
- + crc >>= 8;
- + }
- +}
- +
- +static inline unsigned long long Lt_get_data_size(const Lzip_trailer data)
- +{
- + unsigned long long tmp = 0;
- + int i;
- + for (i = 11; i >= 4; --i) {
- + tmp <<= 8;
- + tmp += data[i];
- + }
- + return tmp;
- +}
- +
- +static inline void Lt_set_data_size(Lzip_trailer data, unsigned long long sz)
- +{
- + int i;
- + for (i = 4; i <= 11; ++i) {
- + data[i] = (uint8_t)sz;
- + sz >>= 8;
- + }
- +}
- +
- +static inline unsigned long long Lt_get_member_size(const Lzip_trailer data)
- +{
- + unsigned long long tmp = 0;
- + int i;
- + for (i = 19; i >= 12; --i) {
- + tmp <<= 8;
- + tmp += data[i];
- + }
- + return tmp;
- +}
- +
- +static inline void Lt_set_member_size(Lzip_trailer data, unsigned long long sz)
- +{
- + int i;
- + for (i = 12; i <= 19; ++i) {
- + data[i] = (uint8_t)sz;
- + sz >>= 8;
- + }
- +}
- diff -urdN busybox-1.29.1.old/archival/libarchive/open_transformer.c busybox-1.29.1.new/archival/libarchive/open_transformer.c
- --- busybox-1.29.1.old/archival/libarchive/open_transformer.c 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/archival/libarchive/open_transformer.c 2018-07-17 00:03:25.000000000 +0200
- @@ -194,6 +194,17 @@
- USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";)
- goto found_magic;
- }
- + if (ENABLE_FEATURE_SEAMLESS_LZ
- + && magic.b16[0] == LZIP_MAGIC1
- + ) {
- + xstate->signature_skipped = 4;
- + xread(fd, magic.b16, sizeof(magic.b16[0]));
- + if (magic.b16[0] == LZIP_MAGIC2) {
- + xstate->xformer = unpack_lz_stream;
- + USE_FOR_NOMMU(xstate->xformer_prog = "lunzip";)
- + goto found_magic;
- + }
- + }
- if (ENABLE_FEATURE_SEAMLESS_XZ
- && magic.b16[0] == XZ_MAGIC1
- ) {
- @@ -210,6 +221,7 @@
- if (fail_if_not_compressed)
- bb_error_msg_and_die("no gzip"
- IF_FEATURE_SEAMLESS_BZ2("/bzip2")
- + IF_FEATURE_SEAMLESS_LZ("/lzip")
- IF_FEATURE_SEAMLESS_XZ("/xz")
- " magic");
-
- diff -urdN busybox-1.29.1.old/archival/lzip.c busybox-1.29.1.new/archival/lzip.c
- --- busybox-1.29.1.old/archival/lzip.c 1970-01-01 01:00:00.000000000 +0100
- +++ busybox-1.29.1.new/archival/lzip.c 2018-07-20 16:23:47.000000000 +0200
- @@ -0,0 +1,1433 @@
- +/*
- + * lzip implementation for busybox
- + *
- + * Copyright (C) 2012-2018 Antonio Diaz Diaz.
- + *
- + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- + */
- +
- +//config:config LZIP
- +//config: bool "lzip"
- +//config: default y
- +//config: help
- +//config: lzip is a lossless data compressor with a user interface similar to
- +//config: the one of gzip or bzip2. lzip can compress about as fast as gzip or
- +//config: compress most files more than bzip2 (depending on compression level).
- +//config: Decompression speed is intermediate between gzip and bzip2. lzip is
- +//config: better than gzip and bzip2 from a data recovery perspective.
- +//config:
- +//config:config FEATURE_LZIP_DECOMPRESS
- +//config: bool "Enable decompression"
- +//config: default y
- +//config: depends on LZIP || LUNZIP
- +//config: help
- +//config: Enable -d (--decompress) and -t (--test) options for lzip.
- +//config: This will be automatically selected if lunzip is enabled.
- +
- +//applet:IF_LZIP(APPLET(lzip, BB_DIR_USR_BIN, BB_SUID_DROP))
- +
- +//kbuild:lib-$(CONFIG_LZIP) += lzip.o
- +
- +//usage:#define lzip_trivial_usage
- +//usage: "[-123456789c"
- +//usage: IF_FEATURE_LZIP_DECOMPRESS("d") "fk"
- +//usage: IF_FEATURE_LZIP_DECOMPRESS("t")
- +//usage: "] [-m MATCH_LENGTH] [-s DICT_SIZE] [FILE]..."
- +//usage:#define lzip_full_usage "\n\n"
- +//usage: "Compress FILEs (or stdin) with lzip algorithm\n"
- +//usage: "\n -1..9 Compression level"
- +//usage: "\n -c Write to stdout"
- +//usage: IF_FEATURE_LZIP_DECOMPRESS("\n -d Decompress")
- +//usage: "\n -f Force"
- +//usage: "\n -k Keep input files"
- +//usage: "\n -m Match length limit [36]"
- +//usage: "\n -s Dictionary size limit [8MiB]"
- +//usage: IF_FEATURE_LZIP_DECOMPRESS("\n -t Test compressed file integrity")
- +
- +
- +#include "libbb.h"
- +#include "bb_archive.h"
- +#include "libarchive/lzip.h"
- +
- +
- +#if CHAR_BIT != 8
- +#error "Environments where CHAR_BIT != 8 are not supported."
- +#endif
- +
- +
- +static void CRC32_update_byte(uint32_t * crc, const uint8_t byte)
- +{
- + *crc = global_crc32_table[(*crc ^ byte) & 0xFF] ^ (*crc >> 8);
- +}
- +
- +
- +enum { max_num_trials = 1 << 12,
- + price_shift_bits = 6,
- + price_step_bits = 2,
- + price_step = 1 << price_step_bits
- +};
- +
- +
- +static uint8_t * dis_slots;
- +
- +static void Dis_slots_init(void)
- +{
- + int i, size, slot;
- + dis_slots = xmalloc((1 << 10) * sizeof dis_slots[0]);
- +
- + for (slot = 0; slot < 4; ++slot) dis_slots[slot] = slot;
- + for (i = 4, size = 2, slot = 4; slot < 20; slot += 2) {
- + memset(&dis_slots[i], slot, size);
- + memset(&dis_slots[i + size], slot + 1, size);
- + size <<= 1;
- + i += size;
- + }
- +}
- +
- +static uint8_t get_slot(const unsigned dis)
- +{
- + if (dis < (1 << 10)) return dis_slots[dis];
- + if (dis < (1 << 19)) return dis_slots[dis>> 9] + 18;
- + if (dis < (1 << 28)) return dis_slots[dis>>18] + 36;
- + return dis_slots[dis>>27] + 54;
- +}
- +
- +
- +static int * prob_prices;
- +
- +static void Prob_prices_init(void)
- +{
- + int i, j;
- + prob_prices =
- + xmalloc((bit_model_total >> price_step_bits) * sizeof prob_prices[0]);
- + for( i = 0; i < bit_model_total >> price_step_bits; ++i ) {
- + unsigned val = ( i * price_step ) + ( price_step / 2 );
- + int bits = 0; /* base 2 logarithm of val */
- + for( j = 0; j < price_shift_bits; ++j ) {
- + val = val * val;
- + bits <<= 1;
- + while( val >= 1 << 16 ) { val >>= 1; ++bits; }
- + }
- + bits += 15; /* remaining bits in val */
- + prob_prices[i] = ( bit_model_total_bits << price_shift_bits ) - bits;
- + }
- +}
- +
- +static inline int get_price(const int probability)
- +{
- + return prob_prices[probability >> price_step_bits];
- +}
- +
- +
- +static inline int price0(const Bit_model probability)
- +{
- + return get_price(probability);
- +}
- +
- +static inline int price1(const Bit_model probability)
- +{
- + return get_price(bit_model_total - probability);
- +}
- +
- +static int price_bit(const Bit_model bm, const bool bit)
- +{
- + return (bit ? price1(bm) : price0(bm));
- +}
- +
- +
- +static int price_symbol(const Bit_model bm[], int symbol, const int num_bits)
- +{
- + int price = 0;
- + symbol |= (1 << num_bits);
- + while (symbol > 1) {
- + const bool bit = symbol & 1;
- + symbol >>= 1;
- + price += price_bit(bm[symbol], bit);
- + }
- + return price;
- +}
- +
- +
- +static int price_symbol_reversed(const Bit_model bm[], int symbol,
- + const int num_bits)
- +{
- + int price = 0;
- + int model = 1;
- + int i;
- + for (i = num_bits; i > 0; --i) {
- + const bool bit = symbol & 1;
- + symbol >>= 1;
- + price += price_bit(bm[model], bit);
- + model = (model << 1) | bit;
- + }
- + return price;
- +}
- +
- +
- +static int price_matched(const Bit_model bm[], unsigned symbol,
- + unsigned match_byte)
- +{
- + int price = 0;
- + unsigned mask = 0x100;
- + symbol |= mask;
- +
- + while (true) {
- + const unsigned match_bit = (match_byte <<= 1) & mask;
- + const bool bit = (symbol <<= 1) & 0x100;
- + price += price_bit( bm[(symbol>>9)+match_bit+mask], bit );
- + if (symbol >= 0x10000) return price;
- + mask &= ~(match_bit ^ symbol); /* if( match_bit != bit ) mask = 0; */
- + }
- +}
- +
- +
- +enum { /* bytes to keep in buffer before dictionary */
- + before_size = max_num_trials,
- + /* bytes to keep in buffer after pos */
- + after_size = ( 2 * max_match_len ) + 1,
- + num_prev_positions3 = 1 << 16,
- + num_prev_positions2 = 1 << 10,
- + num_prev_positions23 = num_prev_positions2 + num_prev_positions3
- +};
- +
- +struct Matchfinder {
- + unsigned long long partial_data_pos;
- + uint8_t *buffer; /* input buffer */
- + int32_t *prev_positions; /* 1 + last seen position of key. else 0 */
- + int32_t *pos_array; /* tree of previous positions of key */
- + int match_len_limit;
- + int buffer_size;
- + int dictionary_size; /* bytes to keep in buffer before pos */
- + int pos; /* current pos in buffer */
- + int cyclic_pos; /* current pos in dictionary */
- + int stream_pos; /* first byte not yet read from file */
- + int pos_limit; /* when reached, a new block must be read */
- + int key4_mask;
- + int num_prev_positions; /* size of prev_positions */
- + int pos_array_size;
- + int cycles;
- + bool at_stream_end; /* stream_pos shows real end of file */
- +};
- +
- +static bool Mf_read_block(struct Matchfinder * const mf)
- +{
- + if (!mf->at_stream_end && mf->stream_pos < mf->buffer_size) {
- + const int size = mf->buffer_size - mf->stream_pos;
- + const int rd = full_read(STDIN_FILENO,
- + mf->buffer + mf->stream_pos, size);
- + mf->stream_pos += rd;
- + if (rd < size) {
- + mf->at_stream_end = true;
- + mf->pos_limit = mf->buffer_size;
- + }
- + }
- + return mf->pos < mf->stream_pos;
- +}
- +
- +static void Mf_normalize_pos(struct Matchfinder * const mf)
- +{
- + int i;
- + const int offset = mf->pos - before_size - mf->dictionary_size;
- + const int size = mf->stream_pos - offset;
- + if (mf->at_stream_end) return;
- + memmove(mf->buffer, mf->buffer + offset, size);
- + mf->partial_data_pos += offset;
- + mf->pos -= offset; /* pos = before_size + dictionary_size */
- + mf->stream_pos -= offset;
- + for (i = 0; i < mf->num_prev_positions; ++i)
- + mf->prev_positions[i] -= MIN(mf->prev_positions[i], offset);
- + for (i = 0; i < mf->pos_array_size; ++i)
- + mf->pos_array[i] -= MIN(mf->pos_array[i], offset);
- + Mf_read_block(mf);
- +}
- +
- +static bool Mf_init(struct Matchfinder * const mf, const int dict_size,
- + const int match_len_limit)
- +{
- + const int buffer_size_limit = (2 * dict_size) + before_size + after_size;
- + unsigned size;
- + int i;
- +
- + mf->partial_data_pos = 0;
- + mf->match_len_limit = match_len_limit;
- + mf->pos = 0;
- + mf->cyclic_pos = 0;
- + mf->stream_pos = 0;
- + mf->cycles = (match_len_limit < max_match_len) ?
- + 16 + (match_len_limit / 2) : 256;
- + mf->at_stream_end = false;
- +
- + mf->buffer_size = MAX(65536, dict_size);
- + mf->buffer = (uint8_t *) malloc(mf->buffer_size);
- + if (!mf->buffer) return false;
- + if (Mf_read_block(mf) && !mf->at_stream_end &&
- + mf->buffer_size < buffer_size_limit) {
- + uint8_t *tmp;
- + mf->buffer_size = buffer_size_limit;
- + tmp = (uint8_t *) realloc(mf->buffer, mf->buffer_size);
- + if (!tmp) { free(mf->buffer); return false; }
- + mf->buffer = tmp;
- + Mf_read_block(mf);
- + }
- + if (mf->at_stream_end && mf->stream_pos < dict_size)
- + mf->dictionary_size = MAX(min_dictionary_size, mf->stream_pos);
- + else
- + mf->dictionary_size = dict_size;
- + mf->pos_limit = mf->buffer_size;
- + if (!mf->at_stream_end) mf->pos_limit -= after_size;
- + size = 1 << MAX(16, real_bits(mf->dictionary_size - 1) - 2);
- + if(mf->dictionary_size > 1 << 26) /* 64 MiB */
- + size >>= 1;
- + mf->key4_mask = size - 1;
- + size += num_prev_positions23;
- + mf->num_prev_positions = size;
- +
- + mf->pos_array_size = 2 * (mf->dictionary_size + 1);
- + size += mf->pos_array_size;
- + if (size * sizeof mf->prev_positions[0] <= size) mf->prev_positions = 0;
- + else mf->prev_positions =
- + (int32_t *) malloc(size * sizeof mf->prev_positions[0]);
- + if (!mf->prev_positions) { free(mf->buffer); return false; }
- + mf->pos_array = mf->prev_positions + mf->num_prev_positions;
- + for (i = 0; i < mf->num_prev_positions; ++i) mf->prev_positions[i] = 0;
- + return true;
- +}
- +
- +static void Mf_free(struct Matchfinder * const mf)
- +{
- + free(mf->prev_positions);
- + free(mf->buffer);
- +}
- +
- +static inline uint8_t Mf_peek(const struct Matchfinder * const mf,
- + const int distance)
- +{
- + return mf->buffer[mf->pos-distance];
- +}
- +
- +static inline int Mf_available_bytes(const struct Matchfinder * const mf)
- +{
- + return mf->stream_pos - mf->pos;
- +}
- +
- +static inline unsigned long long
- +Mf_data_position(const struct Matchfinder * const mf)
- +{
- + return mf->partial_data_pos + mf->pos;
- +}
- +
- +static inline bool Mf_finished(const struct Matchfinder * const mf)
- +{
- + return mf->at_stream_end && mf->pos >= mf->stream_pos;
- +}
- +
- +static inline const uint8_t *
- +Mf_ptr_to_current_pos(const struct Matchfinder * const mf)
- +{
- + return mf->buffer + mf->pos;
- +}
- +
- +static int Mf_true_match_len(const struct Matchfinder * const mf,
- + const int index, const int distance)
- +{
- + const uint8_t * const data = mf->buffer + mf->pos;
- + int i = index;
- + const int len_limit = MIN(Mf_available_bytes(mf), max_match_len);
- + while (i < len_limit && data[i - distance] == data[i]) ++i;
- + return i;
- +}
- +
- +static void Mf_move_pos(struct Matchfinder * const mf)
- +{
- + if (++mf->cyclic_pos > mf->dictionary_size) mf->cyclic_pos = 0;
- + if (++mf->pos >= mf->pos_limit) Mf_normalize_pos(mf);
- +}
- +
- +static int Mf_longest_match_len(struct Matchfinder * const mf,
- + int * const distances)
- +{
- + int32_t *ptr0 = mf->pos_array + (mf->cyclic_pos << 1);
- + int32_t *ptr1 = ptr0 + 1;
- + int32_t *newptr;
- + int len = 0, len0 = 0, len1 = 0;
- + int maxlen = min_match_len - 1;
- + const int pos1 = mf->pos + 1;
- + const int min_pos = (mf->pos > mf->dictionary_size) ?
- + mf->pos - mf->dictionary_size : 0;
- + const uint8_t * const data = Mf_ptr_to_current_pos(mf);
- + int count, key2, key3, key4, newpos1;
- + unsigned tmp;
- + int len_limit = mf->match_len_limit;
- +
- + if (len_limit > Mf_available_bytes(mf)) {
- + len_limit = Mf_available_bytes(mf);
- + if (len_limit < 4) return 0;
- + }
- +
- + tmp = global_crc32_table[data[0]] ^ data[1];
- + key2 = tmp & (num_prev_positions2 - 1);
- + tmp ^= ((unsigned) data[2] << 8);
- + key3 = num_prev_positions2 + (tmp & (num_prev_positions3 - 1));
- + key4 = num_prev_positions2 + num_prev_positions3 +
- + ((tmp ^ (global_crc32_table[data[3]] << 5)) & mf->key4_mask);
- +
- + if (distances) {
- + int np2 = mf->prev_positions[key2];
- + int np3 = mf->prev_positions[key3];
- + if (np2 > min_pos && mf->buffer[np2-1] == data[0]) {
- + distances[2] = mf->pos - np2;
- + maxlen = 2;
- + } else
- + distances[2] = 0x7FFFFFFF;
- + if (np2 != np3 && np3 > min_pos && mf->buffer[np3-1] == data[0]) {
- + distances[3] = mf->pos - np3;
- + maxlen = 3;
- + } else
- + distances[3] = 0x7FFFFFFF;
- + distances[4] = 0x7FFFFFFF;
- + }
- +
- + mf->prev_positions[key2] = pos1;
- + mf->prev_positions[key3] = pos1;
- + newpos1 = mf->prev_positions[key4];
- + mf->prev_positions[key4] = pos1;
- +
- + for (count = mf->cycles;;) {
- + int delta;
- + if (newpos1 <= min_pos || --count < 0) {
- + *ptr0 = *ptr1 = 0;
- + break;
- + }
- + delta = pos1 - newpos1;
- + newptr = mf->pos_array +
- + ((mf->cyclic_pos - delta +
- + ((mf->cyclic_pos >= delta) ? 0 : mf->dictionary_size + 1)) << 1);
- +
- + if (data[len-delta] == data[len]) {
- + while (++len < len_limit && data[len-delta] == data[len]) {}
- + if (distances && maxlen < len)
- + while (maxlen < len)
- + distances[++maxlen] = delta - 1;
- +
- + if (len >= len_limit) {
- + *ptr0 = newptr[0];
- + *ptr1 = newptr[1];
- + break;
- + }
- + }
- + if (data[len-delta] < data[len]) {
- + *ptr0 = newpos1;
- + ptr0 = newptr + 1;
- + newpos1 = *ptr0;
- + len0 = len;
- + if (len1 < len) len = len1;
- + } else {
- + *ptr1 = newpos1;
- + ptr1 = newptr;
- + newpos1 = *ptr1;
- + len1 = len;
- + if (len0 < len) len = len0;
- + }
- + }
- + if (distances) {
- + if (distances[3] > distances[4])
- + distances[3] = distances[4];
- + if (distances[2] > distances[3])
- + distances[2] = distances[3];
- + }
- + return maxlen;
- +}
- +
- +
- +enum { re_buffer_size = 65536 };
- +
- +struct Range_encoder {
- + uint64_t low;
- + unsigned long long partial_member_pos;
- + uint8_t *buffer; /* output buffer */
- + int pos; /* current pos in buffer */
- + uint32_t range;
- + unsigned ff_count;
- + uint8_t cache;
- + bool write_error;
- +};
- +
- +static void Re_flush_data(struct Range_encoder * const renc)
- +{
- + if (renc->pos > 0) {
- + if (full_write(STDOUT_FILENO, renc->buffer, renc->pos) != renc->pos)
- + renc->write_error = true;
- + renc->partial_member_pos += renc->pos;
- + renc->pos = 0;
- + }
- +}
- +
- +static void Re_put_byte(struct Range_encoder * const renc, const uint8_t b)
- +{
- + renc->buffer[renc->pos] = b;
- + if (++renc->pos >= re_buffer_size) Re_flush_data(renc);
- +}
- +
- +static void Re_shift_low(struct Range_encoder * const renc)
- +{
- + if(renc->low >> 24 != 0xFF) {
- + const bool carry = (renc->low > 0xFFFFFFFFU);
- + Re_put_byte(renc, renc->cache + carry);
- + for (; renc->ff_count > 0; --renc->ff_count)
- + Re_put_byte(renc, 0xFF + carry);
- + renc->cache = renc->low >> 24;
- + } else
- + ++renc->ff_count;
- + renc->low = (renc->low & 0x00FFFFFFU) << 8;
- +}
- +
- +static bool Re_init(struct Range_encoder * const renc)
- +{
- + renc->low = 0;
- + renc->partial_member_pos = 0;
- + renc->buffer = (uint8_t *) malloc(re_buffer_size);
- + if (!renc->buffer) return false;
- + renc->pos = 0;
- + renc->range = 0xFFFFFFFFU;
- + renc->ff_count = 0;
- + renc->cache = 0;
- + renc->write_error = false;
- + return true;
- +}
- +
- +static inline void Re_free(struct Range_encoder * const renc)
- +{
- + free(renc->buffer);
- +}
- +
- +static inline unsigned long long
- +Re_member_position(const struct Range_encoder * const renc)
- +{
- + return renc->partial_member_pos + renc->pos + renc->ff_count;
- +}
- +
- +static void Re_flush(struct Range_encoder * const renc)
- +{
- + int i;
- + for (i = 0; i < 5; ++i) Re_shift_low(renc);
- +}
- +
- +static void Re_encode(struct Range_encoder * const renc,
- + const int symbol, const int num_bits)
- +{
- + unsigned mask;
- + for (mask = 1 << ( num_bits - 1 ); mask > 0; mask >>= 1) {
- + renc->range >>= 1;
- + if (symbol &mask) renc->low += renc->range;
- + if (renc->range <= 0x00FFFFFFU) {
- + renc->range <<= 8;
- + Re_shift_low(renc);
- + }
- + }
- +}
- +
- +static void Re_encode_bit(struct Range_encoder * const renc,
- + Bit_model * const probability, const bool bit)
- +{
- + const uint32_t bound = (renc->range >> bit_model_total_bits) * *probability;
- + if (!bit) {
- + renc->range = bound;
- + *probability += (bit_model_total - *probability) >> bit_model_move_bits;
- + } else {
- + renc->low += bound;
- + renc->range -= bound;
- + *probability -= *probability >> bit_model_move_bits;
- + }
- + if (renc->range <= 0x00FFFFFFU) {
- + renc->range <<= 8;
- + Re_shift_low(renc);
- + }
- +}
- +
- +static void Re_encode_tree(struct Range_encoder * const renc,
- + Bit_model bm[], const int symbol,
- + const int num_bits)
- +{
- + int model = 1;
- + int i;
- + for (i = num_bits - 1; i >= 0; --i) {
- + const bool bit = (symbol >> i) & 1;
- + Re_encode_bit(renc, &bm[model], bit);
- + model = (model << 1) | bit;
- + }
- +}
- +
- +static void Re_encode_tree_reversed(struct Range_encoder * const renc,
- + Bit_model bm[], int symbol, const int num_bits)
- +{
- + int model = 1;
- + int i;
- + for (i = num_bits; i > 0; --i) {
- + const bool bit = symbol & 1;
- + symbol >>= 1;
- + Re_encode_bit(renc, &bm[model], bit);
- + model = (model << 1) | bit;
- + }
- +}
- +
- +static void Re_encode_matched(struct Range_encoder * const renc,
- + Bit_model bm[], unsigned symbol,
- + unsigned match_byte)
- +{
- + unsigned mask = 0x100;
- + symbol |= mask;
- +
- + while (true) {
- + const unsigned match_bit = (match_byte <<= 1) & mask;
- + const bool bit = (symbol <<= 1) & 0x100;
- + Re_encode_bit( renc, &bm[(symbol>>9)+match_bit+mask], bit );
- + if (symbol >= 0x10000) break;
- + mask &= ~(match_bit ^ symbol); /* if( match_bit != bit ) mask = 0; */
- + }
- +}
- +
- +static void Re_encode_len( struct Range_encoder * const renc,
- + struct Len_model * const lm,
- + int symbol, const int pos_state )
- +{
- + bool bit = ( ( symbol -= min_match_len ) >= len_low_symbols );
- + Re_encode_bit( renc, &lm->choice1, bit );
- + if( !bit )
- + Re_encode_tree( renc, lm->bm_low[pos_state], symbol, len_low_bits );
- + else {
- + bit = ((symbol -= len_low_symbols) >= len_mid_symbols );
- + Re_encode_bit( renc, &lm->choice2, bit );
- + if( !bit )
- + Re_encode_tree( renc, lm->bm_mid[pos_state],
- + symbol, len_mid_bits );
- + else
- + Re_encode_tree( renc, lm->bm_high,
- + symbol - len_mid_symbols, len_high_bits );
- + }
- +}
- +
- +
- +struct Len_encoder {
- + struct Len_model lm;
- + int len_symbols;
- + int prices[pos_states][max_len_symbols];
- + int counters[pos_states];
- +};
- +
- +static void Lee_update_prices(struct Len_encoder * const le, const int pos_state)
- +{
- + int * const pps = le->prices[pos_state];
- + int tmp = price0(le->lm.choice1);
- + int len = 0;
- +
- + for (; len < len_low_symbols && len < le->len_symbols; ++len)
- + pps[len] = tmp +
- + price_symbol(le->lm.bm_low[pos_state], len, len_low_bits);
- + tmp = price1(le->lm.choice1);
- + for (; len < len_low_symbols + len_mid_symbols && len < le->len_symbols; ++len)
- + pps[len] = tmp + price0(le->lm.choice2) +
- + price_symbol(le->lm.bm_mid[pos_state],
- + len - len_low_symbols, len_mid_bits);
- + for (; len < le->len_symbols; ++len)
- + /* using 4 slots per value makes "Lee_price" faster */
- + le->prices[3][len] = le->prices[2][len] =
- + le->prices[1][len] = le->prices[0][len] =
- + tmp + price1(le->lm.choice2) +
- + price_symbol(le->lm.bm_high,
- + len - len_low_symbols - len_mid_symbols,
- + len_high_bits);
- + le->counters[pos_state] = le->len_symbols;
- +}
- +
- +static void Lee_init(struct Len_encoder * const le, const int len_limit)
- +{
- + int i;
- + Lm_init(&le->lm);
- + le->len_symbols = len_limit + 1 - min_match_len;
- + for (i = 0; i < pos_states; ++i) Lee_update_prices(le, i);
- +}
- +
- +static void Lee_encode(struct Len_encoder * const le,
- + struct Range_encoder * const renc,
- + int symbol, const int pos_state)
- +{
- + Re_encode_len(renc, &le->lm, symbol, pos_state);
- + if (--le->counters[pos_state] <= 0)
- + Lee_update_prices(le, pos_state);
- +}
- +
- +static int Lee_price(const struct Len_encoder * const le,
- + const int symbol, const int pos_state)
- +{
- + return le->prices[pos_state][symbol - min_match_len];
- +}
- +
- +
- +enum { infinite_price = 0x0FFFFFFF,
- + num_rep_distances = 4 /* must be 4 */
- +};
- +
- +struct Trial {
- + State state;
- + int price; /* dual use var; cumulative price, match length */
- + int dis; /* rep index or match distance. (-1 for literal) */
- + int prev_index; /* index of prev trial in trials[] */
- + int reps[num_rep_distances];
- +};
- +
- +static void Tr_update(struct Trial * const trial, const int pr,
- + const int distance, const int p_i)
- +{
- + if (pr < trial->price) {
- + trial->price = pr;
- + trial->dis = distance;
- + trial->prev_index = p_i;
- + }
- +}
- +
- +
- +struct LZ_encoder {
- + int longest_match_found;
- + uint32_t crc;
- +
- + Bit_model bm_literal[1 << literal_context_bits][0x300];
- + Bit_model bm_match[states][pos_states];
- + Bit_model bm_rep[states];
- + Bit_model bm_rep0[states];
- + Bit_model bm_rep1[states];
- + Bit_model bm_rep2[states];
- + Bit_model bm_len[states][pos_states];
- + Bit_model bm_dis_slot[len_states][1 << dis_slot_bits];
- + Bit_model bm_dis[modeled_distances-end_dis_model+1];
- + Bit_model bm_align[dis_align_size];
- +
- + struct Matchfinder *matchfinder;
- + struct Range_encoder renc;
- + struct Len_encoder match_len_encoder;
- + struct Len_encoder rep_len_encoder;
- +
- + int match_distances[max_match_len+1];
- + struct Trial trials[max_num_trials];
- +
- + int dis_slot_prices[len_states][2*max_dictionary_bits];
- + int dis_prices[len_states][modeled_distances];
- + int align_prices[dis_align_size];
- + int align_price_count;
- + int num_dis_slots;
- +};
- +
- +static void LZe_fill_align_prices(struct LZ_encoder * const e)
- +{
- + int i;
- + for (i = 0; i < dis_align_size; ++i)
- + e->align_prices[i] =
- + price_symbol_reversed(e->bm_align, i, dis_align_bits);
- + e->align_price_count = dis_align_size;
- +}
- +
- +static bool LZe_init(struct LZ_encoder * const e,
- + struct Matchfinder * const mf, const Lzip_header header)
- +{
- + int i;
- + e->longest_match_found = 0;
- + e->crc = 0xFFFFFFFFU;
- + Bm_array_init(&e->bm_literal[0][0], lz_num_models);
- + e->matchfinder = mf;
- + if (!Re_init(&e->renc)) return false;
- + Lee_init(&e->match_len_encoder, e->matchfinder->match_len_limit);
- + Lee_init(&e->rep_len_encoder, e->matchfinder->match_len_limit);
- + LZe_fill_align_prices(e);
- + e->num_dis_slots = 2 * real_bits(e->matchfinder->dictionary_size - 1);
- + e->trials[1].prev_index = 0;
- + for (i = 0; i < Lh_size; ++i)
- + Re_put_byte(&e->renc, header[i]);
- + return true;
- +}
- +
- +static inline void LZe_free(struct LZ_encoder * const e)
- +{
- + Re_free(&e->renc);
- +}
- +
- +static inline unsigned LZe_crc(const struct LZ_encoder * const e)
- +{
- + return e->crc ^ 0xFFFFFFFFU;
- +}
- +
- + /* move-to-front dis in/into reps; do nothing if( dis4 <= 0 ) */
- +static void mtf_reps(const int dis4, int reps[num_rep_distances])
- +{
- + if (dis4 >= num_rep_distances) { /* match */
- + reps[3] = reps[2]; reps[2] = reps[1]; reps[1] = reps[0];
- + reps[0] = dis4 - num_rep_distances;
- + } else if (dis4 > 0) { /* repeated match */
- + const int distance = reps[dis4];
- + int i; for (i = dis4; i > 0; --i)
- + reps[i] = reps[i - 1];
- + reps[0] = distance;
- + }
- +}
- +
- +static int LZe_price_shortrep(const struct LZ_encoder * const e,
- + const State state, const int pos_state)
- +{
- + return price0(e->bm_rep0[state]) + price0(e->bm_len[state][pos_state]);
- +}
- +
- +static int LZe_price_rep(const struct LZ_encoder * const e, const int rep,
- + const State state, const int pos_state)
- +{
- + int price;
- + if (rep == 0)
- + return price0(e->bm_rep0[state]) +
- + price1(e->bm_len[state][pos_state]);
- + price = price1(e->bm_rep0[state]);
- + if (rep == 1)
- + price += price0(e->bm_rep1[state]);
- + else {
- + price += price1(e->bm_rep1[state]);
- + price += price_bit(e->bm_rep2[state], rep - 2);
- + }
- + return price;
- +}
- +
- +static int LZe_price_dis(const struct LZ_encoder * const e,
- + const int dis, const int len_state)
- +{
- + if (dis < modeled_distances)
- + return e->dis_prices[len_state][dis];
- + else
- + return e->dis_slot_prices[len_state][get_slot(dis)] +
- + e->align_prices[dis & (dis_align_size - 1)];
- +}
- +
- +static int LZe_price_pair(const struct LZ_encoder * const e,
- + const int dis, const int len,
- + const int pos_state)
- +{
- + if (len <= min_match_len && dis >= modeled_distances)
- + return infinite_price;
- + return Lee_price(&e->match_len_encoder, len, pos_state) +
- + LZe_price_dis(e, dis, get_len_state(len));
- +}
- +
- +static int LZe_price_literal(const struct LZ_encoder * const e,
- + uint8_t prev_byte, uint8_t symbol)
- +{
- + return price_symbol(e->bm_literal[get_lit_state(prev_byte)], symbol, 8);
- +}
- +
- +static int LZe_price_matched(const struct LZ_encoder * const e,
- + uint8_t prev_byte, uint8_t symbol,
- + uint8_t match_byte)
- +{
- + return price_matched(e->bm_literal[get_lit_state(prev_byte)], symbol,
- + match_byte);
- +}
- +
- +static void LZe_encode_literal(struct LZ_encoder * const e,
- + uint8_t prev_byte, uint8_t symbol)
- +{
- + Re_encode_tree(&e->renc,
- + e->bm_literal[get_lit_state(prev_byte)], symbol, 8);
- +}
- +
- +static void LZe_encode_matched(struct LZ_encoder * const e,
- + uint8_t prev_byte, uint8_t symbol,
- + uint8_t match_byte)
- +{
- + Re_encode_matched(&e->renc, e->bm_literal[get_lit_state(prev_byte)],
- + symbol, match_byte);
- +}
- +
- +static void LZe_encode_pair(struct LZ_encoder * const e,
- + const unsigned dis, const int len,
- + const int pos_state)
- +{
- + const int dis_slot = get_slot(dis);
- + Lee_encode(&e->match_len_encoder, &e->renc, len, pos_state);
- + Re_encode_tree(&e->renc, e->bm_dis_slot[get_len_state(len)], dis_slot,
- + dis_slot_bits);
- +
- + if (dis_slot >= start_dis_model) {
- + const int direct_bits = (dis_slot >> 1) - 1;
- + const unsigned base = (2 | (dis_slot & 1)) << direct_bits;
- + const unsigned direct_dis = dis - base;
- +
- + if (dis_slot < end_dis_model)
- + Re_encode_tree_reversed(&e->renc,
- + e->bm_dis + (base - dis_slot),
- + direct_dis, direct_bits);
- + else {
- + Re_encode(&e->renc, direct_dis >> dis_align_bits,
- + direct_bits - dis_align_bits);
- + Re_encode_tree_reversed(&e->renc, e->bm_align,
- + direct_dis, dis_align_bits);
- + if (--e->align_price_count <= 0)
- + LZe_fill_align_prices(e);
- + }
- + }
- +}
- +
- +static int LZe_read_match_distances(struct LZ_encoder * const e)
- +{
- + int len = Mf_longest_match_len(e->matchfinder, e->match_distances);
- + if (len == e->matchfinder->match_len_limit && len < max_match_len)
- + len = Mf_true_match_len(e->matchfinder, len,
- + e->match_distances[len] + 1);
- + return len;
- +}
- +
- +static void LZe_move_pos(struct LZ_encoder * const e, int n)
- +{
- + while (true) {
- + Mf_move_pos(e->matchfinder);
- + if( --n <= 0 ) break;
- + Mf_longest_match_len(e->matchfinder, 0);
- + }
- +}
- +
- +static void LZe_backward(struct LZ_encoder * const e, int cur)
- +{
- + int * const dis = &e->trials[cur].dis;
- + while (cur > 0) {
- + const int prev_index = e->trials[cur].prev_index;
- + struct Trial * const prev_trial = &e->trials[prev_index];
- + prev_trial->price = cur - prev_index; /* len */
- + cur = *dis;
- + *dis = prev_trial->dis;
- + prev_trial->dis = cur;
- + cur = prev_index;
- + }
- +}
- +
- + /* End Of Stream mark => (dis == 0xFFFFFFFFU, len == min_match_len) */
- +static void LZe_full_flush(struct LZ_encoder * const e, const State state)
- +{
- + int i;
- + const int pos_state = Mf_data_position(e->matchfinder) & pos_state_mask;
- + Lzip_trailer trailer;
- + Re_encode_bit(&e->renc, &e->bm_match[state][pos_state], 1);
- + Re_encode_bit(&e->renc, &e->bm_rep[state], 0);
- + LZe_encode_pair(e, 0xFFFFFFFFU, min_match_len, pos_state);
- + Re_flush(&e->renc);
- + Lt_set_data_crc(trailer, LZe_crc(e));
- + Lt_set_data_size(trailer, Mf_data_position(e->matchfinder));
- + Lt_set_member_size(trailer, Re_member_position(&e->renc) + Lt_size);
- + for (i = 0; i < Lt_size; ++i)
- + Re_put_byte(&e->renc, trailer[i]);
- + Re_flush_data(&e->renc);
- +}
- +
- +
- +static void LZe_update_distance_prices(struct LZ_encoder * const e)
- +{
- + int dis, len_state;
- + for (dis = start_dis_model; dis < modeled_distances; ++dis) {
- + const int dis_slot = dis_slots[dis];
- + const int direct_bits = (dis_slot >> 1) - 1;
- + const int base = (2 | (dis_slot & 1)) << direct_bits;
- + const int price =
- + price_symbol_reversed(e->bm_dis + (base - dis_slot),
- + dis - base, direct_bits);
- + for (len_state = 0; len_state < len_states; ++len_state)
- + e->dis_prices[len_state][dis] = price;
- + }
- +
- + for (len_state = 0; len_state < len_states; ++len_state) {
- + int * const dsp = e->dis_slot_prices[len_state];
- + int * const dp = e->dis_prices[len_state];
- + const Bit_model * const bmds = e->bm_dis_slot[len_state];
- + int slot = 0;
- + for (; slot < end_dis_model; ++slot)
- + dsp[slot] = price_symbol(bmds, slot, dis_slot_bits);
- + for (; slot < e->num_dis_slots; ++slot)
- + dsp[slot] = price_symbol(bmds, slot, dis_slot_bits) +
- + ((((slot >> 1) - 1) - dis_align_bits) << price_shift_bits);
- +
- + for (dis = 0; dis < start_dis_model; ++dis)
- + dp[dis] = dsp[dis];
- + for (; dis < modeled_distances; ++dis)
- + dp[dis] += dsp[dis_slots[dis]];
- + }
- +}
- +
- +
- +/* Returns the number of bytes advanced (ahead).
- + trials[0]..trials[ahead-1] contain the steps to encode.
- + ( trials[0].dis == -1 && trials[0].price == 1 ) means literal.
- + A match/rep longer or equal than match_len_limit finishes the sequence.
- +*/
- +static int LZe_sequence_optimizer(struct LZ_encoder * const e,
- + const int reps[num_rep_distances],
- + const State state)
- +{
- + int main_len, i, rep, cur = 0, num_trials;
- + int replens[num_rep_distances];
- + int rep_index = 0;
- +
- + if (e->longest_match_found > 0) { /* from previous call */
- + main_len = e->longest_match_found;
- + e->longest_match_found = 0;
- + } else
- + main_len = LZe_read_match_distances(e);
- +
- + for (i = 0; i < num_rep_distances; ++i) {
- + replens[i] = Mf_true_match_len(e->matchfinder, 0, reps[i] + 1);
- + if (replens[i] > replens[rep_index]) rep_index = i;
- + }
- + if (replens[rep_index] >= e->matchfinder->match_len_limit) {
- + e->trials[0].dis = rep_index;
- + e->trials[0].price = replens[rep_index];
- + LZe_move_pos(e, replens[rep_index]);
- + return replens[rep_index];
- + }
- +
- + if (main_len >= e->matchfinder->match_len_limit) {
- + e->trials[0].dis =
- + e->match_distances[e->matchfinder->match_len_limit] +
- + num_rep_distances;
- + e->trials[0].price = main_len;
- + LZe_move_pos(e, main_len);
- + return main_len;
- + }
- +
- + {
- + const int pos_state = Mf_data_position(e->matchfinder) & pos_state_mask;
- + const int match_price = price1(e->bm_match[state][pos_state]);
- + const int rep_match_price = match_price + price1(e->bm_rep[state]);
- + const uint8_t prev_byte = Mf_peek(e->matchfinder, 1);
- + const uint8_t cur_byte = Mf_peek(e->matchfinder, 0);
- + const uint8_t match_byte = Mf_peek(e->matchfinder, reps[0] + 1);
- +
- + e->trials[1].price = price0(e->bm_match[state][pos_state]);
- + if (St_is_char(state))
- + e->trials[1].price +=
- + LZe_price_literal(e, prev_byte, cur_byte);
- + else
- + e->trials[1].price +=
- + LZe_price_matched(e, prev_byte, cur_byte, match_byte);
- + e->trials[1].dis = -1; /* literal */
- +
- + if (match_byte == cur_byte)
- + Tr_update(&e->trials[1], rep_match_price +
- + LZe_price_shortrep(e, state, pos_state), 0, 0);
- +
- + if (main_len < min_match_len) {
- + e->trials[0].dis = e->trials[1].dis;
- + e->trials[0].price = 1;
- + Mf_move_pos(e->matchfinder);
- + return 1;
- + }
- +
- + e->trials[0].state = state;
- + for (i = 0; i < num_rep_distances; ++i)
- + e->trials[0].reps[i] = reps[i];
- +
- + if (main_len <= replens[rep_index]) {
- + int len;
- +
- + main_len = replens[rep_index];
- + for (len = min_match_len; len <= main_len; ++len)
- + e->trials[len].price = infinite_price;
- + } else {
- + int len;
- + const int normal_match_price =
- + match_price + price0(e->bm_rep[state]);
- + for (len = min_match_len; len <= main_len; ++len) {
- + e->trials[len].dis =
- + e->match_distances[len] + num_rep_distances;
- + e->trials[len].prev_index = 0;
- + e->trials[len].price = normal_match_price +
- + LZe_price_pair(e, e->match_distances[len],
- + len, pos_state);
- + }
- + }
- +
- + for (rep = 0; rep < num_rep_distances; ++rep) {
- + const int price = rep_match_price +
- + LZe_price_rep(e, rep, state, pos_state);
- + int len;
- + for (len = min_match_len; len <= replens[rep]; ++len)
- + Tr_update(&e->trials[len], price +
- + Lee_price(&e->rep_len_encoder, len, pos_state),
- + rep, 0);
- + }
- + }
- +
- + num_trials = main_len;
- +
- + while (true) { /* price optimization loop */
- + struct Trial *cur_trial, *next_trial;
- + int newlen, pos_state, prev_index, len_limit;
- + int next_price, match_price, rep_match_price;
- + uint8_t prev_byte, cur_byte, match_byte;
- +
- + Mf_move_pos(e->matchfinder);
- + if (++cur >= num_trials) { /* no more initialized trials */
- + LZe_backward(e, cur);
- + return cur;
- + }
- + newlen = LZe_read_match_distances(e);
- + if (newlen >= e->matchfinder->match_len_limit) {
- + e->longest_match_found = newlen;
- + LZe_backward(e, cur);
- + return cur;
- + }
- +
- + /* give final values to current trial */
- + cur_trial = &e->trials[cur];
- + prev_index = cur_trial->prev_index;
- + cur_trial->state = e->trials[prev_index].state;
- +
- + for (i = 0; i < num_rep_distances; ++i)
- + cur_trial->reps[i] = e->trials[prev_index].reps[i];
- +
- + if (prev_index == cur - 1) {
- + if (cur_trial->dis == 0)
- + cur_trial->state = St_set_short_rep(cur_trial->state);
- + else
- + cur_trial->state = St_set_char(cur_trial->state);
- + } else {
- + if (cur_trial->dis < num_rep_distances)
- + cur_trial->state = St_set_rep(cur_trial->state);
- + else
- + cur_trial->state = St_set_match(cur_trial->state);
- + mtf_reps(cur_trial->dis, cur_trial->reps);
- + }
- +
- + pos_state = Mf_data_position(e->matchfinder) & pos_state_mask;
- + prev_byte = Mf_peek(e->matchfinder, 1);
- + cur_byte = Mf_peek(e->matchfinder, 0);
- + match_byte = Mf_peek(e->matchfinder, cur_trial->reps[0] + 1);
- +
- + next_price = cur_trial->price +
- + price0(e->bm_match[cur_trial->state][pos_state]);
- + if (St_is_char(cur_trial->state))
- + next_price += LZe_price_literal(e, prev_byte, cur_byte);
- + else
- + next_price += LZe_price_matched(e, prev_byte, cur_byte,
- + match_byte);
- + /* try last updates to next trial */
- + next_trial = &e->trials[cur + 1];
- +
- + Tr_update(next_trial, next_price, -1, cur); /* literal */
- +
- + match_price = cur_trial->price +
- + price1(e->bm_match[cur_trial->state][pos_state]);
- + rep_match_price = match_price + price1(e->bm_rep[cur_trial->state]);
- +
- + if (match_byte == cur_byte && next_trial->dis != 0)
- + Tr_update(next_trial, rep_match_price +
- + LZe_price_shortrep(e, cur_trial->state,
- + pos_state), 0, cur);
- +
- + len_limit = MIN(MIN(max_num_trials - 1 - cur,
- + Mf_available_bytes(e->matchfinder)),
- + e->matchfinder->match_len_limit);
- + if (len_limit < min_match_len) continue;
- +
- + for (rep = 0; rep < num_rep_distances; ++rep) {
- + const int dis = cur_trial->reps[rep] + 1;
- + int len = 0;
- + const uint8_t * const data =
- + Mf_ptr_to_current_pos(e->matchfinder);
- + while (len < len_limit && data[len] == data[len - dis])
- + ++len;
- + if (len >= min_match_len) {
- + const int price = rep_match_price +
- + LZe_price_rep(e, rep, cur_trial->state, pos_state);
- + while (num_trials < cur + len)
- + e->trials[++num_trials].price = infinite_price;
- + for (; len >= min_match_len; --len)
- + Tr_update(&e->trials[cur + len], price +
- + Lee_price(&e->rep_len_encoder, len,
- + pos_state), rep, cur);
- + }
- + }
- +
- + if (newlen <= len_limit &&
- + (newlen > min_match_len ||
- + (newlen == min_match_len &&
- + e->match_distances[min_match_len] < modeled_distances))) {
- + const int normal_match_price = match_price +
- + price0(e->bm_rep[cur_trial->state]);
- + int len;
- + int dis = e->match_distances[min_match_len];
- + int len_state = get_len_state(min_match_len);
- + int dis_price = infinite_price;
- +
- + while (num_trials < cur + newlen)
- + e->trials[++num_trials].price = infinite_price;
- +
- + if (dis < modeled_distances)
- + Tr_update(&e->trials[cur + min_match_len],
- + normal_match_price +
- + e->dis_prices[len_state][dis] +
- + Lee_price(&e->match_len_encoder,
- + min_match_len, pos_state),
- + dis + num_rep_distances, cur);
- +
- + for (len = min_match_len + 1; len <= newlen; ++len) {
- + if (dis != e->match_distances[len] ||
- + len_state < len_states - 1) {
- + dis = e->match_distances[len];
- + len_state = get_len_state(len);
- + dis_price = LZe_price_dis(e, dis, len_state);
- + }
- + Tr_update(&e->trials[cur + len],
- + normal_match_price + dis_price +
- + Lee_price(&e->match_len_encoder, len, pos_state),
- + dis + num_rep_distances, cur);
- + }
- + }
- + }
- +}
- +
- +
- +static bool LZe_encode_member(struct LZ_encoder * const e)
- +{
- + const int dis_price_count =
- + (e->matchfinder->match_len_limit > 12) ? 512 : 2048;
- + int dis_price_counter = 0;
- + int ahead, i;
- + int reps[num_rep_distances];
- + State state = 0;
- + for (i = 0; i < num_rep_distances; ++i) reps[i] = 0;
- +
- + if (!Mf_finished(e->matchfinder)) { /* encode first byte */
- + const uint8_t prev_byte = 0;
- + const uint8_t cur_byte = Mf_peek(e->matchfinder, 0);
- + Re_encode_bit(&e->renc, &e->bm_match[state][0], 0);
- + LZe_encode_literal(e, prev_byte, cur_byte);
- + CRC32_update_byte(&e->crc, cur_byte);
- + Mf_longest_match_len(e->matchfinder, 0);
- + Mf_move_pos(e->matchfinder);
- + }
- +
- + while (!Mf_finished(e->matchfinder)) {
- + if (dis_price_counter <= 0) {
- + LZe_update_distance_prices(e);
- + dis_price_counter = dis_price_count;
- + }
- +
- + ahead = LZe_sequence_optimizer(e, reps, state);
- + dis_price_counter -= ahead;
- +
- + for (i = 0; ahead > 0;) {
- + const int pos_state =
- + (Mf_data_position(e->matchfinder) - ahead) & pos_state_mask;
- + const int dis = e->trials[i].dis;
- + const int len = e->trials[i].price;
- +
- + bool bit = (dis < 0);
- + Re_encode_bit(&e->renc, &e->bm_match[state][pos_state], !bit);
- + if (bit) { /* literal byte */
- + const uint8_t prev_byte = Mf_peek(e->matchfinder, ahead + 1);
- + const uint8_t cur_byte = Mf_peek(e->matchfinder, ahead);
- + CRC32_update_byte(&e->crc, cur_byte);
- + if (St_is_char(state))
- + LZe_encode_literal(e, prev_byte, cur_byte);
- + else {
- + const uint8_t match_byte =
- + Mf_peek(e->matchfinder, ahead + reps[0] + 1);
- + LZe_encode_matched(e, prev_byte, cur_byte, match_byte);
- + }
- + state = St_set_char(state);
- + } else { /* match or repeated match */
- +
- + e->crc = crc32_block_endian0(e->crc,
- + Mf_ptr_to_current_pos(e->matchfinder) - ahead,
- + len, global_crc32_table);
- + mtf_reps(dis, reps);
- + bit = (dis < num_rep_distances);
- + Re_encode_bit(&e->renc, &e->bm_rep[state], bit);
- + if (bit) { /* repeated match */
- + bit = (dis == 0);
- + Re_encode_bit(&e->renc, &e->bm_rep0[state], !bit);
- + if (bit)
- + Re_encode_bit(&e->renc, &e->bm_len[state][pos_state], len > 1);
- + else {
- + Re_encode_bit(&e->renc, &e->bm_rep1[state], dis > 1);
- + if (dis > 1)
- + Re_encode_bit(&e->renc, &e->bm_rep2[state], dis > 2);
- + }
- + if (len == 1)
- + state = St_set_short_rep(state);
- + else {
- + Lee_encode(&e->rep_len_encoder,
- + &e->renc, len, pos_state);
- + state = St_set_rep(state);
- + }
- + } else { /* match */
- + LZe_encode_pair(e, dis - num_rep_distances, len, pos_state);
- + state = St_set_match(state);
- + }
- + }
- + ahead -= len;
- + i += len;
- + }
- + }
- + LZe_full_flush(e, state);
- + return !e->renc.write_error;
- +}
- +
- +
- +struct Lzma_options {
- + int dictionary_size; /* 4KiB..512MiB */
- + int match_len_limit; /* 5..273 */
- +} encoder_options;
- +
- +
- +static int getnum(const char * const ptr, const int llimit, const int ulimit)
- +{
- + long result;
- + char *tail;
- + errno = 0;
- + result = strtol(ptr, &tail, 0);
- + if (tail == ptr || errno)
- + goto error;
- + if (tail[0]) {
- + int factor = (tail[1] == 'i') ? 1024 : 1000;
- + int exponent = 0, i;
- +
- + switch (tail[0]) {
- + case 'M':
- + exponent = 2;
- + break;
- + case 'K':
- + if (factor == 1024) {
- + exponent = 1;
- + break;
- + }
- + goto error;
- + case 'k':
- + if (factor == 1000) {
- + exponent = 1;
- + break;
- + }
- + default:
- + goto error;
- + }
- + for (i = 0; i < exponent; ++i) {
- + if (LONG_MAX / factor >= labs(result))
- + result *= factor;
- + else
- + goto error;
- + }
- + }
- + if (result >= llimit && result <= ulimit)
- + return result;
- + error:
- + bb_error_msg_and_die("invalid number");
- +}
- +
- +
- +static int get_dict_size(const char * const arg)
- +{
- + char *tail;
- + long bits = strtol(arg, &tail, 0);
- + if (bits >= min_dictionary_bits &&
- + bits <= max_dictionary_bits && *tail == 0)
- + return (1 << bits);
- + return getnum(arg, min_dictionary_size, max_dictionary_size);
- +}
- +
- +
- +static IF_DESKTOP(long long) int FAST_FUNC pack_lzip(transformer_state_t *xstate UNUSED_PARAM)
- +{
- + int retval = 0;
- + Lzip_header header;
- + struct Matchfinder matchfinder;
- + struct LZ_encoder * encoder;
- +
- + Lh_set_magic(header);
- + if (!Lh_set_dictionary_size(header, encoder_options.dictionary_size) ||
- + encoder_options.match_len_limit < min_match_len_limit ||
- + encoder_options.match_len_limit > max_match_len)
- + bb_error_msg_and_die("internal error");
- +
- + if (!Mf_init(&matchfinder, Lh_get_dictionary_size(header),
- + encoder_options.match_len_limit)) {
- + bb_error_msg(bb_msg_memory_exhausted);
- + return -1;
- + }
- + Lh_set_dictionary_size(header, matchfinder.dictionary_size);
- +
- + encoder = malloc(sizeof(struct LZ_encoder));
- + if (!encoder || !LZe_init(encoder, &matchfinder, header)) {
- + bb_error_msg(bb_msg_memory_exhausted);
- + retval = -1;
- + } else {
- + if (!LZe_encode_member(encoder)) {
- + bb_perror_msg(bb_msg_write_error);
- + retval = -1;
- + }
- + LZe_free(encoder);
- + }
- + free(encoder);
- + Mf_free(&matchfinder);
- + return retval;
- +}
- +
- +
- +int lzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
- +#if ENABLE_FEATURE_LZIP_DECOMPRESS
- +int lzip_main(int argc, char **argv)
- +#else
- +int lzip_main(int argc UNUSED_PARAM, char **argv)
- +#endif
- +{
- + /* Mapping from gzip/bzip2 style 1..9 compression modes
- + to the corresponding LZMA compression modes. */
- + const struct Lzma_options option_mapping[] = {
- + {1 << 20, 5}, /* -0 */
- + {1 << 20, 5}, /* -1 */
- + {3 << 19, 6}, /* -2 */
- + {1 << 21, 8}, /* -3 */
- + {3 << 20, 12}, /* -4 */
- + {1 << 22, 20}, /* -5 */
- + {1 << 23, 36}, /* -6 */
- + {1 << 24, 68}, /* -7 */
- + {3 << 23, 132}, /* -8 */
- + {1 << 25, 273} /* -9 */
- + };
- + int i;
- + char *m_arg;
- + char *s_arg;
- + /* Must match BBUNPK_foo constants! */
- + unsigned opt = getopt32(argv, BBUNPK_OPTSTR IF_FEATURE_LZIP_DECOMPRESS("dt") "0123456789Fm:s:", &m_arg, &s_arg);
- +
- +#if ENABLE_FEATURE_LZIP_DECOMPRESS /* lunzip_main may not be visible... */
- + if (opt & (BBUNPK_OPT_DECOMPRESS|BBUNPK_OPT_TEST)) /* -d and/or -t */
- + return lunzip_main(argc, argv);
- +#endif
- + /* drop BBUNPK_OPTSTR "dt" bits */
- + opt >>= (BBUNPK_OPTSTRLEN IF_FEATURE_LZIP_DECOMPRESS(+ 2));
- +
- + encoder_options = option_mapping[6]; /* default = "-6" */
- +
- + for (i = 9; i >= 7; --i)
- + if (opt & (1 << i))
- + encoder_options = option_mapping[i];
- + for (i = 0; i <= 6; ++i)
- + if (opt & (1 << i))
- + encoder_options = option_mapping[i];
- + if (opt & (1 << 11)) /* -m */
- + encoder_options.match_len_limit =
- + getnum(m_arg, min_match_len_limit, max_match_len);
- + if (opt & (1 << 12)) /* -s */
- + encoder_options.dictionary_size = get_dict_size(s_arg);
- + /* end process options */
- + option_mask32 &= BBUNPK_OPTSTRMASK; /* retain only -cfkvq */
- +
- + /* Initialize the CRC32 table */
- + global_crc32_new_table_le();
- + if (!dis_slots) {
- + Dis_slots_init();
- + Prob_prices_init();
- + }
- +
- + argv += optind;
- + return bbunpack(argv, pack_lzip, append_ext, "lz");
- +}
- diff -urdN busybox-1.29.1.old/archival/tar.c busybox-1.29.1.new/archival/tar.c
- --- busybox-1.29.1.old/archival/tar.c 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/archival/tar.c 2018-07-17 00:03:25.000000000 +0200
- @@ -43,7 +43,7 @@
- //config:config FEATURE_TAR_AUTODETECT
- //config: bool "Autodetect compressed tarballs"
- //config: default y
- -//config: depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ)
- +//config: depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZ || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ)
- //config: help
- //config: With this option tar can automatically detect compressed
- //config: tarballs. Currently it works only on files (not pipes etc).
- @@ -756,6 +756,7 @@
- //usage: IF_FEATURE_SEAMLESS_GZ("z")
- //usage: IF_FEATURE_SEAMLESS_XZ("J")
- //usage: IF_FEATURE_SEAMLESS_BZ2("j")
- +//usage: IF_FEATURE_SEAMLESS_LZ("y")
- //usage: IF_FEATURE_SEAMLESS_LZMA("a")
- //usage: IF_FEATURE_TAR_CREATE("h")
- //usage: IF_FEATURE_TAR_NOPRESERVE_TIME("m")
- @@ -795,6 +796,9 @@
- //usage: IF_FEATURE_SEAMLESS_BZ2(
- //usage: "\n -j (De)compress using bzip2"
- //usage: )
- +//usage: IF_FEATURE_SEAMLESS_LZ(
- +//usage: "\n -y (De)compress using lzip"
- +//usage: )
- //usage: IF_FEATURE_SEAMLESS_LZMA(
- //usage: "\n -a (De)compress using lzma"
- //usage: )
- @@ -832,6 +836,7 @@
- IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,)
- IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,)
- IF_FEATURE_SEAMLESS_XZ( OPTBIT_XZ ,) // 16th bit
- + IF_FEATURE_SEAMLESS_LZ( OPTBIT_LZIP ,)
- IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,)
- IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
- #if ENABLE_FEATURE_TAR_LONG_OPTIONS
- @@ -859,6 +864,7 @@
- OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X
- OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z
- OPT_XZ = IF_FEATURE_SEAMLESS_XZ( (1 << OPTBIT_XZ )) + 0, // J
- + OPT_LZIP = IF_FEATURE_SEAMLESS_LZ( (1 << OPTBIT_LZIP )) + 0, // y
- OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z
- OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
- OPT_STRIP_COMPONENTS = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_STRIP_COMPONENTS)) + 0, // strip-components
- @@ -868,7 +874,7 @@
- OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
- OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite
-
- - OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_COMPRESS),
- + OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_LZIP | OPT_COMPRESS),
- };
- #if ENABLE_FEATURE_TAR_LONG_OPTIONS
- static const char tar_longopts[] ALIGN1 =
- @@ -901,6 +907,9 @@
- # if ENABLE_FEATURE_SEAMLESS_GZ
- "gzip\0" No_argument "z"
- # endif
- +# if ENABLE_FEATURE_SEAMLESS_LZ
- + "lzip\0" No_argument "y"
- +# endif
- # if ENABLE_FEATURE_SEAMLESS_XZ
- "xz\0" No_argument "J"
- # endif
- @@ -1003,6 +1012,7 @@
- IF_FEATURE_TAR_FROM( "T:*X:*")
- IF_FEATURE_SEAMLESS_GZ( "z" )
- IF_FEATURE_SEAMLESS_XZ( "J" )
- + IF_FEATURE_SEAMLESS_LZ( "y" )
- IF_FEATURE_SEAMLESS_Z( "Z" )
- IF_FEATURE_TAR_NOPRESERVE_TIME("m")
- IF_FEATURE_TAR_LONG_OPTIONS("\xf9:") // --strip-components
- @@ -1052,6 +1062,7 @@
- showopt(OPT_EXCLUDE_FROM );
- showopt(OPT_GZIP );
- showopt(OPT_XZ );
- + showopt(OPT_LZIP );
- showopt(OPT_COMPRESS );
- showopt(OPT_NOPRESERVE_TIME );
- showopt(OPT_STRIP_COMPONENTS);
- @@ -1184,6 +1195,8 @@
- zipMode = "gzip";
- if (opt & OPT_BZIP2)
- zipMode = "bzip2";
- + if (opt & OPT_LZIP)
- + zipMode = "lzip";
- if (opt & OPT_LZMA)
- zipMode = "lzma";
- if (opt & OPT_XZ)
- @@ -1220,6 +1233,10 @@
- USE_FOR_MMU(IF_FEATURE_SEAMLESS_BZ2(xformer = unpack_bz2_stream;))
- USE_FOR_NOMMU(xformer_prog = "bunzip2";)
- }
- + if (opt & OPT_LZIP) {
- + USE_FOR_MMU(IF_FEATURE_SEAMLESS_LZ(xformer = unpack_lz_stream;))
- + USE_FOR_NOMMU(xformer_prog = "lunzip";)
- + }
- if (opt & OPT_LZMA) {
- USE_FOR_MMU(IF_FEATURE_SEAMLESS_LZMA(xformer = unpack_lzma_stream;))
- USE_FOR_NOMMU(xformer_prog = "unlzma";)
- diff -urdN busybox-1.29.1.old/configs/TEST_nommu_defconfig busybox-1.29.1.new/configs/TEST_nommu_defconfig
- --- busybox-1.29.1.old/configs/TEST_nommu_defconfig 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/configs/TEST_nommu_defconfig 2018-07-17 00:03:25.000000000 +0200
- @@ -107,6 +107,7 @@
- CONFIG_FEATURE_SEAMLESS_LZMA=y
- CONFIG_FEATURE_SEAMLESS_BZ2=y
- CONFIG_FEATURE_SEAMLESS_GZ=y
- +CONFIG_FEATURE_SEAMLESS_LZ=y
- CONFIG_FEATURE_SEAMLESS_Z=y
- CONFIG_AR=y
- CONFIG_FEATURE_AR_LONG_FILENAMES=y
- @@ -120,6 +121,8 @@
- CONFIG_GUNZIP=y
- CONFIG_GZIP=y
- CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
- +CONFIG_LUNZIP=y
- +CONFIG_LZIP=y
- CONFIG_LZOP=y
- CONFIG_LZOP_COMPR_HIGH=y
- CONFIG_RPM2CPIO=y
- diff -urdN busybox-1.29.1.old/configs/TEST_noprintf_defconfig busybox-1.29.1.new/configs/TEST_noprintf_defconfig
- --- busybox-1.29.1.old/configs/TEST_noprintf_defconfig 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/configs/TEST_noprintf_defconfig 2018-07-17 00:03:25.000000000 +0200
- @@ -118,6 +118,7 @@
- CONFIG_FEATURE_SEAMLESS_LZMA=y
- CONFIG_FEATURE_SEAMLESS_BZ2=y
- CONFIG_FEATURE_SEAMLESS_GZ=y
- +CONFIG_FEATURE_SEAMLESS_LZ=y
- CONFIG_FEATURE_SEAMLESS_Z=y
- # CONFIG_AR is not set
- # CONFIG_FEATURE_AR_LONG_FILENAMES is not set
- @@ -132,6 +133,8 @@
- # CONFIG_GUNZIP is not set
- # CONFIG_GZIP is not set
- # CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
- +# CONFIG_LUNZIP is not set
- +# CONFIG_LZIP is not set
- # CONFIG_LZOP is not set
- # CONFIG_LZOP_COMPR_HIGH is not set
- # CONFIG_RPM2CPIO is not set
- diff -urdN busybox-1.29.1.old/configs/TEST_rh9_defconfig busybox-1.29.1.new/configs/TEST_rh9_defconfig
- --- busybox-1.29.1.old/configs/TEST_rh9_defconfig 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/configs/TEST_rh9_defconfig 2018-07-17 00:03:25.000000000 +0200
- @@ -116,6 +116,7 @@
- CONFIG_FEATURE_SEAMLESS_LZMA=y
- CONFIG_FEATURE_SEAMLESS_BZ2=y
- CONFIG_FEATURE_SEAMLESS_GZ=y
- +CONFIG_FEATURE_SEAMLESS_LZ=y
- CONFIG_FEATURE_SEAMLESS_Z=y
- CONFIG_AR=y
- CONFIG_FEATURE_AR_LONG_FILENAMES=y
- @@ -130,6 +131,8 @@
- CONFIG_GUNZIP=y
- CONFIG_GZIP=y
- CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
- +CONFIG_LUNZIP=y
- +CONFIG_LZIP=y
- CONFIG_LZOP=y
- # CONFIG_LZOP_COMPR_HIGH is not set
- CONFIG_RPM2CPIO=y
- diff -urdN busybox-1.29.1.old/configs/android2_defconfig busybox-1.29.1.new/configs/android2_defconfig
- --- busybox-1.29.1.old/configs/android2_defconfig 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/configs/android2_defconfig 2018-07-17 00:03:25.000000000 +0200
- @@ -121,6 +121,7 @@
- CONFIG_FEATURE_SEAMLESS_LZMA=y
- CONFIG_FEATURE_SEAMLESS_BZ2=y
- CONFIG_FEATURE_SEAMLESS_GZ=y
- +CONFIG_FEATURE_SEAMLESS_LZ=y
- CONFIG_FEATURE_SEAMLESS_Z=y
- CONFIG_AR=y
- CONFIG_FEATURE_AR_LONG_FILENAMES=y
- @@ -135,6 +136,8 @@
- CONFIG_GUNZIP=y
- CONFIG_GZIP=y
- # CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
- +CONFIG_LUNZIP=y
- +CONFIG_LZIP=y
- CONFIG_LZOP=y
- CONFIG_LZOP_COMPR_HIGH=y
- CONFIG_RPM2CPIO=y
- diff -urdN busybox-1.29.1.old/configs/android_defconfig busybox-1.29.1.new/configs/android_defconfig
- --- busybox-1.29.1.old/configs/android_defconfig 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/configs/android_defconfig 2018-07-17 00:03:25.000000000 +0200
- @@ -141,6 +141,7 @@
- CONFIG_FEATURE_SEAMLESS_LZMA=y
- CONFIG_FEATURE_SEAMLESS_BZ2=y
- CONFIG_FEATURE_SEAMLESS_GZ=y
- +CONFIG_FEATURE_SEAMLESS_LZ=y
- CONFIG_FEATURE_SEAMLESS_Z=y
- CONFIG_AR=y
- CONFIG_FEATURE_AR_LONG_FILENAMES=y
- @@ -156,6 +157,8 @@
- CONFIG_GZIP=y
- # CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
- CONFIG_GZIP_FAST=0
- +CONFIG_LUNZIP=y
- +CONFIG_LZIP=y
- CONFIG_LZOP=y
- CONFIG_LZOP_COMPR_HIGH=y
- CONFIG_RPM2CPIO=y
- diff -urdN busybox-1.29.1.old/configs/android_ndk_defconfig busybox-1.29.1.new/configs/android_ndk_defconfig
- --- busybox-1.29.1.old/configs/android_ndk_defconfig 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/configs/android_ndk_defconfig 2018-07-17 00:03:25.000000000 +0200
- @@ -131,6 +131,7 @@
- CONFIG_FEATURE_SEAMLESS_LZMA=y
- CONFIG_FEATURE_SEAMLESS_BZ2=y
- CONFIG_FEATURE_SEAMLESS_GZ=y
- +CONFIG_FEATURE_SEAMLESS_LZ=y
- CONFIG_FEATURE_SEAMLESS_Z=y
- CONFIG_AR=y
- CONFIG_FEATURE_AR_LONG_FILENAMES=y
- @@ -153,6 +154,8 @@
- # CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
- CONFIG_GZIP_FAST=0
- # CONFIG_FEATURE_GZIP_LEVELS is not set
- +CONFIG_LUNZIP=y
- +CONFIG_LZIP=y
- CONFIG_LZOP=y
- CONFIG_LZOP_COMPR_HIGH=y
- CONFIG_RPM=y
- diff -urdN busybox-1.29.1.old/configs/cygwin_defconfig busybox-1.29.1.new/configs/cygwin_defconfig
- --- busybox-1.29.1.old/configs/cygwin_defconfig 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/configs/cygwin_defconfig 2018-07-17 00:03:25.000000000 +0200
- @@ -121,6 +121,7 @@
- CONFIG_FEATURE_SEAMLESS_LZMA=y
- CONFIG_FEATURE_SEAMLESS_BZ2=y
- CONFIG_FEATURE_SEAMLESS_GZ=y
- +CONFIG_FEATURE_SEAMLESS_LZ=y
- # CONFIG_FEATURE_SEAMLESS_Z is not set
- # CONFIG_AR is not set
- # CONFIG_FEATURE_AR_LONG_FILENAMES is not set
- @@ -135,6 +136,8 @@
- CONFIG_GUNZIP=y
- CONFIG_GZIP=y
- CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
- +CONFIG_LUNZIP=y
- +CONFIG_LZIP=y
- CONFIG_LZOP=y
- # CONFIG_LZOP_COMPR_HIGH is not set
- CONFIG_RPM2CPIO=y
- diff -urdN busybox-1.29.1.old/configs/freebsd_defconfig busybox-1.29.1.new/configs/freebsd_defconfig
- --- busybox-1.29.1.old/configs/freebsd_defconfig 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/configs/freebsd_defconfig 2018-07-17 00:03:25.000000000 +0200
- @@ -119,6 +119,7 @@
- CONFIG_FEATURE_SEAMLESS_LZMA=y
- CONFIG_FEATURE_SEAMLESS_BZ2=y
- CONFIG_FEATURE_SEAMLESS_GZ=y
- +CONFIG_FEATURE_SEAMLESS_LZ=y
- CONFIG_FEATURE_SEAMLESS_Z=y
- CONFIG_AR=y
- CONFIG_FEATURE_AR_LONG_FILENAMES=y
- @@ -133,6 +134,8 @@
- CONFIG_GUNZIP=y
- CONFIG_GZIP=y
- CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
- +CONFIG_LUNZIP=y
- +CONFIG_LZIP=y
- CONFIG_LZOP=y
- # CONFIG_LZOP_COMPR_HIGH is not set
- CONFIG_RPM2CPIO=y
- diff -urdN busybox-1.29.1.old/include/bb_archive.h busybox-1.29.1.new/include/bb_archive.h
- --- busybox-1.29.1.old/include/bb_archive.h 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/include/bb_archive.h 2018-07-17 00:03:25.000000000 +0200
- @@ -9,6 +9,8 @@
- COMPRESS_MAGIC = 0x1f9d,
- GZIP_MAGIC = 0x1f8b,
- BZIP2_MAGIC = 256 * 'B' + 'Z',
- + LZIP_MAGIC1 = 0x4C5A,
- + LZIP_MAGIC2 = 0x4950,
- /* .xz signature: 0xfd, '7', 'z', 'X', 'Z', 0x00 */
- /* More info at: http://tukaani.org/xz/xz-file-format.txt */
- XZ_MAGIC1 = 256 * 0xfd + '7',
- @@ -21,6 +23,8 @@
- COMPRESS_MAGIC = 0x9d1f,
- GZIP_MAGIC = 0x8b1f,
- BZIP2_MAGIC = 'B' + 'Z' * 256,
- + LZIP_MAGIC1 = 0x5A4C,
- + LZIP_MAGIC2 = 0x5049,
- XZ_MAGIC1 = 0xfd + '7' * 256,
- XZ_MAGIC2 = 'z' + ('X' + ('Z' + 0 * 256) * 256) * 256,
- XZ_MAGIC1a = 0xfd + ('7' + ('z' + 'X' * 256) * 256) * 256,
- @@ -196,6 +200,7 @@
- char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC;
- char get_header_tar_xz(archive_handle_t *archive_handle) FAST_FUNC;
- char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC;
- +char get_header_tar_lz(archive_handle_t *archive_handle) FAST_FUNC;
- char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC;
- char get_header_tar_xz(archive_handle_t *archive_handle) FAST_FUNC;
-
- @@ -251,6 +256,7 @@
- IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate) FAST_FUNC;
- IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate) FAST_FUNC;
- IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate) FAST_FUNC;
- +IF_DESKTOP(long long) int unpack_lz_stream(transformer_state_t *xstate) FAST_FUNC;
- IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate) FAST_FUNC;
- IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate) FAST_FUNC;
-
- diff -urdN busybox-1.29.1.old/include/libbb.h busybox-1.29.1.new/include/libbb.h
- --- busybox-1.29.1.old/include/libbb.h 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/include/libbb.h 2018-07-17 00:03:25.000000000 +0200
- @@ -879,6 +879,7 @@
- #define SEAMLESS_COMPRESSION (0 \
- || ENABLE_FEATURE_SEAMLESS_XZ \
- || ENABLE_FEATURE_SEAMLESS_LZMA \
- + || ENABLE_FEATURE_SEAMLESS_LZ \
- || ENABLE_FEATURE_SEAMLESS_BZ2 \
- || ENABLE_FEATURE_SEAMLESS_GZ \
- || ENABLE_FEATURE_SEAMLESS_Z)
- @@ -1332,6 +1333,7 @@
- /* Don't need IF_xxx() guard for these */
- int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
- int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
- +int lunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-
- #if ENABLE_ROUTE
- void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC;
- diff -urdN busybox-1.29.1.old/miscutils/man.c busybox-1.29.1.new/miscutils/man.c
- --- busybox-1.29.1.old/miscutils/man.c 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/miscutils/man.c 2018-07-17 00:03:25.000000000 +0200
- @@ -180,6 +180,11 @@
- if (run_pipe(filename_with_zext, man, level))
- return 1;
- #endif
- +#if ENABLE_FEATURE_SEAMLESS_LZ
- + strcpy(ext, "lz");
- + if (run_pipe(filename_with_zext, man, level))
- + return 1;
- +#endif
- #if ENABLE_FEATURE_SEAMLESS_BZ2
- strcpy(ext, "bz2");
- if (run_pipe(filename_with_zext, man, level))
- diff -urdN busybox-1.29.1.old/scripts/fix_ws.sh busybox-1.29.1.new/scripts/fix_ws.sh
- --- busybox-1.29.1.old/scripts/fix_ws.sh 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/scripts/fix_ws.sh 2018-07-17 00:03:25.000000000 +0200
- @@ -19,6 +19,7 @@
- | while read name; do
- test "YES" = "${name/*.bz2/YES}" && continue
- test "YES" = "${name/*.gz/YES}" && continue
- + test "YES" = "${name/*.lz/YES}" && continue
- test "YES" = "${name/*.png/YES}" && continue
- test "YES" = "${name/*.gif/YES}" && continue
- test "YES" = "${name/*.jpg/YES}" && continue
- diff -urdN busybox-1.29.1.old/testsuite/bunzip2.tests busybox-1.29.1.new/testsuite/bunzip2.tests
- --- busybox-1.29.1.old/testsuite/bunzip2.tests 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/testsuite/bunzip2.tests 2018-07-17 00:03:25.000000000 +0200
- @@ -9,6 +9,9 @@
- elif test "${0##*/}" = "bunzip2.tests"; then
- unpack=bunzip2
- ext=bz2
- +elif test "${0##*/}" = "lunzip.tests"; then
- + unpack=lunzip
- + ext=lz
- else
- echo "WTF? argv0='$0'"
- exit 1
- @@ -35,6 +38,13 @@
- $ECHO -ne "\x17\x72\x45\x38\x50\x90\x5b\xb8\xe8\xa3"
- }
-
- +hello_lz() {
- +# Lzipped "HELLO\n"
- +$ECHO -ne "\x4c\x5a\x49\x50\x01\x0c\x00\x24\x11\x45\xcf\x72\xcd\x3d\x3a\xdf"
- +$ECHO -ne "\xff\xff\xdd\x12\x00\x00\x6e\xd7\xac\xfd\x06\x00\x00\x00\x00\x00"
- +$ECHO -ne "\x00\x00\x2a\x00\x00\x00\x00\x00\x00\x00"
- +}
- +
- # We had bunzip2 error on this .bz2 file (fixed in rev 22521)
- test1_bz2()
- {
- @@ -530,6 +540,12 @@
- expected="ok\n"
- prep; check "$unpack: delete src" "${bb}$unpack t2.$ext; test ! -f t2.$ext && echo ok"
-
- +expected="ok\n"
- +rm -f t1.*
- +hello_$ext > t1.t$ext
- +check "$unpack: replace .t$ext --> .tar" \
- +"${bb}$unpack t1.t$ext && test -f t1.tar && test ! -f t1.t$ext && echo ok"
- +
- )
- rm -rf testdir
-
- diff -urdN busybox-1.29.1.old/testsuite/bzcat.tests busybox-1.29.1.new/testsuite/bzcat.tests
- --- busybox-1.29.1.old/testsuite/bzcat.tests 2018-07-02 13:23:06.000000000 +0200
- +++ busybox-1.29.1.new/testsuite/bzcat.tests 2018-07-19 02:04:10.000000000 +0200
- @@ -30,10 +30,18 @@
- $ECHO -ne "\x17\x72\x45\x38\x50\x90\x5b\xb8\xe8\xa3"
- }
-
- +hello_lz() {
- +# Lzipped "HELLO\n"
- +$ECHO -ne "\x4c\x5a\x49\x50\x01\x0c\x00\x24\x11\x45\xcf\x72\xcd\x3d\x3a\xdf"
- +$ECHO -ne "\xff\xff\xdd\x12\x00\x00\x6e\xd7\xac\xfd\x06\x00\x00\x00\x00\x00"
- +$ECHO -ne "\x00\x00\x2a\x00\x00\x00\x00\x00\x00\x00"
- +}
- +
- test x"$CONFIG_ZCAT" = x"y" && \
- for ext in \
- `test x"$CONFIG_FEATURE_SEAMLESS_GZ" = x"y" && echo gz` \
- `test x"$CONFIG_FEATURE_SEAMLESS_BZ2" = x"y" && echo bz2` \
- + `test x"$CONFIG_FEATURE_SEAMLESS_LZ" = x"y" && echo lz` \
- `test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && echo Z`
- do
- prep() {
- diff -urdN busybox-1.29.1.old/testsuite/lunzip.tests busybox-1.29.1.new/testsuite/lunzip.tests
- --- busybox-1.29.1.old/testsuite/lunzip.tests 1970-01-01 01:00:00.000000000 +0100
- +++ busybox-1.29.1.new/testsuite/lunzip.tests 2018-07-17 00:03:25.000000000 +0200
- @@ -0,0 +1,3 @@
- +#!/bin/sh
- +
- +. ./bunzip2.tests
- diff -urdN busybox-1.29.1.old/testsuite/lzip.tests busybox-1.29.1.new/testsuite/lzip.tests
- --- busybox-1.29.1.old/testsuite/lzip.tests 1970-01-01 01:00:00.000000000 +0100
- +++ busybox-1.29.1.new/testsuite/lzip.tests 2018-07-17 14:06:36.000000000 +0200
- @@ -0,0 +1,58 @@
- +#!/bin/sh
- +# Copyright (C) 2012-2018 Antonio Diaz Diaz.
- +# Licensed under GPLv2 or later, see file LICENSE in this source tree.
- +
- +. ./testing.sh
- +
- +rm -rf lzip.testdir 2>/dev/null
- +mkdir lzip.testdir
- +
- +# Lzipped "a"
- +$ECHO -ne "\x4c\x5a\x49\x50\x01\x0c\x00\x30\xc1\xfb\xff\xff\xff\xe0\x00\x00\
- +\x00\x43\xbe\xb7\xe8\x01\x00\x00\x00\x00\x00\x00\x00\x25\x00\x00\
- +\x00\x00\x00\x00\x00" > lzip.testdir/a.lz
- +
- +# Lzipped zero-length file
- +$ECHO -ne "\x4c\x5a\x49\x50\x01\x0c\x00\x83\xff\xfb\xff\xff\xc0\x00\x00\x00\
- +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24\x00\x00\x00\
- +\x00\x00\x00\x00" > lzip.testdir/zero.lz
- +
- +
- +# testing "test name" "commands" "expected result" "file input" "stdin"
- +
- +testing "lzip reads from standard input" \
- +"busybox lzip | cmp lzip.testdir/a.lz -" "" "" "a"
- +
- +testing "lzip accepts single minus" \
- +"busybox lzip - | cmp lzip.testdir/a.lz -" "" "" "a"
- +
- +testing "lzip compresses a zero-length file" \
- +"> zero ; busybox lzip -c zero | cmp lzip.testdir/zero.lz -" "" "" ""
- +
- +testing "lzip replaces original file" \
- +"$ECHO foo > lzip.testdir/foo
- +rm -f lzip.testdir/foo.lz 2>/dev/null
- +busybox lzip lzip.testdir/foo
- +test -f lzip.testdir/foo.lz && test ! -f lzip.testdir/foo && echo ok" \
- +"ok\n" "" ""
- +
- +testing "lzip replaces multiple files" \
- +"$ECHO foo > lzip.testdir/foo
- +$ECHO bar > lzip.testdir/bar
- +rm -f lzip.testdir/foo.lz 2>/dev/null
- +rm -f lzip.testdir/bar.lz 2>/dev/null
- +busybox lzip lzip.testdir/foo lzip.testdir/bar
- +test -f lzip.testdir/foo.lz && test ! -f lzip.testdir/foo && echo ok1
- +test -f lzip.testdir/bar.lz && test ! -f lzip.testdir/bar && echo ok2" \
- +"ok1\nok2\n" "" ""
- +
- +testing "lzip -c does not remove original file" \
- +"$ECHO foo > lzip.testdir/foo
- +busybox lzip -c lzip.testdir/foo >/dev/null
- +test -f lzip.testdir/foo && echo ok" "ok\n" "" ""
- +
- +
- +# Clean up
- +rm -rf lzip.testdir 2>/dev/null
- +
- +exit $FAILCOUNT
- diff -urdN busybox-1.29.1.old/testsuite/tar.tests.~1~ busybox-1.29.1.new/testsuite/tar.tests.~1~
- --- busybox-1.29.1.old/testsuite/tar.tests.~1~ 1970-01-01 01:00:00.000000000 +0100
- +++ busybox-1.29.1.new/testsuite/tar.tests.~1~ 2018-07-17 00:03:25.000000000 +0200
- @@ -0,0 +1,368 @@
- +#!/bin/sh
- +# Copyright 2009 by Denys Vlasenko
- +# Licensed under GPLv2, see file LICENSE in this source tree.
- +
- +. ./testing.sh
- +
- +unset LANG
- +unset LANGUAGE
- +unset LC_COLLATE
- +unset LC_ALL
- +umask 022
- +
- +# testing "test name" "script" "expected result" "file input" "stdin"
- +
- +testing "Empty file is not a tarball" '\
- +tar xvf - 2>&1; echo $?
- +' "\
- +tar: short read
- +1
- +" \
- +"" ""
- +SKIP=
- +
- +optional FEATURE_SEAMLESS_GZ GUNZIP
- +# In NOMMU case, "invalid magic" message comes from gunzip child process.
- +# Otherwise, it comes from tar.
- +# Need to fix output up to avoid false positive.
- +testing "Empty file is not a tarball.tar.gz" '\
- +{ tar xvzf - 2>&1; echo $?; } | grep -Fv "invalid magic"
- +' "\
- +tar: short read
- +1
- +" \
- +"" ""
- +SKIP=
- +
- +testing "Two zeroed blocks is a ('truncated') empty tarball" '\
- +dd if=/dev/zero bs=512 count=2 2>/dev/null | tar xvf - 2>&1; echo $?
- +' "\
- +0
- +" \
- +"" ""
- +SKIP=
- +
- +testing "Twenty zeroed blocks is an empty tarball" '\
- +dd if=/dev/zero bs=512 count=20 2>/dev/null | tar xvf - 2>&1; echo $?
- +' "\
- +0
- +" \
- +"" ""
- +SKIP=
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +# "tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input":
- +# GNU tar 1.26 records as hardlinks:
- +# input_hard2 -> input_hard1
- +# input_hard1 -> input_hard1 (!!!)
- +# input_dir/file -> input_dir/file
- +# input -> input
- +# As of 1.24.0, we don't record last two: for them, nlink==1
- +# and we check for "hardlink"ness only files with nlink!=1
- +# We also don't use "hrw-r--r--" notation for hardlinks in "tar tv" listing.
- +optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES
- +testing "tar hardlinks and repeated files" '\
- +>input_hard1
- +ln input_hard1 input_hard2
- +mkdir input_dir
- +>input_dir/file
- +chmod -R 644 *
- +chmod 755 input_dir
- +tar cf test.tar input input_dir/ input_hard1 input_hard2 input_hard1 input_dir/ input
- +tar tvf test.tar | sed "s/.*[0-9] input/input/"
- +rm -rf input_dir
- +tar xf test.tar 2>&1
- +echo Ok: $?
- +ls -l . input_dir/* | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
- +' "\
- +input
- +input_dir/
- +input_dir/file
- +input_hard1
- +input_hard2 -> input_hard1
- +input_hard1 -> input_hard1
- +input_dir/
- +input_dir/file
- +input
- +Ok: 0
- +-rw-r--r-- input_dir/file
- +drwxr-xr-x input_dir
- +-rw-r--r-- input_hard1
- +-rw-r--r-- input_hard2
- +" \
- +"" ""
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES
- +testing "tar hardlinks mode" '\
- +>input_hard1
- +chmod 741 input_hard1
- +ln input_hard1 input_hard2
- +mkdir input_dir
- +ln input_hard1 input_dir
- +ln input_hard2 input_dir
- +chmod 550 input_dir
- +# On some filesystems, input_dir/input_hard2 is returned by readdir
- +# BEFORE input_dir/input_hard1! Thats why we cant just "tar cf ... input_*":
- +tar cf test.tar input_dir/input_hard* input_hard*
- +tar tvf test.tar | sed "s/.*[0-9] input/input/"
- +chmod 770 input_dir
- +rm -rf input_*
- +tar xf test.tar 2>&1
- +echo Ok: $?
- +ls -l . input_dir/* | grep "input.*hard" | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
- +' "\
- +input_dir/input_hard1
- +input_dir/input_hard2 -> input_dir/input_hard1
- +input_hard1 -> input_dir/input_hard1
- +input_hard2 -> input_dir/input_hard1
- +Ok: 0
- +-rwxr----x input_dir/input_hard1
- +-rwxr----x input_dir/input_hard2
- +-rwxr----x input_hard1
- +-rwxr----x input_hard2
- +" \
- +"" ""
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +optional FEATURE_TAR_CREATE FEATURE_LS_SORTFILES
- +testing "tar symlinks mode" '\
- +>input_file
- +chmod 741 input_file
- +ln -s input_file input_soft
- +mkdir input_dir
- +ln input_file input_dir
- +ln input_soft input_dir
- +chmod 550 input_dir
- +tar cf test.tar input_dir/* input_[fs]*
- +tar tvf test.tar | sed "s/.*[0-9] input/input/" | sort
- +chmod 770 input_dir
- +rm -rf input_*
- +tar xf test.tar 2>&1
- +echo Ok: $?
- +ls -l . input_dir/* | grep "input_[fs]" | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
- +' "\
- +input_dir/input_file
- +input_dir/input_soft -> input_file
- +input_file -> input_dir/input_file
- +input_soft -> input_dir/input_soft
- +Ok: 0
- +-rwxr----x input_dir/input_file
- +lrwxrwxrwx input_file
- +-rwxr----x input_file
- +lrwxrwxrwx input_file
- +" \
- +"" ""
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +optional FEATURE_TAR_CREATE FEATURE_TAR_LONG_OPTIONS
- +testing "tar --overwrite" "\
- +ln input input_hard
- +tar cf test.tar input_hard
- +echo WRONG >input
- +# --overwrite opens 'input_hard' without unlinking,
- +# thus 'input_hard' still linked to 'input' and we write 'Ok' into it
- +tar xf test.tar --overwrite 2>&1 && cat input
- +" "\
- +Ok
- +" \
- +"Ok\n" ""
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +test x"$SKIP_KNOWN_BUGS" = x"" && {
- +# Needs to be run under non-root for meaningful test
- +optional FEATURE_TAR_CREATE
- +testing "tar writing into read-only dir" '\
- +mkdir input_dir
- +>input_dir/input_file
- +chmod 550 input_dir
- +tar cf test.tar input_dir
- +tar tvf test.tar | sed "s/.*[0-9] input/input/"
- +chmod 770 input_dir
- +rm -rf input_*
- +tar xf test.tar 2>&1
- +echo Ok: $?
- +ls -l input_dir/* . | grep input_ | sed "s/\\(^[^ ]*\\) .* input/\\1 input/"
- +chmod 770 input_dir
- +' "\
- +input_dir/
- +input_dir/input_file
- +Ok: 0
- +-rw-r--r-- input_dir/input_file
- +dr-xr-x--- input_dir
- +" \
- +"" ""
- +SKIP=
- +}
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +# Had a bug where on extract autodetect first "switched off" -z
- +# and then failed to recognize .tgz extension
- +optional FEATURE_TAR_CREATE FEATURE_SEAMLESS_GZ GUNZIP
- +testing "tar extract tgz" "\
- +dd count=1 bs=1M if=/dev/zero of=F0 2>/dev/null
- +tar -czf F0.tgz F0
- +rm F0
- +tar -xzvf F0.tgz && echo Ok
- +rm F0 || echo BAD
- +" "\
- +F0
- +Ok
- +" \
- +"" ""
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +# Do we detect XZ-compressed data (even w/o .tar.xz or txz extension)?
- +# (the uuencoded hello_world.txz contains one empty file named "hello_world")
- +optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_XZ
- +testing "tar extract txz" "\
- +uudecode -o input && tar tf input && echo Ok
- +" "\
- +hello_world
- +Ok
- +" \
- +"" "\
- +begin-base64 644 hello_world.txz
- +/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AX/AEldADQZSe6ODIZQ3rSQ8kAJ
- +SnMPTX+XWGKW3Yu/Rwqg4Ik5wqgQKgVH97J8yA8IvZ4ahaCQogUNHRkXibr2
- +Q615wcb2G7fJU49AhWAAAAAAUA8gu9DyXfAAAWWADAAAAB5FXGCxxGf7AgAA
- +AAAEWVo=
- +====
- +"
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +# On extract, everything up to and including last ".." component is stripped
- +optional FEATURE_TAR_CREATE
- +testing "tar strips /../ on extract" "\
- +rm -rf input_* test.tar 2>/dev/null
- +mkdir input_dir
- +echo Ok >input_dir/file
- +tar cf test.tar ./../tar.tempdir/input_dir/../input_dir 2>&1
- +rm -rf input_* 2>/dev/null
- +tar -vxf test.tar 2>&1
- +cat input_dir/file 2>&1
- +" "\
- +tar: removing leading './../tar.tempdir/input_dir/../' from member names
- +input_dir/
- +input_dir/file
- +Ok
- +" \
- +"" ""
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +# attack.tar.bz2 has symlink pointing to a system file
- +# followed by a regular file with the same name
- +# containing "root::0:0::/root:/bin/sh":
- +# lrwxrwxrwx root/root passwd -> /tmp/passwd
- +# -rw-r--r-- root/root passwd
- +# naive tar implementation may end up creating the symlink
- +# and then writing into it.
- +# The correct implementation unlinks target before
- +# creating the second file.
- +# We test that /tmp/passwd remains empty:
- +optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
- +testing "tar does not extract into symlinks" "\
- +>>/tmp/passwd && uudecode -o input && tar xf input 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
- +" "\
- +tar: skipping unsafe symlink to '/tmp/passwd' in archive, set EXTRACT_UNSAFE_SYMLINKS=1 to extract
- +0
- +" \
- +"" "\
- +begin-base64 644 attack.tar.bz2
- +QlpoOTFBWSZTWRVn/bIAAKt7hMqwAEBAAP2QAhB0Y96AAACACCAAlISgpqe0
- +po0DIaDynqAkpDRP1ANAhiYNSPR8VchKhAz0AK59+DA6FcMKBggOARIJdVHL
- +DGllrjs20ATUgR1HmccBX3EhoMnpMJaNyggmxgLDMz54lBnBTJO/1L1lbMS4
- +l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
- +====
- +"
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +# And same with -k
- +optional UUDECODE FEATURE_TAR_AUTODETECT FEATURE_SEAMLESS_BZ2
- +testing "tar -k does not extract into symlinks" "\
- +>>/tmp/passwd && uudecode -o input && tar xf input -k 2>&1 && rm passwd; cat /tmp/passwd; echo \$?
- +" "\
- +tar: skipping unsafe symlink to '/tmp/passwd' in archive, set EXTRACT_UNSAFE_SYMLINKS=1 to extract
- +0
- +" \
- +"" "\
- +begin-base64 644 attack.tar.bz2
- +QlpoOTFBWSZTWRVn/bIAAKt7hMqwAEBAAP2QAhB0Y96AAACACCAAlISgpqe0
- +po0DIaDynqAkpDRP1ANAhiYNSPR8VchKhAz0AK59+DA6FcMKBggOARIJdVHL
- +DGllrjs20ATUgR1HmccBX3EhoMnpMJaNyggmxgLDMz54lBnBTJO/1L1lbMS4
- +l4/V8LDoe90yiWJhOJvIypgEfxdyRThQkBVn/bI=
- +====
- +"
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +optional UNICODE_SUPPORT FEATURE_TAR_GNU_EXTENSIONS FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT
- +testing "Pax-encoded UTF8 names and symlinks" '\
- +tar xvf ../tar.utf8.tar.bz2 2>&1; echo $?
- +export LANG=en_US.UTF-8
- +ls -l etc/ssl/certs/* | sed "s:.*etc/:etc/:" | sort
- +unset LANG
- +rm -rf etc usr
- +' "\
- +etc/ssl/certs/3b2716e5.0
- +etc/ssl/certs/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
- +tar: skipping unsafe symlink to '/usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt' in archive, set EXTRACT_UNSAFE_SYMLINKS=1 to extract
- +etc/ssl/certs/f80cc7f6.0
- +usr/share/ca-certificates/mozilla/EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.crt
- +0
- +etc/ssl/certs/3b2716e5.0 -> EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
- +etc/ssl/certs/f80cc7f6.0 -> EBG_Elektronik_Sertifika_Hizmet_Sağlayıcısı.pem
- +" \
- +"" ""
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +mkdir tar.tempdir && cd tar.tempdir || exit 1
- +optional FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT
- +testing "Symlink attack: create symlink and then write through it" '\
- +exec 2>&1
- +uudecode -o input && tar xvf input; echo $?
- +ls /tmp/bb_test_evilfile
- +ls bb_test_evilfile
- +ls symlink/bb_test_evilfile
- +' "\
- +anything.txt
- +symlink
- +tar: skipping unsafe symlink to '/tmp' in archive, set EXTRACT_UNSAFE_SYMLINKS=1 to extract
- +symlink/bb_test_evilfile
- +0
- +ls: /tmp/bb_test_evilfile: No such file or directory
- +ls: bb_test_evilfile: No such file or directory
- +symlink/bb_test_evilfile
- +" \
- +"" "\
- +begin-base64 644 tar_symlink_attack.tar.bz2
- +QlpoOTFBWSZTWZgs7bQAALT/hMmQAFBAAf+AEMAGJPPv32AAAIAIMAC5thlR
- +omAjAmCMADQT1BqNE0AEwAAjAEwElTKeo9NTR6h6gaeoA0DQNLVdwZZ5iNTk
- +AQwCAV6S00QFJYhrlfFkVCEDEGtgNVqYrI0uK3ggnt30gqk4e1TTQm5QIAKa
- +SJqzRGSFLMmOloHSAcvLiFxxRiQtQZF+qPxbo173ZDISOAoNoPN4PQPhBhKS
- +n8fYaKlioCTzL2oXYczyUUIP4u5IpwoSEwWdtoA=
- +====
- +"
- +SKIP=
- +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null
- +
- +exit $FAILCOUNT
|