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 
15 #include <glib.h>
16 
17 #include "file-data.h"
18 #include "file-utils.h"
19 #include "glib-utils.h"
20 #include "fr-command.h"
21 #include "fr-command-lrzip.h"
22 
23 static void fr_command_lrzip_class_init  (FrCommandLrzipClass *class);
24 static void fr_command_lrzip_init        (FrCommand         *afile);
25 static void fr_command_lrzip_finalize    (GObject           *object);
26 
27 /* Parent Class */
28 
29 static FrCommandClass *parent_class = NULL;
30 
31 
32 /* -- list -- */
33 
34 
35 static void
list__process_line(char * line,gpointer data)36 list__process_line (char     *line,
37 		    gpointer  data)
38 {
39 	FileData  *fdata;
40 	FrCommand *comm = FR_COMMAND (data);
41 
42 	g_return_if_fail (line != NULL);
43 
44 	if (strlen (line) == 0)
45 		return;
46 
47 	if (! g_str_has_prefix (line, "Decompressed file size:"))
48 		return;
49 
50 	fdata = file_data_new ();
51 	fdata->size = g_ascii_strtoull (get_last_field (line, 4), NULL, 10);
52 
53 	struct stat st;
54 
55 	if (stat (comm->filename, &st) == 0)
56 		fdata->modified = st.st_mtim.tv_sec;
57 	else
58 		time(&(fdata->modified));
59 
60 	fdata->encrypted = FALSE;
61 
62 	char *new_fname = g_strdup (file_name_from_path (comm->filename));
63 	if (g_str_has_suffix (new_fname, ".lrz"))
64 		new_fname[strlen (new_fname) - 4] = '\0';
65 
66 	if (*new_fname == '/') {
67 		fdata->full_path = g_strdup (new_fname);
68 		fdata->original_path = fdata->full_path;
69 	}
70 	else {
71 		fdata->full_path = g_strconcat ("/", new_fname, NULL);
72 		fdata->original_path = fdata->full_path + 1;
73 	}
74 	fdata->path = remove_level_from_path (fdata->full_path);
75 	fdata->name = new_fname;
76 	fdata->dir = FALSE;
77 	fdata->link = NULL;
78 
79 	if (fdata->name == 0)
80 		file_data_free (fdata);
81 	else
82 		fr_command_add_file (comm, fdata);
83 }
84 
85 
86 static void
fr_command_lrzip_list(FrCommand * comm)87 fr_command_lrzip_list (FrCommand  *comm)
88 {
89 	fr_process_set_err_line_func (comm->process, list__process_line, comm);
90 
91 	fr_process_begin_command (comm->process, "lrzip");
92 	fr_process_add_arg (comm->process, "-i");
93 	fr_process_add_arg (comm->process, comm->filename);
94 	fr_process_end_command (comm->process);
95 	fr_process_start (comm->process);
96 }
97 
98 
99 static void
fr_command_lrzip_add(FrCommand * comm,const char * from_file,GList * file_list,const char * base_dir,gboolean update,gboolean recursive)100 fr_command_lrzip_add (FrCommand  *comm,
101 		      const char *from_file,
102 		      GList      *file_list,
103 		      const char *base_dir,
104 		      gboolean    update,
105 		      gboolean    recursive)
106 {
107 	fr_process_begin_command (comm->process, "lrzip");
108 
109 	if (base_dir != NULL)
110 		fr_process_set_working_dir (comm->process, base_dir);
111 
112 	/* preserve links. */
113 
114 	switch (comm->compression) {
115 	case FR_COMPRESSION_VERY_FAST:
116 		fr_process_add_arg (comm->process, "-l"); break;
117 	case FR_COMPRESSION_FAST:
118 		fr_process_add_arg (comm->process, "-g"); break;
119 	case FR_COMPRESSION_NORMAL:
120 		fr_process_add_arg (comm->process, "-b"); break;
121 	case FR_COMPRESSION_MAXIMUM:
122 		fr_process_add_arg (comm->process, "-z"); break;
123 	}
124 
125 	fr_process_add_arg (comm->process, "-o");
126 	fr_process_add_arg (comm->process, comm->filename);
127 	fr_process_add_arg (comm->process, (char *) file_list->data);
128 
129 	fr_process_end_command (comm->process);
130 }
131 
132 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)133 fr_command_lrzip_extract (FrCommand  *comm,
134 			  const char *from_file,
135 			  GList      *file_list,
136 			  const char *dest_dir,
137 			  gboolean    overwrite,
138 			  gboolean    skip_older,
139 			  gboolean    junk_paths)
140 {
141 	fr_process_begin_command (comm->process, "lrzip");
142 	fr_process_add_arg (comm->process, "-d");
143 
144 	if (dest_dir != NULL) {
145 		fr_process_add_arg (comm->process, "-O");
146 		fr_process_add_arg (comm->process, dest_dir);
147 	}
148 	if (overwrite)
149 		fr_process_add_arg (comm->process, "-f");
150 
151 	fr_process_add_arg (comm->process, comm->filename);
152 	fr_process_end_command (comm->process);
153 }
154 
155 
156 /*
157 static void
158 fr_command_lrzip_test (FrCommand   *comm)
159 {
160 	fr_process_begin_command (comm->process, "lrzip");
161 	fr_process_add_arg (comm->process, "-t");
162 	fr_process_add_arg (comm->process, comm->filename);
163 	fr_process_end_command (comm->process);
164 }
165 */
166 
167 
168 const char *lrzip_mime_type[] = { "application/x-lrzip", NULL };
169 
170 
171 static const char **
fr_command_lrzip_get_mime_types(FrCommand * comm)172 fr_command_lrzip_get_mime_types (FrCommand *comm)
173 {
174 	return lrzip_mime_type;
175 }
176 
177 
178 static FrCommandCap
fr_command_lrzip_get_capabilities(FrCommand * comm,const char * mime_type,gboolean check_command)179 fr_command_lrzip_get_capabilities (FrCommand  *comm,
180 				   const char *mime_type,
181 				   gboolean    check_command)
182 {
183 	FrCommandCap capabilities = FR_COMMAND_CAN_DO_NOTHING;
184 
185 	if (is_program_available ("lrzip", check_command))
186 		capabilities |= FR_COMMAND_CAN_READ_WRITE;
187 
188 	return capabilities;
189 }
190 
191 
192 static const char *
fr_command_lrzip_get_packages(FrCommand * comm,const char * mime_type)193 fr_command_lrzip_get_packages (FrCommand  *comm,
194 			       const char *mime_type)
195 {
196 	return PACKAGES ("lrzip");
197 }
198 
199 
200 static void
fr_command_lrzip_class_init(FrCommandLrzipClass * class)201 fr_command_lrzip_class_init (FrCommandLrzipClass *class)
202 {
203 	GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
204 	FrCommandClass *afc;
205 
206 	parent_class = g_type_class_peek_parent (class);
207 	afc = (FrCommandClass*) class;
208 
209 	gobject_class->finalize = fr_command_lrzip_finalize;
210 
211 	afc->list             = fr_command_lrzip_list;
212 	afc->add              = fr_command_lrzip_add;
213 	afc->extract          = fr_command_lrzip_extract;
214 	afc->get_mime_types   = fr_command_lrzip_get_mime_types;
215 	afc->get_capabilities = fr_command_lrzip_get_capabilities;
216 	afc->get_packages     = fr_command_lrzip_get_packages;
217 }
218 
219 
220 static void
fr_command_lrzip_init(FrCommand * comm)221 fr_command_lrzip_init (FrCommand *comm)
222 {
223 	comm->propAddCanUpdate             = FALSE;
224 	comm->propAddCanReplace            = FALSE;
225 	comm->propAddCanStoreFolders       = FALSE;
226 	comm->propExtractCanAvoidOverwrite = TRUE;
227 	comm->propExtractCanSkipOlder      = FALSE;
228 	comm->propExtractCanJunkPaths      = FALSE;
229 	comm->propPassword                 = FALSE;
230 	comm->propTest                     = FALSE;
231 }
232 
233 
234 static void
fr_command_lrzip_finalize(GObject * object)235 fr_command_lrzip_finalize (GObject *object)
236 {
237 	g_return_if_fail (object != NULL);
238 	g_return_if_fail (FR_IS_COMMAND_LRZIP (object));
239 
240 	/* Chain up */
241 	if (G_OBJECT_CLASS (parent_class)->finalize)
242 		G_OBJECT_CLASS (parent_class)->finalize (object);
243 }
244 
245 
246 GType
fr_command_lrzip_get_type()247 fr_command_lrzip_get_type ()
248 {
249 	static GType type = 0;
250 
251 	if (! type) {
252 		GTypeInfo type_info = {
253 			sizeof (FrCommandLrzipClass),
254 			NULL,
255 			NULL,
256 			(GClassInitFunc) fr_command_lrzip_class_init,
257 			NULL,
258 			NULL,
259 			sizeof (FrCommandLrzip),
260 			0,
261 			(GInstanceInitFunc) fr_command_lrzip_init
262 		};
263 
264 		type = g_type_register_static (FR_TYPE_COMMAND,
265 					       "FRCommandLrzip",
266 					       &type_info,
267 					       0);
268 	}
269 
270 	return type;
271 }
272