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, 14 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.