source: MondoRescue/branches/3.1/mondo/src/common/libmondo-fork.c@ 3190

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