summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2013-08-04 00:15:39 +0800
committerLAN-TW <lantw44@gmail.com>2013-08-04 00:15:39 +0800
commiteb09b3fa8c3026188615b4255c94249104055f4b (patch)
tree6ad225161a4c690b2786380a36dfdd86d895ab7c
parentc0603c06173781dc34090cd784d81a6fb46288fb (diff)
downloadgsoc2013-libgnome-autoar-eb09b3fa8c3026188615b4255c94249104055f4b.tar
gsoc2013-libgnome-autoar-eb09b3fa8c3026188615b4255c94249104055f4b.tar.gz
gsoc2013-libgnome-autoar-eb09b3fa8c3026188615b4255c94249104055f4b.tar.bz2
gsoc2013-libgnome-autoar-eb09b3fa8c3026188615b4255c94249104055f4b.tar.lz
gsoc2013-libgnome-autoar-eb09b3fa8c3026188615b4255c94249104055f4b.tar.xz
gsoc2013-libgnome-autoar-eb09b3fa8c3026188615b4255c94249104055f4b.tar.zst
gsoc2013-libgnome-autoar-eb09b3fa8c3026188615b4255c94249104055f4b.zip
Workaround for some libarchive problems
1. archive_write_data may return 0. The manual page says it will return bytes actually written or -1 on error, but it does not say what zero means. This will cause infinite loop in the program. 2. libarchive may use NULL as its error message. It is not expected because NULL is not a valid string. Therefore, I remove replace g_error_new_literal with g_error_new to make sure the function return when error occurs.
-rw-r--r--gnome-autoar/autoar-create.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/gnome-autoar/autoar-create.c b/gnome-autoar/autoar-create.c
index 388c325..8dd36f4 100644
--- a/gnome-autoar/autoar-create.c
+++ b/gnome-autoar/autoar-create.c
@@ -44,6 +44,7 @@ G_DEFINE_TYPE (AutoarCreate, autoar_create, G_TYPE_OBJECT)
(G_TYPE_INSTANCE_GET_PRIVATE ((o), AUTOAR_TYPE_CREATE, AutoarCreatePrivate))
#define BUFFER_SIZE (64 * 1024)
+#define ARCHIVE_WRITE_RETRY_TIMES 5
struct _AutoarCreatePrivate
{
@@ -390,9 +391,11 @@ autoar_create_do_write_data (AutoarCreate *arcreate,
while ((r = archive_write_header (a, entry)) == ARCHIVE_RETRY);
if (r == ARCHIVE_FATAL) {
if (arcreate->priv->error == NULL)
- arcreate->priv->error = g_error_new_literal (autoar_create_quark,
- archive_errno (a),
- archive_error_string (a));
+ arcreate->priv->error = g_error_new (autoar_create_quark,
+ archive_errno (a),
+ "\'%s\': %s",
+ archive_entry_pathname (entry),
+ archive_error_string (a));
return;
}
@@ -402,6 +405,7 @@ autoar_create_do_write_data (AutoarCreate *arcreate,
if (archive_entry_size (entry) > 0 && archive_entry_filetype (entry) == AE_IFREG) {
GInputStream *istream;
ssize_t read_actual, written_actual, written_acc;
+ int written_try;
g_debug ("autoar_create_do_write_data: entry size is %"G_GUINT64_FORMAT,
archive_entry_size (entry));
@@ -429,10 +433,14 @@ autoar_create_do_write_data (AutoarCreate *arcreate,
arcreate->priv->completed_files);
if (read_actual > 0) {
written_acc = 0;
+ written_try = 0;
do {
written_actual = archive_write_data (a, (const char*)(arcreate->priv->buffer) + written_acc, read_actual);
written_acc += written_actual > 0 ? written_actual : 0;
- } while (written_acc < read_actual && written_actual >= 0);
+ written_try = written_actual ? 0 : written_try + 1;
+ /* archive_write_data may return zero, so we have to limit the
+ * retry times to prevent infinite loop */
+ } while (written_acc < read_actual && written_actual >= 0 && written_try < ARCHIVE_WRITE_RETRY_TIMES);
}
} while (read_actual > 0 && written_actual >= 0);
@@ -443,11 +451,13 @@ autoar_create_do_write_data (AutoarCreate *arcreate,
if (read_actual < 0)
return;
- if (written_actual < 0) {
+ if (written_actual < 0 || written_try >= ARCHIVE_WRITE_RETRY_TIMES) {
if (arcreate->priv->error == NULL)
- arcreate->priv->error = g_error_new_literal (autoar_create_quark,
- archive_errno (a),
- archive_error_string (a));
+ arcreate->priv->error = g_error_new (autoar_create_quark,
+ archive_errno (a),
+ "\'%s\': %s",
+ archive_entry_pathname (entry),
+ archive_error_string (a));
return;
}
g_debug ("autoar_create_do_write_data: write data OK");
@@ -1074,9 +1084,10 @@ autoar_create_run (AutoarCreate *arcreate,
if (r != ARCHIVE_OK) {
archive_write_free (a);
if (arcreate->priv->error == NULL)
- arcreate->priv->error = g_error_new_literal (autoar_create_quark,
- archive_errno (a),
- archive_error_string (a));
+ arcreate->priv->error = g_error_new (autoar_create_quark,
+ archive_errno (a),
+ "%s",
+ archive_error_string (a));
autoar_common_g_signal_emit (in_thread, arcreate,
autoar_create_signals[ERROR],
0, arcreate->priv->error);
@@ -1171,9 +1182,10 @@ autoar_create_run (AutoarCreate *arcreate,
r = archive_write_close (a);
if (r != ARCHIVE_OK) {
if (arcreate->priv->error == NULL)
- arcreate->priv->error = g_error_new_literal (autoar_create_quark,
- archive_errno (a),
- archive_error_string (a));
+ arcreate->priv->error = g_error_new (autoar_create_quark,
+ archive_errno (a),
+ "%s",
+ archive_error_string (a));
archive_write_free (a);
return;