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