1 /******************************* LICENCE **************************************
2 * Any code in this file may be redistributed or modified under the terms of
3 * the GNU General Public Licence as published by the Free Software
4 * Foundation; version 2 of the licence.
5 ****************************** END LICENCE ***********************************/
6
7 /******************************************************************************
8 * Author:
9 * Andrew Smith, http://littlesvr.ca/misc/contactandrew.php
10 *
11 * Contributors:
12 *
13 ******************************************************************************/
14
15 #include <gtk/gtk.h>
16 #include <gdk/gdkkeysyms.h>
17 #include <libintl.h>
18 #include <errno.h>
19 #include <signal.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22
23 #include "isomaster.h"
24 #include "bk/bkIoWrappers.h"
25
26 #include <sys/wait.h>
27
28 #define MAX_RANDOM_BASE_NAME_LEN 26
29 #define RANDOM_STR_NAME_LEN 6
30
31 /* milliseconds */
32 #define TIMEOUT_TIME 50
33
34 /* files that I created in the temp dir for editing */
35 TempFileCreated* GBLtempFilesList = NULL;
36
37 extern GtkWidget* GBLfsTreeView;
38 extern char* GBLfsCurrentDir;
39 extern bool GBLisoPaneActive;
40 extern GtkWidget* GBLisoTreeView;
41 extern char* GBLisoCurrentDir;
42 extern VolInfo GBLvolInfo;
43 extern GtkWidget* GBLmainWindow;
44 extern bool GBLisoChangesProbable;
45 extern AppSettings GBLappSettings;
46
47 static bool GBLeditFailed;
48 static bool GBLviewFailed;
49
50 /******************************************************************************
51 * addToTempFilesList()
52 * Appends a node to the front of the list.
53 * */
addToTempFilesList(const char * pathAndName)54 void addToTempFilesList(const char* pathAndName)
55 {
56 TempFileCreated* newNode;
57
58 newNode = malloc(sizeof(TempFileCreated));
59 if(newNode == NULL)
60 fatalError("newNode = malloc(sizeof(TempFileCreated)) failed\n");
61
62 newNode->pathAndName = malloc(strlen(pathAndName) + 1);
63 if(newNode == NULL)
64 fatalError("newNode.pathAndName = malloc(strlen(pathAndName) + 1) failed\n");
65
66 strcpy(newNode->pathAndName, pathAndName);
67
68 newNode->next = GBLtempFilesList;
69
70 GBLtempFilesList = newNode;
71 }
72
checkEditFailed(gpointer data)73 gboolean checkEditFailed(gpointer data)
74 {
75 if(GBLeditFailed)
76 {
77 GtkWidget* warningDialog;
78 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
79 GTK_DIALOG_DESTROY_WITH_PARENT,
80 GTK_MESSAGE_ERROR,
81 GTK_BUTTONS_CLOSE,
82 _("Edit failed, please check Options/Editor"));
83 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
84 gtk_dialog_run(GTK_DIALOG(warningDialog));
85 gtk_widget_destroy(warningDialog);
86
87 return FALSE;
88 }
89 else
90 return TRUE;
91 }
92
checkViewFailed(gpointer data)93 gboolean checkViewFailed(gpointer data)
94 {
95 if(GBLviewFailed)
96 {
97 GtkWidget* warningDialog;
98 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
99 GTK_DIALOG_DESTROY_WITH_PARENT,
100 GTK_MESSAGE_ERROR,
101 GTK_BUTTONS_CLOSE,
102 _("View failed, please check Options/Viewer"));
103 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
104 gtk_dialog_run(GTK_DIALOG(warningDialog));
105 gtk_widget_destroy(warningDialog);
106
107 return FALSE;
108 }
109 else
110 return TRUE;
111 }
112
copyFsToFs(const char * src,const char * dest)113 bool copyFsToFs(const char* src, const char* dest)
114 {
115 BkStatStruct statStruct;
116 int srcFile;
117 int destFile;
118 int rc;
119 const int blockSize = 102400;
120 int count;
121 int numBlocks;
122 int sizeLastBlock;
123 char buffer[blockSize];
124
125 rc = bkStat(src, &statStruct);
126 if(rc != 0)
127 return false;
128
129 srcFile = open(src, O_RDONLY);
130 if(srcFile <= 0)
131 return false;
132
133 destFile = open(dest, O_WRONLY | O_CREAT | O_EXCL, 0600);
134 if(destFile <= 0)
135 {
136 bkClose(srcFile);
137 return false;
138 }
139
140 numBlocks = statStruct.st_size / blockSize;
141 sizeLastBlock = statStruct.st_size % blockSize;
142
143 for(count = 0; count < numBlocks; count++)
144 {
145 rc = bkRead(srcFile, buffer, blockSize);
146 if(rc != blockSize)
147 {
148 bkClose(srcFile);
149 bkClose(destFile);
150 return false;
151 }
152
153 rc = bkWrite(destFile, buffer, blockSize);
154 if(rc != blockSize)
155 {
156 bkClose(srcFile);
157 bkClose(destFile);
158 return false;
159 }
160 }
161
162 if(sizeLastBlock > 0)
163 {
164 rc = bkRead(srcFile, buffer, sizeLastBlock);
165 if(rc != sizeLastBlock)
166 {
167 bkClose(srcFile);
168 bkClose(destFile);
169 return false;
170 }
171 rc = bkWrite(destFile, buffer, sizeLastBlock);
172 if(rc != sizeLastBlock)
173 {
174 bkClose(srcFile);
175 bkClose(destFile);
176 return false;
177 }
178 }
179
180 bkClose(srcFile);
181 bkClose(destFile);
182
183 return true;
184 }
185
deleteTempFiles(void)186 void deleteTempFiles(void)
187 {
188 TempFileCreated* next;
189
190 while(GBLtempFilesList != NULL)
191 {
192 next = GBLtempFilesList->next;
193
194 unlink(GBLtempFilesList->pathAndName);
195
196 free(GBLtempFilesList->pathAndName);
197 free(GBLtempFilesList);
198
199 GBLtempFilesList = next;
200 }
201 }
202
editSelectedBtnCbk(GtkMenuItem * menuitem,gpointer data)203 void editSelectedBtnCbk(GtkMenuItem *menuitem, gpointer data)
204 {
205 GtkTreeSelection* selection;
206 static guint timeoutTag = 0;
207
208 gboolean fsViewHasFocus;
209 gboolean isoViewHasFocus;
210
211 g_object_get(GBLfsTreeView, "is-focus", &fsViewHasFocus, NULL);
212 g_object_get(GBLisoTreeView, "is-focus", &isoViewHasFocus, NULL);
213
214 if(fsViewHasFocus)
215 {
216 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(GBLfsTreeView));
217
218 /* kill the previous timeout function (if any) */
219 if(timeoutTag != 0)
220 g_source_remove(timeoutTag);
221
222 GBLeditFailed = false;
223
224 /* a timeout that will keep checking whether GBLviewFailed */
225 timeoutTag = g_timeout_add(TIMEOUT_TIME, checkViewFailed, NULL);
226
227 gtk_tree_selection_selected_foreach(selection, editSelectedFsRowCbk, NULL);
228 }
229 else if(isoViewHasFocus)
230 {
231 /* do nothing if no image open */
232 if(!GBLisoPaneActive)
233 return;
234
235 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(GBLisoTreeView));
236
237 /* kill the previous timeout function (if any) */
238 if(timeoutTag != 0)
239 g_source_remove(timeoutTag);
240
241 GBLeditFailed = false;
242
243 /* a timeout that will keep checking whether GBLeditFailed */
244 timeoutTag = g_timeout_add(TIMEOUT_TIME, checkEditFailed, NULL);
245
246 gtk_tree_selection_selected_foreach(selection, editSelectedIsoRowCbk, NULL);
247
248 /* can't put this in the callback because gtk complains */
249 //refreshIsoView();
250 }
251 }
252
editSelectedFsRowCbk(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iterator,gpointer data)253 void editSelectedFsRowCbk(GtkTreeModel* model, GtkTreePath* path,
254 GtkTreeIter* iterator, gpointer data)
255 {
256 int fileType;
257 char* itemName;
258 char* randomizedItemName;
259 char* pathAndNameOnFs;
260 char* pathAndNameInTempDir;
261 GtkWidget* warningDialog;
262 bool copiedOk;
263
264 gtk_tree_model_get(model, iterator, COLUMN_HIDDEN_TYPE, &fileType,
265 COLUMN_FILENAME, &itemName, -1);
266 if(fileType != FILE_TYPE_REGULAR)
267 {
268 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
269 GTK_DIALOG_DESTROY_WITH_PARENT,
270 GTK_MESSAGE_ERROR,
271 GTK_BUTTONS_CLOSE,
272 _("'%s' is not a regular file"),
273 itemName);
274 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
275 gtk_dialog_run(GTK_DIALOG(warningDialog));
276 gtk_widget_destroy(warningDialog);
277
278 g_free(itemName);
279 return;
280 }
281
282 /* create full path and name for the file on the fs */
283 pathAndNameOnFs = malloc(strlen(GBLfsCurrentDir) + strlen(itemName) + 1);
284 if(pathAndNameOnFs == NULL)
285 fatalError("malloc(strlen(GBLfsCurrentDir) + strlen(itemName) + 1) failed");
286 strcpy(pathAndNameOnFs, GBLfsCurrentDir);
287 strcat(pathAndNameOnFs, itemName);
288
289 /* create full path and name for the extracted file */
290 randomizedItemName = makeRandomFilename(itemName);
291 pathAndNameInTempDir = malloc(strlen(GBLappSettings.tempDir) +
292 strlen(randomizedItemName) + 2);
293 if(pathAndNameInTempDir == NULL)
294 fatalError("malloc(strlen(GBLappSettings.tempDir) + "
295 "strlen(randomizedItemName) + 2) failed");
296 strcpy(pathAndNameInTempDir, GBLappSettings.tempDir);
297
298 strcat(pathAndNameInTempDir, "/"); /* doesn't hurt even if not needed */
299
300 strcat(pathAndNameInTempDir, randomizedItemName);
301
302 /* disable warnings, so user isn't confused with 'continue' buttons */
303 bool(*savedWarningCbk)(const char*) = GBLvolInfo.warningCbk;
304 GBLvolInfo.warningCbk = NULL;
305
306 /* copy the file to the temporary directory */
307 copiedOk = copyFsToFs(pathAndNameOnFs, pathAndNameInTempDir);
308 if(!copiedOk)
309 {
310 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
311 GTK_DIALOG_DESTROY_WITH_PARENT,
312 GTK_MESSAGE_ERROR,
313 GTK_BUTTONS_CLOSE,
314 "Failed to copy '%s' to '%s'",
315 pathAndNameOnFs,
316 pathAndNameInTempDir);
317 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
318 gtk_dialog_run(GTK_DIALOG(warningDialog));
319 gtk_widget_destroy(warningDialog);
320
321 g_free(itemName);
322 free(randomizedItemName);
323 free(pathAndNameOnFs);
324 free(pathAndNameInTempDir);
325 GBLvolInfo.warningCbk = savedWarningCbk;
326 return;
327 }
328
329 addToTempFilesList(pathAndNameInTempDir);
330
331 /* start the viewer */
332 if(!fork())
333 {
334 execlp(GBLappSettings.editor, "editor", pathAndNameInTempDir, NULL);
335
336 kill(getppid(), SIGUSR2);
337
338 exit(1);
339 }
340
341 g_free(itemName);
342 free(randomizedItemName);
343 free(pathAndNameOnFs);
344 free(pathAndNameInTempDir);
345 GBLvolInfo.warningCbk = savedWarningCbk;
346 }
347
editSelectedIsoRowCbk(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iterator,gpointer data)348 void editSelectedIsoRowCbk(GtkTreeModel* model, GtkTreePath* path,
349 GtkTreeIter* iterator, gpointer data)
350 {
351 int fileType;
352 char* itemName;
353 char* randomizedItemName;
354 char* pathAndNameOnFs; /* to extract to and add from */
355 char* pathAndNameOnIso; /* to delete from iso */
356 int rc;
357 GtkWidget* warningDialog;
358
359 gtk_tree_model_get(model, iterator, COLUMN_HIDDEN_TYPE, &fileType,
360 COLUMN_FILENAME, &itemName, -1);
361
362 if(fileType != FILE_TYPE_REGULAR)
363 {
364 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
365 GTK_DIALOG_DESTROY_WITH_PARENT,
366 GTK_MESSAGE_ERROR,
367 GTK_BUTTONS_CLOSE,
368 _("'%s' is not a regular file"),
369 itemName);
370 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
371 gtk_dialog_run(GTK_DIALOG(warningDialog));
372 gtk_widget_destroy(warningDialog);
373
374 g_free(itemName);
375 return;
376 }
377
378 /* create full path and name for the file on the iso */
379 pathAndNameOnIso = malloc(strlen(GBLisoCurrentDir) + strlen(itemName) + 1);
380 if(pathAndNameOnIso == NULL)
381 fatalError("malloc(strlen(GBLisoCurrentDir) + strlen(itemName) + 1) failed");
382 strcpy(pathAndNameOnIso, GBLisoCurrentDir);
383 strcat(pathAndNameOnIso, itemName);
384
385 /* create full path and name for the extracted file */
386 randomizedItemName = makeRandomFilename(itemName);
387 pathAndNameOnFs = malloc(strlen(GBLappSettings.tempDir) +
388 strlen(randomizedItemName) + 2);
389 if(pathAndNameOnFs == NULL)
390 fatalError("malloc(strlen(GBLappSettings.tempDir) + "
391 "strlen(randomizedItemName) + 2) failed");
392 strcpy(pathAndNameOnFs, GBLappSettings.tempDir);
393
394 strcat(pathAndNameOnFs, "/"); /* doesn't hurt even if not needed */
395
396 strcat(pathAndNameOnFs, randomizedItemName);
397
398 /* disable warnings, so user isn't confused with 'continue' buttons */
399 bool(*savedWarningCbk)(const char*) = GBLvolInfo.warningCbk;
400 GBLvolInfo.warningCbk = NULL;
401
402 /* extract the file to the temporary directory */
403 rc = bk_extract_as(&GBLvolInfo, pathAndNameOnIso,
404 GBLappSettings.tempDir,
405 randomizedItemName, false, activityProgressUpdaterCbk);
406 if(rc <= 0)
407 {
408 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
409 GTK_DIALOG_DESTROY_WITH_PARENT,
410 GTK_MESSAGE_ERROR,
411 GTK_BUTTONS_CLOSE,
412 _("Failed to extract '%s': '%s'"),
413 pathAndNameOnIso,
414 bk_get_error_string(rc));
415 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
416 gtk_dialog_run(GTK_DIALOG(warningDialog));
417 gtk_widget_destroy(warningDialog);
418
419 g_free(itemName);
420 free(randomizedItemName);
421 free(pathAndNameOnFs);
422 free(pathAndNameOnIso);
423 GBLvolInfo.warningCbk = savedWarningCbk;
424 return;
425 }
426
427 addToTempFilesList(pathAndNameOnFs);
428
429 /* start the editor */
430 if(!fork())
431 {
432 execlp(GBLappSettings.editor, "editor", pathAndNameOnFs, NULL);
433
434 kill(getppid(), SIGUSR1);
435
436 exit(1);
437 }
438
439 /* delete the file from the iso */
440 rc = bk_delete(&GBLvolInfo, pathAndNameOnIso);
441 if(rc <= 0)
442 {
443 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
444 GTK_DIALOG_DESTROY_WITH_PARENT,
445 GTK_MESSAGE_ERROR,
446 GTK_BUTTONS_CLOSE,
447 _("Failed to delete '%s': '%s'"),
448 pathAndNameOnIso,
449 bk_get_error_string(rc));
450 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
451 gtk_dialog_run(GTK_DIALOG(warningDialog));
452 gtk_widget_destroy(warningDialog);
453
454 g_free(itemName);
455 free(randomizedItemName);
456 free(pathAndNameOnFs);
457 free(pathAndNameOnIso);
458 GBLvolInfo.warningCbk = savedWarningCbk;
459 return;
460 }
461
462 GBLisoChangesProbable = true;
463
464 /* add the file back fom tmp */
465 rc = bk_add_as(&GBLvolInfo, pathAndNameOnFs, GBLisoCurrentDir, itemName,
466 activityProgressUpdaterCbk);
467 if(rc <= 0)
468 {
469 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
470 GTK_DIALOG_DESTROY_WITH_PARENT,
471 GTK_MESSAGE_ERROR,
472 GTK_BUTTONS_CLOSE,
473 _("Failed to add '%s': '%s'"),
474 pathAndNameOnFs,
475 bk_get_error_string(rc));
476 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
477 gtk_dialog_run(GTK_DIALOG(warningDialog));
478 gtk_widget_destroy(warningDialog);
479 }
480
481 g_free(itemName);
482 free(randomizedItemName);
483 free(pathAndNameOnFs);
484 free(pathAndNameOnIso);
485 GBLvolInfo.warningCbk = savedWarningCbk;
486 }
487
488 /* caller must free the string returned */
makeRandomFilename(const char * sourceName)489 char* makeRandomFilename(const char* sourceName)
490 {
491 int sourceNameLen;
492 char* newName;
493 char randomStr[RANDOM_STR_NAME_LEN];
494 int numRandomCharsFilled;
495
496 if(strlen(sourceName) > MAX_RANDOM_BASE_NAME_LEN)
497 sourceNameLen = MAX_RANDOM_BASE_NAME_LEN;
498 else
499 sourceNameLen = strlen(sourceName);
500
501 newName = malloc(sourceNameLen + RANDOM_STR_NAME_LEN + 2);
502 if(newName == NULL)
503 fatalError("newName = malloc(sourceNameLen + RANDOM_STR_NAME_LEN + 2) failed\n");
504
505 numRandomCharsFilled = 0;
506 while(numRandomCharsFilled < RANDOM_STR_NAME_LEN)
507 {
508 char oneRandomChar;
509 bool gotGoodChar;
510
511 #ifdef HAVE_ARC4RANDOM
512 oneRandomChar = arc4random_uniform('Z'-'A'+1) + 'A';
513 #else
514 gotGoodChar = false;
515 while(!gotGoodChar)
516 {
517 oneRandomChar = random();
518 if(64 < oneRandomChar && oneRandomChar < 91)
519 {
520 gotGoodChar = true;
521 }
522 }
523 #endif
524
525 randomStr[numRandomCharsFilled] = oneRandomChar;
526
527 numRandomCharsFilled++;
528 }
529
530 strncpy(newName, randomStr, RANDOM_STR_NAME_LEN);
531 newName[RANDOM_STR_NAME_LEN] = '\0';
532 strcat(newName, "-");
533 strncat(newName, sourceName, sourceNameLen);
534 newName[RANDOM_STR_NAME_LEN + sourceNameLen + 1] = '\0';
535
536 return newName;
537 }
538
viewSelectedBtnCbk(GtkMenuItem * menuitem,gpointer data)539 void viewSelectedBtnCbk(GtkMenuItem *menuitem, gpointer data)
540 {
541 GtkTreeSelection* selection;
542 static guint timeoutTag = 0;
543
544 gboolean fsViewHasFocus;
545 gboolean isoViewHasFocus;
546
547 g_object_get(GBLfsTreeView, "is-focus", &fsViewHasFocus, NULL);
548 g_object_get(GBLisoTreeView, "is-focus", &isoViewHasFocus, NULL);
549
550 if(fsViewHasFocus)
551 {
552 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(GBLfsTreeView));
553
554 /* kill the previous timeout function (if any) */
555 if(timeoutTag != 0)
556 g_source_remove(timeoutTag);
557
558 GBLviewFailed = false;
559
560 /* a timeout that will keep checking whether GBLviewFailed */
561 timeoutTag = g_timeout_add(TIMEOUT_TIME, checkViewFailed, NULL);
562
563 gtk_tree_selection_selected_foreach(selection, viewSelectedFsRowCbk, NULL);
564 }
565 else if(isoViewHasFocus)
566 {
567 /* do nothing if no image open */
568 if(!GBLisoPaneActive)
569 return;
570
571 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(GBLisoTreeView));
572
573 /* kill the previous timeout function (if any) */
574 if(timeoutTag != 0)
575 g_source_remove(timeoutTag);
576
577 GBLviewFailed = false;
578
579 /* a timeout that will keep checking whether GBLviewFailed */
580 timeoutTag = g_timeout_add(TIMEOUT_TIME, checkViewFailed, NULL);
581
582 gtk_tree_selection_selected_foreach(selection, viewSelectedIsoRowCbk, NULL);
583 }
584 }
585
viewSelectedFsRowCbk(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iterator,gpointer data)586 void viewSelectedFsRowCbk(GtkTreeModel* model, GtkTreePath* path,
587 GtkTreeIter* iterator, gpointer data)
588 {
589 int fileType;
590 char* itemName;
591 char* randomizedItemName;
592 char* pathAndNameOnFs;
593 char* pathAndNameInTempDir;
594 GtkWidget* warningDialog;
595 bool copiedOk;
596
597 gtk_tree_model_get(model, iterator, COLUMN_HIDDEN_TYPE, &fileType,
598 COLUMN_FILENAME, &itemName, -1);
599 if(fileType != FILE_TYPE_REGULAR)
600 {
601 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
602 GTK_DIALOG_DESTROY_WITH_PARENT,
603 GTK_MESSAGE_ERROR,
604 GTK_BUTTONS_CLOSE,
605 _("'%s' is not a regular file"),
606 itemName);
607 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
608 gtk_dialog_run(GTK_DIALOG(warningDialog));
609 gtk_widget_destroy(warningDialog);
610
611 g_free(itemName);
612 return;
613 }
614
615 /* create full path and name for the file on the fs */
616 pathAndNameOnFs = malloc(strlen(GBLfsCurrentDir) + strlen(itemName) + 1);
617 if(pathAndNameOnFs == NULL)
618 fatalError("malloc(strlen(GBLfsCurrentDir) + strlen(itemName) + 1) failed");
619 strcpy(pathAndNameOnFs, GBLfsCurrentDir);
620 strcat(pathAndNameOnFs, itemName);
621
622 /* create full path and name for the extracted file */
623 randomizedItemName = makeRandomFilename(itemName);
624 pathAndNameInTempDir = malloc(strlen(GBLappSettings.tempDir) +
625 strlen(randomizedItemName) + 2);
626 if(pathAndNameInTempDir == NULL)
627 fatalError("malloc(strlen(GBLappSettings.tempDir) + "
628 "strlen(randomizedItemName) + 2) failed");
629 strcpy(pathAndNameInTempDir, GBLappSettings.tempDir);
630
631 strcat(pathAndNameInTempDir, "/"); /* doesn't hurt even if not needed */
632
633 strcat(pathAndNameInTempDir, randomizedItemName);
634
635 /* disable warnings, so user isn't confused with 'continue' buttons */
636 bool(*savedWarningCbk)(const char*) = GBLvolInfo.warningCbk;
637 GBLvolInfo.warningCbk = NULL;
638
639 /* copy the file to the temporary directory */
640 copiedOk = copyFsToFs(pathAndNameOnFs, pathAndNameInTempDir);
641 if(!copiedOk)
642 {
643 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
644 GTK_DIALOG_DESTROY_WITH_PARENT,
645 GTK_MESSAGE_ERROR,
646 GTK_BUTTONS_CLOSE,
647 "Failed to copy '%s' to '%s'",
648 pathAndNameOnFs,
649 pathAndNameInTempDir);
650 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
651 gtk_dialog_run(GTK_DIALOG(warningDialog));
652 gtk_widget_destroy(warningDialog);
653
654 g_free(itemName);
655 free(randomizedItemName);
656 free(pathAndNameOnFs);
657 free(pathAndNameInTempDir);
658 GBLvolInfo.warningCbk = savedWarningCbk;
659 return;
660 }
661
662 addToTempFilesList(pathAndNameInTempDir);
663
664 /* start the viewer */
665 if(!fork())
666 {
667 execlp(GBLappSettings.viewer, "viewer", pathAndNameInTempDir, NULL);
668
669 kill(getppid(), SIGUSR2);
670
671 exit(1);
672 }
673
674 g_free(itemName);
675 free(randomizedItemName);
676 free(pathAndNameOnFs);
677 free(pathAndNameInTempDir);
678 GBLvolInfo.warningCbk = savedWarningCbk;
679 }
680
viewSelectedIsoRowCbk(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iterator,gpointer data)681 void viewSelectedIsoRowCbk(GtkTreeModel* model, GtkTreePath* path,
682 GtkTreeIter* iterator, gpointer data)
683 {
684 int fileType;
685 char* itemName;
686 char* randomizedItemName;
687 char* pathAndNameOnFs; /* to extract to and add from */
688 char* pathAndNameOnIso; /* to delete from iso */
689 int rc;
690 GtkWidget* warningDialog;
691
692 gtk_tree_model_get(model, iterator, COLUMN_HIDDEN_TYPE, &fileType,
693 COLUMN_FILENAME, &itemName, -1);
694 if(fileType != FILE_TYPE_REGULAR)
695 {
696 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
697 GTK_DIALOG_DESTROY_WITH_PARENT,
698 GTK_MESSAGE_ERROR,
699 GTK_BUTTONS_CLOSE,
700 _("'%s' is not a regular file"),
701 itemName);
702 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
703 gtk_dialog_run(GTK_DIALOG(warningDialog));
704 gtk_widget_destroy(warningDialog);
705
706 g_free(itemName);
707 return;
708 }
709
710 /* create full path and name for the file on the iso */
711 pathAndNameOnIso = malloc(strlen(GBLisoCurrentDir) + strlen(itemName) + 1);
712 if(pathAndNameOnIso == NULL)
713 fatalError("malloc(strlen(GBLisoCurrentDir) + strlen(itemName) + 1) failed");
714 strcpy(pathAndNameOnIso, GBLisoCurrentDir);
715 strcat(pathAndNameOnIso, itemName);
716
717 /* create full path and name for the extracted file */
718 randomizedItemName = makeRandomFilename(itemName);
719 pathAndNameOnFs = malloc(strlen(GBLappSettings.tempDir) +
720 strlen(randomizedItemName) + 2);
721 if(pathAndNameOnFs == NULL)
722 fatalError("malloc(strlen(GBLappSettings.tempDir) + "
723 "strlen(randomizedItemName) + 2) failed");
724 strcpy(pathAndNameOnFs, GBLappSettings.tempDir);
725
726 strcat(pathAndNameOnFs, "/"); /* doesn't hurt even if not needed */
727
728 strcat(pathAndNameOnFs, randomizedItemName);
729
730 /* disable warnings, so user isn't confused with 'continue' buttons */
731 bool(*savedWarningCbk)(const char*) = GBLvolInfo.warningCbk;
732 GBLvolInfo.warningCbk = NULL;
733
734 /* extract the file to the temporary directory */
735 rc = bk_extract_as(&GBLvolInfo, pathAndNameOnIso,
736 GBLappSettings.tempDir,
737 randomizedItemName, false, activityProgressUpdaterCbk);
738 if(rc <= 0)
739 {
740 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
741 GTK_DIALOG_DESTROY_WITH_PARENT,
742 GTK_MESSAGE_ERROR,
743 GTK_BUTTONS_CLOSE,
744 _("Failed to extract '%s': '%s'"),
745 pathAndNameOnIso,
746 bk_get_error_string(rc));
747 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
748 gtk_dialog_run(GTK_DIALOG(warningDialog));
749 gtk_widget_destroy(warningDialog);
750
751 g_free(itemName);
752 free(randomizedItemName);
753 free(pathAndNameOnFs);
754 free(pathAndNameOnIso);
755 GBLvolInfo.warningCbk = savedWarningCbk;
756 return;
757 }
758
759 addToTempFilesList(pathAndNameOnFs);
760
761 /* start the viewer */
762 if(!fork())
763 {
764 execlp(GBLappSettings.viewer, "viewer", pathAndNameOnFs, NULL);
765
766 kill(getppid(), SIGUSR2);
767
768 exit(1);
769 }
770
771 g_free(itemName);
772 free(randomizedItemName);
773 free(pathAndNameOnFs);
774 free(pathAndNameOnIso);
775 GBLvolInfo.warningCbk = savedWarningCbk;
776 }
777
sigusr1(int signum)778 void sigusr1(int signum)
779 {
780 GBLeditFailed = true;
781 }
782
sigusr2(int signum)783 void sigusr2(int signum)
784 {
785 GBLviewFailed = true;
786 }
787