summaryrefslogtreecommitdiff
path: root/src/fr-command-rar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fr-command-rar.c')
-rw-r--r--src/fr-command-rar.c185
1 files changed, 87 insertions, 98 deletions
diff --git a/src/fr-command-rar.c b/src/fr-command-rar.c
index 7794510..6bb70cd 100644
--- a/src/fr-command-rar.c
+++ b/src/fr-command-rar.c
@@ -20,6 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#define _XOPEN_SOURCE 700
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -49,10 +51,26 @@ static FrCommandClass *parent_class = NULL;
static gboolean date_newstyle = FALSE;
-static gboolean
-have_rar (void)
+static const struct {
+ const gchar *command;
+ FrCommandCaps capabilities;
+} candidate_commands[] = {
+ { "rar", FR_COMMAND_CAN_READ_WRITE | FR_COMMAND_CAN_CREATE_VOLUMES },
+ { "unrar", FR_COMMAND_CAN_READ },
+ { "unrar-free", FR_COMMAND_CAN_READ }
+};
+
+static const gchar *
+get_rar_command (void)
{
- return is_program_in_path ("rar");
+ for (guint i = 0; i < G_N_ELEMENTS(candidate_commands); i++) {
+ if (is_program_in_path (candidate_commands[i].command))
+ return candidate_commands[i].command;
+ }
+
+ /* this should never happen as we shouldn't get called if none of the
+ * candidate exist, but better safe than sorry */
+ return "unrar";
}
/* -- list -- */
@@ -112,46 +130,19 @@ static time_t
mktime_from_string (const char *date_s,
const char *time_s)
{
- struct tm tm = {0, };
- char **fields;
+ struct tm tm = {0, };
+ char *date_time_s;
tm.tm_isdst = -1;
-
- /* date */
-
- fields = g_strsplit (date_s, "-", 3);
- if (fields[0] != NULL) {
- if (date_newstyle)
- tm.tm_year = atoi (fields[0]) - 1900;
- else
- tm.tm_mday = atoi (fields[0]);
- if (fields[1] != NULL) {
- tm.tm_mon = atoi (fields[1]) - 1;
- if (fields[2] != NULL) {
- if (date_newstyle)
- tm.tm_mday = atoi (fields[2]);
- else
- tm.tm_year = 100 + atoi (fields[2]);
- }
- }
- }
- g_strfreev (fields);
-
- /* time */
-
- fields = g_strsplit (time_s, ":", 2);
- if (fields[0] != NULL) {
- tm.tm_hour = atoi (fields[0]);
- if (fields[1] != NULL)
- tm.tm_min = atoi (fields[1]);
- }
- g_strfreev (fields);
+ date_time_s = g_strjoin (" ", date_s, time_s, NULL);
+ strptime (date_time_s, date_newstyle ? "%Y-%m-%d %H:%M" : "%d-%m-%y %H:%M", &tm);
+ g_free (date_time_s);
return mktime (&tm);
}
static gboolean
-attribute_field_with_space (char *line)
+attribute_field_with_space (const char *line)
{
/* sometimes when the archive is encrypted the attributes field is
* like this: "* ..A...."
@@ -172,7 +163,7 @@ parse_name_field (char *line,
fdata->encrypted = (line[0] == '*') ? TRUE : FALSE;
- if (rar_comm->rar5)
+ if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5)
/* rar-5 output adds trailing spaces to short file names :( */
name_field = g_strchomp (g_strdup (get_last_field (line, attribute_field_with_space (line) ? 9 : 8)));
else
@@ -201,8 +192,8 @@ 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'))
+ (rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5 && attr_field[3] == 'D') ||
+ (rar_comm->output_type != FR_COMMAND_RAR_TYPE_RAR5 && attr_field[1] == 'D'))
return TRUE;
return FALSE;
@@ -219,39 +210,27 @@ process_line (char *line,
g_return_if_fail (line != NULL);
if (! rar_comm->list_started) {
- if (strncmp (line, "RAR ", 4) == 0) {
- int version;
- sscanf (line, "RAR %d.", &version);
- rar_comm->rar5 = (version >= 5);
+ int version = 0;
- if (version > 5)
- date_newstyle = TRUE;
- else if (version == 5)
- {
- sscanf (line, "RAR 5.%d ", &version);
- if (version >= 30)
- date_newstyle = TRUE;
- }
-
- }
- else if (strncmp (line, "UNRAR ", 6) == 0) {
- int version;
- sscanf (line, "UNRAR %d.", &version);
- rar_comm->rar5 = (version >= 5);
+ if (sscanf (line, "RAR %d.", &version) == 1 || sscanf (line, "UNRAR %d.", &version) == 1) {
+ rar_comm->output_type = (version >= 5) ? FR_COMMAND_RAR_TYPE_RAR5 : FR_COMMAND_RAR_TYPE_RAR4;
if (version > 5)
date_newstyle = TRUE;
- else if (version == 5)
+ else if (version == 5 && (sscanf (line, "RAR 5.%d ", &version) == 1 ||
+ sscanf (line, "UNRAR 5.%d ", &version) == 1))
{
- sscanf (line, "UNRAR 5.%d ", &version);
if (version >= 30)
date_newstyle = TRUE;
}
-
+ }
+ else if (g_str_has_prefix (line, "unrar-free ")) {
+ rar_comm->output_type = FR_COMMAND_RAR_TYPE_UNRAR_FREE;
+ date_newstyle = FALSE;
}
else if (strncmp (line, "--------", 8) == 0) {
rar_comm->list_started = TRUE;
- if (! rar_comm->rar5)
+ if (rar_comm->output_type != FR_COMMAND_RAR_TYPE_RAR5)
rar_comm->rar4_odd_line = TRUE;
}
else if (strncmp (line, "Volume ", 7) == 0)
@@ -264,35 +243,27 @@ process_line (char *line,
return;
}
- if (rar_comm->rar4_odd_line || rar_comm->rar5)
+ if (rar_comm->rar4_odd_line || rar_comm->output_type == FR_COMMAND_RAR_TYPE_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;
+ int n_fields;
+
+ if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5)
+ n_fields = 6 + (attribute_field_with_space (line) != 0);
+ else if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_UNRAR_FREE)
+ n_fields = 4;
+ else
+ n_fields = 6;
fdata = rar_comm->fdata;
/* read file info. */
- fields = split_line (line, attribute_field_with_space (line) ? 7 : 6);
- if (rar_comm->rar5) {
- int offset = attribute_field_with_space (line) ? 1 : 0;
-
- size_field = fields[1+offset];
- ratio_field = fields[3+offset];
- date_field = fields[4+offset];
- time_field = fields[5+offset];
- attr_field = fields[0+offset];
- }
- 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) {
+ fields = split_line (line, n_fields);
+ if (g_strv_length (fields) < (guint) n_fields) {
/* wrong line format, treat this line as a filename line */
g_strfreev (fields);
file_data_free (rar_comm->fdata);
@@ -301,6 +272,30 @@ process_line (char *line,
parse_name_field (line, rar_comm);
}
else {
+ if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_RAR5) {
+ int offset = attribute_field_with_space (line) ? 1 : 0;
+
+ size_field = fields[1+offset];
+ ratio_field = fields[3+offset];
+ date_field = fields[4+offset];
+ time_field = fields[5+offset];
+ attr_field = fields[0+offset];
+ }
+ else if (rar_comm->output_type == FR_COMMAND_RAR_TYPE_UNRAR_FREE) {
+ size_field = fields[0];
+ date_field = fields[1];
+ time_field = fields[2];
+ attr_field = fields[3];
+ ratio_field = "";
+ }
+ else {
+ size_field = fields[0];
+ ratio_field = fields[2];
+ date_field = fields[3];
+ time_field = fields[4];
+ attr_field = fields[5];
+ }
+
if ((strcmp (ratio_field, "<->") == 0)
|| (strcmp (ratio_field, "<--") == 0))
{
@@ -341,7 +336,7 @@ process_line (char *line,
}
}
- if (! rar_comm->rar5)
+ if (rar_comm->output_type != FR_COMMAND_RAR_TYPE_RAR5)
rar_comm->rar4_odd_line = ! rar_comm->rar4_odd_line;
}
@@ -375,10 +370,7 @@ fr_command_rar_list (FrCommand *comm)
fr_process_set_out_line_func (comm->process, process_line, comm);
- if (have_rar ())
- fr_process_begin_command (comm->process, "rar");
- else
- fr_process_begin_command (comm->process, "unrar");
+ fr_process_begin_command (comm->process, get_rar_command ());
fr_process_set_begin_func (comm->process, list__begin, comm);
fr_process_add_arg (comm->process, "v");
fr_process_add_arg (comm->process, "-c-");
@@ -579,10 +571,7 @@ fr_command_rar_extract (FrCommand *comm,
process_line__extract,
comm);
- if (have_rar ())
- fr_process_begin_command (comm->process, "rar");
- else
- fr_process_begin_command (comm->process, "unrar");
+ fr_process_begin_command (comm->process, get_rar_command ());
fr_process_add_arg (comm->process, "x");
@@ -623,10 +612,7 @@ fr_command_rar_extract (FrCommand *comm,
static void
fr_command_rar_test (FrCommand *comm)
{
- if (have_rar ())
- fr_process_begin_command (comm->process, "rar");
- else
- fr_process_begin_command (comm->process, "unrar");
+ fr_process_begin_command (comm->process, get_rar_command ());
fr_process_add_arg (comm->process, "t");
@@ -713,10 +699,13 @@ fr_command_rar_get_capabilities (FrCommand *comm,
FrCommandCaps capabilities;
capabilities = FR_COMMAND_CAN_ARCHIVE_MANY_FILES | FR_COMMAND_CAN_ENCRYPT | FR_COMMAND_CAN_ENCRYPT_HEADER;
- if (is_program_available ("rar", check_command))
- capabilities |= FR_COMMAND_CAN_READ_WRITE | FR_COMMAND_CAN_CREATE_VOLUMES;
- else if (is_program_available ("unrar", check_command))
- capabilities |= FR_COMMAND_CAN_READ;
+ /* add command-specific capabilities depending on availability */
+ for (guint i = 0; i < G_N_ELEMENTS (candidate_commands); i++) {
+ if (is_program_available (candidate_commands[i].command, check_command)) {
+ capabilities |= candidate_commands[i].capabilities;
+ break;
+ }
+ }
/* multi-volumes are read-only */
if ((comm->files->len > 0) && comm->multi_volume && (capabilities & FR_COMMAND_CAN_WRITE))
@@ -729,7 +718,7 @@ static const char *
fr_command_rar_get_packages (FrCommand *comm,
const char *mime_type)
{
- return PACKAGES ("rar,unrar");
+ return PACKAGES ("rar,unrar,unrar-free");
}
static void