misc: Add support for GError reporting.
authorTomas Mlcoch <xtojaj@gmail.com>
Sat, 1 Jun 2013 16:03:03 +0000 (18:03 +0200)
committerTomas Mlcoch <xtojaj@gmail.com>
Sat, 1 Jun 2013 16:03:03 +0000 (18:03 +0200)
src/createrepo_c.c
src/error.c
src/error.h
src/locate_metadata.c
src/mergerepo_c.c
src/misc.c
src/misc.h
src/parsepkg.c
tests/test_misc.c
tests/test_sqlite.c
tests/test_xml_file.c

index f5bfb1a..a7faefc 100644 (file)
@@ -115,7 +115,7 @@ sigint_catcher(int sig)
     CR_UNUSED(sig);
     g_message("SIGINT catched: Terminating...");
     if (tmp_repodata_path)
-        cr_remove_dir(tmp_repodata_path);
+        cr_remove_dir(tmp_repodata_path, NULL);
     exit(1);
 }
 
@@ -786,8 +786,8 @@ main(int argc, char **argv)
                 cmd_options->groupfile_fullpath, groupfile);
 
         int ret;
-        ret = cr_better_copy_file(cmd_options->groupfile_fullpath, groupfile);
-        if (ret != CR_COPY_OK) {
+        ret = cr_better_copy_file(cmd_options->groupfile_fullpath, groupfile, NULL);
+        if (ret != CRE_OK) {
             g_critical("Error while copy %s -> %s",
                        cmd_options->groupfile_fullpath, groupfile);
         }
@@ -805,7 +805,7 @@ main(int argc, char **argv)
 
         g_debug("Copy groupfile %s -> %s", src_groupfile, groupfile);
 
-        if (cr_better_copy_file(src_groupfile, groupfile) != CR_COPY_OK)
+        if (cr_better_copy_file(src_groupfile, groupfile, NULL) != CRE_OK)
             g_critical("Error while copy %s -> %s", src_groupfile, groupfile);
     }
 
@@ -824,7 +824,7 @@ main(int argc, char **argv)
 
         g_debug("Copy updateinfo %s -> %s", src_updateinfo, updateinfo);
 
-        if (cr_better_copy_file(src_updateinfo, updateinfo) != CR_COPY_OK)
+        if (cr_better_copy_file(src_updateinfo, updateinfo, NULL) != CRE_OK)
             g_critical("Error while copy %s -> %s", src_updateinfo, updateinfo);
     }
 
@@ -1066,9 +1066,9 @@ main(int argc, char **argv)
 
         // Compress dbs
 
-        cr_compress_file(pri_db_filename, NULL, sqlite_compression);
-        cr_compress_file(fil_db_filename, NULL, sqlite_compression);
-        cr_compress_file(oth_db_filename, NULL, sqlite_compression);
+        cr_compress_file(pri_db_filename, NULL, sqlite_compression, NULL);
+        cr_compress_file(fil_db_filename, NULL, sqlite_compression, NULL);
+        cr_compress_file(oth_db_filename, NULL, sqlite_compression, NULL);
 
         remove(pri_db_filename);
         remove(fil_db_filename);
index 399c39d..b70b5f3 100644 (file)
@@ -101,6 +101,12 @@ cr_parsepkg_error_quark(void)
 }
 
 GQuark
