diff options
author | Perberos <[email protected]> | 2011-11-09 22:53:33 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-11-09 22:53:33 -0300 |
commit | 70438138096a47b2505ac55634cd94947ce378b6 (patch) | |
tree | e45e49dda10a71616466500a4ab65d1c54b5f6c1 /src/fr-command-cfile.c | |
download | engrampa-70438138096a47b2505ac55634cd94947ce378b6.tar.bz2 engrampa-70438138096a47b2505ac55634cd94947ce378b6.tar.xz |
initial
Diffstat (limited to 'src/fr-command-cfile.c')
-rw-r--r-- | src/fr-command-cfile.c | 619 |
1 files changed, 619 insertions, 0 deletions
diff --git a/src/fr-command-cfile.c b/src/fr-command-cfile.c new file mode 100644 index 0000000..d986575 --- /dev/null +++ b/src/fr-command-cfile.c @@ -0,0 +1,619 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * File-Roller + * + * Copyright (C) 2001 The Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> + +#include <glib.h> + +#include "file-data.h" +#include "file-utils.h" +#include "glib-utils.h" +#include "fr-command.h" +#include "fr-command-cfile.h" + + +/* Parent Class */ + +static FrCommandClass *parent_class = NULL; + + +static char * +get_uncompressed_name_from_archive (FrCommand *comm, + const char *archive) +{ + GFile *file; + GInputStream *stream; + char *filename = NULL; + + if (! is_mime_type (comm->mime_type, "application/x-gzip")) + return NULL; + + file = g_file_new_for_path (archive); + + stream = (GInputStream *) g_file_read (file, NULL, NULL); + if (stream != NULL) { + gboolean filename_present = TRUE; + char buffer[10]; + + if (g_input_stream_read (stream, buffer, 10, NULL, NULL) >= 0) { + /* Check whether the FLG.FNAME is set */ + if (((unsigned char)(buffer[3]) & 0x08) != 0x08) + filename_present = FALSE; + + /* Check whether the FLG.FEXTRA is set */ + if (((unsigned char)(buffer[3]) & 0x04) == 0x04) + filename_present = FALSE; + } + + if (filename_present) { + GString *str = NULL; + + str = g_string_new (""); + while (g_input_stream_read (stream, buffer, 1, NULL, NULL) > 0) { + if (buffer[0] == '\0') { + filename = g_strdup (file_name_from_path (str->str)); +#ifdef DEBUG + g_message ("filename is: %s", filename); +#endif + break; + } + g_string_append_c (str, buffer[0]); + } + g_string_free (str, TRUE); + } + g_object_unref (stream); + } + g_object_unref (file); + + return filename; +} + + +static void +list__process_line (char *line, + gpointer data) +{ + FrCommand *comm = FR_COMMAND (data); + FileData *fdata; + char **fields; + char *filename; + + fdata = file_data_new (); + + fields = split_line (line, 2); + if (strcmp (fields[1], "-1") != 0) + fdata->size = g_ascii_strtoull (fields[1], NULL, 10); + g_strfreev (fields); + + if (fdata->size == 0) + fdata->size = get_file_size (comm->filename); + + filename = get_uncompressed_name_from_archive (comm, comm->filename); + if (filename == NULL) + filename = remove_extension_from_path (comm->filename); + + fdata->full_path = g_strconcat ("/", + file_name_from_path (filename), + NULL); + g_free (filename); + + fdata->original_path = fdata->full_path + 1; + fdata->link = NULL; + fdata->modified = get_file_mtime_for_path (comm->filename); + + fdata->name = g_strdup (file_name_from_path (fdata->full_path)); + fdata->path = remove_level_from_path (fdata->full_path); + + if (*fdata->name == 0) + file_data_free (fdata); + else + fr_command_add_file (comm, fdata); +} + + +static void +fr_command_cfile_list (FrCommand *comm) +{ + FrCommandCFile *comm_cfile = FR_COMMAND_CFILE (comm); + + if (is_mime_type (comm->mime_type, "application/x-gzip")) { + /* gzip let us known the uncompressed size */ + + fr_process_set_out_line_func (FR_COMMAND (comm)->process, + list__process_line, + comm); + + fr_process_begin_command (comm->process, "gzip"); + fr_process_add_arg (comm->process, "-l"); + fr_process_add_arg (comm->process, "-q"); + fr_process_add_arg (comm->process, comm->filename); + fr_process_end_command (comm->process); + fr_process_start (comm->process); + } + else { + /* ... other compressors do not support this feature so + * simply use the archive size, suboptimal but there is no + * alternative. */ + + FileData *fdata; + char *filename; + + fdata = file_data_new (); + + filename = remove_extension_from_path (comm->filename); + fdata->full_path = g_strconcat ("/", + file_name_from_path (filename), + NULL); + g_free (filename); + + fdata->original_path = fdata->full_path + 1; + fdata->link = NULL; + fdata->size = get_file_size_for_path (comm->filename); + fdata->modified = get_file_mtime_for_path (comm->filename); + + fdata->name = g_strdup (file_name_from_path (fdata->full_path)); + fdata->path = remove_level_from_path (fdata->full_path); + + if (*fdata->name == 0) + file_data_free (fdata); + else + fr_command_add_file (comm, fdata); + + comm_cfile->error.type = FR_PROC_ERROR_NONE; + comm_cfile->error.status = 0; + g_signal_emit_by_name (G_OBJECT (comm), + "done", + comm->action, + &comm_cfile->error); + } +} + + +static void +fr_command_cfile_add (FrCommand *comm, + const char *from_file, + GList *file_list, + const char *base_dir, + gboolean update, + gboolean recursive) +{ + const char *filename; + char *temp_dir; + char *temp_file; + char *compressed_filename; + + if ((file_list == NULL) || (file_list->data == NULL)) + return; + + /* copy file to the temp dir */ + + temp_dir = get_temp_work_dir (NULL); + filename = file_list->data; + temp_file = g_strconcat (temp_dir, "/", filename, NULL); + + fr_process_begin_command (comm->process, "cp"); + fr_process_set_working_dir (comm->process, base_dir); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, filename); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + + /**/ + + if (is_mime_type (comm->mime_type, "application/x-gzip")) { + fr_process_begin_command (comm->process, "gzip"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, filename); + fr_process_end_command (comm->process); + compressed_filename = g_strconcat (filename, ".gz", NULL); + } + else if (is_mime_type (comm->mime_type, "application/x-bzip")) { + fr_process_begin_command (comm->process, "bzip2"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, filename); + fr_process_end_command (comm->process); + compressed_filename = g_strconcat (filename, ".bz2", NULL); + } + else if (is_mime_type (comm->mime_type, "application/x-compress")) { + fr_process_begin_command (comm->process, "compress"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, filename); + fr_process_end_command (comm->process); + compressed_filename = g_strconcat (filename, ".Z", NULL); + } + else if (is_mime_type (comm->mime_type, "application/x-lzip")) { + fr_process_begin_command (comm->process, "lzip"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, filename); + fr_process_end_command (comm->process); + compressed_filename = g_strconcat (filename, ".lz", NULL); + } + else if (is_mime_type (comm->mime_type, "application/x-lzma")) { + fr_process_begin_command (comm->process, "lzma"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, filename); + fr_process_end_command (comm->process); + compressed_filename = g_strconcat (filename, ".lzma", NULL); + } + else if (is_mime_type (comm->mime_type, "application/x-xz")) { + fr_process_begin_command (comm->process, "xz"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, filename); + fr_process_end_command (comm->process); + compressed_filename = g_strconcat (filename, ".xz", NULL); + } + else if (is_mime_type (comm->mime_type, "application/x-lzop")) { + fr_process_begin_command (comm->process, "lzop"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "-fU"); + fr_process_add_arg (comm->process, "--no-stdin"); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, filename); + fr_process_end_command (comm->process); + compressed_filename = g_strconcat (filename, ".lzo", NULL); + } + else if (is_mime_type (comm->mime_type, "application/x-rzip")) { + fr_process_begin_command (comm->process, "rzip"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, filename); + fr_process_end_command (comm->process); + compressed_filename = g_strconcat (filename, ".rz", NULL); + } + + /* copy compressed file to the dest dir */ + + fr_process_begin_command (comm->process, "cp"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, compressed_filename); + fr_process_add_arg (comm->process, comm->filename); + fr_process_end_command (comm->process); + + /* remove the temp dir */ + + fr_process_begin_command (comm->process, "rm"); + fr_process_set_sticky (comm->process, TRUE); + fr_process_add_arg (comm->process, "-rf"); + fr_process_add_arg (comm->process, "--"); + fr_process_add_arg (comm->process, temp_dir); + fr_process_end_command (comm->process); + + g_free (compressed_filename); + g_free (temp_file); + g_free (temp_dir); +} + + +static void +fr_command_cfile_delete (FrCommand *comm, + const char *from_file, + GList *file_list) +{ + /* never called */ +} + + +static void +fr_command_cfile_extract (FrCommand *comm, + const char *from_file, + GList *file_list, + const char *dest_dir, + gboolean overwrite, + gboolean skip_older, + gboolean junk_paths) +{ + char *temp_dir; + char *dest_file; + char *temp_file; + char *uncompr_file; + char *compr_file; + + /* copy file to the temp dir, remove the already existing file first */ + + temp_dir = get_temp_work_dir (NULL); + temp_file = g_strconcat (temp_dir, + "/", + file_name_from_path (comm->filename), + NULL); + + fr_process_begin_command (comm->process, "cp"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, comm->filename); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + + /* uncompress the file */ + + if (is_mime_type (comm->mime_type, "application/x-gzip")) { + fr_process_begin_command (comm->process, "gzip"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, "-d"); + fr_process_add_arg (comm->process, "-n"); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + } + else if (is_mime_type (comm->mime_type, "application/x-bzip")) { + fr_process_begin_command (comm->process, "bzip2"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, "-d"); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + } + else if (is_mime_type (comm->mime_type, "application/x-compress")) { + if (is_program_in_path ("gzip")) { + fr_process_begin_command (comm->process, "gzip"); + fr_process_add_arg (comm->process, "-d"); + fr_process_add_arg (comm->process, "-n"); + } + else + fr_process_begin_command (comm->process, "uncompress"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + } + else if (is_mime_type (comm->mime_type, "application/x-lzip")) { + fr_process_begin_command (comm->process, "lzip"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, "-d"); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + } + else if (is_mime_type (comm->mime_type, "application/x-lzma")) { + fr_process_begin_command (comm->process, "lzma"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, "-d"); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + } + else if (is_mime_type (comm->mime_type, "application/x-xz")) { + fr_process_begin_command (comm->process, "xz"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, "-d"); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + } + else if (is_mime_type (comm->mime_type, "application/x-lzop")) { + fr_process_begin_command (comm->process, "lzop"); + fr_process_set_working_dir (comm->process, temp_dir); + fr_process_add_arg (comm->process, "-d"); + fr_process_add_arg (comm->process, "-fU"); + fr_process_add_arg (comm->process, "--no-stdin"); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + } + else if (is_mime_type (comm->mime_type, "application/x-rzip")) { + fr_process_begin_command (comm->process, "rzip"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, "-d"); + fr_process_add_arg (comm->process, temp_file); + fr_process_end_command (comm->process); + } + + /* copy uncompress file to the dest dir */ + + uncompr_file = remove_extension_from_path (temp_file); + + compr_file = get_uncompressed_name_from_archive (comm, comm->filename); + if (compr_file == NULL) + compr_file = remove_extension_from_path (file_name_from_path (comm->filename)); + dest_file = g_strconcat (dest_dir, + "/", + compr_file, + NULL); + + fr_process_begin_command (comm->process, "cp"); + fr_process_add_arg (comm->process, "-f"); + fr_process_add_arg (comm->process, uncompr_file); + fr_process_add_arg (comm->process, dest_file); + fr_process_end_command (comm->process); + + /* remove the temp dir */ + + fr_process_begin_command (comm->process, "rm"); + fr_process_set_sticky (comm->process, TRUE); + fr_process_add_arg (comm->process, "-rf"); + fr_process_add_arg (comm->process, temp_dir); + fr_process_end_command (comm->process); + + g_free (dest_file); + g_free (compr_file); + g_free (uncompr_file); + g_free (temp_file); + g_free (temp_dir); +} + + +const char *cfile_mime_type[] = { "application/x-gzip", + "application/x-bzip", + "application/x-compress", + "application/x-lzip", + "application/x-lzma", + "application/x-lzop", + "application/x-rzip", + "application/x-xz", + NULL }; + + +const char ** +fr_command_cfile_get_mime_types (FrCommand *comm) +{ + return cfile_mime_type; +} + + +FrCommandCap +fr_command_cfile_get_capabilities (FrCommand *comm, + const char *mime_type, + gboolean check_command) +{ + FrCommandCap capabilities; + + capabilities = FR_COMMAND_CAN_DO_NOTHING; + if (is_mime_type (mime_type, "application/x-gzip")) { + if (is_program_available ("gzip", check_command)) + capabilities |= FR_COMMAND_CAN_READ_WRITE; + } + else if (is_mime_type (mime_type, "application/x-bzip")) { + if (is_program_available ("bzip2", check_command)) + capabilities |= FR_COMMAND_CAN_READ_WRITE; + } + else if (is_mime_type (mime_type, "application/x-compress")) { + if (is_program_available ("compress", check_command)) + capabilities |= FR_COMMAND_CAN_WRITE; + if (is_program_available ("uncompress", check_command) || is_program_available ("gzip", check_command)) + capabilities |= FR_COMMAND_CAN_READ; + } + else if (is_mime_type (mime_type, "application/x-lzip")) { + if (is_program_available ("lzip", check_command)) + capabilities |= FR_COMMAND_CAN_READ_WRITE; + } + else if (is_mime_type (mime_type, "application/x-lzma")) { + if (is_program_available ("lzma", check_command)) + capabilities |= FR_COMMAND_CAN_READ_WRITE; + } + else if (is_mime_type (mime_type, "application/x-xz")) { + if (is_program_available ("xz", check_command)) + capabilities |= FR_COMMAND_CAN_READ_WRITE; + } + else if (is_mime_type (mime_type, "application/x-lzop")) { + if (is_program_available ("lzop", check_command)) + capabilities |= FR_COMMAND_CAN_READ_WRITE; + } + else if (is_mime_type (mime_type, "application/x-rzip")) { + if (is_program_available ("rzip", check_command)) + capabilities |= FR_COMMAND_CAN_READ_WRITE; + } + + return capabilities; +} + + +static void +fr_command_cfile_finalize (GObject *object) +{ + g_return_if_fail (object != NULL); + g_return_if_fail (FR_IS_COMMAND_CFILE (object)); + + /* Chain up */ + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +static const char * +fr_command_cfile_get_packages (FrCommand *comm, + const char *mime_type) +{ + if (is_mime_type (mime_type, "application/x-gzip")) + return PACKAGES ("gzip"); + else if (is_mime_type (mime_type, "application/x-bzip")) + return PACKAGES ("bzip2"); + else if (is_mime_type (mime_type, "application/x-compress")) + return PACKAGES ("ncompress"); + else if (is_mime_type (mime_type, "application/x-lzip")) + return PACKAGES ("lzip"); + else if (is_mime_type (mime_type, "application/x-lzma")) + return PACKAGES ("lzma"); + else if (is_mime_type (mime_type, "application/x-xz")) + return PACKAGES ("xz"); + else if (is_mime_type (mime_type, "application/x-lzop")) + return PACKAGES ("lzop"); + else if (is_mime_type (mime_type, "application/x-rzip")) + return PACKAGES ("rzip"); + + return NULL; +} + + +static void +fr_command_cfile_class_init (FrCommandCFileClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + FrCommandClass *afc; + + parent_class = g_type_class_peek_parent (class); + afc = (FrCommandClass*) class; + + gobject_class->finalize = fr_command_cfile_finalize; + + afc->list = fr_command_cfile_list; + afc->add = fr_command_cfile_add; + afc->delete = fr_command_cfile_delete; + afc->extract = fr_command_cfile_extract; + afc->get_mime_types = fr_command_cfile_get_mime_types; + afc->get_capabilities = fr_command_cfile_get_capabilities; + afc->get_packages = fr_command_cfile_get_packages; +} + + +static void +fr_command_cfile_init (FrCommand *comm) +{ + comm->propAddCanUpdate = TRUE; + comm->propAddCanReplace = TRUE; + comm->propExtractCanAvoidOverwrite = FALSE; + comm->propExtractCanSkipOlder = FALSE; + comm->propExtractCanJunkPaths = FALSE; + comm->propPassword = FALSE; + comm->propTest = FALSE; +} + + +GType +fr_command_cfile_get_type () +{ + static GType type = 0; + + if (! type) { + GTypeInfo type_info = { + sizeof (FrCommandCFileClass), + NULL, + NULL, + (GClassInitFunc) fr_command_cfile_class_init, + NULL, + NULL, + sizeof (FrCommandCFile), + 0, + (GInstanceInitFunc) fr_command_cfile_init + }; + + type = g_type_register_static (FR_TYPE_COMMAND, + "FRCommandCFile", + &type_info, + 0); + } + + return type; +} |