[gcab/wip/hughsie/future: 6/18] Use g_autoptr() to fix several memory leaks in the library
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcab/wip/hughsie/future: 6/18] Use g_autoptr() to fix several memory leaks in the library
- Date: Wed, 13 Dec 2017 23:02:52 +0000 (UTC)
commit d02b7219132c83c7c9b3e1d4738def38b44689e9
Author: Richard Hughes <richard hughsie com>
Date: Tue Dec 12 15:31:33 2017 +0000
Use g_autoptr() to fix several memory leaks in the library
The biggest change is to use the new-ish G_DECLARE_FINAL_TYPE to get rid of a
lot of C boilerplate.
This also gives us the new g_autoptr() cleanup functions for each object which
we can use to clean up the memory management in the command line tool and
removes a lot of memory leaks in the error paths.
gcab.c | 203 +++++++++++++++++++++++-------------------------
libgcab/gcab-cabinet.c | 116 +++++++++++----------------
libgcab/gcab-cabinet.h | 24 ++----
libgcab/gcab-file.c | 45 ++++++++++-
libgcab/gcab-file.h | 24 ++----
libgcab/gcab-folder.c | 96 +++++++++++------------
libgcab/gcab-folder.h | 16 +----
libgcab/gcab-priv.h | 29 ++------
8 files changed, 254 insertions(+), 299 deletions(-)
---
diff --git a/gcab.c b/gcab.c
index 18f5842..4d04ae3 100644
--- a/gcab.c
+++ b/gcab.c
@@ -1,6 +1,7 @@
/*
* LibGCab
* Copyright (c) 2012, Marc-André Lureau <marcandre lureau gmail com>
+ * Copyright (c) 2017, Richard Hughes <richard hughsie com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,20 +27,6 @@
#include <locale.h>
#include <glib/gi18n.h>
-G_GNUC_PRINTF(1, 2) static void
-gcab_error (const gchar *format, ...)
-{
- va_list args;
-
- g_fprintf (stderr, PACKAGE_NAME ": ");
- va_start(args, format);
- g_vfprintf (stderr, format, args);
- va_end(args);
- g_fprintf (stderr, "\n");
-
- exit (1);
-}
-
int verbose = 0;
static gboolean
@@ -52,11 +39,10 @@ file_callback (GCabFile *cabfile, gpointer data)
return TRUE;
if (file) {
- gchar *path = g_file_get_relative_path (cwd, file);
+ g_autofree gchar *path = g_file_get_relative_path (cwd, file);
if (!path)
path = g_file_get_parse_name (file);
g_print ("%s\n", path);
- g_free (path);
} else {
g_print ("%s\n", gcab_file_get_name (cabfile));
}
@@ -86,35 +72,35 @@ remove_leading_path (gchar *name)
return name + i;
}
-static
-void save_array_to_file (const GByteArray *array, const gchar *base, const gchar *suffix)
+static gboolean
+save_array_to_file (const GByteArray *array, const gchar *base, const gchar *suffix, GError **error)
{
- GError *error = NULL;
- gchar *resname = g_strdup_printf ("%s.%s", base, suffix);
+ g_autofree gchar *resname = NULL;
+ g_autoptr(GFile) outputfile = NULL;
+ g_autoptr(GOutputStream) output = NULL;
+ resname = g_strdup_printf ("%s.%s", base, suffix);
g_print (_("Dumping %s data to: %s ...\n"), suffix, resname);
- GFile *outputfile = g_file_new_for_commandline_arg (resname);
- GOutputStream *output = G_OUTPUT_STREAM (g_file_replace (outputfile, NULL, FALSE, 0, NULL, &error));
-
- if (!error)
- g_output_stream_write_all (output, array->data, array->len, NULL, NULL, &error);
-
- if (error)
- gcab_error (_("can't write file %s: %s"), resname, error->message);
-
- g_object_unref (output);
- g_object_unref (outputfile);
- g_free (resname);
- g_clear_error (&error);
+ outputfile = g_file_new_for_commandline_arg (resname);
+ output = G_OUTPUT_STREAM (g_file_replace (outputfile, NULL, FALSE, 0, NULL, error));
+ if (output == NULL) {
+ g_prefix_error (error, _("Cannot write file %s: "), resname);
+ return FALSE;
+ }
+ if (!g_output_stream_write_all (output, array->data, array->len, NULL, NULL, error)) {
+ g_prefix_error (error, _("Cannot write file %s: "), resname);
+ return FALSE;
+ }
+ return TRUE;
}
int
main (int argc, char *argv[])
{
- GError *error = NULL;
- GOptionContext *context;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GOptionContext) context = NULL;
- gchar **args = NULL;
- gchar *change = NULL;
+ g_auto(GStrv) args = NULL;
+ g_autofree gchar *change = NULL;
gboolean version = FALSE;
gboolean nopath = FALSE;
gboolean space = FALSE;
@@ -151,50 +137,59 @@ main (int argc, char *argv[])
g_set_prgname (PACKAGE_NAME);
context = g_option_context_new (_("- create a Cabinet file"));
- gchar *s = g_strdup_printf (_("Report bugs to <%s>"), PACKAGE_BUGREPORT);
+ g_autofree gchar *s = g_strdup_printf (_("Report bugs to <%s>"), PACKAGE_BUGREPORT);
g_option_context_set_description (context, s);
- g_free(s);
g_option_context_set_summary (context, _("\
gcab saves many files together into a cabinet archive, and can restore\n\
individual files from the archive.\
"));
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
- if (!g_option_context_parse (context, &argc, &argv, &error))
- gcab_error (_("option parsing failed: %s\n"), (error && error->message) ? error->message : "unknown
error");
- g_option_context_free(context);
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ g_printerr ("%s: %s\n", _("Option parsing failed"), error->message);
+ return EXIT_FAILURE;
+ }
if (version) {
g_printf (PACKAGE_STRING "\n");
return 0;
}
- if ((list + extract + create + dump_reserved + list_details) != 1)
- gcab_error (_("Please specify a single operation."));
+ if ((list + extract + create + dump_reserved + list_details) != 1) {
+ g_printerr ("%s\n", _("Please specify a single operation"));
+ return EXIT_FAILURE;
+ }
- if (!args || args[0] == NULL)
- gcab_error (_("cabinet file must be specified."));
+ if (!args || args[0] == NULL) {
+ g_printerr ("%s\n", _("Cabinet file must be specified"));
+ return EXIT_FAILURE;
+ }
- GCancellable *cancellable = g_cancellable_new ();
- GCabCabinet *cabinet = gcab_cabinet_new ();
- GCabFolder *folder;
- GFile *outputfile;
- GOutputStream *output;
- GFile *cwd;
+ g_autoptr(GCabCabinet) cabinet = gcab_cabinet_new ();
+ g_autoptr(GCabFolder) folder = NULL;
+ g_autoptr(GCancellable) cancellable = g_cancellable_new ();
+ g_autoptr(GFile) cwd = NULL;
+ g_autoptr(GFile) outputfile = NULL;
+ g_autoptr(GOutputStream) output = NULL;
if (list || list_details || extract || dump_reserved) {
- GFile *file = g_file_new_for_commandline_arg (args[0]);
- GInputStream *in = G_INPUT_STREAM (g_file_read (file, cancellable, &error));
+ g_autoptr(GFile) file = g_file_new_for_commandline_arg (args[0]);
+ g_autoptr(GInputStream) in = G_INPUT_STREAM (g_file_read (file, cancellable, &error));
- if (!in)
- gcab_error (_("can't open %s for reading: %s\n"), args[0], (error && error->message) ?
error->message : "unknown error");
- if (!gcab_cabinet_load (cabinet, in, cancellable, &error))
- gcab_error (_("error reading %s: %s\n"), args[0], (error && error->message) ? error->message :
"unknown error");
+ if (in == NULL) {
+ g_printerr ("%s %s: %s\n", _("Cannot open file for reading"), args[0], error->message);
+ return EXIT_FAILURE;
+ }
+ if (!gcab_cabinet_load (cabinet, in, cancellable, &error)) {
+ g_printerr ("%s %s: %s\n", _("Error reading"), args[0], error->message);
+ return EXIT_FAILURE;
+ }
if (list || list_details) {
GPtrArray *folders = gcab_cabinet_get_folders (cabinet);
for (guint i = 0; i < folders->len; i++) {
- GSList *l, *files = gcab_folder_get_files (g_ptr_array_index (folders, i));
+ GSList *l;
+ g_autoptr(GSList) files = gcab_folder_get_files (g_ptr_array_index (folders, i));
for (l = files; l != NULL; l = l->next) {
if (list_details) {
@@ -215,93 +210,91 @@ individual files from the archive.\
g_print ("%s\n", gcab_file_get_name (GCAB_FILE (l->data)));
}
}
- g_slist_free (files);
}
} else if (extract) {
- g_object_unref (file);
+ g_autoptr(GFile) file2 = NULL;
if (change == NULL)
change = g_get_current_dir ();
- file = g_file_new_for_path (change);
-
- if (!gcab_cabinet_extract (cabinet, file, file_callback, NULL, NULL, cancellable, &error))
- gcab_error (_("error during extraction: %s"), (error && error->message) ? error->message :
"unknown error");
+ file2 = g_file_new_for_path (change);
+ if (!gcab_cabinet_extract (cabinet, file2, file_callback, NULL, NULL, cancellable, &error)) {
+ g_printerr ("%s: %s\n", _("Error during extraction"), error->message);
+ return EXIT_FAILURE;
+ }
} else if (dump_reserved) {
- GByteArray *reserved;
-
+ g_autoptr(GByteArray) reserved = NULL;
g_object_get (cabinet, "reserved", &reserved, NULL);
if (reserved != NULL) {
- save_array_to_file (reserved, args[0], "header");
- g_byte_array_unref (reserved);
+ if (!save_array_to_file (reserved, args[0], "header", &error)) {
+ g_printerr ("%s\n", error->message);
+ return EXIT_FAILURE;
+ }
}
reserved = (GByteArray *)gcab_cabinet_get_signature (cabinet, cancellable, &error);
- if (error)
- gcab_error (_("error while reading signature: %s"), (error && error->message) ?
error->message : "unknown error");
+ if (reserved == NULL)
+ g_printerr ("%s: %s\n", _("Error while reading signature"), error->message);
if (reserved != NULL)
- save_array_to_file (reserved, args[0], "signature");
+ if (!save_array_to_file (reserved, args[0], "signature", &error)) {
+ g_printerr ("%s\n", error->message);
+ return EXIT_FAILURE;
+ }
}
-
- g_object_unref (in);
- g_object_unref (file);
- goto end;
+ return EXIT_SUCCESS;
}
- if (args[1] == NULL)
- gcab_error (_("please specify input files."));
+ if (args[1] == NULL) {
+ g_printerr ("%s\n", _("No input files specified"));
+ return EXIT_FAILURE;
+ }
if (space) {
- GByteArray *reserved = g_byte_array_sized_new (space);
+ g_autoptr(GByteArray) reserved = g_byte_array_sized_new (space);
g_byte_array_set_size (reserved, space);
g_object_set (cabinet, "reserved", reserved, NULL);
- g_byte_array_unref (reserved);
}
folder = gcab_folder_new (compress ? GCAB_COMPRESSION_MSZIP : 0);
for (gint i = 1; args[i]; i++) {
- GFile *file = g_file_new_for_commandline_arg (args[i]);
- gchar *name = nopath ? g_path_get_basename (args[i]) : g_strdup (args[i]);
- GCabFile *cabfile = gcab_file_new_with_file (
+ g_autoptr(GFile) file = g_file_new_for_commandline_arg (args[i]);
+ g_autofree gchar *name = nopath ? g_path_get_basename (args[i]) : g_strdup (args[i]);
+ g_autoptr(GCabFile) cabfile = gcab_file_new_with_file (
remove_leading_path (name), file);
if (!gcab_folder_add_file (folder, cabfile, TRUE, NULL, &error)) {
- g_warning (_("Can't add file %s: %s"), args[i], (error && error->message) ? error->message :
"unknown error");
+ g_warning ("%s %s: %s", _("Cannot add file"), args[i], error->message);
g_clear_error (&error);
}
-
- g_object_unref (cabfile);
- g_free (name);
- g_object_unref (file);
}
- if (gcab_folder_get_nfiles (folder) == 0)
- gcab_error (_("no files to be archived."));
+ if (gcab_folder_get_nfiles (folder) == 0) {
+ g_printerr ("%s\n", _("No files to be archived"));
+ return EXIT_FAILURE;
+ }
outputfile = g_file_new_for_commandline_arg (args[0]);
output = G_OUTPUT_STREAM (g_file_replace (outputfile, NULL, FALSE,
0, NULL, &error));
- if (error)
- gcab_error (_("can't create cab file %s: %s"), args[0], (error && error->message) ? error->message :
"unknown error");
+ if (output == NULL) {
+ g_printerr ("%s %s: %s\n", _("Cannot create cab file"), args[0], error->message);
+ return EXIT_FAILURE;
+ }
cwd = g_file_new_for_commandline_arg (".");
- if (!gcab_cabinet_add_folder (cabinet, folder, &error))
- gcab_error (_("can't add folder to cab file %s: %s"), args[0], (error && error->message) ?
error->message : "unknown error");
+ if (!gcab_cabinet_add_folder (cabinet, folder, &error)) {
+ g_printerr ("%s %s: %s\n", _("Cannot add folder to cab file"), args[0], error->message);
+ return EXIT_FAILURE;
+ }
if (!gcab_cabinet_write (cabinet, output,
file_callback,
NULL,
cwd,
NULL,
- &error))
- gcab_error (_("can't write cab file %s: %s"), args[0], (error && error->message) ? error->message :
"unknown error");
-
- g_object_unref (cwd);
- g_object_unref (output);
- g_object_unref (outputfile);
-
-end:
- g_object_unref (cabinet);
- g_object_unref (cancellable);
+ &error)) {
+ g_printerr ("%s %s: %s\n", _("Cannot write cab file"), args[0], error->message);
+ return EXIT_FAILURE;
+ }
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/libgcab/gcab-cabinet.c b/libgcab/gcab-cabinet.c
index 2c015e3..a1a64c4 100644
--- a/libgcab/gcab-cabinet.c
+++ b/libgcab/gcab-cabinet.c
@@ -1,6 +1,7 @@
/*
* LibGCab
* Copyright (c) 2012, Marc-André Lureau <marcandre lureau gmail com>
+ * Copyright (c) 2017, Richard Hughes <richard hughsie com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -35,13 +36,7 @@
* extracting and creation of archives.
*/
-struct _GCabCabinetClass
-{
- GObjectClass parent_class;
-};
-
-struct _GCabCabinet
-{
+struct _GCabCabinet {
GObject parent_instance;
GPtrArray *folders;
@@ -82,7 +77,8 @@ gcab_cabinet_finalize (GObject *object)
g_byte_array_unref (self->reserved);
if (self->signature)
g_byte_array_unref (self->signature);
- g_clear_object (&self->stream);
+ if (self->stream)
+ g_object_unref (self->stream);
G_OBJECT_CLASS (gcab_cabinet_parent_class)->finalize (object);
}
@@ -242,18 +238,15 @@ gcab_cabinet_write (GCabCabinet *self,
g_return_val_if_fail (self->folders->len == 1, FALSE);
GCabFolder *cabfolder = g_ptr_array_index (self->folders, 0);
- GCabFile *file;
gsize nfiles = gcab_folder_get_nfiles (cabfolder);
- GInputStream *in = NULL;
- GDataOutputStream *dstream = NULL;
- gboolean success = FALSE;
+ g_autoptr(GDataOutputStream) dstream = NULL;
gssize len, offset = 0;
cdata_t block = { 0, };
guint8 data[DATABLOCKSIZE];
gsize written;
size_t sumstr = 0;
- GSList *l, *files;
- cfile_t *prevf = NULL;
+ g_autoptr(GSList) files = NULL;
+ GCabFile *prevf = NULL;
dstream = g_data_output_stream_new (out);
g_data_output_stream_set_byte_order (dstream, G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
@@ -268,83 +261,79 @@ gcab_cabinet_write (GCabCabinet *self,
}
files = gcab_folder_get_files (cabfolder);
- for (l = files; l != NULL; l = l->next)
- sumstr += strlen (GCAB_FILE (l->data)->name) + 1;
+ for (GSList *l = files; l != NULL; l = l->next) {
+ GCabFile *cabfile = GCAB_FILE (l->data);
+ sumstr += strlen (gcab_file_get_name (cabfile)) + 1;
+ }
- folder.typecomp = cabfolder->comptype;
+ folder.typecomp = gcab_folder_get_comptype (cabfolder);
folder.offsetdata = header.offsetfiles + nfiles * 16 + sumstr;
folder.ndatab = gcab_folder_get_ndatablocks (cabfolder);
/* avoid seeking to allow growing output streams */
for (guint i = 0; i < folder.offsetdata; i++)
if (!g_data_output_stream_put_byte (dstream, 0, cancellable, error))
- goto end;
+ return FALSE;
+
+ for (GSList *l = files; l != NULL; l = l->next) {
+ g_autoptr(GInputStream) in = NULL;
- for (l = files; l != NULL; l = l->next) {
- file = GCAB_FILE (l->data);
+ GCabFile *file = GCAB_FILE (l->data);
if (file_callback)
file_callback (file, user_data);
- g_clear_object (&in);
- in = G_INPUT_STREAM (g_file_read (file->file, cancellable, error));
+ in = G_INPUT_STREAM (g_file_read (gcab_file_get_gfile (file), cancellable, error));
if (in == NULL)
- goto end;
+ return FALSE;
while ((len = g_input_stream_read (in,
&data[offset], DATABLOCKSIZE - offset,
cancellable, error)) == (DATABLOCKSIZE - offset)) {
if (!cdata_write (&block, dstream, folder.typecomp, data, DATABLOCKSIZE, &written, cancellable,
error))
- goto end;
+ return FALSE;
header.size += written;
offset = 0;
}
if (len == -1)
- goto end;
+ return FALSE;
offset += len;
}
if (offset != 0) {
if (!cdata_write (&block, dstream, folder.typecomp, data, offset, &written, cancellable, error))
- goto end;
+ return FALSE;
header.size += written;
}
if (!g_seekable_seek (G_SEEKABLE (out), 0,
G_SEEK_SET, cancellable, error))
- goto end;
+ return FALSE;
header.nfiles = nfiles;
header.size += header.offsetfiles + nfiles * 16; /* 1st part cfile struct = 16 bytes */
header.size += sumstr;
if (!cheader_write (&header, dstream, cancellable, error))
- goto end;
+ return FALSE;
if (!cfolder_write (&folder, dstream, cancellable, error))
- goto end;
+ return FALSE;
- for (l = files; l != NULL; l = l->next) {
- file = GCAB_FILE (l->data);
- file->cfile.uoffset = prevf ? prevf->uoffset + prevf->usize : 0;
- prevf = &file->cfile;
+ for (GSList *l = files; l != NULL; l = l->next) {
+ GCabFile *file = GCAB_FILE (l->data);
+ gcab_file_set_uoffset (file, prevf ? gcab_file_get_uoffset (prevf) + gcab_file_get_usize (prevf) :
0);
+ prevf = file;
/* automatically set flag if UTF-8 encoding */
- if (!g_str_is_ascii (file->cfile.name))
- file->cfile.fattr |= GCAB_FILE_ATTRIBUTE_NAME_IS_UTF;
+ if (!g_str_is_ascii (gcab_file_get_name (file)))
+ gcab_file_add_attribute (file, GCAB_FILE_ATTRIBUTE_NAME_IS_UTF);
- if (!cfile_write (&file->cfile, dstream, cancellable, error))
- goto end;
+ if (!cfile_write (gcab_file_get_cfile (file), dstream, cancellable, error))
+ return FALSE;
}
- success = TRUE;
-
-end:
- g_clear_object (&dstream);
- g_clear_object (&in);
- g_slist_free (files);
-
- return success;
+ return TRUE;
}
/**
@@ -413,16 +402,13 @@ gcab_cabinet_load (GCabCabinet *self,
self->stream = g_object_ref (stream);
- gboolean success = FALSE;
cheader_t cheader;
- GDataInputStream *in = g_data_input_stream_new (stream);
+ g_autoptr(GDataInputStream) in = g_data_input_stream_new (stream);
g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (in), FALSE);
g_data_input_stream_set_byte_order (in, G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
- GPtrArray *folders = self->folders;
-
if (!cheader_read (&cheader, in, cancellable, error))
- goto end;
+ return FALSE;
if (cheader.reserved)
g_object_set (self, "reserved",
@@ -432,48 +418,40 @@ gcab_cabinet_load (GCabCabinet *self,
for (guint i = 0; i < cheader.nfolders; i++) {
cfolder_t cfolder = { 0, };
if (!cfolder_read (&cfolder, cheader.res_folder, in, cancellable, error))
- goto end;
+ return FALSE;
GCabFolder *folder = gcab_folder_new_with_cfolder (&cfolder, stream);
if (cfolder.reserved)
g_object_set (folder, "reserved",
g_byte_array_new_take (cfolder.reserved, cheader.res_folder),
NULL);
- g_ptr_array_add (folders, folder);
+ g_ptr_array_add (self->folders, folder);
cfolder.reserved = NULL;
}
for (guint i = 0; i < cheader.nfiles; i++) {
cfile_t cfile = { 0, };
if (!cfile_read (&cfile, in, cancellable, error))
- goto end;
+ return FALSE;
- if (cfile.index >= folders->len) {
+ if (cfile.index >= self->folders->len) {
g_set_error (error, GCAB_ERROR, GCAB_ERROR_FORMAT,
"Invalid folder index");
- goto end;
+ return FALSE;
}
- GCabFolder *folder = g_ptr_array_index (folders, cfile.index);
+ GCabFolder *folder = g_ptr_array_index (self->folders, cfile.index);
if (folder == NULL) {
g_set_error (error, GCAB_ERROR, GCAB_ERROR_FORMAT,
"Invalid folder pointer");
- goto end;
+ return FALSE;
}
- GCabFile *file = gcab_file_new_with_cfile (&cfile);
- if (!gcab_folder_add_file (folder, file, FALSE, cancellable, error)) {
- g_object_unref (file);
- goto end;
- }
+ g_autoptr(GCabFile) file = gcab_file_new_with_cfile (&cfile);
+ if (!gcab_folder_add_file (folder, file, FALSE, cancellable, error))
+ return FALSE;
}
-
- success = TRUE;
-
-end:
- if (in)
- g_object_unref (in);
- return success;
+ return TRUE;
}
/**
diff --git a/libgcab/gcab-cabinet.h b/libgcab/gcab-cabinet.h
index e63763f..a880aa0 100644
--- a/libgcab/gcab-cabinet.h
+++ b/libgcab/gcab-cabinet.h
@@ -29,12 +29,13 @@
G_BEGIN_DECLS
+/**
+ * GCabCabinet:
+ *
+ * An opaque object holding a Cabinet file reference.
+ **/
#define GCAB_TYPE_CABINET (gcab_cabinet_get_type ())
-#define GCAB_CABINET(cabinet) (G_TYPE_CHECK_INSTANCE_CAST ((cabinet), GCAB_TYPE_CABINET,
GCabCabinet))
-#define GCAB_CABINET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCAB_TYPE_CABINET,
GCabCabinetClass))
-#define GCAB_IS_CABINET(cabinet) (G_TYPE_CHECK_INSTANCE_TYPE ((cabinet), GCAB_TYPE_CABINET))
-#define GCAB_IS_CABINET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCAB_TYPE_CABINET))
-#define GCAB_CABINET_GET_CLASS(cabinet) (G_TYPE_INSTANCE_GET_CLASS ((cabinet), GCAB_TYPE_CABINET,
GCabCabinetClass))
+G_DECLARE_FINAL_TYPE(GCabCabinet, gcab_cabinet, GCAB, CABINET, GObject)
/**
* GCAB_ERROR:
@@ -58,17 +59,6 @@ typedef enum GCabError
GCAB_ERROR_FAILED,
} GCabError;
-typedef struct _GCabCabinetClass GCabCabinetClass;
-
-/**
- * GCabCabinet:
- *
- * An opaque object holding a Cabinet file reference.
- **/
-typedef struct _GCabCabinet GCabCabinet;
-
-GType gcab_cabinet_get_type (void) G_GNUC_CONST;
-
GCabCabinet * gcab_cabinet_new (void);
gboolean gcab_cabinet_load (GCabCabinet *cabinet,
GInputStream *stream,
@@ -110,8 +100,6 @@ const GByteArray * gcab_cabinet_get_signature (GCabCabinet *cabinet,
GCancellable *cancellable,
GError **error);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GCabCabinet, g_object_unref)
-
G_END_DECLS
#endif /* _GCAB_CABINET_H_ */
diff --git a/libgcab/gcab-file.c b/libgcab/gcab-file.c
index 39284e4..72a6744 100644
--- a/libgcab/gcab-file.c
+++ b/libgcab/gcab-file.c
@@ -1,6 +1,7 @@
/*
* LibGCab
* Copyright (c) 2012, Marc-André Lureau <marcandre lureau gmail com>
+ * Copyright (c) 2017, Richard Hughes <richard hughsie com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -38,9 +39,14 @@
* must return a valid handle.
*/
-struct _GCabFileClass
+struct _GCabFile
{
- GObjectClass parent_class;
+ GObject parent_instance;
+
+ gchar *name;
+ gchar *extract_name;
+ GFile *file;
+ cfile_t cfile;
};
enum {
@@ -181,6 +187,41 @@ gcab_file_set_uoffset (GCabFile *self, guint32 uoffset)
return TRUE;
}
+G_GNUC_INTERNAL guint32
+gcab_file_get_uoffset (GCabFile *self)
+{
+ g_return_val_if_fail (GCAB_IS_FILE (self), 0);
+ return self->cfile.uoffset;
+}
+
+G_GNUC_INTERNAL guint32
+gcab_file_get_usize (GCabFile *self)
+{
+ g_return_val_if_fail (GCAB_IS_FILE (self), 0);
+ return self->cfile.usize;
+}
+
+G_GNUC_INTERNAL GFile *
+gcab_file_get_gfile (GCabFile *self)
+{
+ g_return_val_if_fail (GCAB_IS_FILE (self), NULL);
+ return self->file;
+}
+
+G_GNUC_INTERNAL void
+gcab_file_add_attribute (GCabFile *self, guint32 attribute)
+{
+ g_return_if_fail (GCAB_IS_FILE (self));
+ self->cfile.fattr |= attribute;
+}
+
+G_GNUC_INTERNAL cfile_t *
+gcab_file_get_cfile (GCabFile *self)
+{
+ g_return_val_if_fail (GCAB_IS_FILE (self), NULL);
+ return &self->cfile;
+}
+
/**
* gcab_file_get_size:
* @file: a #GCabFile
diff --git a/libgcab/gcab-file.h b/libgcab/gcab-file.h
index b7579f4..60e59d1 100644
--- a/libgcab/gcab-file.h
+++ b/libgcab/gcab-file.h
@@ -26,14 +26,13 @@
G_BEGIN_DECLS
+/**
+ * GCabFile:
+ *
+ * An opaque object, referencing a file in a Cabinet.
+ **/
#define GCAB_TYPE_FILE (gcab_file_get_type ())
-#define GCAB_FILE(file) (G_TYPE_CHECK_INSTANCE_CAST ((file), GCAB_TYPE_FILE, GCabFile))
-#define GCAB_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCAB_TYPE_FILE, GCabFileClass))
-#define GCAB_IS_FILE(file) (G_TYPE_CHECK_INSTANCE_TYPE ((file), GCAB_TYPE_FILE))
-#define GCAB_IS_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCAB_TYPE_FILE))
-#define GCAB_FILE_GET_CLASS(file) (G_TYPE_INSTANCE_GET_CLASS ((file), GCAB_TYPE_FILE, GCabFileClass))
-
-typedef struct _GCabFileClass GCabFileClass;
+G_DECLARE_FINAL_TYPE(GCabFile, gcab_file, GCAB, FILE, GObject)
/**
* GCabFileAttribute:
@@ -57,13 +56,6 @@ typedef enum
} GCabFileAttribute;
/**
- * GCabFile:
- *
- * An opaque object, referencing a file in a Cabinet.
- **/
-typedef struct _GCabFile GCabFile;
-
-/**
* GCabFileCallback:
* @file: the file being processed
* @user_data: user data passed to the callback.
@@ -73,8 +65,6 @@ typedef struct _GCabFile GCabFile;
**/
typedef gboolean (*GCabFileCallback) (GCabFile *file, gpointer user_data);
-GType gcab_file_get_type (void) G_GNUC_CONST;
-
GCabFile * gcab_file_new_with_file (const gchar *name, GFile *file);
GFile * gcab_file_get_file (GCabFile *file);
const gchar * gcab_file_get_name (GCabFile *file);
@@ -84,8 +74,6 @@ void gcab_file_get_date (GCabFile *file, GTimeVal *r
const gchar * gcab_file_get_extract_name (GCabFile *file);
void gcab_file_set_extract_name (GCabFile *file, const gchar *name);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GCabFile, g_object_unref)
-
G_END_DECLS
#endif /* _GCAB_FILE_H_ */
diff --git a/libgcab/gcab-folder.c b/libgcab/gcab-folder.c
index 10acd9a..f834753 100644
--- a/libgcab/gcab-folder.c
+++ b/libgcab/gcab-folder.c
@@ -1,6 +1,7 @@
/*
* LibGCab
* Copyright (c) 2012, Marc-André Lureau <marcandre lureau gmail com>
+ * Copyright (c) 2017, Richard Hughes <richard hughsie com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -44,9 +45,16 @@
* gcab_folder_add_file().
*/
-struct _GCabFolderClass
+struct _GCabFolder
{
- GObjectClass parent_class;
+ GObject parent_instance;
+
+ GSList *files;
+ GHashTable *hash;
+ gint comptype;
+ GByteArray *reserved;
+ cfolder_t cfolder;
+ GInputStream *stream;
};
enum {
@@ -160,12 +168,20 @@ gcab_folder_get_ndatablocks (GCabFolder *self)
gsize total_size = 0;
GSList *l;
- for (l = self->files; l != NULL; l = l->next)
- total_size += GCAB_FILE (l->data)->cfile.usize;
+ for (l = self->files; l != NULL; l = l->next) {
+ GCabFile *file = GCAB_FILE (l->data);
+ total_size += gcab_file_get_usize (file);
+ }
return total_size / DATABLOCKSIZE + 1 ;
}
+G_GNUC_INTERNAL gint
+gcab_folder_get_comptype (GCabFolder *self)
+{
+ return self->comptype;
+}
+
static gboolean
add_file (GCabFolder *self, GCabFile *file, GError **error)
{
@@ -194,33 +210,25 @@ add_file_info (GCabFolder *self, GCabFile *file, GFileInfo *info,
if (!recurse)
return TRUE;
- GFileEnumerator *dir = g_file_enumerate_children (file->file, FILE_ATTRS, 0, NULL, error);
- if (*error) {
+ g_autoptr(GFileEnumerator) dir = g_file_enumerate_children (gcab_file_get_gfile (file), FILE_ATTRS,
0, NULL, error);
+ if (dir == NULL) {
g_warning ("Couldn't enumerate directory %s: %s", name, (*error)->message);
g_clear_error (error);
return TRUE;
}
while ((info = g_file_enumerator_next_file (dir, NULL, error)) != NULL) {
- GFile *child = g_file_get_child (file->file, g_file_info_get_name (info));
- gchar *child_name = g_build_path ("\\", name, g_file_info_get_name (info), NULL);
- GCabFile *child_file = gcab_file_new_with_file (child_name, child);
-
- add_file_info (self, child_file, info, child_name, recurse, error);
- if (*error) {
+ g_autoptr(GFile) child = g_file_get_child (gcab_file_get_gfile (file), g_file_info_get_name
(info));
+ g_autofree gchar *child_name = g_build_path ("\\", name, g_file_info_get_name (info), NULL);
+ g_autoptr(GCabFile) child_file = gcab_file_new_with_file (child_name, child);
+ if (!add_file_info (self, child_file, info, child_name, recurse, error)) {
g_warning ("Couldn't add file %s: %s",
child_name, (*error)->message);
g_clear_error (error);
}
-
- g_object_unref (child_file);
- g_free (child_name);
- g_object_unref (child);
g_object_unref (info);
}
- g_object_unref (dir);
-
} else if (file_type == G_FILE_TYPE_REGULAR) {
gcab_file_update_info (file, info);
if (!add_file (self, file, error))
@@ -263,13 +271,11 @@ gcab_folder_add_file (GCabFolder *self, GCabFile *file,
if (gfile) {
g_return_val_if_fail (G_IS_FILE (gfile), FALSE);
- GFileInfo *info = g_file_query_info (gfile, FILE_ATTRS, 0, NULL, error);
+ g_autoptr(GFileInfo) info = g_file_query_info (gfile, FILE_ATTRS, 0, NULL, error);
if (info == NULL)
return FALSE;
-
success = add_file_info (self, file, info,
gcab_file_get_name (file), recurse, error);
- g_object_unref (info);
} else {
success = add_file (self, file, error);
}
@@ -346,7 +352,7 @@ sort_by_offset (GCabFile *a, GCabFile *b)
g_return_val_if_fail (a != NULL, 0);
g_return_val_if_fail (b != NULL, 0);
- return (gint64)a->cfile.uoffset - (gint64)b->cfile.uoffset;
+ return (gint64) gcab_file_get_uoffset (a) - (gint64) gcab_file_get_uoffset (b);
}
G_GNUC_INTERNAL gboolean
@@ -361,9 +367,10 @@ gcab_folder_extract (GCabFolder *self,
{
GError *my_error = NULL;
gboolean success = FALSE;
- GDataInputStream *data = NULL;
- GFileOutputStream *out = NULL;
- GSList *f, *files = NULL;
+ g_autoptr(GDataInputStream) data = NULL;
+ g_autoptr(GFileOutputStream) out = NULL;
+ GSList *f = NULL;
+ g_autoptr(GSList) files = NULL;
cdata_t cdata = { 0, };
guint32 nubytes = 0;
@@ -382,52 +389,45 @@ gcab_folder_extract (GCabFolder *self,
if (file_callback && !file_callback (file, callback_data))
continue;
- gchar *fname = g_strdup (gcab_file_get_extract_name (file));
+ g_autofree gchar *fname = g_strdup (gcab_file_get_extract_name (file));
int i = 0, len = strlen (fname);
for (i = 0; i < len; i++)
if (fname[i] == '\\')
fname[i] = '/';
- GFile *gfile = g_file_resolve_relative_path (path, fname);
- g_free (fname);
+ g_autoptr(GFile) gfile = g_file_resolve_relative_path (path, fname);
if (!g_file_has_prefix (gfile, path)) {
// "Rebase" the file in the given path, to ensure we never escape it
- char *rawpath = g_file_get_path (gfile);
+ g_autofree gchar *rawpath = g_file_get_path (gfile);
if (rawpath != NULL) {
char *newpath = rawpath;
while (*newpath != 0 && *newpath == G_DIR_SEPARATOR) {
newpath++;
}
- GFile *newgfile = g_file_resolve_relative_path (path, newpath);
- g_free (rawpath);
- g_object_unref (gfile);
- gfile = newgfile;
+ g_autoptr(GFile) newgfile = g_file_resolve_relative_path (path, newpath);
+ g_set_object (&gfile, newgfile);
}
}
- GFile *parent = g_file_get_parent (gfile);
+ g_autoptr(GFile) parent = g_file_get_parent (gfile);
if (!g_file_make_directory_with_parents (parent, cancellable, &my_error)) {
if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
g_clear_error (&my_error);
else {
- g_object_unref (gfile);
- g_object_unref (parent);
g_propagate_error (error, my_error);
goto end;
}
}
- g_object_unref (parent);
- g_clear_object (&out);
- out = g_file_replace (gfile, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, cancellable, error);
- g_object_unref (gfile);
- if (!out)
+ g_autoptr(GFileOutputStream) out2 = NULL;
+ out2 = g_file_replace (gfile, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, cancellable, error);
+ if (!out2)
goto end;
- guint32 usize = file->cfile.usize;
- guint32 uoffset = file->cfile.uoffset;
+ guint32 usize = gcab_file_get_usize (file);
+ guint32 uoffset = gcab_file_get_uoffset (file);
/* let's rewind if need be */
if (uoffset < nubytes) {
@@ -446,11 +446,11 @@ gcab_folder_extract (GCabFolder *self,
goto end;
continue;
} else {
- gsize offset = file->cfile.uoffset > nubytes ?
- file->cfile.uoffset - nubytes : 0;
+ gsize offset = gcab_file_get_uoffset (file) > nubytes ?
+ gcab_file_get_uoffset (file) - nubytes : 0;
const void *p = &cdata.out[offset];
gsize count = MIN (usize, cdata.nubytes - offset);
- if (!g_output_stream_write_all (G_OUTPUT_STREAM (out), p, count,
+ if (!g_output_stream_write_all (G_OUTPUT_STREAM (out2), p, count,
NULL, cancellable, error))
goto end;
usize -= count;
@@ -462,10 +462,6 @@ gcab_folder_extract (GCabFolder *self,
success = TRUE;
end:
- g_slist_free (files);
-
- g_clear_object (&data);
- g_clear_object (&out);
cdata_finish (&cdata, NULL);
return success;
diff --git a/libgcab/gcab-folder.h b/libgcab/gcab-folder.h
index f858686..12a191b 100644
--- a/libgcab/gcab-folder.h
+++ b/libgcab/gcab-folder.h
@@ -27,21 +27,13 @@
G_BEGIN_DECLS
-#define GCAB_TYPE_FOLDER (gcab_folder_get_type ())
-#define GCAB_FOLDER(folder) (G_TYPE_CHECK_INSTANCE_CAST ((folder), GCAB_TYPE_FOLDER, GCabFolder))
-#define GCAB_FOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCAB_TYPE_FOLDER, GCabFolderClass))
-#define GCAB_IS_FOLDER(folder) (G_TYPE_CHECK_INSTANCE_TYPE ((folder), GCAB_TYPE_FOLDER))
-#define GCAB_IS_FOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCAB_TYPE_FOLDER))
-#define GCAB_FOLDER_GET_CLASS(folder) (G_TYPE_INSTANCE_GET_CLASS ((folder), GCAB_TYPE_FOLDER,
GCabFolderClass))
-
-typedef struct _GCabFolderClass GCabFolderClass;
-
/**
* GCabFolder:
*
* An opaque object, referencing a folder in a Cabinet.
**/
-typedef struct _GCabFolder GCabFolder;
+#define GCAB_TYPE_FOLDER (gcab_folder_get_type ())
+G_DECLARE_FINAL_TYPE(GCabFolder, gcab_folder, GCAB, FOLDER, GObject)
/**
* GCabCompression:
@@ -63,8 +55,6 @@ typedef enum
GCAB_COMPRESSION_MASK = 0xf,
} GCabCompression;
-GType gcab_folder_get_type (void) G_GNUC_CONST;
-
GCabFolder * gcab_folder_new (gint comptype);
gboolean gcab_folder_add_file (GCabFolder *cabfolder,
GCabFile *cabfile,
@@ -74,8 +64,6 @@ gboolean gcab_folder_add_file (GCabFolder *cabfolder,
guint gcab_folder_get_nfiles (GCabFolder *cabfolder);
GSList * gcab_folder_get_files (GCabFolder *cabfolder);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(GCabFolder, g_object_unref)
-
G_END_DECLS
#endif /* _GCAB_FILE_H_ */
diff --git a/libgcab/gcab-priv.h b/libgcab/gcab-priv.h
index 349735b..b2cb232 100644
--- a/libgcab/gcab-priv.h
+++ b/libgcab/gcab-priv.h
@@ -40,35 +40,18 @@
_GCAB_GET (data, 1, 32, 8) | \
_GCAB_GET (data, 0, 32, 0))
-
-struct _GCabFile
-{
- GObject parent_instance;
-
- gchar *name;
- gchar *extract_name;
- GFile *file;
- cfile_t cfile;
-};
-
-struct _GCabFolder
-{
- GObject parent_instance;
-
- GSList *files;
- GHashTable *hash;
- gint comptype;
- GByteArray *reserved;
- cfolder_t cfolder;
- GInputStream *stream;
-};
-
GCabFolder * gcab_folder_new_with_cfolder (const cfolder_t *folder, GInputStream *stream);
GCabFile * gcab_file_new_with_cfile (const cfile_t *file);
gboolean gcab_file_update_info (GCabFile *file, GFileInfo *info);
+guint32 gcab_file_get_uoffset (GCabFile *file);
gboolean gcab_file_set_uoffset (GCabFile *file, guint32 uoffset);
+guint32 gcab_file_get_usize (GCabFile *file);
+GFile *gcab_file_get_gfile (GCabFile *file);
+cfile_t *gcab_file_get_cfile (GCabFile *file);
+void gcab_file_add_attribute (GCabFile *file, guint32 attribute);
+gint gcab_folder_get_comptype (GCabFolder *folder);
gsize gcab_folder_get_ndatablocks (GCabFolder *folder);
gboolean gcab_folder_extract (GCabFolder *self,
GFile *path,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]