+cr_misc_error_quark(void)
+{
+    return g_quark_from_static_string("cr_misc_error");
+}
+
+GQuark
 cr_repomd_error_quark(void)
 {
     return g_quark_from_static_string("cr_repomd_error");
index 534ad39..cbb5186 100644 (file)
@@ -72,6 +72,8 @@ typedef enum {
         (22) Xz (lzma) library related error */
     CRE_OPENSSL, /*!<
         (23) OpenSSL library related error */
+    CRE_CURL, /*!<
+        (24) Curl library related error */
 } cr_Error;
 
 /** Converts cr_Error return code to error string.
@@ -87,6 +89,7 @@ const char *cr_strerror(cr_Error rc);
 #define CR_LOAD_METADATA_ERROR          cr_load_metadata_error_quark()
 #define CR_LOCATE_METADATA_ERROR        cr_locate_metadata_error_quark()
 #define CR_PARSEPKG_ERROR               cr_parsepkg_error_quark()
+#define CR_MISC_ERROR                   cr_misc_error_quark()
 #define CR_REPOMD_ERROR                 cr_repomd_error_quark()
 #define CR_REPOMD_RECORD_ERROR          cr_repomd_record_error_quark()
 #define CR_XML_DUMP_FILELISTS_ERROR     cr_xml_dump_filelists_error_quark()
@@ -104,6 +107,7 @@ GQuark cr_db_error_quark(void);
 GQuark cr_load_metadata_error_quark(void);
 GQuark cr_locate_metadata_error_quark(void);
 GQuark cr_parsepkg_error_quark(void);
+GQuark cr_misc_error_quark(void);
 GQuark cr_repomd_error_quark(void);
 GQuark cr_repomd_record_error_quark(void);
 GQuark cr_xml_dump_filelists_error_quark(void);
index 6cf7e05..952673b 100644 (file)
@@ -45,7 +45,7 @@ cr_metadatalocation_free(struct cr_MetadataLocation *ml)
 
     if (ml->tmp && ml->local_path) {
         g_debug("%s: Removing %s", __func__,  ml->local_path);
-        cr_remove_dir(ml->local_path);
+        cr_remove_dir(ml->local_path, NULL);
     }
 
     g_free(ml->pri_xml_href);
@@ -358,30 +358,31 @@ cr_get_remote_metadata(const char *repopath, int ignore_sqlite)
 
 
     // Download all other repofiles
-    char *error = NULL;
+    GError *tmp_err = NULL;
 
     if (r_location->pri_xml_href)
-        cr_download(handle, r_location->pri_xml_href, tmp_repodata, &error);
-    if (!error && r_location->fil_xml_href)
-        cr_download(handle, r_location->fil_xml_href, tmp_repodata, &error);
-    if (!error && r_location->oth_xml_href)
-        cr_download(handle, r_location->oth_xml_href, tmp_repodata, &error);
-    if (!error && r_location->pri_sqlite_href)
-        cr_download(handle, r_location->pri_sqlite_href, tmp_repodata, &error);
-    if (!error && r_location->fil_sqlite_href)
-        cr_download(handle, r_location->fil_sqlite_href, tmp_repodata, &error);
-    if (!error && r_location->oth_sqlite_href)
-        cr_download(handle, r_location->oth_sqlite_href, tmp_repodata, &error);
-    if (!error && r_location->groupfile_href)
-        cr_download(handle, r_location->groupfile_href, tmp_repodata, &error);
-    if (!error && r_location->cgroupfile_href)
-        cr_download(handle, r_location->cgroupfile_href, tmp_repodata, &error);
-    if (!error && r_location->updateinfo_href)
-        cr_download(handle, r_location->updateinfo_href, tmp_repodata, &error);
-
-    if (error) {
-        g_critical("%s: Error while downloadig files: %s", __func__, error);
-        g_free(error);
+        cr_download(handle, r_location->pri_xml_href, tmp_repodata, &tmp_err);
+    if (!tmp_err && r_location->fil_xml_href)
+        cr_download(handle, r_location->fil_xml_href, tmp_repodata, &tmp_err);
+    if (!tmp_err && r_location->oth_xml_href)
+        cr_download(handle, r_location->oth_xml_href, tmp_repodata, &tmp_err);
+    if (!tmp_err && r_location->pri_sqlite_href)
+        cr_download(handle, r_location->pri_sqlite_href, tmp_repodata, &tmp_err);
+    if (!tmp_err && r_location->fil_sqlite_href)
+        cr_download(handle, r_location->fil_sqlite_href, tmp_repodata, &tmp_err);
+    if (!tmp_err && r_location->oth_sqlite_href)
+        cr_download(handle, r_location->oth_sqlite_href, tmp_repodata, &tmp_err);
+    if (!tmp_err && r_location->groupfile_href)
+        cr_download(handle, r_location->groupfile_href, tmp_repodata, &tmp_err);
+    if (!tmp_err && r_location->cgroupfile_href)
+        cr_download(handle, r_location->cgroupfile_href, tmp_repodata, &tmp_err);
+    if (!tmp_err && r_location->updateinfo_href)
+        cr_download(handle, r_location->updateinfo_href, tmp_repodata, &tmp_err);
+
+    if (tmp_err) {
+        g_critical("%s: Error while downloadig files: %s",
+                   __func__, tmp_err->message);
+        g_error_free(tmp_err);
         goto get_remote_metadata_cleanup;
     }
 
@@ -401,7 +402,7 @@ get_remote_metadata_cleanup:
     g_free(tmp_repodata);
     g_free(url);
     curl_easy_cleanup(handle);
-    if (!ret) cr_remove_dir(tmp_dir);
+    if (!ret) cr_remove_dir(tmp_dir, NULL);
     if (r_location) cr_metadatalocation_free(r_location);
 
     return ret;
index a315822..51992c2 100644 (file)
@@ -1227,17 +1227,23 @@ dump_merged_metadata(GHashTable *merged_hashtable,
         cr_db_close(oth_db, NULL);
 
         // Compress dbs
-        gchar *pri_db_filename = g_strconcat(cmd_options->tmp_out_repo, "/primary.sqlite", NULL);
-        gchar *fil_db_filename = g_strconcat(cmd_options->tmp_out_repo, "/filelists.sqlite", NULL);
-        gchar *oth_db_filename = g_strconcat(cmd_options->tmp_out_repo, "/other.sqlite", NULL);
+        gchar *pri_db_filename = g_strconcat(cmd_options->tmp_out_repo,
+                                             "/primary.sqlite", NULL);
+        gchar *fil_db_filename = g_strconcat(cmd_options->tmp_out_repo,
+                                             "/filelists.sqlite", NULL);
+        gchar *oth_db_filename = g_strconcat(cmd_options->tmp_out_repo,
+                                             "/other.sqlite", NULL);
 
         gchar *pri_db_c_filename = g_strconcat(pri_db_filename, db_suffix, NULL);
         gchar *fil_db_c_filename = g_strconcat(fil_db_filename, db_suffix, NULL);
         gchar *oth_db_c_filename = g_strconcat(oth_db_filename, db_suffix, NULL);
 
-        cr_compress_file(pri_db_filename, NULL, cmd_options->db_compression_type);
-        cr_compress_file(fil_db_filename, NULL, cmd_options->db_compression_type);
-        cr_compress_file(oth_db_filename, NULL, cmd_options->db_compression_type);
+        cr_compress_file(pri_db_filename, NULL,
+                         cmd_options->db_compression_type, NULL);
+        cr_compress_file(fil_db_filename, NULL,
+                         cmd_options->db_compression_type, NULL);
+        cr_compress_file(oth_db_filename, NULL,
+                         cmd_options->db_compression_type, NULL);
 
         remove(pri_db_filename);
         remove(fil_db_filename);
@@ -1493,7 +1499,7 @@ main(int argc, char **argv)
             struct cr_MetadataLocation *loc;
             loc = (struct cr_MetadataLocation  *) element->data;
             if (!groupfile && loc->groupfile_href) {
-                if (cr_copy_file(loc->groupfile_href, cmd_options->tmp_out_repo) == CR_COPY_OK) {
+                if (cr_copy_file(loc->groupfile_href, cmd_options->tmp_out_repo, NULL) == CRE_OK) {
                     groupfile = g_strconcat(cmd_options->tmp_out_repo,
                                             cr_get_filename(loc->groupfile_href),
                                             NULL);
@@ -1504,7 +1510,7 @@ main(int argc, char **argv)
         }
     } else {
         // Use groupfile specified by user
-        if (cr_copy_file(cmd_options->groupfile, cmd_options->tmp_out_repo) == CR_COPY_OK) {
+        if (cr_copy_file(cmd_options->groupfile, cmd_options->tmp_out_repo, NULL) == CRE_OK) {
             groupfile = g_strconcat(cmd_options->tmp_out_repo,
                                     cr_get_filename(cmd_options->groupfile),
                                     NULL);
index f63e30d..5d0986b 100644 (file)
@@ -220,7 +220,7 @@ cr_is_primary(const char *filename)
 #define VAL_LEN         4       // Len of numeric values in rpm
 
 struct cr_HeaderRangeStruct
-cr_get_header_byte_range(const char *filename)
+cr_get_header_byte_range(const char *filename, GError **err)
 {
     /* Values readed by fread are 4 bytes long and stored as big-endian.
      * So there is htonl function to convert this big-endian number into host
@@ -229,6 +229,8 @@ cr_get_header_byte_range(const char *filename)
 
     struct cr_HeaderRangeStruct results;
 
+    assert(!err || *err == NULL);
+
     results.start = 0;
     results.end   = 0;
 
@@ -239,6 +241,8 @@ cr_get_header_byte_range(const char *filename)
     if (!fp) {
         g_debug("%s: Cannot open file %s (%s)", __func__, filename,
                 strerror(errno));
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Cannot open %s: %s", filename, strerror(errno));
         return results;
     }
 
@@ -248,16 +252,29 @@ cr_get_header_byte_range(const char *filename)
     if (fseek(fp, 104, SEEK_SET) != 0) {
         g_debug("%s: fseek fail on %s (%s)", __func__, filename,
                 strerror(errno));
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Cannot seek over %s: %s", filename, strerror(errno));
         fclose(fp);
         return results;
     }
 
     unsigned int sigindex = 0;
     unsigned int sigdata  = 0;
-    fread(&sigindex, VAL_LEN, 1, fp);
+    if (fread(&sigindex, VAL_LEN, 1, fp) != 1) {
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "fread() error on %s: %s", filename, strerror(errno));
+        fclose(fp);
+        return results;
+    }
     sigindex = htonl(sigindex);
-    fread(&sigdata, VAL_LEN, 1, fp);
+    if (fread(&sigdata, VAL_LEN, 1, fp) != 1) {
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "fread() error on %s: %s", filename, strerror(errno));
+        fclose(fp);
+        return results;
+    }
     sigdata = htonl(sigdata);
+
     unsigned int sigindexsize = sigindex * 16;
     unsigned int sigsize = sigdata + sigindexsize;
     unsigned int disttoboundary = sigsize % 8;
@@ -271,9 +288,19 @@ cr_get_header_byte_range(const char *filename)
 
     unsigned int hdrindex = 0;
     unsigned int hdrdata  = 0;
-    fread(&hdrindex, VAL_LEN, 1, fp);
+    if (fread(&hdrindex, VAL_LEN, 1, fp) != 1) {
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "fread() error on %s: %s", filename, strerror(errno));
+        fclose(fp);
+        return results;
+    }
     hdrindex = htonl(hdrindex);
-    fread(&hdrdata, VAL_LEN, 1, fp);
+    if (fread(&hdrdata, VAL_LEN, 1, fp) != 1) {
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "fread() error on %s: %s", filename, strerror(errno));
+        fclose(fp);
+        return results;
+    }
     hdrdata = htonl(hdrdata);
     unsigned int hdrindexsize = hdrindex * 16;
     unsigned int hdrsize = hdrdata + hdrindexsize + 16;
@@ -287,6 +314,9 @@ cr_get_header_byte_range(const char *filename)
     if (hdrend < hdrstart) {
         g_debug("%s: sanity check fail on %s (%d > %d))", __func__,
                 filename, hdrstart, hdrend);
+        g_set_error(err, CR_MISC_ERROR, CRE_ERROR,
+                    "sanity check error on %s (hdrstart: %d > hdrend: %d)",
+                    filename, hdrstart, hdrend);
         return results;
     }
 
@@ -319,64 +349,72 @@ cr_get_filename(const char *filepath)
 
 
 int
-cr_copy_file(const char *src, const char *in_dst)
+cr_copy_file(const char *src, const char *in_dst, GError **err)
 {
+    int ret = CRE_OK;
     size_t readed;
     char buf[BUFFER_SIZE];
+    gchar *dst = (gchar *) in_dst;
 
-    FILE *orig;
-    FILE *new;
+    FILE *orig = NULL;
+    FILE *new  = NULL;
 
-    if (!src || !in_dst) {
-        g_debug("%s: File name cannot be NULL", __func__);
-        return CR_COPY_ERR;
-    }
+    assert(src);
+    assert(in_dst);
+    assert(!err || *err == NULL);
 
     // If destination is dir use filename from src
-    gchar *dst = (gchar *) in_dst;
-    if (g_str_has_suffix(in_dst, "/")) {
+    if (g_str_has_suffix(in_dst, "/"))
         dst = g_strconcat(in_dst, cr_get_filename(src), NULL);
-    }
 
-    if ((orig = fopen(src, "r")) == NULL) {
+    if ((orig = fopen(src, "rb")) == NULL) {
         g_debug("%s: Cannot open source file %s (%s)", __func__, src,
                 strerror(errno));
-        return CR_COPY_ERR;
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Cannot open file %s: %s", src, strerror(errno));
+        ret = CRE_IO;
+        goto copy_file_cleanup;
     }
 
-    if ((new = fopen(dst, "w")) == NULL) {
+    if ((new = fopen(dst, "wb")) == NULL) {
         g_debug("%s: Cannot open destination file %s (%s)", __func__, dst,
                 strerror(errno));
-        fclose(orig);
-        return CR_COPY_ERR;
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Cannot open file %s: %s", dst, strerror(errno));
+        ret = CRE_IO;
+        goto copy_file_cleanup;
     }
 
     while ((readed = fread(buf, 1, BUFFER_SIZE, orig)) > 0) {
-        if (fwrite(buf, 1, readed, new) != readed) {
-            g_debug("%s: Error while copy %s -> %s (%s)", __func__, src,
-                    dst, strerror(errno));
-            fclose(new);
-            fclose(orig);
-            return CR_COPY_ERR;
+        if (readed != BUFFER_SIZE && ferror(orig)) {
+            g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Error while read %s: %s", src, strerror(errno));
+            ret = CRE_IO;
+            goto copy_file_cleanup;
         }
 
-        if (readed != BUFFER_SIZE && ferror(orig)) {
+        if (fwrite(buf, 1, readed, new) != readed) {
             g_debug("%s: Error while copy %s -> %s (%s)", __func__, src,
                     dst, strerror(errno));
-            fclose(new);
-            fclose(orig);
-            return CR_COPY_ERR;
+            g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Error while write %s: %s", dst, strerror(errno));
+            ret = CRE_IO;
+            goto copy_file_cleanup;
         }
     }
 
-    if (dst != in_dst) {
+copy_file_cleanup:
+
+    if (dst != in_dst)
         g_free(dst);
-    }
 
-    fclose(new);
-    fclose(orig);
+    if (new)
+        fclose(new);
+
+    if (orig)
+        fclose(orig);
 
-    return CR_COPY_OK;
+    return ret;
 }
 
 
@@ -384,173 +422,193 @@ cr_copy_file(const char *src, const char *in_dst)
 int
 cr_compress_file(const char *src,
                  const char *in_dst,
-                 cr_CompressionType compression)
+                 cr_CompressionType compression,
+                 GError **err)
 {
+    int ret = CRE_OK;
     int readed;
     char buf[BUFFER_SIZE];
+    FILE *orig = NULL;
+    CR_FILE *new = NULL;
+    gchar *dst = (gchar *) in_dst;
+    GError *tmp_err = NULL;
 
-    FILE *orig;
-    CR_FILE *new;
-
-    if (!src) {
-        g_debug("%s: File name cannot be NULL", __func__);
-        return CR_COPY_ERR;
-    }
-
-    if (compression == CR_CW_AUTO_DETECT_COMPRESSION ||
-        compression == CR_CW_UNKNOWN_COMPRESSION) {
-        g_debug("%s: Bad compression type", __func__);
-        return CR_COPY_ERR;
-    }
+    assert(src);
+    assert(!err || *err == NULL);
 
     // Src must be a file NOT a directory
     if (!g_file_test(src, G_FILE_TEST_IS_REGULAR)) {
         g_debug("%s: Source (%s) must be directory!", __func__, src);
-        return CR_COPY_ERR;
+        g_set_error(err, CR_MISC_ERROR, CRE_NOFILE,
+                    "Not a regular file: %s", src);
+        return CRE_NOFILE;
     }
 
-    gchar *dst = (gchar *) in_dst;
     if (!dst) {
         // If destination is NULL, use src + compression suffix
-        const gchar *suffix = cr_compression_suffix(compression);
-        dst = g_strconcat(src, suffix, NULL);
-    } else {
+        dst = g_strconcat(src,
+                          cr_compression_suffix(compression),
+                          NULL);
+    } else if (g_str_has_suffix(in_dst, "/")) {
         // If destination is dir use filename from src + compression suffix
-        if (g_str_has_suffix(in_dst, "/")) {
-            const gchar *suffix = cr_compression_suffix(compression);
-            dst = g_strconcat(in_dst, cr_get_filename(src), suffix, NULL);
-        }
+        dst = g_strconcat(in_dst,
+                          cr_get_filename(src),
+                          cr_compression_suffix(compression),
+                          NULL);
     }
 
-    if ((orig = fopen(src, "r")) == NULL) {
+    orig = fopen(src, "rb");
+    if (orig == NULL) {
         g_debug("%s: Cannot open source file %s (%s)", __func__, src,
                 strerror(errno));
-        return CR_COPY_ERR;
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Cannot open %s: %s", src, strerror(errno));
+        ret = CRE_IO;
+        goto compress_file_cleanup;
     }
 
-    if ((new = cr_open(dst, CR_CW_MODE_WRITE, compression, NULL)) == NULL) {
+    new = cr_open(dst, CR_CW_MODE_WRITE, compression, &tmp_err);
+    if (tmp_err) {
         g_debug("%s: Cannot open destination file %s", __func__, dst);
-        fclose(orig);
-        return CR_COPY_ERR;
+        g_propagate_prefixed_error(err, tmp_err, "Cannot open %s: ", dst);
+        ret = CRE_IO;
+        goto compress_file_cleanup;
     }
 
     while ((readed = fread(buf, 1, BUFFER_SIZE, orig)) > 0) {
-        if (cr_write(new, buf, readed, NULL) != readed) {
-            g_debug("%s: Error while copy %s -> %s", __func__, src, dst);
-            cr_close(new, NULL);
-            fclose(orig);
-            return CR_COPY_ERR;
-        }
-
         if (readed != BUFFER_SIZE && ferror(orig)) {
             g_debug("%s: Error while copy %s -> %s (%s)", __func__, src,
                     dst, strerror(errno));
-            cr_close(new, NULL);
-            fclose(orig);
-            return CR_COPY_ERR;
+            g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                        "Error while read %s: %s", src, strerror(errno));
+            ret = CRE_IO;
+            goto compress_file_cleanup;
+        }
+
+        cr_write(new, buf, readed, &tmp_err);
+        if (tmp_err) {
+            g_debug("%s: Error while copy %s -> %s", __func__, src, dst);
+            g_propagate_prefixed_error(err, tmp_err,
+                    "Error while read %s: ", dst);
+            ret = CRE_IO;
+            goto compress_file_cleanup;
         }
     }
 
+compress_file_cleanup:
+
     if (dst != in_dst)
         g_free(dst);
 
-    cr_close(new, NULL);
-    fclose(orig);
+    if (orig)
+        fclose(orig);
+
+    if (new)
+        cr_close(new, NULL);
 
-    return CR_COPY_OK;
+    return ret;
 }
 
 
 
-void
-cr_download(CURL *handle, const char *url, const char *in_dst, char **error)
+int
+cr_download(CURL *handle,
+            const char *url,
+            const char *in_dst,
+            GError **err)
 {
     CURLcode rcode;
     FILE *file = NULL;
 
+    assert(!err || *err == NULL);
 
     // If destination is dir use filename from src
 
     gchar *dst = NULL;
-    if (g_str_has_suffix(in_dst, "/")) {
+    if (g_str_has_suffix(in_dst, "/"))
         dst = g_strconcat(in_dst, cr_get_filename(url), NULL);
-    } else if (g_file_test(in_dst, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
+    else if (g_file_test(in_dst, G_FILE_TEST_IS_DIR))
         dst = g_strconcat(in_dst, "/", cr_get_filename(url), NULL);
-    } else {
+    else
         dst = g_strdup(in_dst);
-    }
 
-    file = fopen(dst, "w");
+    file = fopen(dst, "wb");
     if (!file) {
-        *error = g_strdup_printf("%s: Cannot open %s", __func__, dst);
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Cannot open %s: %s", dst, strerror(errno));
         remove(dst);
         g_free(dst);
-        return;
+        return CRE_IO;
     }
 
 
     // Set URL
 
-    if (curl_easy_setopt(handle, CURLOPT_URL, url) != CURLE_OK) {
-        *error = g_strdup_printf("%s: curl_easy_setopt(CURLOPT_URL) error",
-                                 __func__);
+    rcode = curl_easy_setopt(handle, CURLOPT_URL, url);
+    if (rcode != CURLE_OK) {
+        g_set_error(err, CR_MISC_ERROR, CRE_CURL,
+                    "curl_easy_setopt failed: %s", curl_easy_strerror(rcode));
         fclose(file);
         remove(dst);
         g_free(dst);
-        return;
+        return CRE_CURL;
     }
 
 
     // Set output file descriptor
 
-    if (curl_easy_setopt(handle, CURLOPT_WRITEDATA, file) != CURLE_OK) {
-        *error = g_strdup_printf(
-                        "%s: curl_easy_setopt(CURLOPT_WRITEDATA) error",
-                         __func__);
+    rcode = curl_easy_setopt(handle, CURLOPT_WRITEDATA, file);
+    if (rcode != CURLE_OK) {
+        g_set_error(err, CR_MISC_ERROR, CRE_CURL,
+                    "curl_easy_setopt failed: %s", curl_easy_strerror(rcode));
         fclose(file);
         remove(dst);
         g_free(dst);
-        return;
+        return CRE_CURL;
     }
 
     rcode = curl_easy_perform(handle);
-    if (rcode != 0) {
-        *error = g_strdup_printf("%s: curl_easy_perform() error: %s",
-                                 __func__, curl_easy_strerror(rcode));
+    if (rcode != CURLE_OK) {
+        g_set_error(err, CR_MISC_ERROR, CRE_CURL,
+                    "curl_easy_perform failed: %s", curl_easy_strerror(rcode));
         fclose(file);
         remove(dst);
         g_free(dst);
-        return;
+        return CRE_CURL;
     }
 
-
     g_debug("%s: Successfully downloaded: %s", __func__, dst);
 
     fclose(file);
     g_free(dst);
+
+    return CRE_OK;
 }
 
 
 
 int
-cr_better_copy_file(const char *src, const char *in_dst)
+cr_better_copy_file(const char *src, const char *in_dst, GError **err)
 {
-    if (!strstr(src, "://")) {
-        // Probably local path
-        return cr_copy_file(src, in_dst);
-    }
+    GError *tmp_err = NULL;
+
+    assert(!err || *err == NULL);
+
+    if (!strstr(src, "://"))   // Probably local path
+        return cr_copy_file(src, in_dst, err);
 
-    char *error = NULL;
     CURL *handle = curl_easy_init();
-    cr_download(handle, src, in_dst, &error);
+    cr_download(handle, src, in_dst, &tmp_err);
     curl_easy_cleanup(handle);
-    if (error) {
+    if (tmp_err) {
         g_debug("%s: Error while downloading %s: %s", __func__, src,
-                error);
-        return CR_COPY_ERR;
+                tmp_err->message);
+        g_propagate_prefixed_error(err, tmp_err,
+                                   "Error while downloading %s: ", src);
+        return CRE_CURL;
     }
 
-    return CR_COPY_OK;
+    return CRE_OK;
 }
 
 
@@ -572,9 +630,20 @@ cr_remove_dir_cb(const char *fpath,
 
 
 int
-cr_remove_dir(const char *path)
+cr_remove_dir(const char *path, GError **err)
 {
-    return nftw(path, cr_remove_dir_cb, 64, FTW_DEPTH | FTW_PHYS);
+    int ret;
+
+    assert(!err || *err == NULL);
+
+    ret = nftw(path, cr_remove_dir_cb, 64, FTW_DEPTH | FTW_PHYS);
+    if (ret != 0) {
+        g_set_error(err, CR_MISC_ERROR, CRE_IO,
+                    "Cannot remove dir %s: %s", path, strerror(errno));
+        return CRE_IO;
+    }
+
+    return CRE_OK;
 }
 
 
index 823f511..c05cdf4 100644 (file)
@@ -111,9 +111,11 @@ struct cr_HeaderRangeStruct {
 
 /** Return header byte range.
  * @param filename      filename
+ * @param err           GError **
  * @return              header range (start = end = 0 on error)
  */
-struct cr_HeaderRangeStruct cr_get_header_byte_range(const char *filename);
+struct cr_HeaderRangeStruct cr_get_header_byte_range(const char *filename,
+                                                     GError **err);
 
 /** Return pointer to the rest of string after last '/'.
  * (e.g. for "/foo/bar" returns "bar")
@@ -122,29 +124,28 @@ struct cr_HeaderRangeStruct cr_get_header_byte_range(const char *filename);
  */
 char *cr_get_filename(const char *filepath);
 
-#define CR_COPY_OK              0       /*!< Copy successfully finished */
-#define CR_COPY_ERR             1       /*!< Error while copy */
-
 /** Download a file from the URL into the in_dst via curl handle.
- * If *error == NULL then download was successfull.
  * @param handle        CURL handle
  * @param url           source url
  * @param destination   destination (if destination is dir, filename from the
  *                      url is used)
- * @param error         pointer to string pointer for error message
- *                      (mandatory argument!)
+ * @param err           GError **
+ * @return              cr_Error
  */
-void cr_download(CURL *handle,
-                 const char *url,
-                 const char *destination,
-                 char **error);
+int cr_download(CURL *handle,
+                const char *url,
+                const char *destination,
+                GError **err);
 
 /** Copy file.
  * @param src           source filename
  * @param dst           destination (if dst is dir, filename of src is used)
- * @return              CR_COPY_OK or CR_COPY_ERR on error
+ * @param err           GError **
+ * @return              cr_Error return code
  */
-int cr_copy_file(const char *src, const char *dst);
+int cr_copy_file(const char *src,
+                 const char *dst,
+                 GError **err);
 
 /** Compress file.
  * @param src           source filename
@@ -152,24 +153,30 @@ int cr_copy_file(const char *src, const char *dst);
  *                      compression suffix is used.
  *                      If dst is NULL, src + compression suffix is used)
  * @param compression   type of compression
- * @return              CR_COPY_OK or CR_COPY_ERR on error
+ * @param err           GError **
+ * @return              cr_Error return code
  */
 int cr_compress_file(const char *src,
                      const char *dst,
-                     cr_CompressionType compression);
+                     cr_CompressionType compression,
+                     GError **err);
 
 /** Better copy file. Source (src) could be remote address (http:// or ftp://).
  * @param src           source filename
  * @param dst           destination (if dst is dir, filename of src is used)
- * @return              CR_COPY_OK or CR_COPY_ERR on error
+ * @param err           GError **
+ * @return              cr_Error return code
  */
