20
19
#include "config.h"
22
21
#include "string_utils.h"
24
extern int output_fd, input_fd;
27
gchar *cpio_tmp = NULL;
31
gsize bytes_written = 0;
34
GIOChannel *ioc_cpio , *input_ioc, *output_ioc;
36
void OpenRPM ( XArchive *archive )
22
extern gboolean batch_mode;
24
void xa_open_rpm (XArchive *archive)
38
26
unsigned char bytes[8];
39
int dl,il,sigsize,offset;
28
int dl,il,sigsize,offset,response;
29
gchar *ibs,*executable;
30
gchar *gzip_tmp = NULL;
42
35
signal (SIGPIPE, SIG_IGN);
43
36
stream = fopen ( archive->path , "r" );
44
37
if (stream == NULL)
46
39
gchar *msg = g_strdup_printf (_("Can't open RPM file %s:") , archive->path);
47
response = ShowGtkMessageDialog (GTK_WINDOW (MainWindow) , GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,
48
msg,g_strerror (errno));
40
response = xa_show_message_dialog (GTK_WINDOW (xa_main_window) , GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,
41
msg,g_strerror(errno));
45
archive->can_extract = archive->has_properties = TRUE;
46
archive->can_add = archive->has_sfx = archive->has_test = FALSE;
52
47
archive->dummy_size = 0;
53
48
archive->nr_of_files = 0;
54
archive->nr_of_dirs = 0;
55
50
archive->format ="RPM";
56
char *names[]= {(_("Filename")),(_("Permission")),(_("Symbolic Link")),(_("Hard Link")),(_("Owner")),(_("Group")),(_("Size"))};
57
GType types[]= {G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_UINT64};
58
xa_create_liststore ( 7, names , (GType *)types, archive );
52
char *names[]= {(_("Points to")),(_("Size")),(_("Permission")),(_("Date")),(_("Hard Link")),(_("Owner")),(_("Group")),NULL};
53
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};
54
archive->column_types = g_malloc0(sizeof(types));
55
for (i = 0; i < 10; i++)
56
archive->column_types[i] = types[i];
58
xa_create_liststore (archive,names);
59
59
if (fseek ( stream, 104 , SEEK_CUR ) )
62
response = ShowGtkMessageDialog (GTK_WINDOW (MainWindow),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't fseek to position 104:"),g_strerror(errno));
62
response = xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't fseek to position 104:"),g_strerror(errno));
65
65
if ( fread ( bytes, 1, 8, stream ) == 0 )
68
response = ShowGtkMessageDialog (GTK_WINDOW (MainWindow),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't read data from file:"),g_strerror(errno));
68
response = xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't read data from file:"),g_strerror(errno));
71
71
il = 256 * ( 256 * ( 256 * bytes[0] + bytes[1]) + bytes[2] ) + bytes[3];
90
90
offset = offset + sigsize;
93
cpio_tmp = g_strdup ("/tmp/xarchiver-XXXXXX");
94
fd = g_mkstemp ( cpio_tmp );
93
/* Create a unique temp dir in /tmp */
94
result = xa_create_temp_directory (archive);
98
gzip_tmp = g_strconcat (archive->tmp,"/file.gz_bz",NULL);
95
99
ibs = g_strdup_printf ( "%u" , offset );
97
//Now I run dd to have the bzip2 / gzip compressed cpio archive in /tmp
98
gchar *command = g_strconcat ( "dd if=" , archive->escaped_path, " ibs=" , ibs , " skip=1 of=" , cpio_tmp , NULL );
101
/* Now I run dd to have the bzip2 / gzip compressed cpio archive in /tmp */
102
gchar *command = g_strconcat ( "dd if=",archive->escaped_path," ibs=",ibs," skip=1 of=",gzip_tmp,NULL);
100
archive->parse_output = 0;
101
SpawnAsyncProcess ( archive , command , 0, 0);
103
if ( archive->child_pid == 0 )
110
g_child_watch_add ( archive->child_pid , (GChildWatchFunc) DecompressCPIO , cpio_tmp );
113
GChildWatchFunc *DecompressCPIO (GPid pid , gint status , gpointer data)
117
current_page = gtk_notebook_get_current_page(notebook);
119
if ( WIFEXITED(status) )
121
if ( WEXITSTATUS (status) )
123
Update_StatusBar ( _("Operation failed."));
124
gtk_widget_hide ( viewport2 );
125
xa_set_window_title (MainWindow , NULL);
126
response = ShowGtkMessageDialog (GTK_WINDOW (MainWindow),GTK_DIALOG_MODAL,GTK_MESSAGE_QUESTION,GTK_BUTTONS_YES_NO,_("Error while extracting the cpio archive from the rpm one."),("Do you want to view the command line output?") );
127
if (response == GTK_RESPONSE_YES)
128
xa_show_cmd_line_output (NULL);
131
xa_set_button_state (1,1,0,0,0,0);
132
xa_hide_progress_bar_stop_button(archive[current_page]);
136
cpio_tmp = xa_open_temp_file ( gzip );
137
if (cpio_tmp != NULL)
138
g_child_watch_add ( archive[current_page]->child_pid , (GChildWatchFunc) OpenCPIO , gzip );
144
GChildWatchFunc *OpenCPIO (GPid pid , gint exit_code , gpointer data)
148
current_page = gtk_notebook_get_current_page(notebook);
150
if ( WIFEXITED( exit_code ) )
152
if ( WEXITSTATUS ( exit_code ) )
154
Update_StatusBar ( _("Operation failed."));
155
gtk_widget_hide ( viewport2 );
156
xa_set_window_title (MainWindow , NULL);
157
response = ShowGtkMessageDialog (GTK_WINDOW (MainWindow),GTK_DIALOG_MODAL,GTK_MESSAGE_QUESTION,GTK_BUTTONS_YES_NO,_("An error occurred while decompressing the cpio archive."),_("Do you want to view the command line output?") );
158
if (response == GTK_RESPONSE_YES)
159
xa_show_cmd_line_output (NULL);
163
xa_set_button_state (1,1,0,0,0,0);
164
xa_hide_progress_bar_stop_button(archive[current_page]);
168
/* Let's delete the tmp gzip compressed CPIO archive since we don't need it anymore */
171
/* Now I have to open the CPIO temp file in read mode and spawn the
172
command cpio -tv with an input pipe so to receive the output from
173
the opened CPIO temp file */
175
archive[current_page]->parse_output = 0;
176
SpawnAsyncProcess ( archive[current_page] , "cpio -tv" , 1, 0 );
177
if ( archive[current_page]->child_pid == 0 )
183
output_ioc = g_io_channel_unix_new ( output_fd );
184
g_io_add_watch (output_ioc, G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, ReadCPIOOutput, archive[current_page] );
185
g_io_channel_set_encoding (output_ioc, locale , NULL);
186
g_io_channel_set_flags ( output_ioc , G_IO_FLAG_NONBLOCK , NULL );
188
input_ioc = g_io_channel_unix_new ( input_fd );
189
g_io_add_watch (input_ioc, G_IO_IN|G_IO_OUT|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, WriteCPIOInput, NULL );
190
g_io_channel_set_encoding (input_ioc, NULL , NULL);
192
ioc_cpio = g_io_channel_new_file ( cpio_tmp , "r" , NULL );
193
g_io_channel_set_encoding (ioc_cpio , NULL , NULL);
194
g_io_channel_set_flags ( ioc_cpio , G_IO_FLAG_NONBLOCK , NULL );
196
g_child_watch_add ( archive[current_page]->child_pid, (GChildWatchFunc) xa_watch_child, archive[current_page]);
201
gboolean WriteCPIOInput (GIOChannel *ioc, GIOCondition cond, gpointer data)
203
if (cond & (G_IO_IN | G_IO_PRI | G_IO_OUT) )
205
/* Doing so I write to the input pipe of the g_spawned "cpio -tv" so to produce the list of files in the cpio archive */
206
status = g_io_channel_read_chars ( ioc_cpio , buffer, sizeof(buffer), &bytes_read, &error);
207
if ( status != G_IO_STATUS_EOF)
209
status = g_io_channel_write_chars ( ioc , buffer , bytes_read , &bytes_written , &error );
210
if (status == G_IO_STATUS_ERROR)
212
response = ShowGtkMessageDialog (GTK_WINDOW (MainWindow),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("An error occurred:"),error->message);
213
g_error_free (error);
214
CloseChannels ( ioc_cpio );
215
CloseChannels ( ioc );
219
while ( bytes_read != bytes_written )
220
status = g_io_channel_write_chars ( ioc , buffer + bytes_written , bytes_read - bytes_written , &bytes_written , &error );
221
g_print ("*Written:%d\tStatus:%d\n",bytes_written,status);
223
g_io_channel_flush ( ioc , NULL );
104
list = g_slist_append(list,command);
106
result = xa_run_command (archive,list);
112
if (xa_detect_archive_type (gzip_tmp) == XARCHIVETYPE_GZIP)
113
executable = "gzip -dc ";
115
executable = "bzip2 -dc ";
117
command = g_strconcat("sh -c \"",executable,gzip_tmp," > ",archive->tmp,"/file.cpio\"",NULL);
120
list = g_slist_append(list,command);
121
result = xa_run_command (archive,list);
124
gtk_widget_set_sensitive(Stop_button,FALSE);
125
xa_set_button_state (1,1,1,1,archive->can_add,archive->can_extract,0,archive->has_test,archive->has_properties,archive->has_passwd,0);
126
gtk_label_set_text(GTK_LABEL(total_label),"");
129
/* And finally cpio to receive the content */
130
command = g_strconcat ("sh -c \"cpio -tv < ",archive->tmp,"/file.cpio\"",NULL);
131
archive->parse_output = xa_get_cpio_line_content;
132
xa_spawn_async_process (archive,command);
136
void xa_get_cpio_line_content (gchar *line, gpointer data)
138
XArchive *archive = data;
142
gint n = 0, a = 0 ,linesize = 0;
143
gboolean dir = FALSE;
145
linesize = strlen(line);
146
archive->nr_of_files++;
154
for(n=a; n < linesize && line[n] == ' '; ++n);
161
for(; n < linesize && line[n] != ' '; ++n);
167
for(; n < linesize && line[n] == ' '; ++n);
170
for(; n < linesize && line[n] != ' '; ++n);
176
for(; n < linesize && line[n] == ' '; ++n);
179
for(; n < linesize && line[n] != ' '; ++n);
182
archive->dummy_size += g_ascii_strtoull(item[1],NULL,0);
190
line[linesize-1] = '\0';
194
gchar *temp = g_strrstr (filename,"->");
198
gint len = strlen(filename) - strlen(temp);
199
item[0] = filename + a + len;
200
filename[strlen(filename) - strlen(temp)] = '\0';
208
/* Work around for cpio, which does
209
* not output / with directories */
211
if(line[linesize-2] != '/')
212
filename = g_strconcat(line + n, "/", NULL);
228
CloseChannels ( ioc_cpio );
229
CloseChannels ( ioc );
237
gboolean ReadCPIOOutput (GIOChannel *ioc, GIOCondition cond, gpointer data)
239
XArchive *archive = data;
240
gchar **fields = NULL;
242
gchar *filename = NULL;
243
GIOStatus status = G_IO_STATUS_NORMAL;
247
/* Is there output from "cpio -tv" to read ? */
248
if (cond & (G_IO_IN | G_IO_PRI) )
252
status = g_io_channel_read_line ( ioc, &line, NULL, NULL , NULL );
256
fields = split_line (line , 5);
257
filename = get_last_field (line , 9);
258
gtk_list_store_append (archive->liststore, &iter);
259
if ( g_str_has_prefix(fields[0] , "d") == FALSE)
260
archive->nr_of_files++;
262
archive->nr_of_dirs++;
264
temp = g_strrstr (filename,"->");
267
gtk_list_store_set (archive->liststore, &iter,2,g_strstrip(&temp[3]),-1);
268
temp = g_strstrip(g_strndup(filename, strlen(filename) - strlen(temp) ));
269
gtk_list_store_set (archive->liststore, &iter,0,temp,-1);
274
gtk_list_store_set (archive->liststore, &iter,2,NULL,-1);
275
gtk_list_store_set (archive->liststore, &iter,0,filename,-1);
278
gtk_list_store_set (archive->liststore, &iter,1,fields[0],-1);
279
gtk_list_store_set (archive->liststore, &iter,3,fields[1],-1);
280
gtk_list_store_set (archive->liststore, &iter,4,fields[2],-1);
281
gtk_list_store_set (archive->liststore, &iter,5,fields[3],-1);
282
gtk_list_store_set (archive->liststore, &iter,6,strtoll(fields[4],NULL,0),-1);
284
while (gtk_events_pending() )
285
gtk_main_iteration();
287
archive->dummy_size += strtoll(fields[4],NULL,0);
288
g_strfreev ( fields );
291
while (status == G_IO_STATUS_NORMAL);
293
if (status == G_IO_STATUS_ERROR || status == G_IO_STATUS_EOF)
296
else if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL) )
298
done: CloseChannels (ioc);
299
gtk_tree_view_set_model (GTK_TREE_VIEW(archive->treeview), archive->model);
300
g_object_unref (archive->model);
301
archive->tmp = cpio_tmp;
307
void CloseChannels ( GIOChannel *ioc )
309
g_io_channel_shutdown ( ioc,TRUE,NULL );
310
g_io_channel_unref (ioc);
313
gchar *xa_open_temp_file ( gchar *temp_path )
317
current_page = gtk_notebook_get_current_page(notebook);
318
gchar *command = NULL;
319
tmp = g_strdup ("/tmp/xarchiver-XXXXXX");
320
fd = g_mkstemp ( tmp );
321
stream = fdopen ( fd , "w" );
324
response = ShowGtkMessageDialog (GTK_WINDOW (MainWindow),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't write to /tmp:"),g_strerror(errno) );
328
if (xa_detect_archive_type ( NULL , temp_path ) == XARCHIVETYPE_GZIP)
329
command = g_strconcat ( "gzip -dc " , temp_path , NULL );
214
filename = g_strdup(line + n);
331
command = g_strconcat ( "bzip2 -dc " , temp_path , NULL );
332
archive[current_page]->parse_output = 0;
333
SpawnAsyncProcess ( archive[current_page] , command , 0, 0);
335
if ( archive[current_page]->child_pid == 0 )
342
GIOChannel *ioc = g_io_channel_unix_new ( output_fd );
343
g_io_channel_set_encoding (ioc, NULL , NULL);
344
g_io_channel_set_flags ( ioc , G_IO_FLAG_NONBLOCK , NULL );
345
g_io_add_watch (ioc, G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, ExtractToDifferentLocation, stream);
217
filename = g_strdup(line + n);
219
entry = xa_set_archive_entries_for_each_row (archive,filename,item);
349
gboolean ExtractToDifferentLocation (GIOChannel *ioc, GIOCondition cond, gpointer data)
223
gboolean xa_rpm_extract(XArchive *archive,GSList *files)
355
GError *error = NULL;
357
if (cond & (G_IO_IN | G_IO_PRI) )
361
status = g_io_channel_read_chars (ioc, buffer, sizeof(buffer), &bytes_read, &error);
364
/* Write the content of the bzip/gzip extracted file to the file pointed by the file stream */
365
fwrite (buffer, 1, bytes_read, stream);
367
else if (error != NULL)
369
response = ShowGtkMessageDialog (GTK_WINDOW (MainWindow),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK, _("An error occurred:"),error->message);
370
g_error_free (error);
374
while (status == G_IO_STATUS_NORMAL);
376
if (status == G_IO_STATUS_ERROR || status == G_IO_STATUS_EOF)
379
else if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL) )
383
g_io_channel_shutdown ( ioc,TRUE,NULL );
384
g_io_channel_unref (ioc);
225
gchar *command = NULL,*e_filename = NULL;
226
GSList *list = NULL,*_files = NULL;
227
GString *names = g_string_new("");
228
gboolean result = FALSE;
233
e_filename = xa_escape_filename((gchar*)_files->data,"$'`\"\\!?* ()[]&|:;<>#");
234
g_string_prepend (names,e_filename);
235
g_string_prepend_c (names,' ');
236
_files = _files->next;
238
g_slist_foreach(files,(GFunc)g_free,NULL);
241
chdir (archive->extraction_path);
242
command = g_strconcat ( "sh -c \"cpio -id" , names->str," < ",archive->tmp,"/file.cpio\"",NULL);
244
g_string_free(names,TRUE);
245
list = g_slist_append(list,command);
246
result = xa_run_command (archive,list);