compression_wrapper: Better error messages for XZ errors and more tests.
authorTomas Mlcoch <tmlcoch@redhat.com>
Wed, 29 May 2013 11:42:54 +0000 (13:42 +0200)
committerTomas Mlcoch <tmlcoch@redhat.com>
Wed, 29 May 2013 11:42:54 +0000 (13:42 +0200)
src/compression_wrapper.c
tests/test_compression_wrapper.c

index d5f0d57..55bba9d 100644 (file)
@@ -708,10 +708,59 @@ cr_read(CR_FILE *cr_file, void *buffer, unsigned int len, GError **err)
 
                 // Decode
                 lret = lzma_code(stream, LZMA_RUN);
+
                 if (lret != LZMA_OK && lret != LZMA_STREAM_END) {
-                    g_debug("%s: XZ: Error while decoding (%d)", __func__, lret);
+                    const char *err_msg;
+
+                    switch (lret) {
+                        case LZMA_MEM_ERROR:
+                            err_msg = "Memory allocation failed";
+                            break;
+                       case LZMA_FORMAT_ERROR:
+                            // .xz magic bytes weren't found.
+                            err_msg = "The input is not in the .xz format";
+                            break;
+                       case LZMA_OPTIONS_ERROR:
+                            // For example, the headers specify a filter
+                            // that isn't supported by this liblzma
+                            // version (or it hasn't been enabled when
+                            // building liblzma, but no-one sane does
+                            // that unless building liblzma for an
+                            // embedded system). Upgrading to a newer
+                            // liblzma might help.
+                            //
+                            // Note that it is unlikely that the file has
+                            // accidentally became corrupt if you get this
+                            // error. The integrity of the .xz headers is
+                            // always verified with a CRC32, so
+                            // unintentionally corrupt files can be
+                            // distinguished from unsupported files.
+                            err_msg = "Unsupported compression options";
+                            break;
+                       case LZMA_DATA_ERROR:
+                            err_msg = "Compressed file is corrupt";
+                            break;
+                       case LZMA_BUF_ERROR:
+                            // Typically this error means that a valid
+                            // file has got truncated, but it might also
+                            // be a damaged part in the file that makes
+                            // the decoder think the file is truncated.
+                            // If you prefer, you can use the same error
+                            // message for this as for LZMA_DATA_ERROR.
+                            err_msg = "Compressed file is truncated or "
+                                      "otherwise corrupt";
+                            break;
+                       default:
+                            // This is most likely LZMA_PROG_ERROR.
+                            err_msg = "Unknown error, possibly a bug";
+                            break;
+                    }
+
+                    g_debug("%s: XZ: Error while decoding (%d): %s",
+                            __func__, lret, err_msg);
                     g_set_error(err, CR_COMPRESSION_WRAPPER_ERROR, CRE_XZ,
-                                "XZ: Error while deconding(%d)", lret);
+                                "XZ: Error while decoding (%d): %s",
+                                lret, err_msg);
                     return CR_CW_ERR;  // Error while decoding
                 }
 
index 6e490cf..193b036 100644 (file)
@@ -438,6 +438,8 @@ test_cr_error_handling(void)
     g_error_free(tmp_err);
     tmp_err = NULL;
 
+    // Opening dir for writing
+
     f = cr_open("/", CR_CW_MODE_WRITE, CR_CW_NO_COMPRESSION, &tmp_err);
     g_assert(!f);
     g_assert(tmp_err);
@@ -445,6 +447,69 @@ test_cr_error_handling(void)
     g_error_free(tmp_err);
     tmp_err = NULL;
 
+    f = cr_open("/", CR_CW_MODE_WRITE, CR_CW_GZ_COMPRESSION, &tmp_err);
+    g_assert(!f);
+    g_assert(tmp_err);
+    g_assert_cmpint(tmp_err->code, ==, CRE_GZ);
+    g_error_free(tmp_err);
+    tmp_err = NULL;
+
+    f = cr_open("/", CR_CW_MODE_WRITE, CR_CW_BZ2_COMPRESSION, &tmp_err);
+    g_assert(!f);
+    g_assert(tmp_err);
+    g_assert_cmpint(tmp_err->code, ==, CRE_IO);
+    g_error_free(tmp_err);
+    tmp_err = NULL;
+
+    f = cr_open("/", CR_CW_MODE_WRITE, CR_CW_XZ_COMPRESSION, &tmp_err);
+    g_assert(!f);
+    g_assert(tmp_err);
+    g_assert_cmpint(tmp_err->code, ==, CRE_XZ);
+    g_error_free(tmp_err);
+    tmp_err = NULL;
+
+    // Opening plain text file as compressed
+
+    char buf[256];
+    int ret;
+
+    // gzread can read compressed as well as uncompressed, so this test
+    // is useful.
+    f = cr_open(FILE_COMPRESSED_1_PLAIN, CR_CW_MODE_READ,
+                CR_CW_GZ_COMPRESSION, &tmp_err);
+    g_assert(f);
+    ret = cr_read(f, buf, 256, &tmp_err);
+    g_assert_cmpint(ret, ==, FILE_COMPRESSED_1_CONTENT_LEN);
+    g_assert(!tmp_err);
+    ret = cr_close(f, &tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
+    g_assert(!tmp_err);
+
+    f = cr_open(FILE_COMPRESSED_1_PLAIN, CR_CW_MODE_READ,
+                CR_CW_BZ2_COMPRESSION, &tmp_err);
+    g_assert(f);
+    ret = cr_read(f, buf, 256, &tmp_err);
+    g_assert_cmpint(ret, ==, -1);
+    g_assert(tmp_err);
+    g_assert_cmpint(tmp_err->code, ==, CRE_BZ2);
+    g_error_free(tmp_err);
+    tmp_err = NULL;
+    ret = cr_close(f, &tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
+    g_assert(!tmp_err);
+
+    f = cr_open(FILE_COMPRESSED_1_PLAIN, CR_CW_MODE_READ,
+                CR_CW_XZ_COMPRESSION, &tmp_err);
+    g_assert(f);
+    ret = cr_read(f, buf, 256, &tmp_err);
+    g_assert_cmpint(ret, ==, -1);
+    g_assert(tmp_err);
+    g_assert_cmpint(tmp_err->code, ==, CRE_XZ);
+    g_error_free(tmp_err);
+    tmp_err = NULL;
+    ret = cr_close(f, &tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
+    g_assert(!tmp_err);
 }