source: MondoRescue/branches/2.06/mondo/mondo/common/libmondo-fork.c@ 296

Last change on this file since 296 was 296, checked in by andree, 18 years ago

Replaced partimagehack with ntfsclone from ntfsprogs package. Replaced
all occurrences of strings 'partimagehack' and 'partimage' with 'ntfsprog'.

  • Property svn:keywords set to Id
File size: 22.3 KB
Line 
1/* libmondo-fork.c
2 $Id: libmondo-fork.c 296 2006-01-11 09:10:31Z andree $
3
4- subroutines for handling forking/pthreads/etc.
5
6
701/20/2006
8- replaced partimagehack with ntfsclone
9
1006/20/2004
11- create fifo /var/log/partimagehack-debug.log and empty it
12 to keep ramdisk from filling up
13
1404/13/2004
15- >= should be <= g_loglevel
16
1711/15/2003
18- changed a few []s to char*s
19
2010/12
21- rewrote partimagehack handling (multiple fifos, chunks, etc.)
22
2310/11
24- partimagehack now has debug level of N (set in my-stuff.h)
25
2610/08
27- call to partimagehack when restoring will now log errors to /var/log/....log
28
2910/06
30- cleaned up logging a bit
31
3209/30
33- line 735 - missing char* cmd in sprintf()
34
3509/28
36- added run_external_binary_with_percentage_indicator()
37- rewritten eval_call_to_make_ISO()
38
3909/18
40- call mkstemp instead of mktemp
41
4209/13
43- major NTFS hackage
44
4509/12
46- paranoid_system("rm -f /tmp/ *PARTIMAGE*") before calling partimagehack
47
4809/11
49- forward-ported unbroken feed_*_partimage() subroutines
50 from early August 2003
51
5209/08
53- detect & use partimagehack if it exists
54
5509/05
56- finally finished partimagehack hack :)
57
5807/04
59- added subroutines to wrap around partimagehack
60
6104/27
62- don't echo (...res=%d...) at end of log_it()
63 unnecessarily
64- replace newtFinished() and newtInit() with
65 newtSuspend() and newtResume()
66
6704/24
68- added some assert()'s and log_OS_error()'s
69
7004/09
71- cleaned up run_program_and_log_output()
72
7304/07
74- cleaned up code a bit
75- let run_program_and_log_output() accept -1 (only log if _no error_)
76
7701/02/2003
78- in eval_call_to_make_ISO(), append output to MONDO_LOGFILE
79 instead of a temporary stderr text file
80
8112/10
82- patch by Heiko Schlittermann to handle % chars in issue.net
83
8411/18
85- if mkisofs in eval_call_to_make_ISO() returns an error then return it,
86 whether ISO was created or not
87
8810/30
89- if mkisofs in eval_call_to_make_ISO() returns an error then find out if
90 the output (ISO) file has been created; if it has then return 0 anyway
91
9208/01 - 09/30
93- run_program_and_log_output() now takes boolean operator to specify
94 whether it will log its activities in the event of _success_
95- system() now includes 2>/dev/null
96- enlarged some tmp[]'s
97- added run_program_and_log_to_screen() and run_program_and_log_output()
98
9907/24
100- created
101*/
102
103
104#include "my-stuff.h"
105#include "mondostructures.h"
106#include "libmondo-fork.h"
107#include "libmondo-string-EXT.h"
108#include "libmondo-gui-EXT.h"
109#include "libmondo-files-EXT.h"
110#include "libmondo-tools-EXT.h"
111#include "lib-common-externs.h"
112
113/*@unused@*/
114//static char cvsid[] = "$Id: libmondo-fork.c 296 2006-01-11 09:10:31Z andree $";
115
116extern char *g_tmpfs_mountpt;
117extern t_bkptype g_backup_media_type;
118extern bool g_text_mode;
119pid_t g_buffer_pid = 0;
120
121
122/**
123 * Call a program and retrieve its last line of output.
124 * @param call The program to run.
125 * @return The last line of its output.
126 * @note The returned value points to static storage that will be overwritten with each call.
127 */
128char *call_program_and_get_last_line_of_output(char *call)
129{
130 /*@ buffers ***************************************************** */
131 static char result[512];
132 char *tmp;
133
134 /*@ pointers **************************************************** */
135 FILE *fin;
136
137 /*@ initialize data ********************************************* */
138 malloc_string(tmp);
139 result[0] = '\0';
140 tmp[0] = '\0';
141
142 /*@******************************************************************** */
143
144 assert_string_is_neither_NULL_nor_zerolength(call);
145 if ((fin = popen(call, "r"))) {
146 for (fgets(tmp, MAX_STR_LEN, fin); !feof(fin);
147 fgets(tmp, MAX_STR_LEN, fin)) {
148 if (strlen(tmp) > 1) {
149 strcpy(result, tmp);
150 }
151 }
152 paranoid_pclose(fin);
153 } else {
154 log_OS_error("Unable to popen call");
155 }
156 strip_spaces(result);
157 return (result);
158}
159
160
161
162
163
164
165#define MONDO_POPMSG "Your PC will not retract the CD tray automatically. Please call mondoarchive with the -m (manual CD tray) flag."
166
167/**
168 * Call mkisofs to create an ISO image.
169 * @param bkpinfo The backup information structure. Fields used:
170 * - @c bkpinfo->manual_cd_tray
171 * - @c bkpinfo->backup_media_type
172 * - @c bkpinfo->please_dont_eject_when_restoring
173 * @param basic_call The call to mkisofs. May contain tokens that will be resolved to actual data. The tokens are:
174 * - @c _ISO_ will become the ISO file (@p isofile)
175 * - @c _CD#_ becomes the CD number (@p cd_no)
176 * - @c _ERR_ becomes the logfile (@p g_logfile)
177 * @param isofile Replaces @c _ISO_ in @p basic_call. Should probably be the ISO image to create (-o parameter to mkisofs).
178 * @param cd_no Replaces @c _CD#_ in @p basic_call. Should probably be the CD number.
179 * @param logstub Unused.
180 * @param what_i_am_doing The action taking place (e.g. "Making ISO #1"). Used as the title of the progress dialog.
181 * @return Exit code of @c mkisofs (0 is success, anything else indicates failure).
182 * @bug @p logstub is unused.
183 */
184int
185eval_call_to_make_ISO(struct s_bkpinfo *bkpinfo,
186 char *basic_call, char *isofile,
187 int cd_no, char *logstub, char *what_i_am_doing)
188{
189
190 /*@ int's *** */
191 int retval = 0;
192
193
194 /*@ buffers *** */
195 char *midway_call, *ultimate_call, *tmp, *command, *incoming,
196 *old_stderr, *cd_number_str;
197 char *p;
198
199/*@*********** End Variables ***************************************/
200
201 log_msg(3, "Starting");
202 assert(bkpinfo != NULL);
203 assert_string_is_neither_NULL_nor_zerolength(basic_call);
204 assert_string_is_neither_NULL_nor_zerolength(isofile);
205 assert_string_is_neither_NULL_nor_zerolength(logstub);
206 if (!(midway_call = malloc(1200))) {
207 fatal_error("Cannot malloc midway_call");
208 }
209 if (!(ultimate_call = malloc(1200))) {
210 fatal_error("Cannot malloc ultimate_call");
211 }
212 if (!(tmp = malloc(1200))) {
213 fatal_error("Cannot malloc tmp");
214 }
215 if (!(command = malloc(1200))) {
216 fatal_error("Cannot malloc command");
217 }
218 malloc_string(incoming);
219 malloc_string(old_stderr);
220 malloc_string(cd_number_str);
221
222 incoming[0] = '\0';
223 old_stderr[0] = '\0';
224
225 sprintf(cd_number_str, "%d", cd_no);
226 resolve_naff_tokens(midway_call, basic_call, isofile, "_ISO_");
227 resolve_naff_tokens(tmp, midway_call, cd_number_str, "_CD#_");
228 resolve_naff_tokens(ultimate_call, tmp, MONDO_LOGFILE, "_ERR_");
229 log_msg(4, "basic call = '%s'", basic_call);
230 log_msg(4, "midway_call = '%s'", midway_call);
231 log_msg(4, "tmp = '%s'", tmp);
232 log_msg(4, "ultimate call = '%s'", ultimate_call);
233 sprintf(command, "%s >> %s", ultimate_call, MONDO_LOGFILE);
234
235 log_to_screen
236 ("Please be patient. Do not be alarmed by on-screen inactivity.");
237 log_msg(4, "Calling open_evalcall_form() with what_i_am_doing='%s'",
238 what_i_am_doing);
239 strcpy(tmp, command);
240 if (bkpinfo->manual_cd_tray) {
241 p = strstr(tmp, "2>>");
242 if (p) {
243 sprintf(p, " ");
244 while (*p == ' ') {
245 p++;
246 }
247 for (; *p != ' '; p++) {
248 *p = ' ';
249 }
250 }
251 strcpy(command, tmp);
252#ifndef _XWIN
253 if (!g_text_mode) {
254 newtSuspend();
255 }
256#endif
257 log_msg(1, "command = '%s'", command);
258 retval += system(command);
259 if (!g_text_mode) {
260 newtResume();
261 }
262 if (retval) {
263 log_msg(2, "Basic call '%s' returned an error.", basic_call);
264 popup_and_OK("Press ENTER to continue.");
265 popup_and_OK
266 ("mkisofs and/or cdrecord returned an error. CD was not created");
267 }
268 }
269 /* if text mode then do the above & RETURN; if not text mode, do this... */
270 else {
271 log_msg(3, "command = '%s'", command);
272// yes_this_is_a_goto:
273 retval =
274 run_external_binary_with_percentage_indicator_NEW
275 (what_i_am_doing, command);
276 }
277
278 paranoid_free(midway_call);
279 paranoid_free(ultimate_call);
280 paranoid_free(tmp);
281 paranoid_free(command);
282 paranoid_free(incoming);
283 paranoid_free(old_stderr);
284 paranoid_free(cd_number_str);
285/*
286 if (bkpinfo->backup_media_type == dvd && !bkpinfo->please_dont_eject_when_restoring)
287 {
288 log_msg(3, "Ejecting DVD device");
289 eject_device(bkpinfo->media_device);
290 }
291*/
292 return (retval);
293}
294
295
296
297
298/**
299 * Run a program and log its output (stdout and stderr) to the logfile.
300 * @param program The program to run. Passed to the shell, so you can use pipes etc.
301 * @param debug_level If @p g_loglevel is higher than this, do not log the output.
302 * @return The exit code of @p program (depends on the command, but 0 almost always indicates success).
303 */
304int run_program_and_log_output(char *program, int debug_level)
305{
306 /*@ buffer ****************************************************** */
307 char callstr[MAX_STR_LEN * 2];
308 char incoming[MAX_STR_LEN * 2];
309 char tmp[MAX_STR_LEN * 2];
310 char initial_label[MAX_STR_LEN * 2];
311
312 /*@ int ********************************************************* */
313 int res;
314 int i;
315 int len;
316 bool log_if_failure = FALSE;
317 bool log_if_success = FALSE;
318
319 /*@ pointers *************************************************** */
320 FILE *fin;
321 char *p;
322
323 /*@ end vars *************************************************** */
324
325 assert(program != NULL);
326 if (!program[0]) {
327 log_msg(2, "Warning - asked to run zerolength program");
328 return (1);
329 }
330// if (debug_level == TRUE) { debug_level=5; }
331
332 // assert_string_is_neither_NULL_nor_zerolength(program);
333
334 if (debug_level <= g_loglevel) {
335 log_if_success = TRUE;
336 log_if_failure = TRUE;
337 }
338 sprintf(callstr,
339 "%s > /tmp/mondo-run-prog-thing.tmp 2> /tmp/mondo-run-prog-thing.err",
340 program);
341 while ((p = strchr(callstr, '\r'))) {
342 *p = ' ';
343 }
344 while ((p = strchr(callstr, '\n'))) {
345 *p = ' ';
346 } /* single '=' is intentional */
347
348
349 len = (int) strlen(program);
350 for (i = 0; i < 35 - len / 2; i++) {
351 tmp[i] = '-';
352 }
353 tmp[i] = '\0';
354 strcat(tmp, " ");
355 strcat(tmp, program);
356 strcat(tmp, " ");
357 for (i = 0; i < 35 - len / 2; i++) {
358 strcat(tmp, "-");
359 }
360 strcpy(initial_label, tmp);
361 res = system(callstr);
362 if (((res == 0) && log_if_success) || ((res != 0) && log_if_failure)) {
363 log_msg(0, "running: %s", callstr);
364 log_msg(0,
365 "--------------------------------start of output-----------------------------");
366 }
367 if (log_if_failure
368 &&
369 system
370 ("cat /tmp/mondo-run-prog-thing.err >> /tmp/mondo-run-prog-thing.tmp 2> /dev/null"))
371 {
372 log_OS_error("Command failed");
373 }
374 unlink("/tmp/mondo-run-prog-thing.err");
375 fin = fopen("/tmp/mondo-run-prog-thing.tmp", "r");
376 if (fin) {
377 for (fgets(incoming, MAX_STR_LEN, fin); !feof(fin);
378 fgets(incoming, MAX_STR_LEN, fin)) {
379 /* patch by Heiko Schlittermann */
380 p = incoming;
381 while (p && *p) {
382 if ((p = strchr(p, '%'))) {
383 memmove(p, p + 1, strlen(p) + 1);
384 p += 2;
385 }
386 }
387 /* end of patch */
388 strip_spaces(incoming);
389 if ((res == 0 && log_if_success)
390 || (res != 0 && log_if_failure)) {
391 log_msg(0, incoming);
392 }
393 }
394 paranoid_fclose(fin);
395 }
396 unlink("/tmp/mondo-run-prog-thing.tmp");
397 if ((res == 0 && log_if_success) || (res != 0 && log_if_failure)) {
398 log_msg(0,
399 "--------------------------------end of output------------------------------");
400 if (res) {
401 log_msg(0, "...ran with res=%d", res);
402 } else {
403 log_msg(0, "...ran just fine. :-)");
404 }
405 }
406// else
407// { log_msg (0, "-------------------------------ran w/ res=%d------------------------------", res); }
408 return (res);
409}
410
411
412
413/**
414 * Run a program and log its output to the screen.
415 * @param basic_call The program to run.
416 * @param what_i_am_doing The title of the evalcall form.
417 * @return The return value of the command (varies, but 0 almost always means success).
418 * @see run_program_and_log_output
419 * @see log_to_screen
420 */
421int run_program_and_log_to_screen(char *basic_call, char *what_i_am_doing)
422{
423 /*@ int ******************************************************** */
424 int retval = 0;
425 int res = 0;
426 int i;
427
428 /*@ pointers **************************************************** */
429 FILE *fin;
430
431 /*@ buffers **************************************************** */
432 char tmp[MAX_STR_LEN * 2];
433 char command[MAX_STR_LEN * 2];
434 char lockfile[MAX_STR_LEN];
435
436 /*@ end vars *************************************************** */
437
438 assert_string_is_neither_NULL_nor_zerolength(basic_call);
439
440 sprintf(lockfile, "/tmp/mojo-jojo.blah.XXXXXX");
441 mkstemp(lockfile);
442 sprintf(command,
443 "echo hi > %s ; %s >> %s 2>> %s; res=$?; sleep 1; rm -f %s; exit $res",
444 lockfile, basic_call, MONDO_LOGFILE, MONDO_LOGFILE, lockfile);
445 open_evalcall_form(what_i_am_doing);
446 sprintf(tmp, "Executing %s", basic_call);
447 log_msg(2, tmp);
448 if (!(fin = popen(command, "r"))) {
449 log_OS_error("Unable to popen-in command");
450 sprintf(tmp, "Failed utterly to call '%s'", command);
451 log_to_screen(tmp);
452 return (1);
453 }
454 if (!does_file_exist(lockfile)) {
455 log_to_screen("Waiting for external binary to start");
456 for (i = 0; i < 60 && !does_file_exist(lockfile); sleep(1), i++) {
457 log_msg(3, "Waiting for lockfile %s to exist", lockfile);
458 }
459 }
460#ifdef _XWIN
461 /* This only can update when newline goes into the file,
462 but it's *much* prettier/faster on Qt. */
463 while (does_file_exist(lockfile)) {
464 while (!feof(fin)) {
465 if (!fgets(tmp, 512, fin))
466 break;
467 log_to_screen(tmp);
468 }
469 usleep(500000);
470 }
471#else
472 /* This works on Newt, and it gives quicker updates. */
473 for (; does_file_exist(lockfile); sleep(1)) {
474 log_file_end_to_screen(MONDO_LOGFILE, "");
475 update_evalcall_form(1);
476 }
477#endif
478 /* Evaluate the status returned by pclose to get the exit code of the called program. */
479 errno = 0;
480 res = pclose(fin);
481 /* Log actual pclose errors. */
482 if (errno) log_msg(5, "pclose err: %d", errno);
483 /* Check if we have a valid status. If we do, extract the called program's exit code. */
484 /* If we don't, highlight this fact by returning -1. */
485 if (WIFEXITED(res)) {
486 retval = WEXITSTATUS(res);
487 } else {
488 retval = -1;
489 }
490 close_evalcall_form();
491 unlink(lockfile);
492 return (retval);
493}
494
495
496
497
498/**
499 * Apparently unused. @bug This has a purpose, but what?
500 */
501#define PIMP_START_SZ "STARTSTARTSTART9ff3kff9a82gv34r7fghbkaBBC2T231hc81h42vws8"
502#define PIMP_END_SZ "ENDENDEND0xBBC10xBBC2T231hc81h42vws89ff3kff9a82gv34r7fghbka"
503
504
505
506
507int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived, char direction)
508{
509// if dir=='w' then copy from orig to archived
510// if dir=='r' then copy from archived to orig
511 char *tmp;
512 char *buf;
513 long int bytes_to_be_read, bytes_read_in, bytes_written_out =
514 0, bufcap, subsliceno = 0;
515 int retval = 0;
516 FILE *fin;
517 FILE *fout;
518 FILE *ftmp;
519
520 log_msg(5, "Opening.");
521 malloc_string(tmp);
522 tmp[0] = '\0';
523 bufcap = 256L * 1024L;
524 if (!(buf = malloc(bufcap))) {
525 fatal_error("Failed to malloc() buf");
526 }
527
528 if (direction == 'w') {
529 fin = f_orig;
530 fout = f_archived;
531 sprintf(tmp, "%-64s", PIMP_START_SZ);
532 if (fwrite(tmp, 1, 64, fout) != 64) {
533 fatal_error("Can't write the introductory block");
534 }
535 while (1) {
536 bytes_to_be_read = bytes_read_in = fread(buf, 1, bufcap, fin);
537 if (bytes_read_in == 0) {
538 break;
539 }
540 sprintf(tmp, "%-64ld", bytes_read_in);
541 if (fwrite(tmp, 1, 64, fout) != 64) {
542 fatal_error("Cannot write introductory block");
543 }
544 log_msg(7,
545 "subslice #%ld --- I have read %ld of %ld bytes in from f_orig",
546 subsliceno, bytes_read_in, bytes_to_be_read);
547 bytes_written_out += fwrite(buf, 1, bytes_read_in, fout);
548 sprintf(tmp, "%-64ld", subsliceno);
549 if (fwrite(tmp, 1, 64, fout) != 64) {
550 fatal_error("Cannot write post-thingy block");
551 }
552 log_msg(7, "Subslice #%d written OK", subsliceno);
553 subsliceno++;
554 }
555 sprintf(tmp, "%-64ld", 0L);
556 if (fwrite(tmp, 1, 64L, fout) != 64L) {
557 fatal_error("Cannot write final introductory block");
558 }
559 } else {
560 fin = f_archived;
561 fout = f_orig;
562 if (fread(tmp, 1, 64L, fin) != 64L) {
563 fatal_error("Cannot read the introductory block");
564 }
565 log_msg(5, "tmp is %s", tmp);
566 if (!strstr(tmp, PIMP_START_SZ)) {
567 fatal_error("Can't find intro blk");
568 }
569 if (fread(tmp, 1, 64L, fin) != 64L) {
570 fatal_error("Cannot read introductory blk");
571 }
572 bytes_to_be_read = atol(tmp);
573 while (bytes_to_be_read > 0) {
574 log_msg(7, "subslice#%ld, bytes=%ld", subsliceno,
575 bytes_to_be_read);
576 bytes_read_in = fread(buf, 1, bytes_to_be_read, fin);
577 if (bytes_read_in != bytes_to_be_read) {
578 fatal_error
579 ("Danger, WIll Robinson. Failed to read whole subvol from archives.");
580 }
581 bytes_written_out += fwrite(buf, 1, bytes_read_in, fout);
582 if (fread(tmp, 1, 64, fin) != 64) {
583 fatal_error("Cannot read post-thingy block");
584 }
585 if (atol(tmp) != subsliceno) {
586 log_msg(1, "Wanted subslice %ld but got %ld ('%s')",
587 subsliceno, atol(tmp), tmp);
588 }
589 log_msg(7, "Subslice #%ld read OK", subsliceno);
590 subsliceno++;
591 if (fread(tmp, 1, 64, fin) != 64) {
592 fatal_error("Cannot read introductory block");
593 }
594 bytes_to_be_read = atol(tmp);
595 }
596 }
597
598// log_msg(4, "Written %ld of %ld bytes", bytes_written_out, bytes_read_in);
599
600 if (direction == 'w') {
601 sprintf(tmp, "%-64s", PIMP_END_SZ);
602 if (fwrite(tmp, 1, 64, fout) != 64) {
603 fatal_error("Can't write the final block");
604 }
605 } else {
606 log_msg(1, "tmpA is %s", tmp);
607 if (!strstr(tmp, PIMP_END_SZ)) {
608 if (fread(tmp, 1, 64, fin) != 64) {
609 fatal_error("Can't read the final block");
610 }
611 log_msg(5, "tmpB is %s", tmp);
612 if (!strstr(tmp, PIMP_END_SZ)) {
613 ftmp = fopen("/tmp/out.leftover", "w");
614 bytes_read_in = fread(tmp, 1, 64, fin);
615 log_msg(1, "bytes_read_in = %ld", bytes_read_in);
616// if (bytes_read_in!=128+64) { fatal_error("Can't read the terminating block"); }
617 fwrite(tmp, 1, bytes_read_in, ftmp);
618 sprintf(tmp, "I am here - %ld", ftell(fin));
619// log_msg(0, tmp);
620 fread(tmp, 1, 512, fin);
621 log_msg(0, "tmp = '%s'", tmp);
622 fwrite(tmp, 1, 512, ftmp);
623 fclose(ftmp);
624 fatal_error("Missing terminating block");
625 }
626 }
627 }
628
629 paranoid_free(buf);
630 paranoid_free(tmp);
631 log_msg(3, "Successfully copied %ld bytes", bytes_written_out);
632 return (retval);
633}
634
635
636
637
638/**
639 * Feed @p input_device through ntfsclone to @p output_fname.
640 * @param input_device The device to image.
641 * @param output_fname The file to write.
642 * @return 0 for success, nonzero for failure.
643 */
644int feed_into_ntfsprog(char *input_device, char *output_fname)
645{
646// BACKUP
647 int res = -1;
648 char*command;
649
650 if (!does_file_exist(input_device)) {
651 fatal_error("input device does not exist");
652 }
653 if ( !find_home_of_exe("ntfsclone")) {
654 fatal_error("ntfsclone not found");
655 }
656 malloc_string(command);
657 sprintf(command, "ntfsclone --force --save-image --overwrite %s %s", output_fname, input_device);
658 res = run_program_and_log_output(command, 5);
659 paranoid_free(command);
660 return (res);
661}
662
663
664
665
666
667int run_external_binary_with_percentage_indicator_OLD(char *tt, char *cmd)
668{
669
670 /*@ int *************************************************************** */
671 int res = 0;
672 int percentage = 0;
673 int maxpc = 0;
674 int pcno = 0;
675 int last_pcno = 0;
676
677 /*@ buffers *********************************************************** */
678 char *command;
679 char *tempfile;
680 char *title;
681 /*@ pointers ********************************************************** */
682 FILE *pin;
683
684 malloc_string(title);
685 malloc_string(command);
686 malloc_string(tempfile);
687 assert_string_is_neither_NULL_nor_zerolength(cmd);
688 assert_string_is_neither_NULL_nor_zerolength(title);
689
690 strcpy(title, tt);
691 strcpy(tempfile,
692 call_program_and_get_last_line_of_output
693 ("mktemp -q /tmp/mondo.XXXXXXXX"));
694 sprintf(command, "%s >> %s 2>> %s; rm -f %s", cmd, tempfile, tempfile,
695 tempfile);
696 log_msg(3, command);
697 open_evalcall_form(title);
698 if (!(pin = popen(command, "r"))) {
699 log_OS_error("fmt err");
700 return (1);
701 }
702 maxpc = 100;
703// OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD
704 for (sleep(1); does_file_exist(tempfile); sleep(1)) {
705 pcno = grab_percentage_from_last_line_of_file(MONDO_LOGFILE);
706 if (pcno < 0 || pcno > 100) {
707 log_msg(5, "Weird pc#");
708 continue;
709 }
710 percentage = pcno * 100 / maxpc;
711 if (pcno <= 5 && last_pcno > 40) {
712 close_evalcall_form();
713 strcpy(title, "Verifying...");
714 open_evalcall_form(title);
715 }
716 last_pcno = pcno;
717 update_evalcall_form(percentage);
718 }
719// OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD
720 close_evalcall_form();
721 if (pclose(pin)) {
722 res++;
723 log_OS_error("Unable to pclose");
724 }
725 unlink(tempfile);
726 paranoid_free(command);
727 paranoid_free(tempfile);
728 paranoid_free(title);
729 return (res);
730}
731
732
733
734
735void *run_prog_in_bkgd_then_exit(void *info)
736{
737 char *sz_command;
738 static int res = 4444;
739
740 res = 999;
741 sz_command = (char *) info;
742 log_msg(4, "sz_command = '%s'", sz_command);
743 res = system(sz_command);
744 if (res > 256 && res != 4444) {
745 res = res / 256;
746 }
747 log_msg(4, "child res = %d", res);
748 sz_command[0] = '\0';
749 pthread_exit((void *) (&res));
750}
751
752
753
754
755int run_external_binary_with_percentage_indicator_NEW(char *tt, char *cmd)
756{
757
758 /*@ int *************************************************************** */
759 int res = 0;
760 int percentage = 0;
761 int maxpc = 100;
762 int pcno = 0;
763 int last_pcno = 0;
764 int counter = 0;
765
766 /*@ buffers *********************************************************** */
767 char *command;
768 char *title;
769 /*@ pointers ********************************************************** */
770 static int chldres = 0;
771 int *pchild_result;
772 pthread_t childthread;
773
774 pchild_result = &chldres;
775 assert_string_is_neither_NULL_nor_zerolength(cmd);
776 assert_string_is_neither_NULL_nor_zerolength(tt);
777 *pchild_result = 999;
778
779 malloc_string(title);
780 malloc_string(command);
781 strcpy(title, tt);
782 sprintf(command, "%s 2>> %s", cmd, MONDO_LOGFILE);
783 log_msg(3, "command = '%s'", command);
784 if ((res =
785 pthread_create(&childthread, NULL, run_prog_in_bkgd_then_exit,
786 (void *) command))) {
787 fatal_error("Unable to create an archival thread");
788 }
789
790 log_msg(8, "Parent running");
791 open_evalcall_form(title);
792 for (sleep(1); command[0] != '\0'; sleep(1)) {
793 pcno = grab_percentage_from_last_line_of_file(MONDO_LOGFILE);
794 if (pcno <= 0 || pcno > 100) {
795 log_msg(8, "Weird pc#");
796 continue;
797 }
798 percentage = pcno * 100 / maxpc;
799 if (pcno <= 5 && last_pcno >= 40) {
800 close_evalcall_form();
801 strcpy(title, "Verifying...");
802 open_evalcall_form(title);
803 }
804 if (counter++ >= 5) {
805 counter = 0;
806 log_file_end_to_screen(MONDO_LOGFILE, "");
807 }
808 last_pcno = pcno;
809 update_evalcall_form(percentage);
810 }
811 log_file_end_to_screen(MONDO_LOGFILE, "");
812 close_evalcall_form();
813 pthread_join(childthread, (void *) (&pchild_result));
814 if (pchild_result) {
815 res = *pchild_result;
816 } else {
817 res = 666;
818 }
819 log_msg(3, "Parent res = %d", res);
820 paranoid_free(command);
821 paranoid_free(title);
822 return (res);
823}
824
825
826
827
828/**
829 * Feed @p input_fifo through ntfsclone (restore) to @p output_device.
830 * @param input_fifo The ntfsclone file to read.
831 * @param output_device Where to put the output.
832 * @return The return value of ntfsclone (0 for success).
833 */
834int feed_outfrom_ntfsprog(char *output_device, char *input_fifo)
835{
836// RESTORE
837 int res = -1;
838 char *command;
839
840 if ( !find_home_of_exe("ntfsclone")) {
841 fatal_error("ntfsclone not found");
842 }
843 malloc_string(command);
844 sprintf(command, "ntfsclone --force --restore-image --overwrite %s %s", output_device, input_fifo);
845 res = run_program_and_log_output(command, 5);
846 paranoid_free(command);
847 return (res);
848}
Note: See TracBrowser for help on using the repository browser.