1 /*
2  * fr-command-lrzip.c
3  *
4  *  Created on: 10.04.2010
5  *      Author: Alexander Saprykin
6  */
7 
8 #include <config.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <glib.h>
15 #include "file-data.h"
16 #include "file-utils.h"
17 #include "glib-utils.h"
18 #include "fr-command.h"
19 #include "fr-command-lrzip.h"
20 
21 
22 struct _FrCommandLrzip
23 {
24 	FrCommand  parent_instance;
25 };
26 
27 
G_DEFINE_TYPE(FrCommandLrzip,fr_command_lrzip,fr_command_get_type ())28 G_DEFINE_TYPE (FrCommandLrzip, fr_command_lrzip, fr_command_get_type ())
29 
30 
31 /* -- list -- */
32 
33 
34 static void
35 list__process_line (char     *line,
36 		    gpointer  data)
37 {
38 	FileData  *fdata;
39 	FrCommand *comm = FR_COMMAND (data);
40 
41 	g_return_if_fail (line != NULL);
42 
43 	if (strlen (line) == 0)
44 		return;
45 
46 	if (! g_str_has_prefix (line, "Decompressed file size:"))
47 		return;
48 
49 	fdata = file_data_new ();
50 	fdata->size = g_ascii_strtoull (_g_str_get_last_field (line, 4), NULL, 10);
51 
52 	struct stat st;
53 	if (stat (comm->filename, &st) == 0)
54 #ifdef __APPLE__
55 		fdata->modified = st.st_mtime;
56 #else
57 		fdata->modified = st.st_mtim.tv_sec;
58 #endif
59 	else
60 		time(&(fdata->modified));
61 
62 	fdata->encrypted = FALSE;
63 
64 	char *new_fname = g_strdup (_g_path_get_basename (comm->filename));
65 	if (g_str_has_suffix (new_fname, ".lrz"))
66 		new_fname[strlen (new_fname) - 4] = '\0';
67 
68 	if (*new_fname == '/') {
69 		fdata->full_path = g_strdup (new_fname);
70 		fdata->original_path = fdata->full_path;
71 	}
72 	else {
73 		fdata->full_path = g_strconcat ("/", new_fname, NULL);
74 		fdata->original_path = fdata->full_path + 1;
75 	}
76 	fdata->path = _g_path_remove_level (fdata->full_path);
77 	fdata->name = new_fname;
78 	fdata->dir = FALSE;
79 	fdata->link = NULL;
80 
81 	if (fdata->name == 0)
82 		file_data_free (fdata);
83 	else
84 		fr_archive_add_file (FR_ARCHIVE (comm), fdata);
85 }
86 
87 
88 static gboolean
fr_command_lrzip_list(FrCommand * comm)89 fr_command_lrzip_list (FrCommand  *comm)
90 {
91 	fr_process_set_err_line_func (comm->process, list__process_line, comm);
92 
93 	fr_process_begin_command (comm->process, "lrzip");
94 	fr_process_add_arg (comm->process, "-i");
95 	fr_process_add_arg (comm->process, comm->filename);
96 	fr_process_end_command (comm->process);
97 
98 	return TRUE;
99 }
100 
101 
102 static void
fr_command_lrzip_add(FrCommand * comm,const char * from_file,GList * file_list,const char * base_dir,gboolean update,gboolean follow_links)103 fr_command_lrzip_add (FrCommand  *comm,
104 		      const char *from_file,
105 		      GList      *file_list,
106 		      const char *base_dir,
107 		      gboolean    update,
108 		      gboolean    follow_links)
109 {
110 	fr_process_begin_command (comm->process, "lrzip");
111 
112 	if (base_dir != NULL)
113 		fr_process_set_working_dir (comm->process, base_dir);
114 
115 	/* preserve links. */
116 
117 	switch (FR_ARCHIVE (comm)->compression) {
118 	case FR_COMPRESSION_VERY_FAST:
119 		fr_process_add_arg (comm->process, "-l"); break;
120 	case FR_COMPRESSION_FAST:
121 		fr_process_add_arg (comm->process, "-g"); break;
122 	case FR_COMPRESSION_NORMAL:
123 		fr_process_add_arg (comm->process, "-b"); break;
124 	case FR_COMPRESSION_MAXIMUM:
125 		fr_process_add_arg (comm->process, "-z"); break;
126 	}
127 
128 	fr_process_add_arg (comm->process, "-o");
129 	fr_process_add_arg (comm->process, comm->filename);
130 	fr_process_add_arg (comm->process, (char *) file_list->data);
131 
132 	fr_process_end_command (comm->process);
133 }
134 
135 static void
fr_command_lrzip_extract(FrCommand * comm,const char * from_file,GList * file_list,const char * dest_dir,gboolean overwrite,gboolean skip_older,gboolean junk_paths)136 fr_command_lrzip_extract (FrCommand  *comm,
137 			  const char *from_file,
138 			  GList      *file_list,
139 			  const char *dest_dir,
140 			  gboolean    overwrite,
141 			  gboolean    skip_older,
142 			  gboolean    junk_paths)
143 {
144 	fr_process_begin_command (comm->process, "lrzip");
145 	fr_process_add_arg (comm->process, "-d");
146 
147 	if (dest_dir != NULL) {
148 		fr_process_add_arg (comm->process, "-O");
149 		fr_process_add_arg (comm->process, dest_dir);
150 	}
151 	if (overwrite)
152 		fr_process_add_arg (comm->process, "-f");
153 
154 	fr_process_add_arg (comm->process, comm->filename);
155 	fr_process_end_command (comm->process);
156 }
157 
158 
159 /*
160 static void
161 fr_command_lrzip_test (FrCommand   *comm)
162 {
163 	fr_process_begin_command (comm->process, "lrzip");
164 	fr_process_add_arg (comm->process, "-t");
165 	fr_process_add_arg (comm->process, comm->filename);
166 	fr_process_end_command (comm->process);
167 }
168 */
169 
170 
171 const char *lrzip_mime_type[] = { "application/x-lrzip", NULL };
172 
173 
174 static const char **
fr_command_lrzip_get_mime_types(FrArchive * archive)175 fr_command_lrzip_get_mime_types (FrArchive *archive)
176 {
177 	return lrzip_mime_type;
178 }
179 
180 
181 static FrArchiveCap
fr_command_lrzip_get_capabilities(FrArchive * archive,const char * mime_type,gboolean check_command)182 fr_command_lrzip_get_capabilities (FrArchive  *archive,
183 				   const char *mime_type,
184 				   gboolean    check_command)
185 {
186 	FrArchiveCap capabilities = FR_ARCHIVE_CAN_DO_NOTHING;
187 
188 	if (_g_program_is_available ("lrzip", check_command))
189 		capabilities |= FR_ARCHIVE_CAN_READ_WRITE;
190 
191 	return capabilities;
192 }
193 
194 
195 static const char *
fr_command_lrzip_get_packages(FrArchive * archive,const char * mime_type)196 fr_command_lrzip_get_packages (FrArchive  *archive,
197 			       const char *mime_type)
198 {
199 	return PACKAGES ("lrzip");
200 }
201 
202 
203 static void
fr_command_lrzip_finalize(GObject * object)204 fr_command_lrzip_finalize (GObject *object)
205 {
206 	g_return_if_fail (object != NULL);
207 	g_return_if_fail (FR_IS_COMMAND_LRZIP (object));
208 
209 	if (G_OBJECT_CLASS (fr_command_lrzip_parent_class)->finalize)
210 		G_OBJECT_CLASS (fr_command_lrzip_parent_class)->finalize (object);
211 }
212 
213 
214 static void
fr_command_lrzip_class_init(FrCommandLrzipClass * klass)215 fr_command_lrzip_class_init (FrCommandLrzipClass *klass)
216 {
217 	GObjectClass   *gobject_class;
218 	FrArchiveClass *archive_class;
219 	FrCommandClass *command_class;
220 
221 	fr_command_lrzip_parent_class = g_type_class_peek_parent (klass);
222 
223 	gobject_class = G_OBJECT_CLASS (klass);
224 	gobject_class->finalize = fr_command_lrzip_finalize;
225 
226 	archive_class = FR_ARCHIVE_CLASS (klass);
227 	archive_class->get_mime_types   = fr_command_lrzip_get_mime_types;
228 	archive_class->get_capabilities = fr_command_lrzip_get_capabilities;
229 	archive_class->get_packages     = fr_command_lrzip_get_packages;
230 
231 	command_class = FR_COMMAND_CLASS (klass);
232 	command_class->list             = fr_command_lrzip_list;
233 	command_class->add              = fr_command_lrzip_add;
234 	command_class->extract          = fr_command_lrzip_extract;
235 }
236 
237 
238 static void
fr_command_lrzip_init(FrCommandLrzip * self)239 fr_command_lrzip_init (FrCommandLrzip *self)
240 {
241 	FrArchive *base = FR_ARCHIVE (self);
242 
243 	base->propAddCanUpdate             = FALSE;
244 	base->propAddCanReplace            = FALSE;
245 	base->propAddCanStoreFolders       = FALSE;
246 	base->propAddCanStoreLinks         = FALSE;
247 	base->propExtractCanAvoidOverwrite = TRUE;
248 	base->propExtractCanSkipOlder      = FALSE;
249 	base->propExtractCanJunkPaths      = FALSE;
250 	base->propPassword                 = FALSE;
251 	base->propTest                     = FALSE;
252 }
253