-int cr_better_copy_file(const char *src, const char *dst);
+int cr_better_copy_file(const char *src,
+                        const char *dst,
+                        GError **err);
 
 /** Recursively remove directory.
  * @param path          filepath
- * @return              0 on success, nonzero on failure (errno is set)
+ * @param err           GError **
+ * @return              cr_Error return code
  */
-int cr_remove_dir(const char *path);
+int cr_remove_dir(const char *path, GError **err);
 
 /** Normalize path (Path with exactly one trailing '/').
  *@param path           path
index f319338..75b4877 100644 (file)
@@ -172,7 +172,13 @@ cr_package_from_rpm(const char *filename,
 
     // Get header range
 
-    struct cr_HeaderRangeStruct hdr_r = cr_get_header_byte_range(filename);
+    struct cr_HeaderRangeStruct hdr_r = cr_get_header_byte_range(filename,
+                                                                 &tmp_err);
+    if (tmp_err) {
+        g_propagate_prefixed_error(err, tmp_err,
+                                   "Error while determinig header range: ");
+        return NULL;
+    }
 
 
     // Get package object
@@ -261,7 +267,13 @@ cr_xml_from_rpm(const char *filename,
 
     // Get header range
 
-    struct cr_HeaderRangeStruct hdr_r = cr_get_header_byte_range(filename);
+    struct cr_HeaderRangeStruct hdr_r = cr_get_header_byte_range(filename,
+                                                                 &tmp_err);
+    if (tmp_err) {
+        g_propagate_prefixed_error(err, tmp_err,
+                                   "Error while determinig header range: ");
+        return result;
+    }
 
 
     // Gen XML
index 6bda53c..b5d91ac 100644 (file)
@@ -25,6 +25,7 @@
 #include "fixtures.h"
 #include "createrepo/checksum.h"
 #include "createrepo/misc.h"
+#include "createrepo/error.h"
 
 #define PACKAGE_01              TEST_PACKAGES_PATH"super_kernel-6.0.1-2.x86_64.rpm"
 #define PACKAGE_01_HEADER_START 280
@@ -356,16 +357,21 @@ static void
 test_cr_get_header_byte_range(void)
 {
     struct cr_HeaderRangeStruct hdr_range;
+    GError *tmp_err = NULL;
 
-    hdr_range = cr_get_header_byte_range(PACKAGE_01);
+    hdr_range = cr_get_header_byte_range(PACKAGE_01, NULL);
     g_assert_cmpuint(hdr_range.start, ==, PACKAGE_01_HEADER_START);
     g_assert_cmpuint(hdr_range.end, ==, PACKAGE_01_HEADER_END);
 
-    hdr_range = cr_get_header_byte_range(PACKAGE_02);
+    hdr_range = cr_get_header_byte_range(PACKAGE_02, &tmp_err);
+    g_assert(!tmp_err);
     g_assert_cmpuint(hdr_range.start, ==, PACKAGE_02_HEADER_START);
     g_assert_cmpuint(hdr_range.end, ==, PACKAGE_02_HEADER_END);
 
-    hdr_range = cr_get_header_byte_range(NON_EXIST_FILE);
+    hdr_range = cr_get_header_byte_range(NON_EXIST_FILE, &tmp_err);
+    g_assert(tmp_err);
+    g_error_free(tmp_err);
+    tmp_err = NULL;
     g_assert_cmpuint(hdr_range.start, ==, 0);
     g_assert_cmpuint(hdr_range.end, ==, 0);
 }
@@ -437,10 +443,12 @@ copyfiletest_test_empty_file(Copyfiletest *copyfiletest, gconstpointer test_data
     CR_UNUSED(test_data);
     int ret;
     char *checksum;
+    GError *tmp_err = NULL;
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    ret = cr_copy_file(TEST_EMPTY_FILE, copyfiletest->dst_file);
-    g_assert_cmpint(ret, ==, CR_COPY_OK);
+    ret = cr_copy_file(TEST_EMPTY_FILE, copyfiletest->dst_file, &tmp_err);
+    g_assert(!tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
     checksum = cr_checksum_file(copyfiletest->dst_file, CR_CHECKSUM_SHA256, NULL);
     g_assert_cmpstr(checksum, ==, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
@@ -456,8 +464,8 @@ copyfiletest_test_text_file(Copyfiletest *copyfiletest, gconstpointer test_data)
     char *checksum;
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    ret = cr_copy_file(TEST_TEXT_FILE, copyfiletest->dst_file);
-    g_assert_cmpint(ret, ==, CR_COPY_OK);
+    ret = cr_copy_file(TEST_TEXT_FILE, copyfiletest->dst_file, NULL);
+    g_assert_cmpint(ret, ==, CRE_OK);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
     checksum = cr_checksum_file(copyfiletest->dst_file, CR_CHECKSUM_SHA256, NULL);
     g_assert_cmpstr(checksum, ==, "2f395bdfa2750978965e4781ddf224c89646c7d7a1569b7ebb023b170f7bd8bb");
@@ -471,10 +479,12 @@ copyfiletest_test_binary_file(Copyfiletest *copyfiletest, gconstpointer test_dat
     CR_UNUSED(test_data);
     int ret;
     char *checksum;
+    GError *tmp_err = NULL;
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    ret = cr_copy_file(TEST_BINARY_FILE, copyfiletest->dst_file);
-    g_assert_cmpint(ret, ==, CR_COPY_OK);
+    ret = cr_copy_file(TEST_BINARY_FILE, copyfiletest->dst_file, &tmp_err);
+    g_assert(!tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
     checksum = cr_checksum_file(copyfiletest->dst_file, CR_CHECKSUM_SHA256, NULL);
     g_assert_cmpstr(checksum, ==, "bf68e32ad78cea8287be0f35b74fa3fecd0eaa91770b48f1a7282b015d6d883e");
@@ -488,17 +498,19 @@ copyfiletest_test_rewrite(Copyfiletest *copyfiletest, gconstpointer test_data)
     CR_UNUSED(test_data);
     int ret;
     char *checksum;
+    GError *tmp_err = NULL;
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    ret = cr_copy_file(TEST_BINARY_FILE, copyfiletest->dst_file);
-    g_assert_cmpint(ret, ==, CR_COPY_OK);
+    ret = cr_copy_file(TEST_BINARY_FILE, copyfiletest->dst_file, NULL);
+    g_assert_cmpint(ret, ==, CRE_OK);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
     checksum = cr_checksum_file(copyfiletest->dst_file, CR_CHECKSUM_SHA256, NULL);
     g_assert_cmpstr(checksum, ==, "bf68e32ad78cea8287be0f35b74fa3fecd0eaa91770b48f1a7282b015d6d883e");
     g_free(checksum);
 
-    ret = cr_copy_file(TEST_TEXT_FILE, copyfiletest->dst_file);
-    g_assert_cmpint(ret, ==, CR_COPY_OK);
+    ret = cr_copy_file(TEST_TEXT_FILE, copyfiletest->dst_file, &tmp_err);
+    g_assert(!tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
     checksum = cr_checksum_file(copyfiletest->dst_file, CR_CHECKSUM_SHA256, NULL);
     g_assert_cmpstr(checksum, ==, "2f395bdfa2750978965e4781ddf224c89646c7d7a1569b7ebb023b170f7bd8bb");
@@ -511,10 +523,20 @@ copyfiletest_test_corner_cases(Copyfiletest *copyfiletest, gconstpointer test_da
 {
     CR_UNUSED(test_data);
     int ret;
+    GError *tmp_err = NULL;
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    ret = cr_copy_file(NON_EXIST_FILE, copyfiletest->dst_file);
-    g_assert_cmpint(ret, ==, CR_COPY_ERR);
+
+    // Withou GError
+    ret = cr_copy_file(NON_EXIST_FILE, copyfiletest->dst_file, NULL);
+    g_assert_cmpint(ret, !=, CRE_OK);
+    g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
+
+    // With GError
+    ret = cr_copy_file(NON_EXIST_FILE, copyfiletest->dst_file, &tmp_err);
+    g_assert(tmp_err);
+    g_error_free(tmp_err);
+    g_assert_cmpint(ret, !=, CRE_OK);
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
 }
 
@@ -525,10 +547,12 @@ compressfile_test_text_file(Copyfiletest *copyfiletest, gconstpointer test_data)
     CR_UNUSED(test_data);
     int ret;
     char *checksum;
+    GError *tmp_err = NULL;
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    ret = cr_compress_file(TEST_TEXT_FILE, copyfiletest->dst_file, CR_CW_GZ_COMPRESSION);
-    g_assert_cmpint(ret, ==, CR_COPY_OK);
+    ret = cr_compress_file(TEST_TEXT_FILE, copyfiletest->dst_file, CR_CW_GZ_COMPRESSION, &tmp_err);
+    g_assert(!tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
     checksum = cr_checksum_file(copyfiletest->dst_file, CR_CHECKSUM_SHA256, NULL);
     g_assert_cmpstr(checksum, ==, "8909fde88a5747d800fd2562b0f22945f014aa7df64cf1c15c7933ae54b72ab6");
@@ -541,13 +565,11 @@ test_cr_download_valid_url_1(Copyfiletest *copyfiletest, gconstpointer test_data
 {
     CR_UNUSED(test_data);
 
-    char *error = NULL;
     CURL *handle = curl_easy_init();
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    cr_download(handle, VALID_URL_01, copyfiletest->dst_file, &error);
+    cr_download(handle, VALID_URL_01, copyfiletest->dst_file, NULL);
     curl_easy_cleanup(handle);
-    g_assert(!error);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
 }
 
@@ -558,13 +580,13 @@ test_cr_download_valid_url_2(Copyfiletest *copyfiletest, gconstpointer test_data
 {
     CR_UNUSED(test_data);
 
-    char *error = NULL;
     CURL *handle = curl_easy_init();
+    GError *tmp_err = NULL;
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    cr_download(handle, VALID_URL_01, copyfiletest->tmp_dir, &error);
+    cr_download(handle, VALID_URL_01, copyfiletest->tmp_dir, &tmp_err);
     curl_easy_cleanup(handle);
-    g_assert(!error);
+    g_assert(!tmp_err);
     char *dst = g_strconcat(copyfiletest->tmp_dir, "/", URL_FILENAME_01, NULL);
     g_assert(g_file_test(dst, G_FILE_TEST_EXISTS));
     g_free(dst);
@@ -576,14 +598,14 @@ test_cr_download_invalid_url(Copyfiletest *copyfiletest, gconstpointer test_data
 {
     CR_UNUSED(test_data);
 
-    char *error = NULL;
     CURL *handle = curl_easy_init();
+    GError *tmp_err = NULL;
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    cr_download(handle, INVALID_URL, copyfiletest->dst_file, &error);
+    cr_download(handle, INVALID_URL, copyfiletest->dst_file, &tmp_err);
     curl_easy_cleanup(handle);
-    g_assert(error);
-    free(error);
+    g_assert(tmp_err);
+    g_error_free(tmp_err);
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
 }
 
@@ -592,13 +614,16 @@ test_cr_download_invalid_url(Copyfiletest *copyfiletest, gconstpointer test_data
 static void
 test_cr_better_copy_file_local(Copyfiletest *copyfiletest, gconstpointer test_data)
 {
-    CR_UNUSED(test_data);
     int ret;
     char *checksum;
+    GError *tmp_err = NULL;
+
+    CR_UNUSED(test_data);
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    ret = cr_better_copy_file(TEST_BINARY_FILE, copyfiletest->dst_file);
-    g_assert_cmpint(ret, ==, CR_COPY_OK);
+    ret = cr_better_copy_file(TEST_BINARY_FILE, copyfiletest->dst_file, &tmp_err);
+    g_assert(!tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
     checksum = cr_checksum_file(copyfiletest->dst_file, CR_CHECKSUM_SHA256, NULL);
     g_assert_cmpstr(checksum, ==, "bf68e32ad78cea8287be0f35b74fa3fecd0eaa91770b48f1a7282b015d6d883e");
@@ -610,12 +635,15 @@ test_cr_better_copy_file_local(Copyfiletest *copyfiletest, gconstpointer test_da
 static void
 test_cr_better_copy_file_url(Copyfiletest *copyfiletest, gconstpointer test_data)
 {
-    CR_UNUSED(test_data);
     int ret;
+    GError *tmp_err = NULL;
+
+    CR_UNUSED(test_data);
 
     g_assert(!g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS));
-    ret = cr_better_copy_file(VALID_URL_01, copyfiletest->dst_file);
-    g_assert_cmpint(ret, ==, CR_COPY_OK);
+    ret = cr_better_copy_file(VALID_URL_01, copyfiletest->dst_file, &tmp_err);
+    g_assert(!tmp_err);
+    g_assert_cmpint(ret, ==, CRE_OK);
     g_assert(g_file_test(copyfiletest->dst_file, G_FILE_TEST_EXISTS|G_FILE_TEST_IS_REGULAR));
 }
 
@@ -666,7 +694,7 @@ test_cr_remove_dir(void)
     g_assert(g_file_test(tmp_file_2, G_FILE_TEST_EXISTS));
     g_assert(g_file_test(tmp_file_3, G_FILE_TEST_EXISTS));
 
-    cr_remove_dir(tmp_dir);
+    cr_remove_dir(tmp_dir, NULL);
 
     g_assert(!g_file_test(tmp_file_1, G_FILE_TEST_EXISTS));
     g_assert(!g_file_test(tmp_file_2, G_FILE_TEST_EXISTS));
index 1e9f8ed..ec0bc4e 100644 (file)
@@ -152,7 +152,7 @@ static void
 testdata_teardown(TestData *testdata, gconstpointer test_data)
 {
     CR_UNUSED(test_data);
-    cr_remove_dir(testdata->tmp_dir);
+    cr_remove_dir(testdata->tmp_dir, NULL);
     g_free(testdata->tmp_dir);
 }
 
index afe9d85..51a0c1b 100644 (file)
@@ -50,7 +50,7 @@ fixtures_teardown(TestFixtures *fixtures, gconstpointer test_data)
     if (!fixtures->tmpdir)
         return;
 
-    cr_remove_dir(fixtures->tmpdir);
+    cr_remove_dir(fixtures->tmpdir, NULL);
     g_free(fixtures->tmpdir);
 }