Commit cfe00b2d authored by jan.koester's avatar jan.koester
Browse files

test

parent 588be448
Loading
Loading
Loading
Loading
+37 −2
Changes for commands/system/tar.cpp: 37 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include <set>
@@ -246,8 +247,13 @@ namespace fresh { namespace cmd {
                 samePerms=false,sameOwner=true,numericOwner=false;
            int verboseLevel=0;
            long strip=0;
            std::string compress;     // gzip, bzip2, xz
            std::string compress;     // gzip, bzip2, xz, or -I's command (with arguments)
            std::vector<std::string> excludes;
            // -T/--files-from lists ("-" is stdin), read once all options
            // are parsed and before -C changes directory, like GNU tar;
            // --null: NUL- instead of newline-separated
            std::vector<std::string> filesFrom;
            bool nullNames=false;
            std::vector<std::string> members;
        };

@@ -801,6 +807,10 @@ namespace fresh { namespace cmd {
                    else if(n=="zstd") o.compress="zstd";
                    else if(n=="strip-components"){ if(!need()) return 2; o.strip=atol(v.c_str()); }
                    else if(n=="exclude"){ if(!need()) return 2; o.excludes.push_back(v); }
                    else if(n=="files-from"){ if(!need()) return 2; o.filesFrom.push_back(v); }
                    else if(n=="null") o.nullNames=true;
                    else if(n=="no-null") o.nullNames=false;
                    else if(n=="use-compress-program"){ if(!need()) return 2; o.compress=v; }
                    else if(n=="owner" || n=="group" || n=="mode" || n=="mtime" || n=="format" ||
                            n=="sort" || n=="pax-option" || n=="blocking-factor" || n=="record-size"){ if(!need()) return 2; }
                    else if(n=="no-recursion" || n=="recursion" || n=="warning" || n=="delay-directory-restore" ||
@@ -836,6 +846,8 @@ namespace fresh { namespace cmd {
                        case 'J': o.compress="xz"; break;
                        case 'f': if(!value(o.archive)) return 2; break;
                        case 'C': if(!value(o.dir)) return 2; break;
                        case 'T': { std::string v; if(!value(v)) return 2; o.filesFrom.push_back(v); break; }
                        case 'I': if(!value(o.compress)) return 2; break;
                        case 'h': case 'P': case 'U': case 'S': case 'W': case 'B': case 'i': break;
                        default:
                            std::cerr << "tar: invalid option -- '" << c << "'" << std::endl;
@@ -847,6 +859,23 @@ namespace fresh { namespace cmd {
                std::cerr << "tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' options" << std::endl;
                return 2;
            }
            for(auto &list: o.filesFrom){
                FILE *f=list=="-" ? stdin : fopen(list.c_str(),"r");
                if(!f){
                    std::cerr << "tar: " << list << ": Cannot open: " << strerror(errno) << std::endl;
                    return 2;
                }
                std::string name;
                int ch;
                while((ch=fgetc(f))!=EOF){
                    if(ch==(o.nullNames ? '\0' : '\n')){
                        if(!name.empty()) o.members.push_back(name);
                        name.clear();
                    }else name+=(char)ch;
                }
                if(!name.empty()) o.members.push_back(name);
                if(f!=stdin) fclose(f);
            }
            if(o.archive.empty()) o.archive="-";

            int fd;
@@ -865,7 +894,13 @@ namespace fresh { namespace cmd {
            pid_t filter=-1;
            int ioFd=fd;
            if(!o.compress.empty()){
                std::vector<std::string> cmd{o.compress};
                // -I "xz -T0": a command with its arguments
                std::vector<std::string> cmd;
                {
                    std::istringstream words(o.compress);
                    std::string word;
                    while(words >> word) cmd.push_back(word);
                }
                if(o.mode!='c') cmd.push_back("-dc");
                else cmd.push_back("-c");
                filter=startFilter(cmd,fd,o.mode!='c',ioFd);
+51 −15
Changes for commands/system/xz.cpp: 51 added lines, 15 removed lines.
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

// CLI entry point for decompress-only "xz": argv parsing and file/stdio
// wiring only -- the actual .xz/LZMA2 decoder lives in lib/xz/xz.h, same
// CLI entry point for "xz": argv parsing and file/stdio wiring only -- the
// actual .xz/LZMA2 decoder and encoder live in lib/xz (xz.h), same
// division of labor as lib/awk vs commands/editor/awk.cpp. dpkg-source's
// own "3.0 (quilt)" format always ships a *.debian.tar.xz alongside the
// *.orig.tar.* -- apt-get source / dpkg-source -x needs to unpack it, and
@@ -65,29 +65,58 @@ namespace fresh { namespace cmd {
        XzCommand():ShellCommand("xz"){}

        int runCommand(int argc,const char **argv){
            // like xz(1): compress unless -d; "xz -c" alone compresses to
            // stdout (tar -J/-I xz when creating), "-dc" decompresses
            bool decompressMode=false;
            bool toStdout=false;
            bool keep=false;
            int level=6;
            std::vector<std::string> files;

            for(int i=1;i<argc;++i){
                std::string arg=argv[i];
                if(arg=="-d" || arg=="--decompress" || arg=="-dc" || arg=="-cd"){
                    if(arg=="-dc" || arg=="-cd") toStdout=true;
                }else if(arg=="-c" || arg=="--stdout" || arg=="--to-stdout"){
                    toStdout=true;
                }else if(arg=="-k" || arg=="--keep"){
                    keep=true;
                }else if(arg=="-f" || arg=="--force" || arg=="-q" || arg=="--quiet" ||
                          arg=="-v" || arg=="--verbose" || arg=="-T" || arg=="--threads"){
                    // accepted, no effect needed for this decompress-only build
                }else if(!arg.empty() && arg[0]=='-' && arg!="-"){
                if(arg.size()>2 && arg.compare(0,2,"--")==0){
                    std::string n=arg.substr(2);
                    size_t eq=n.find('=');
                    if(eq!=std::string::npos) n=n.substr(0,eq);
                    if(n=="decompress" || n=="uncompress") decompressMode=true;
                    else if(n=="compress") decompressMode=false;
                    else if(n=="stdout" || n=="to-stdout") toStdout=true;
                    else if(n=="keep") keep=true;
                    else if(n=="best") level=9;
                    else if(n=="fast") level=0;
                    else if(n=="force" || n=="quiet" || n=="verbose" || n=="extreme" ||
                            n=="threads" || n=="check" || n=="format" || n=="memlimit" ||
                            n=="no-warn" || n=="no-sparse"){
                        // accepted: one thread, CRC32, .xz format
                    }else{
                        std::cerr << "xz: unrecognized option '" << arg << "'" << std::endl;
                        return 1;
                }else{
                    }
                    continue;
                }
                if(arg.size()<2 || arg[0]!='-'){
                    files.push_back(arg);
                    continue;
                }
                for(size_t k=1;k<arg.size();++k){
                    char c=arg[k];
                    if(c=='d') decompressMode=true;
                    else if(c=='z') decompressMode=false;
                    else if(c=='c') toStdout=true;
                    else if(c=='k') keep=true;
                    else if(c>='0' && c<='9') level=c-'0';
                    else if(c=='f' || c=='q' || c=='v' || c=='e'){}
                    else if(c=='T' || c=='C' || c=='F' || c=='M'){
                        // value: the rest of this argument or the next one
                        if(k+1==arg.size()) ++i;
                        break;
                    }else{
                        std::cerr << "xz: invalid option -- '" << c << "'" << std::endl;
                        return 1;
                    }
                }
            }
            (void)keep;

            if(files.empty())
                files.push_back("-");
@@ -110,11 +139,16 @@ namespace fresh { namespace cmd {
                }

                std::vector<unsigned char> output;
                if(decompressMode){
                    if(!fresh::xz::decompress(input,output)){
                        std::cerr << "xz: " << path << ": not in xz format or corrupt" << std::endl;
                        failed=1;
                        continue;
                    }
                }else if(!fresh::xz::compress(input,output,level)){
                    failed=1;
                    continue;
                }

                if(toStdout || path=="-"){
                    if(!output.empty())
@@ -124,7 +158,9 @@ namespace fresh { namespace cmd {
                    std::string outpath=path;
                    static const char suffix[]=".xz";
                    size_t sfxlen=sizeof(suffix)-1;
                    if(outpath.size()>sfxlen && outpath.compare(outpath.size()-sfxlen,sfxlen,suffix)==0)
                    if(!decompressMode)
                        outpath+=suffix;
                    else if(outpath.size()>sfxlen && outpath.compare(outpath.size()-sfxlen,sfxlen,suffix)==0)
                        outpath.resize(outpath.size()-sfxlen);
                    else
                        outpath+=".out";
+1 −1
Changes for lib/xz/CMakeLists.txt: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -3,4 +3,4 @@
# and modprobe/depmod (all three already link into fresh via
# target_sources()), so a plain target_sources() here is enough -- see
# xz.cpp's own header comment.
target_sources(fresh PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/xz.cpp)
target_sources(fresh PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/xz.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xz_encode.cpp)
+3 −4
Changes for lib/xz/xz.cpp: 3 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -25,11 +25,10 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

// Decompress-only .xz/LZMA2, moved here from commands/system/xz.cpp (which
// The .xz/LZMA2 decoder, moved here from commands/system/xz.cpp (which
// is now just the CLI wrapper) so modprobe/depmod can decompress a *.ko.xz
// kernel module in memory without shelling out. No compression side (the
// real xz encoder) is implemented; only unpacking archives someone else
// compressed is ever needed here. Only a single-filter LZMA2 chain is
// kernel module in memory without shelling out. The encoder is
// xz_encode.cpp (the kernel build's kheaders_data.tar.xz needs one). Only a single-filter LZMA2 chain is
// supported (what every plain "xz"/"dpkg-source" invocation, and the
// kernel's own CONFIG_MODULE_COMPRESS_XZ, produces) -- BCJ/delta filter
// chains are rejected with a clear error rather than silently misdecoded.
+6 −1
Changes for lib/xz/xz.h: 6 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

// Decompress-only .xz/LZMA2 engine, shared between the "xz" CLI applet
// .xz/LZMA2 engine (decoder; the encoder is xz_encode.cpp), shared between the "xz" CLI applet
// (commands/system/xz.cpp -- argv parsing and file/stdio wiring only, same
// division of labor as lib/awk vs commands/editor/awk.cpp) and anything
// else in this binary that needs to decompress an in-memory .xz blob
@@ -48,4 +48,9 @@ namespace fresh { namespace xz {
    // should catch the false return and report it themselves instead).
    bool decompress(const std::vector<unsigned char> &input,std::vector<unsigned char> &output);

    // Compresses `input` into one complete .xz stream (one Block, LZMA2,
    // CRC32 check), appended to `output`; level 0-9 as xz's presets
    // (dictionary size, match finder effort). See xz_encode.cpp.
    bool compress(const std::vector<unsigned char> &input,std::vector<unsigned char> &output,int level=6);

}}
Loading