1 /*
2 * Copyright (C) 2008 Giuseppe Torelli - <colossus73@gmail.com>
3 * Copyright (C) 2006 Lukasz 'Sil2100' Zemczak - <sil2100@vexillium.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301 USA.
19 */
20
21 #include <string.h>
22 #include "lha.h"
23 #include "date_utils.h"
24 #include "main.h"
25 #include "string_utils.h"
26 #include "support.h"
27 #include "window.h"
28
29 static gboolean data_line, last_line;
30
xa_lha_check_program(gchar * path)31 gboolean xa_lha_check_program (gchar *path)
32 {
33 gchar *output, *discard;
34 gboolean full_lha;
35
36 g_spawn_command_line_sync(path, &output, &discard, NULL, NULL);
37 full_lha = (g_ascii_strncasecmp("Lhasa ", output, 6) != 0);
38 g_free(discard);
39 g_free(output);
40
41 return full_lha;
42 }
43
xa_lha_ask(XArchive * archive)44 void xa_lha_ask (XArchive *archive)
45 {
46 archive->can_test = TRUE;
47 archive->can_extract = TRUE;
48 archive->can_add = archiver[archive->type].is_compressor;
49 archive->can_delete = archiver[archive->type].is_compressor;
50 archive->can_full_path[0] = TRUE;
51 archive->can_full_path[1] = archiver[archive->type].is_compressor; // n.b.: adds leading slash
52 archive->can_overwrite = TRUE;
53 archive->can_update[1] = archiver[archive->type].is_compressor;
54 archive->can_move = archiver[archive->type].is_compressor;
55 }
56
xa_lha_parse_output(gchar * line,XArchive * archive)57 static void xa_lha_parse_output (gchar *line, XArchive *archive)
58 {
59 XEntry *entry;
60 gpointer item[7];
61 gchar *filename, time[6];
62 unsigned int linesize,n,a;
63 gboolean dir;
64
65 if (last_line)
66 return;
67 if (!data_line)
68 {
69 if (line[0] == '-')
70 {
71 data_line = TRUE;
72 return;
73 }
74 return;
75 }
76 if (strncmp(line,"----",4) == 0)
77 {
78 last_line = TRUE;
79 return;
80 }
81 linesize = strlen(line);
82
83 /* Permission */
84 line[10] = '\0';
85 item[5] = line;
86 dir = (line[0] == 'd');
87
88 /* UID/GID */
89 line[22] = '\0';
90 item[6] = line + 11;
91
92 //TODO verify the len of the size column with a big archive
93 /* Size */
94 for(n = 23;n < linesize;n++)
95 if(line[n] != ' ')
96 break;
97
98 a = n;
99 for(;n < linesize;n++)
100 if(line[n] == ' ')
101 break;
102
103 line[a+(n-a)] = '\0';
104 item[1] = line + a;
105
106 /* Ratio */
107 line[37] = '\0';
108 item[2] = line + 31;
109
110 /* Date and Time */
111 line[50] = '\0';
112 item[3] = line + 38;
113
114 /* Time */
115 if (((char *) item[3])[9] == ':')
116 {
117 memcpy(time, item[3] + 7, 5);
118 time[5] = 0;
119 }
120 else
121 strcpy(time, "-----");
122
123 item[3] = date_MMM_dD_HourYear(item[3]);
124 item[4] = time;
125
126 line[(linesize- 1)] = '\0';
127 filename = line + 51;
128
129 /* Symbolic link */
130 gchar *temp = g_strrstr (filename,"->");
131 if (temp)
132 {
133 gint len = strlen(filename) - strlen(temp);
134 item[0] = (filename +=3) + len;
135 filename -= 3;
136 filename[strlen(filename) - strlen(temp)-1] = '\0';
137 }
138 else
139 item[0] = NULL;
140
141 entry = xa_set_archive_entries_for_each_row(archive, filename, item);
142
143 if (entry)
144 {
145 if (dir)
146 entry->is_dir = TRUE;
147
148 if (!entry->is_dir)
149 archive->files++;
150
151 archive->files_size += g_ascii_strtoull(item[1], NULL, 0);
152 }
153 }
154
xa_lha_list(XArchive * archive)155 void xa_lha_list (XArchive *archive)
156 {
157 const GType types[] = {GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER};
158 const gchar *titles[] = {_("Points to"), _("Original Size"), _("Occupancy"), _("Date"), _("Time"), _("Permissions"), _("UID/GID")};
159 gchar *command;
160 guint i;
161
162 data_line = FALSE;
163 last_line = FALSE;
164 command = g_strconcat(archiver[archive->type].program[0], " l ", archive->path[1], NULL);
165 archive->files_size = 0;
166 archive->files = 0;
167 archive->parse_output = xa_lha_parse_output;
168 xa_spawn_async_process (archive,command);
169 g_free (command);
170
171 archive->columns = 10;
172 archive->size_column = 3;
173 archive->column_types = g_malloc0(sizeof(types));
174
175 for (i = 0; i < archive->columns; i++)
176 archive->column_types[i] = types[i];
177
178 xa_create_liststore(archive, titles);
179 }
180
xa_lha_test(XArchive * archive)181 void xa_lha_test (XArchive *archive)
182 {
183 gchar *command;
184
185 command = g_strconcat(archiver[archive->type].program[0], " t ", archive->path[1], NULL);
186
187 xa_run_command(archive, command);
188 g_free(command);
189 }
190
191 /*
192 * Note: lha does not seem to be able to handle wildcards in file names.
193 */
194
xa_lha_extract(XArchive * archive,GSList * file_list)195 gboolean xa_lha_extract (XArchive *archive, GSList *file_list)
196 {
197 GString *files;
198 gchar *command;
199 gboolean result;
200
201 files = xa_quote_filenames(file_list, NULL, TRUE);
202 command = g_strconcat(archiver[archive->type].program[0],
203 archive->do_full_path ? " x" : " xi",
204 archive->do_overwrite ? "f" : "",
205 "w=", archive->extraction_dir, " ",
206 archive->path[1], files->str, NULL);
207 g_string_free(files,TRUE);
208
209 result = xa_run_command(archive, command);
210 g_free(command);
211
212 return result;
213 }
214
xa_lha_add(XArchive * archive,GSList * file_list,gchar * compression)215 void xa_lha_add (XArchive *archive, GSList *file_list, gchar *compression)
216 {
217 GString *files;
218 gchar *command;
219
220 if (archive->location_path != NULL)
221 archive->child_dir = g_strdup(archive->working_dir);
222
223 if (!compression)
224 compression = "5";
225
226 files = xa_quote_filenames(file_list, NULL, TRUE);
227 command = g_strconcat(archiver[archive->type].program[0],
228 archive->do_update ? " u" : " a",
229 archive->do_move ? "d" : "",
230 "o", compression, " ",
231 archive->path[1], files->str, NULL);
232 g_string_free(files,TRUE);
233
234 xa_run_command(archive, command);
235 g_free(command);
236 }
237
xa_lha_delete(XArchive * archive,GSList * file_list)238 void xa_lha_delete (XArchive *archive, GSList *file_list)
239 {
240 GString *files;
241 gchar *command;
242
243 files = xa_quote_filenames(file_list, NULL, TRUE);
244 command = g_strconcat(archiver[archive->type].program[0], " d ", archive->path[1], files->str, NULL);
245 g_string_free(files,TRUE);
246
247 xa_run_command(archive, command);
248 g_free(command);
249 }
250