source: MondoRescue/branches/2.2.9/mondo/src/common/libmondo-fork.c @ 2225

Last change on this file since 2225 was 2225, checked in by Bruno Cornec, 12 years ago

No need to use sudo for NFS user, just use su and avoid any passwd issue.

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