0

I am trying build an archiver app where zip, 7z, xz etc formats will be compressed i have achieved zip & 7z but finding difficulty in .xz format.

I've found XZ utils-The Tukaani Project i was able to compress with this but while trying to unarchive with other apps to test weather it working not it was giving me error "The contents of file cannot be extracted".

From that library i am using 03_compress_custom.c class for compression ,below code which is present in this class.

Is there any other library to acheive it or if it can be made with NSTask ?

Any Suggestions?

    static bool init_encoder(lzma_stream *strm, uint32 preset)
{
    // Use the default preset (6) for LZMA2.
    //
    // The lzma_options_lzma structure and the lzma_lzma_preset() function
    // are declared in lzma/lzma12.h (src/liblzma/api/lzma/lzma12.h in the
    // source package or e.g. /usr/include/lzma/lzma12.h depending on
    // the install prefix).
    lzma_options_lzma opt_lzma2;
    if (lzma_lzma_preset(&opt_lzma2, preset)) {
        // It should never fail because the default preset
        // (and presets 0-9 optionally with LZMA_PRESET_EXTREME)
        // are supported by all stable liblzma versions.
        //
        // (The encoder initialization later in this function may
        // still fail due to unsupported preset *if* the features
        // required by the preset have been disabled at build time,
        // but no-one does such things except on embedded systems.)
        fprintf(stderr, "Unsupported preset, possibly a bug\n");
        return false;
    }

    // Now we could customize the LZMA2 options if we wanted. For example,
    // we could set the the dictionary size (opt_lzma2.dict_size) to
    // something else than the default (8 MiB) of the default preset.
    // See lzma/lzma12.h for details of all LZMA2 options.
    //
    // The x86 BCJ filter will try to modify the x86 instruction stream so
    // that LZMA2 can compress it better. The x86 BCJ filter doesn't need
    // any options so it will be set to NULL below.
    //
    // Construct the filter chain. The uncompressed data goes first to
    // the first filter in the array, in this case the x86 BCJ filter.
    // The array is always terminated by setting .id = LZMA_VLI_UNKNOWN.
    //
    // See lzma/filter.h for more information about the lzma_filter
    // structure.
    lzma_filter filters[] = {
        { .id = LZMA_FILTER_X86, .options = NULL },
        { .id = LZMA_FILTER_LZMA2, .options = &opt_lzma2 },
        { .id = LZMA_VLI_UNKNOWN, .options = NULL },
    };

    // Initialize the encoder using the custom filter chain.
    lzma_ret ret = lzma_stream_encoder(strm, filters, LZMA_CHECK_CRC64);

    if (ret == LZMA_OK)
        return true;

    const char *msg;
    switch (ret) {
        case LZMA_MEM_ERROR:
            msg = "Memory allocation failed";
            break;

        case LZMA_OPTIONS_ERROR:
            // We are no longer using a plain preset so this error
            // message has been edited accordingly compared to
            // 01_compress_easy.c.
            msg = "Specified filter chain is not supported";
            break;

        case LZMA_UNSUPPORTED_CHECK:
            msg = "Specified integrity check is not supported";
            break;

        default:
            msg = "Unknown error, possibly a bug";
            break;
    }

    fprintf(stderr, "Error initializing the encoder: %s (error code %u)\n",
            msg, ret);
    return false;
}

// This function is identical to the one in 01_compress_easy.c.
static bool compress(lzma_stream *strm, FILE *infile, FILE *outfile)
{
    lzma_action action = LZMA_RUN;

    uint8_t inbuf[BUFSIZ];
    uint8_t outbuf[BUFSIZ];

    strm->next_in = NULL;
    strm->avail_in = 0;
    strm->next_out = outbuf;
    strm->avail_out = sizeof(outbuf);

    while (true) {
        if (strm->avail_in == 0 && !feof(infile)) {
            strm->next_in = inbuf;
            strm->avail_in = fread(inbuf, 1, sizeof(inbuf),
                                   infile);

            if (ferror(infile)) {
                fprintf(stderr, "Read error: %s\n",
                        strerror(errno));
                return false;
            }

            if (feof(infile))
                action = LZMA_FINISH;
        }

        lzma_ret ret = lzma_code(strm, action);

        if (strm->avail_out == 0 || ret == LZMA_STREAM_END) {
            size_t write_size = sizeof(outbuf) - strm->avail_out;

            if (fwrite(outbuf, 1, write_size, outfile)
                != write_size) {
                fprintf(stderr, "Write error: %s\n",
                        strerror(errno));
                return false;
            }

            strm->next_out = outbuf;
            strm->avail_out = sizeof(outbuf);
        }

        if (ret != LZMA_OK) {
            if (ret == LZMA_STREAM_END)
                return true;

            const char *msg;
            switch (ret) {
                case LZMA_MEM_ERROR:
                    msg = "Memory allocation failed";
                    break;

                case LZMA_DATA_ERROR:
                    msg = "File size limits exceeded";
                    break;

                default:
                    msg = "Unknown error, possibly a bug";
                    break;
            }

            fprintf(stderr, "Encoder error: %s (error code %u)\n",
                    msg, ret);
            return false;
        }
    }
}

Finally in this method i am performing compression

FILE *input = fopen(sourcePath.fileSystemRepresentation, "r");
    if(input == NULL) {
        NSLog(@"INPUT ERROR");
    }
    FILE *output = fopen(destinationPath.fileSystemRepresentation, "wb");
    if(output == NULL) {
        NSLog(@"OUTPUT ERROR");
    }

    lzma_stream strm = LZMA_STREAM_INIT;
    bool  success = init_encoder(&strm, level);

    if(success) {
        success = compress(&strm, input, output);
    }
    lzma_end(&strm);


    if (fclose(stdout)) {
        fprintf(stderr, "Write error: %s\n", strerror(errno));
        success = false;
    }

    if(success) {
        NSLog(@"XZ COMPRESSED");
        [self archivingCompleted];
    }
    else {
        NSLog(@"XZ FAILED");
        [self archivingFailedWithError:nil];
    }
osxDev123
  • 21
  • 4
  • This may be completely off the mark, but...: I know that with libz compression there is a difference between a "bare" compressed data stream and a .gz file (the latter has some metadata, like the filename before compression). Could it be that you are writing the "bare" format, while the decompression utility you are testing with expects metadata? – Ture Pålsson Jan 10 '19 at 07:34
  • yes i think the it may be expecting metadata. – osxDev123 Jan 19 '19 at 07:37

0 Answers0