source: MondoRescue/branches/3.0/mondo/src/common/libmondo-fork.c@ 3192

Last change on this file since 3192 was 3192, checked in by Bruno Cornec, 11 years ago
  • revert r3188 & r3189 as I started to work on branch 3.0 before deciding it was much better to do it in 3.2. This will allow some small maintenance work on 3.0 if needed, while pushing all the rest to 3.2 and providing early access to it.
  • Property svn:keywords set to Id
File size: 19.9 KB
Line 
1/* libmondo-fork.c
2 $Id: libmondo-fork.c 3192 2013-09-25 07:03:25Z 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 3192 2013-09-25 07:03:25Z 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[MAX_STR_LEN];
40 char *tmp;
41 char *p;
42
43 /*@ pointers **************************************************** */
44 FILE *fin;
45
46 /*@ initialize data ********************************************* */
47 malloc_string(tmp);
48 result[0] = '\0';
49 tmp[0] = '\0';
50
51 /*@******************************************************************** */
52
53 assert_string_is_neither_NULL_nor_zerolength(call);
54 if ((fin = popen(call, "r"))) {
55 for (p = fgets(tmp, MAX_STR_LEN, fin); !feof(fin) && (p != NULL);
56 p = fgets(tmp, MAX_STR_LEN, fin)) {
57 if (strlen(tmp) > 1) {
58 strcpy(result, tmp);
59 }
60 }
61 paranoid_pclose(fin);
62 } else {
63 log_OS_error("Unable to popen call");
64 }
65 strip_spaces(result);
66 paranoid_free(tmp);
67 return (result);
68}
69
70
71
72
73
74
75#define MONDO_POPMSG "Your PC will not retract the CD tray automatically. Please call mondoarchive with the -m (manual CD tray) flag."
76
77/**
78 * Call mkisofs to create an ISO image.
79 * @param bkpinfo The backup information structure. Fields used:
80 * - @c bkpinfo->manual_cd_tray
81 * - @c bkpinfo->backup_media_type
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->netfs_user) && (strstr(bkpinfo->netfs_proto,"nfs"))) {
136 mr_asprintf(tmp1, "su - %s -c \"%s\"", bkpinfo->netfs_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 = NULL;
259 char incoming[MAX_STR_LEN * 2];
260 char *tmp1 = NULL;
261
262 /*@ int ********************************************************* */
263 int res;
264 bool log_if_failure = FALSE;
265 bool log_if_success = FALSE;
266
267 /*@ pointers *************************************************** */
268 FILE *fin;
269 char *p;
270 char *q;
271
272 /*@ end vars *************************************************** */
273
274 assert(program != NULL);
275 if (!program[0]) {
276 log_msg(2, "Warning - asked to run zerolength program");
277 return (1);
278 }
279// if (debug_level == TRUE) { debug_level=5; }
280
281 // assert_string_is_neither_NULL_nor_zerolength(program);
282
283 if (debug_level <= g_loglevel) {
284 log_if_success = TRUE;
285 log_if_failure = TRUE;
286 }
287 mr_asprintf(callstr, "%s > %s/mondo-run-prog-thing.tmp 2> %s/mondo-run-prog-thing.err", program, bkpinfo->tmpdir, bkpinfo->tmpdir);
288 while ((p = strchr(callstr, '\r'))) {
289 *p = ' ';
290 }
291 while ((p = strchr(callstr, '\n'))) {
292 *p = ' ';
293 } /* single '=' is intentional */
294
295
296 res = system(callstr);
297 if (((res == 0) && log_if_success) || ((res != 0) && log_if_failure)) {
298 log_msg(0, "running: %s", callstr);
299 log_msg(0, "--------------------------------start of output-----------------------------");
300 }
301 mr_free(callstr);
302
303 mr_asprintf(callstr, "cat %s/mondo-run-prog-thing.err >> %s/mondo-run-prog-thing.tmp 2> /dev/null", bkpinfo->tmpdir, bkpinfo->tmpdir);
304 if (log_if_failure && system(callstr)) {
305 log_OS_error("Command failed");
306 }
307 mr_free(callstr);
308
309 mr_asprintf(tmp1, "%s/mondo-run-prog-thing.err", bkpinfo->tmpdir);
310 unlink(tmp1);
311 mr_free(tmp1);
312
313 mr_asprintf(tmp1, "%s/mondo-run-prog-thing.tmp", bkpinfo->tmpdir);
314 fin = fopen(tmp1, "r");
315 if (fin) {
316 for (q = fgets(incoming, MAX_STR_LEN, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN, fin)) {
317 p = incoming;
318 while (p && *p) {
319 if ((p = strchr(p, '%'))) {
320 memmove(p, p + 1, strlen(p) + 1);
321 p += 2;
322 }
323 }
324 /* end of patch */
325 strip_spaces(incoming);
326 if ((res == 0 && log_if_success) || (res != 0 && log_if_failure)) {
327 log_msg(0, incoming);
328 }
329 }
330 paranoid_fclose(fin);
331 }
332 unlink(tmp1);
333 mr_free(tmp1);
334
335 if ((res == 0 && log_if_success) || (res != 0 && log_if_failure)) {
336 log_msg(0,
337 "--------------------------------end of output------------------------------");
338 if (res) {
339 log_msg(0, "...ran with res=%d", res);
340 } else {
341 log_msg(0, "...ran just fine. :-)");
342 }
343 }
344// else
345// { log_msg (0, "-------------------------------ran w/ res=%d------------------------------", res); }
346 return (res);
347}
348
349
350
351/**
352 * Run a program and log its output to the screen.
353 * @param basic_call The program to run.
354 * @param what_i_am_doing The title of the evalcall form.
355 * @return The return value of the command (varies, but 0 almost always means success).
356 * @see run_program_and_log_output
357 * @see log_to_screen
358 */
359int run_program_and_log_to_screen(char *basic_call, char *what_i_am_doing)
360{
361 /*@ int ******************************************************** */
362 int retval = 0;
363 int res = 0;
364 int i;
365
366 /*@ pointers **************************************************** */
367 FILE *fin;
368
369 /*@ buffers **************************************************** */
370 char *tmp = NULL;
371 char *command = NULL;
372 char lockfile[MAX_STR_LEN];
373
374 /*@ end vars *************************************************** */
375
376 assert_string_is_neither_NULL_nor_zerolength(basic_call);
377
378 sprintf(lockfile, "%s/mojo-jojo.bla.bla", bkpinfo->tmpdir);
379
380 mr_asprintf(command,
381 "echo hi > %s ; %s >> %s 2>> %s; res=$?; sleep 1; rm -f %s; exit $res",
382 lockfile, basic_call, MONDO_LOGFILE, MONDO_LOGFILE, lockfile);
383 open_evalcall_form(what_i_am_doing);
384 mr_asprintf(tmp, "Executing %s", basic_call);
385 log_msg(2, tmp);
386 mr_free(tmp);
387
388 if (!(fin = popen(command, "r"))) {
389 log_OS_error("Unable to popen-in command");
390 mr_asprintf(tmp, "Failed utterly to call '%s'", command);
391 log_to_screen(tmp);
392 mr_free(tmp);
393 mr_free(command);
394 return (1);
395 }
396 if (!does_file_exist(lockfile)) {
397 log_to_screen("Waiting for '%s' to start",command);
398 for (i = 0; i < 60 && !does_file_exist(lockfile); sleep(1), i++) {
399 log_msg(3, "Waiting for lockfile %s to exist", lockfile);
400 }
401 }
402 mr_free(command);
403#ifdef _XWIN
404 /* This only can update when newline goes into the file,
405 but it's *much* prettier/faster on Qt. */
406 while (does_file_exist(lockfile)) {
407 while (!feof(fin)) {
408 /* TODO: Dead and wrong code */
409 if (!fgets(tmp, 512, fin))
410 break;
411 log_to_screen(tmp);
412 }
413 usleep(500000);
414 }
415#else
416 /* This works on Newt, and it gives quicker updates. */
417 for (; does_file_exist(lockfile); sleep(1)) {
418 log_file_end_to_screen(MONDO_LOGFILE, "");
419 update_evalcall_form(1);
420 }
421#endif
422 /* Evaluate the status returned by pclose to get the exit code of the called program. */
423 errno = 0;
424 res = pclose(fin);
425 /* Log actual pclose errors. */
426 if (errno) log_msg(5, "pclose err: %d", errno);
427 /* Check if we have a valid status. If we do, extract the called program's exit code. */
428 /* If we don't, highlight this fact by returning -1. */
429 if (WIFEXITED(res)) {
430 retval = WEXITSTATUS(res);
431 } else {
432 retval = -1;
433 }
434 close_evalcall_form();
435 unlink(lockfile);
436 return (retval);
437}
438
439
440
441
442/**
443 * Apparently unused. @bug This has a purpose, but what?
444 */
445#define PIMP_START_SZ "STARTSTARTSTART9ff3kff9a82gv34r7fghbkaBBC2T231hc81h42vws8"
446#define PIMP_END_SZ "ENDENDEND0xBBC10xBBC2T231hc81h42vws89ff3kff9a82gv34r7fghbka"
447
448
449
450
451int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived, char direction)
452{
453// if dir=='w' then copy from orig to archived
454// if dir=='r' then copy from archived to orig
455 char *tmp;
456 char *buf;
457 char filestr[MAX_STR_LEN];
458 long int bytes_to_be_read, bytes_read_in, bytes_written_out =
459 0, bufcap, subsliceno = 0;
460 int retval = 0;
461 FILE *fin;
462 FILE *fout;
463 FILE *ftmp;
464 int tmpcap = 512;
465
466 log_msg(5, "Opening.");
467 if (!(tmp = malloc(tmpcap))) {
468 fatal_error("Failed to malloc() tmp");
469 }
470 tmp[0] = '\0';
471 bufcap = 256L * 1024L;
472 if (!(buf = malloc(bufcap))) {
473 fatal_error("Failed to malloc() buf");
474 }
475
476 if (direction == 'w') {
477 fin = f_orig;
478 fout = f_archived;
479 sprintf(tmp, "%-64s", PIMP_START_SZ);
480 if (fwrite(tmp, 1, 64, fout) != 64) {
481 fatal_error("Can't write the introductory block");
482 }
483 while (1) {
484 bytes_to_be_read = bytes_read_in = fread(buf, 1, bufcap, fin);
485 if (bytes_read_in == 0) {
486 break;
487 }
488 sprintf(tmp, "%-64ld", bytes_read_in);
489 if (fwrite(tmp, 1, 64, fout) != 64) {
490 fatal_error("Cannot write introductory block");
491 }
492 log_msg(7,
493 "subslice #%ld --- I have read %ld of %ld bytes in from f_orig",
494 subsliceno, bytes_read_in, bytes_to_be_read);
495 bytes_written_out += fwrite(buf, 1, bytes_read_in, fout);
496 sprintf(tmp, "%-64ld", subsliceno);
497 if (fwrite(tmp, 1, 64, fout) != 64) {
498 fatal_error("Cannot write post-thingy block");
499 }
500 log_msg(7, "Subslice #%d written OK", subsliceno);
501 subsliceno++;
502 }
503 sprintf(tmp, "%-64ld", 0L);
504 if (fwrite(tmp, 1, 64L, fout) != 64L) {
505 fatal_error("Cannot write final introductory block");
506 }
507 } else {
508 fin = f_archived;
509 fout = f_orig;
510 if (fread(tmp, 1, 64L, fin) != 64L) {
511 fatal_error("Cannot read the introductory block");
512 }
513 log_msg(5, "tmp is %s", tmp);
514 if (!strstr(tmp, PIMP_START_SZ)) {
515 fatal_error("Can't find intro blk");
516 }
517 if (fread(tmp, 1, 64L, fin) != 64L) {
518 fatal_error("Cannot read introductory blk");
519 }
520 bytes_to_be_read = atol(tmp);
521 while (bytes_to_be_read > 0) {
522 log_msg(7, "subslice#%ld, bytes=%ld", subsliceno,
523 bytes_to_be_read);
524 bytes_read_in = fread(buf, 1, bytes_to_be_read, fin);
525 if (bytes_read_in != bytes_to_be_read) {
526 fatal_error
527 ("Danger, WIll Robinson. Failed to read whole subvol from archives.");
528 }
529 bytes_written_out += fwrite(buf, 1, bytes_read_in, fout);
530 if (fread(tmp, 1, 64, fin) != 64) {
531 fatal_error("Cannot read post-thingy block");
532 }
533 if (atol(tmp) != subsliceno) {
534 log_msg(1, "Wanted subslice %ld but got %ld ('%s')",
535 subsliceno, atol(tmp), tmp);
536 }
537 log_msg(7, "Subslice #%ld read OK", subsliceno);
538 subsliceno++;
539 if (fread(tmp, 1, 64, fin) != 64) {
540 fatal_error("Cannot read introductory block");
541 }
542 bytes_to_be_read = atol(tmp);
543 }
544 }
545
546// log_msg(4, "Written %ld of %ld bytes", bytes_written_out, bytes_read_in);
547
548 if (direction == 'w') {
549 sprintf(tmp, "%-64s", PIMP_END_SZ);
550 if (fwrite(tmp, 1, 64, fout) != 64) {
551 fatal_error("Can't write the final block");
552 }
553 } else {
554 log_msg(1, "tmpA is %s", tmp);
555 if (!strstr(tmp, PIMP_END_SZ)) {
556 if (fread(tmp, 1, 64, fin) != 64) {
557 fatal_error("Can't read the final block");
558 }
559 log_msg(5, "tmpB is %s", tmp);
560 if (!strstr(tmp, PIMP_END_SZ)) {
561 sprintf(filestr, "%s/out.leftover", bkpinfo->tmpdir);
562 ftmp = fopen(filestr, "w");
563 bytes_read_in = fread(tmp, 1, 64, fin);
564 log_msg(1, "bytes_read_in = %ld", bytes_read_in);
565// if (bytes_read_in!=128+64) { fatal_error("Can't read the terminating block"); }
566 if (fwrite(tmp, 1, bytes_read_in, ftmp)) {
567 fatal_error("Can't fwrite here");
568 }
569 sprintf(tmp, "I am here - %lld", (long long)ftello(fin));
570// log_msg(0, tmp);
571 if (fread(tmp, 1, tmpcap, fin)) {
572 fatal_error("Can't fread here");
573 }
574 log_msg(0, "tmp = '%s'", tmp);
575 if (fwrite(tmp, 1, tmpcap, ftmp)) {
576 fatal_error("Can't fwrite there");
577 }
578 fclose(ftmp);
579 fatal_error("Missing terminating block");
580 }
581 }
582 }
583
584 paranoid_free(buf);
585 paranoid_free(tmp);
586 log_msg(3, "Successfully copied %ld bytes", bytes_written_out);
587 return (retval);
588}
589
590
591
592
593/**
594 * Feed @p input_device through ntfsclone to @p output_fname.
595 * @param input_device The device to image.
596 * @param output_fname The file to write.
597 * @return 0 for success, nonzero for failure.
598 */
599int feed_into_ntfsprog(char *input_device, char *output_fname)
600{
601// BACKUP
602 int res = -1;
603 char*command;
604
605 if (!does_file_exist(input_device)) {
606 fatal_error("input device does not exist");
607 }
608 if ( !find_home_of_exe("ntfsclone")) {
609 fatal_error("ntfsclone not found");
610 }
611 malloc_string(command);
612 sprintf(command, "ntfsclone --rescue --force --save-image --overwrite %s %s", output_fname, input_device);
613 res = run_program_and_log_output(command, 5);
614 paranoid_free(command);
615 unlink(output_fname);
616 return (res);
617}
618
619
620void *run_prog_in_bkgd_then_exit(void *info)
621{
622 char *sz_command;
623 static int res = 4444;
624
625 res = 999;
626 sz_command = (char *) info;
627 log_msg(4, "sz_command = '%s'", sz_command);
628 res = system(sz_command);
629 if (res > 256 && res != 4444) {
630 res = res / 256;
631 }
632 log_msg(4, "child res = %d", res);
633 sz_command[0] = '\0';
634 pthread_exit((void *) (&res));
635}
636
637
638
639
640int run_external_binary_with_percentage_indicator_NEW(char *tt, char *cmd)
641{
642
643 /*@ int *************************************************************** */
644 int res = 0;
645 int percentage = 0;
646 int maxpc = 100;
647 int pcno = 0;
648 int last_pcno = 0;
649 int counter = 0;
650
651 /*@ buffers *********************************************************** */
652 char *command;
653 char *title;
654 /*@ pointers ********************************************************** */
655 static int chldres = 0;
656 int *pchild_result;
657 pthread_t childthread;
658
659 pchild_result = &chldres;
660 assert_string_is_neither_NULL_nor_zerolength(cmd);
661 assert_string_is_neither_NULL_nor_zerolength(tt);
662 *pchild_result = 999;
663
664 malloc_string(title);
665 malloc_string(command);
666 strcpy(title, tt);
667 sprintf(command, "%s 2>> %s", cmd, MONDO_LOGFILE);
668 log_msg(3, "command = '%s'", command);
669 if ((res =
670 pthread_create(&childthread, NULL, run_prog_in_bkgd_then_exit,
671 (void *) command))) {
672 fatal_error("Unable to create an archival thread");
673 }
674
675 log_msg(8, "Parent running");
676 open_evalcall_form(title);
677 for (sleep(1); command[0] != '\0'; sleep(1)) {
678 pcno = grab_percentage_from_last_line_of_file(MONDO_LOGFILE);
679 if (pcno <= 0 || pcno > 100) {
680 log_msg(8, "Weird pc#");
681 continue;
682 }
683 percentage = pcno * 100 / maxpc;
684 if (pcno <= 5 && last_pcno >= 40) {
685 close_evalcall_form();
686 strcpy(title, "Verifying...");
687 open_evalcall_form(title);
688 }
689 if (counter++ >= 5) {
690 counter = 0;
691 log_file_end_to_screen(MONDO_LOGFILE, "");
692 }
693 last_pcno = pcno;
694 update_evalcall_form(percentage);
695 }
696 log_file_end_to_screen(MONDO_LOGFILE, "");
697 close_evalcall_form();
698 pthread_join(childthread, (void *) (&pchild_result));
699 if (pchild_result) {
700 res = *pchild_result;
701 } else {
702 res = 666;
703 }
704 log_msg(3, "Parent res = %d", res);
705 paranoid_free(command);
706 paranoid_free(title);
707 return (res);
708}
709
710
711
712
713/**
714 * Feed @p input_fifo through ntfsclone (restore) to @p output_device.
715 * @param input_fifo The ntfsclone file to read.
716 * @param output_device Where to put the output.
717 * @return The return value of ntfsclone (0 for success).
718 */
719int feed_outfrom_ntfsprog(char *output_device, char *input_fifo)
720{
721// RESTORE
722 int res = -1;
723 char *command;
724
725 if ( !find_home_of_exe("ntfsclone")) {
726 fatal_error("ntfsclone not found");
727 }
728 malloc_string(command);
729 sprintf(command, "ntfsclone --rescue --force --restore-image --overwrite %s %s", output_device, input_fifo);
730 res = run_program_and_log_output(command, 5);
731 paranoid_free(command);
732 return (res);
733}
Note: See TracBrowser for help on using the repository browser.