summaryrefslogtreecommitdiff
path: root/src/fr-command-rar.c
diff options
context:
space:
mode:
authorStefano Karapetsas <[email protected]>2013-10-24 14:37:28 -0700
committerStefano Karapetsas <[email protected]>2013-10-24 14:37:28 -0700
commit9f27a08a962aaf861ce7ffffc911f5c15a95f4f2 (patch)
treefdfea84de35f79c66d8889ebd6acb6a8def1e901 /src/fr-command-rar.c
parent040aec00a2422b276eed5836a138d8a0231b2611 (diff)
parent14790d2d45e43643ff6b11cde1b1bb53cc4ea9ac (diff)
downloadengrampa-9f27a08a962aaf861ce7ffffc911f5c15a95f4f2.tar.bz2
engrampa-9f27a08a962aaf861ce7ffffc911f5c15a95f4f2.tar.xz
Merge pull request #26 from NiceandGently/master
add support for rar-5.0x
Diffstat (limited to 'src/fr-command-rar.c')
-rw-r--r--src/fr-command-rar.c168
1 files changed, 126 insertions, 42 deletions
diff --git a/src/fr-command-rar.c b/src/fr-command-rar.c
index 6ef0859..631d58a 100644
--- a/src/fr-command-rar.c
+++ b/src/fr-command-rar.c
@@ -56,8 +56,8 @@ have_rar (void)
static time_t
-mktime_from_string (char *date_s,
- char *time_s)
+mktime_from_string (const char *date_s,
+ const char *time_s)
{
struct tm tm = {0, };
char **fields;
@@ -90,6 +90,84 @@ mktime_from_string (char *date_s,
return mktime (&tm);
}
+/* Sample rar-5 listing output:
+
+RAR 5.00 beta 8 Copyright (c) 1993-2013 Alexander Roshal 22 Aug 2013
+Trial version Type RAR -? for help
+
+Archive: test.rar
+Details: RAR 4
+
+ Attributes Size Packed Ratio Date Time Checksum Name
+----------- --------- -------- ----- -------- ----- -------- ----
+ -rw-r--r-- 453 304 67% 05-09-13 09:55 56DA5EF3 loremipsum.txt
+----------- --------- -------- ----- -------- ----- -------- ----
+ 453 304 67% 1
+
+ *
+ * Sample rar-4 listing output:
+ *
+
+RAR 4.20 Copyright (c) 1993-2012 Alexander Roshal 9 Jun 2012
+Trial version Type RAR -? for help
+
+Archive test.rar
+
+Pathname/Comment
+ Size Packed Ratio Date Time Attr CRC Meth Ver
+-------------------------------------------------------------------------------
+ loremipsum.txt
+ 453 304 67% 05-09-13 09:55 -rw-r--r-- 56DA5EF3 m3b 2.9
+-------------------------------------------------------------------------------
+ 1 453 304 67%
+
+ */
+
+static void
+parse_name_field (char *line,
+ FrCommandRar *rar_comm)
+{
+ char *name_field;
+ FileData *fdata;
+
+ rar_comm->fdata = fdata = file_data_new ();
+
+ /* read file name. */
+
+ fdata->encrypted = (line[0] == '*') ? TRUE : FALSE;
+
+ if (rar_comm->rar5)
+ /* rar-5 output adds trailing spaces to short file names :( */
+ name_field = g_strchomp (g_strdup (get_last_field (line, 8)));
+ else
+ name_field = g_strdup (line + 1);
+
+ if (*name_field == '/') {
+ fdata->full_path = g_strdup (name_field);
+ fdata->original_path = fdata->full_path;
+ }
+ else {
+ fdata->full_path = g_strconcat ("/", name_field, NULL);
+ fdata->original_path = fdata->full_path + 1;
+ }
+
+ fdata->link = NULL;
+ fdata->path = remove_level_from_path (fdata->full_path);
+
+ g_free (name_field);
+}
+
+static gboolean
+attr_field_is_dir (const char *attr_field,
+ FrCommandRar *rar_comm)
+{
+ if ((attr_field[0] == 'd') ||
+ (rar_comm->rar5 && attr_field[3] == 'D') ||
+ (!rar_comm->rar5 && attr_field[1] == 'D'))
+ return TRUE;
+
+ return FALSE;
+}
static void
process_line (char *line,
@@ -98,14 +176,24 @@ process_line (char *line,
FrCommand *comm = FR_COMMAND (data);
FrCommandRar *rar_comm = FR_COMMAND_RAR (comm);
char **fields;
- const char *name_field;
g_return_if_fail (line != NULL);
if (! rar_comm->list_started) {
- if (strncmp (line, "--------", 8) == 0) {
+ if (strncmp (line, "RAR ", 4) == 0) {
+ int version;
+ sscanf (line, "RAR %d.", &version);
+ rar_comm->rar5 = (version >= 5);
+ }
+ else if (strncmp (line, "UNRAR ", 6) == 0) {
+ int version;
+ sscanf (line, "UNRAR %d.", &version);
+ rar_comm->rar5 = (version >= 5);
+ }
+ else if (strncmp (line, "--------", 8) == 0) {
rar_comm->list_started = TRUE;
- rar_comm->odd_line = TRUE;
+ if (! rar_comm->rar5)
+ rar_comm->rar4_odd_line = TRUE;
}
else if (strncmp (line, "Volume ", 7) == 0)
comm->multi_volume = TRUE;
@@ -117,24 +205,43 @@ process_line (char *line,
return;
}
- if (! rar_comm->odd_line) {
- FileData *fdata;
+ if (rar_comm->rar4_odd_line || rar_comm->rar5)
+ parse_name_field (line, rar_comm);
+
+ if (! rar_comm->rar4_odd_line) {
+ FileData *fdata;
+ const char *size_field, *ratio_field, *date_field, *time_field, *attr_field;
fdata = rar_comm->fdata;
/* read file info. */
fields = split_line (line, 6);
+ if (rar_comm->rar5) {
+ size_field = fields[1];
+ ratio_field = fields[3];
+ date_field = fields[4];
+ time_field = fields[5];
+ attr_field = fields[0];
+ }
+ else {
+ size_field = fields[0];
+ ratio_field = fields[2];
+ date_field = fields[3];
+ time_field = fields[4];
+ attr_field = fields[5];
+ }
if (g_strv_length (fields) < 6) {
/* wrong line format, treat this line as a filename line */
g_strfreev (fields);
file_data_free (rar_comm->fdata);
rar_comm->fdata = NULL;
- rar_comm->odd_line = TRUE;
+ rar_comm->rar4_odd_line = TRUE;
+ parse_name_field (line, rar_comm);
}
else {
- if ((strcmp (fields[2], "<->") == 0)
- || (strcmp (fields[2], "<--") == 0))
+ if ((strcmp (ratio_field, "<->") == 0)
+ || (strcmp (ratio_field, "<--") == 0))
{
/* ignore files that span more volumes */
@@ -142,10 +249,10 @@ process_line (char *line,
rar_comm->fdata = NULL;
}
else {
- fdata->size = g_ascii_strtoull (fields[0], NULL, 10);
- fdata->modified = mktime_from_string (fields[3], fields[4]);
+ fdata->size = g_ascii_strtoull (size_field, NULL, 10);
+ fdata->modified = mktime_from_string (date_field, time_field);
- if ((fields[5][1] == 'D') || (fields[5][0] == 'd')) {
+ if (attr_field_is_dir (attr_field, rar_comm)) {
char *tmp;
tmp = fdata->full_path;
@@ -159,8 +266,11 @@ process_line (char *line,
fdata->name = dir_name_from_path (fdata->full_path);
fdata->dir = TRUE;
}
- else
+ else {
fdata->name = g_strdup (file_name_from_path (fdata->full_path));
+ if (attr_field[0] == 'l')
+ fdata->link = g_strdup (file_name_from_path (fdata->full_path));
+ }
fr_command_add_file (comm, fdata);
rar_comm->fdata = NULL;
@@ -170,34 +280,8 @@ process_line (char *line,
}
}
- if (rar_comm->odd_line) {
- FileData *fdata;
-
- rar_comm->fdata = fdata = file_data_new ();
-
- /* read file name. */
-
- fdata->encrypted = (line[0] == '*') ? TRUE : FALSE;
-
- name_field = line + 1;
-
- if (*name_field == '/') {
- fdata->full_path = g_strdup (name_field);
- fdata->original_path = fdata->full_path;
- }
- else {
- fdata->full_path = g_strconcat ("/", name_field, NULL);
- fdata->original_path = fdata->full_path + 1;
- }
-
- fdata->link = NULL;
- fdata->path = remove_level_from_path (fdata->full_path);
- }
- else {
-
- }
-
- rar_comm->odd_line = ! rar_comm->odd_line;
+ if (! rar_comm->rar5)
+ rar_comm->rar4_odd_line = ! rar_comm->rar4_odd_line;
}