Ignore:
Timestamp:
Mar 9, 2024, 3:10:04 AM (4 months ago)
Author:
Bruno Cornec
Message:

Fix all remaining compiler errors

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.3/mondo/src/common/libmondo-archive.c

    r3878 r3879  
    3333#include <stdarg.h>
    3434#include <unistd.h>
     35
    3536#define DVDRWFORMAT 1
     37
     38/**
     39 * Maximum number of filesets allowed in this function.
     40 */
     41#define MAX_NOOF_SETS_HERE 32767
     42
     43/**
     44 * Offset of the bkpinfo pointer (in bytes) from the
     45 * buffer passed to create_afio_files_in_background.
     46 */
     47#define BKPINFO_LOC_OFFSET (16+MAX_NOOF_SETS_HERE/8+16)
    3648
    3749
     
    355367
    356368
     369/**
     370 * Create a USB image in @c destfile, from files in @c bkpinfo->scratchdir.
     371 *
     372 * @param bkpinfo The backup information structure. Fields used:
     373 * - @c backup_media_type
     374 * - @c nonbootable_backup
     375 * - @c scratchdir
     376 *
     377 * @param destfile Where to put the generated USB image.
     378 * @return The number of errors encountered (0 for success)
     379 */
     380int make_usb_fs()
     381{
     382    /*@ int ********************************************** */
     383    int retval = 0;
     384    int res;
     385
     386    /*@ buffers ****************************************** */
     387    char *tmp = NULL;
     388    char *tmp1 = NULL;
     389    char *result_sz = NULL;
     390    char *message_to_screen = NULL;
     391    char *old_pwd = NULL;
     392    char *mds = NULL;
     393
     394    assert(bkpinfo != NULL);
     395
     396    log_msg(2, "make_usb_fs --- scratchdir=%s", bkpinfo->scratchdir);
     397    old_pwd = mr_getcwd();
     398    mr_asprintf(tmp, "chmod 700 %s", bkpinfo->scratchdir);
     399    run_program_and_log_output(tmp, FALSE);
     400    mr_free(tmp);
     401    if (chdir(bkpinfo->scratchdir)) {
     402        // FIXME
     403    }
     404
     405    mds = media_descriptor_string(bkpinfo->backup_media_type);
     406    mr_asprintf(message_to_screen, "Copying data to make %s #%d",mds, g_current_media_number);
     407    mr_free(mds);
     408    log_msg(1, message_to_screen);
     409
     410    if (bkpinfo->media_device) {
     411        mr_asprintf(tmp1, "%s1", bkpinfo->media_device);
     412    } else {
     413        mr_asprintf(tmp1, "");
     414    }
     415    if (is_this_device_mounted(tmp1)) {
     416        log_msg(1, "USB device mounted. Remounting it at the right place");
     417        mr_asprintf(tmp, "umount %s", tmp1);
     418        run_program_and_log_output(tmp, FALSE);
     419        mr_free(tmp);
     420    }
     421    mr_free(tmp1);
     422
     423    log_msg(1, "Mounting USB device.");
     424    mr_asprintf(tmp1, "%s/usb", bkpinfo->tmpdir);
     425    mr_asprintf(tmp, "mkdir -p %s", tmp1);
     426    run_program_and_log_output(tmp, FALSE);
     427    mr_free(tmp);
     428
     429
     430    /* Mindi always create one single parition on the USB dev */
     431    mr_asprintf(tmp, "mount %s1 %s", bkpinfo->media_device, tmp1);
     432    run_program_and_log_output(tmp, FALSE);
     433    mr_free(tmp);
     434
     435    if (bkpinfo->nonbootable_backup) {
     436        log_msg(1, "Making nonbootable USB backup not implemented yet");
     437    } else {
     438        log_msg(1, "Making bootable backup");
     439
     440        /* Command to execute */
     441        mr_asprintf(tmp,"cd %s ; rm -fr %s/syslinux ; mv * %s", bkpinfo->scratchdir, tmp1, tmp1);
     442        res = eval_call_to_make_USB(tmp, message_to_screen);
     443        if (res) {
     444            mr_asprintf(result_sz, "%s ...failed",tmp);
     445        } else {
     446            mr_asprintf(result_sz, "%s ...OK",tmp);
     447        }
     448        log_to_screen(result_sz);
     449        mr_free(result_sz);
     450        mr_free(tmp);
     451        retval += res;
     452
     453        /* Recreate the required structure under the scratch dir */
     454        mr_asprintf(tmp,"mkdir %s/archive", bkpinfo->scratchdir);
     455        run_program_and_log_output(tmp, FALSE);
     456        mr_free(tmp);
     457    }
     458    paranoid_free(message_to_screen);
     459
     460    /*  Copy the current logfile - of course incomplete to the media */
     461    mr_system("gzip -c9 %s > %s/archives/%s", MONDO_LOGFILE, tmp1, MONDO_LOGFILENAME);
     462    paranoid_free(tmp1);
     463
     464    if (is_this_device_mounted(bkpinfo->media_device)) {
     465        mr_asprintf(tmp, "umount %s1", bkpinfo->media_device);
     466        run_program_and_log_output(tmp, FALSE);
     467        mr_free(tmp);
     468    }
     469
     470    if (chdir(old_pwd)) {
     471        // FIXME
     472    }
     473    mr_free(old_pwd);
     474    if (retval) {
     475        log_msg(1, "WARNING - make_usb_fs returned an error");
     476    }
     477    return(retval);
     478}
     479
     480
     481/**
     482 * Make sure the user has a valid CD-R(W) in the CD drive.
     483 * @param cd_dev Set to the CD-R(W) device checked.
     484 * @param keep_looping If TRUE, keep pestering user until they insist
     485 * or insert a correct CD; if FALSE, only check once.
     486 * @return 0 (there was an OK CD in the drive) or 1 (there wasn't).
     487 */
     488int interrogate_disk_currently_in_cddrive(char *cd_dev,
     489                                             bool keep_looping)
     490{
     491    int res = 0;
     492    char *bkp = NULL;
     493    char *cdrecord = NULL;
     494
     495    mr_asprintf(bkp, "%s", cd_dev);
     496    if ((cd_dev = find_optical_device()) != NULL) {
     497        if (!system("which cdrecord > /dev/null 2> /dev/null")) {
     498            mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev);
     499        } else if (!system("which dvdrecord > /dev/null 2> /dev/null")) {
     500            mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev);
     501        } else {
     502            log_msg(2, "Oh well. I guess I'll just pray then.");
     503        }
     504        if (cdrecord != NULL) {
     505            if (!keep_looping) {
     506                retract_CD_tray_and_defeat_autorun();
     507                res = run_program_and_log_output(cdrecord, 5);
     508            } else {
     509                while ((res = run_program_and_log_output(cdrecord, 5))) {
     510                    retract_CD_tray_and_defeat_autorun();
     511                    if (ask_me_yes_or_no
     512                        ("Unable to examine CD. Are you sure this is a valid CD-R(W) CD?"))
     513                    {
     514                        log_msg(1, "Well, he insisted...");
     515                        break;
     516                    }
     517                }
     518            }
     519        }
     520    }
     521    mr_free(bkp);
     522
     523    mr_free(cdrecord);
     524    return (res);
     525}
     526
     527
     528/**
     529 * Asks the user to put a CD-R(W) in the drive.
     530 * @param ask_for_one_if_more_than_this (unused)
     531 * @param pmountable If non-NULL, pointed-to value is set to TRUE if the CD is mountable, FALSE otherwise.
     532 */
     533void pause_and_ask_for_cdr(int ask_for_one_if_more_than_this, bool * pmountable) {
     534
     535    /*@ buffers ********************************************* */
     536    char *tmp = NULL;
     537    char *cdrom_dev = NULL;
     538    char *cd_dev = NULL;
     539    char *our_serial_str = NULL;
     540    bool ok_go_ahead_burn_it;
     541    int cd_number = -1;
     542    int attempt_to_mount_returned_this = 999;
     543    char *mtpt = NULL;
     544    char *szcdno = NULL;
     545    char *szserfname = NULL;
     546    char *szunmount = NULL;
     547    char *mds = NULL;
     548
     549    malloc_string(cd_dev);
     550
     551    mds = media_descriptor_string(g_backup_media_type);
     552    log_to_screen("I am about to burn %s #%d", mds, g_current_media_number);
     553    mr_free(mds);
     554    if (g_current_media_number < ask_for_one_if_more_than_this) {
     555        return;
     556    }
     557    log_to_screen("Scanning CD-ROM drive...");
     558    mr_asprintf(mtpt, "%s/cd.mtpt", bkpinfo->tmpdir);
     559    make_hole_for_dir(mtpt);
     560
     561  gotos_make_me_puke:
     562    ok_go_ahead_burn_it = TRUE;
     563    mr_free(cdrom_dev);
     564    if ((cdrom_dev = find_optical_device()) != NULL) {
     565        /* When enabled, it made CD eject-and-retract when wrong CD inserted.. Weird
     566        log_msg(2, "paafcd: Retracting CD-ROM drive if possible" );
     567        retract_CD_tray_and_defeat_autorun();
     568        */
     569        mr_asprintf(tmp, "umount %s", cdrom_dev);
     570        run_program_and_log_output(tmp, 1);
     571        mr_asprintf(szcdno, "%s/archives/THIS-CD-NUMBER", mtpt);
     572        mr_asprintf(szserfname, "%s/archives/SERIAL-STRING", mtpt);
     573        mr_asprintf(szunmount, "umount %s", mtpt);
     574        cd_number = -1;
     575        mr_asprintf(tmp, "mount %s %s", cdrom_dev, mtpt);
     576        mr_asprintf(our_serial_str, "%s", "");
     577        attempt_to_mount_returned_this = run_program_and_log_output(tmp, 1);
     578        mr_free(tmp);
     579
     580        if (attempt_to_mount_returned_this) {
     581            log_msg(4, "Failed to mount %s at %s", cdrom_dev, mtpt);
     582            log_to_screen("If there's a CD/DVD in the drive, it's blank.");
     583        } else if (!does_file_exist(szcdno) || !does_file_exist(szserfname)) {
     584            mds = media_descriptor_string(g_backup_media_type);
     585            log_to_screen("%s has data on it but it's probably not a Mondo CD.", mds);
     586            mr_free(mds);
     587        } else {
     588            mds = media_descriptor_string(g_backup_media_type);
     589            log_to_screen("%s found in drive. It's a Mondo disk.", mds);
     590            mr_free(mds);
     591
     592            cd_number = atoi(last_line_of_file(szcdno));
     593            mr_asprintf(tmp, "cat %s 2> /dev/null", szserfname);
     594            mr_free(our_serial_str);
     595            our_serial_str = call_program_and_get_last_line_of_output(tmp);
     596            mr_free(tmp);
     597            // FIXME - should be able to use last_line_of_file(), surely?
     598        }
     599        mr_free(szcdno);
     600        mr_free(szserfname);
     601
     602        run_program_and_log_output(szunmount, 1);
     603        mr_free(szunmount);
     604
     605        log_msg(2, "paafcd: cd_number = %d", cd_number);
     606        log_msg(2, "our serial str = %s; bkpinfo->serial_string = %s", our_serial_str, bkpinfo->serial_string);
     607        if (cd_number > 0 && !strcmp(our_serial_str, bkpinfo->serial_string)) {
     608            mds = media_descriptor_string(g_backup_media_type);
     609            log_msg(2, "This %s is part of this backup set!", mds);
     610            ok_go_ahead_burn_it = FALSE;
     611            if (cd_number == g_current_media_number - 1) {
     612                log_to_screen("I think you've left the previous %s in the drive.", mds);
     613            } else {
     614                log_to_screen("Please remove this %s. It is part of the backup set you're making now.", mds);
     615            }
     616            mr_free(mds);
     617
     618        } else {
     619            log_to_screen("...but not part of _our_ backup set.");
     620        }
     621        mr_free(our_serial_str);
     622    } else {
     623        mds = media_descriptor_string(g_backup_media_type);
     624        log_msg(2,
     625                "paafcd: Can't find CD-ROM drive. Perhaps it has a blank %s in it?", mds);
     626        if (interrogate_disk_currently_in_cddrive(cd_dev, FALSE)) {
     627            ok_go_ahead_burn_it = FALSE;
     628            log_to_screen("There isn't a writable %s in the drive.", mds);
     629        }
     630        mr_free(mds);
     631    }
     632
     633    if (!ok_go_ahead_burn_it) {
     634        if (!bkpinfo->please_dont_eject) {
     635            eject_device(cdrom_dev);
     636        }
     637        mds = media_descriptor_string(g_backup_media_type);
     638        mr_asprintf(tmp, "I am about to burn %s #%d of the backup set. Please insert %s and press Enter.", mds, g_current_media_number, mds);
     639        mr_free(mds);
     640
     641        popup_and_OK(tmp);
     642        mr_free(tmp);
     643        goto gotos_make_me_puke;
     644    } else {
     645        log_msg(2, "paafcd: OK, going ahead and burning it.");
     646    }
     647
     648    mds = media_descriptor_string(g_backup_media_type);
     649    log_msg(2, "paafcd: OK, I assume I have a blank/reusable %s in the drive...", mds);
     650
     651    log_to_screen("Proceeding w/ %s in drive.", mds);
     652    mr_free(mds);
     653
     654    mr_free(cdrom_dev);
     655    paranoid_free(cd_dev);
     656    mr_free(mtpt);
     657    if (pmountable) {
     658        if (attempt_to_mount_returned_this) {
     659            *pmountable = FALSE;
     660        } else {
     661            *pmountable = TRUE;
     662        }
     663    }
     664
     665}
     666
     667
     668/**
     669 * @addtogroup LLarchiveGroup
     670 * @{
     671 */
     672
     673void pause_for_N_seconds(int how_long, char *msg)
     674{
     675    int i;
     676    open_evalcall_form(msg);
     677    for (i = 0; i < how_long; i++) {
     678        update_evalcall_form((int) ((100.0 / (float) (how_long) * i)));
     679        sleep(1);
     680    }
     681    close_evalcall_form();
     682}
     683
     684
     685/**
     686 * Create an ISO image in @c destfile, from files in @c bkpinfo->scratchdir.
     687 *
     688 * @param bkpinfo The backup information structure. Fields used:
     689 * - @c backup_media_type
     690 * - @c call_after_iso
     691 * - @c call_before_iso
     692 * - @c call_burn_iso
     693 * - @c call_make_iso
     694 * - @c make_cd_use_lilo
     695 * - @c manual_cd_tray
     696 * - @c nonbootable_backup
     697 * - @c scratchdir
     698 *
     699 * @param destfile Where to put the generated ISO image.
     700 * @return The number of errors encountered (0 for success)
     701 */
     702int make_iso_fs(char *destfile) {
     703    /*@ int ********************************************** */
     704    int retval = 0;
     705    int res;
     706
     707    /*@ buffers ****************************************** */
     708    char *tmp = NULL;
     709    char *old_pwd = NULL;
     710    char *result_sz = NULL;
     711    char *message_to_screen = NULL;
     712    char *sz_blank_disk = NULL;
     713    char *isofs_cmd = NULL;
     714    char *full_isofs_cmd = NULL;
     715    char *mds = NULL;
     716    char *uefistr = NULL;
     717    bool cd_is_mountable;
     718
     719    assert(bkpinfo != NULL);
     720    assert_string_is_neither_NULL_nor_zerolength(destfile);
     721
     722    if (bkpinfo->backup_media_type == iso && bkpinfo->manual_cd_tray) {
     723        popup_and_OK("Please insert new media and press Enter.");
     724    }
     725
     726    log_msg(2, "make_iso_fs --- scratchdir=%s --- destfile=%s", bkpinfo->scratchdir, destfile);
     727    old_pwd = mr_getcwd();
     728    mr_asprintf(tmp, "chmod 700 %s", bkpinfo->scratchdir);
     729    run_program_and_log_output(tmp, FALSE);
     730    mr_free(tmp);
     731
     732    if (chdir(bkpinfo->scratchdir)) {
     733        // FIXME
     734    }
     735
     736    if (bkpinfo->call_before_iso != NULL) {
     737        mr_asprintf(message_to_screen, "Running pre-ISO call for CD#%d", g_current_media_number);
     738        res = eval_call_to_make_ISO(bkpinfo->call_before_iso, destfile, g_current_media_number, message_to_screen);
     739        if (res) {
     740            mr_strcat(message_to_screen, "...failed");
     741        } else {
     742            mr_strcat(message_to_screen, "...OK");
     743        }
     744        log_to_screen(message_to_screen);
     745        paranoid_free(message_to_screen);
     746
     747        retval += res;
     748    }
     749
     750    if (bkpinfo->call_make_iso != NULL) {
     751        log_msg(2, "bkpinfo->call_make_iso = %s", bkpinfo->call_make_iso);
     752        mds = media_descriptor_string(bkpinfo->backup_media_type);
     753        mr_asprintf(message_to_screen, "Making an ISO (%s #%d)", mds, g_current_media_number);
     754        mr_free(mds);
     755
     756        pause_and_ask_for_cdr(2, &cd_is_mountable); /* if g_current_media_number >= 2 then pause & ask */
     757        if (retval) {
     758            log_to_screen
     759                ("Serious error(s) occurred already. I shan't try to write to media.");
     760        } else {
     761            res =
     762                eval_call_to_make_ISO(bkpinfo->call_make_iso, bkpinfo->scratchdir, g_current_media_number, message_to_screen);
     763            if (res) {
     764                log_to_screen("%s...failed to write", message_to_screen);
     765            } else {
     766                log_to_screen("%s...OK", message_to_screen);
     767                mr_asprintf(tmp, "tail -n10 %s | grep -F ':-('", MONDO_LOGFILE);
     768                if (!run_program_and_log_output(tmp, 1)) {
     769                    log_to_screen
     770                        ("Despite nonfatal errors, growisofs confirms the write was successful.");
     771                }
     772                mr_free(tmp);
     773            }
     774            retval += res;
     775#ifdef DVDRWFORMAT
     776            mr_asprintf(tmp, "tail -n8 %s | grep 'blank=full.*dvd-compat.*DAO'", MONDO_LOGFILE);
     777            if (g_backup_media_type == dvd
     778                && (res || !run_program_and_log_output(tmp, 1))) {
     779                log_to_screen
     780                    ("Failed to write to disk. I shall blank it and then try again.");
     781                sleep(5);
     782                /* reset error counter before trying to blank DVD */
     783                retval -= res;
     784                sync();
     785                pause_for_N_seconds(5, "Letting DVD drive settle");
     786
     787// dvd+rw-format --- OPTION 2
     788                if (!bkpinfo->please_dont_eject) {
     789                    log_to_screen("Ejecting media to clear drive status.");
     790                    eject_device(bkpinfo->media_device);
     791                    inject_device(bkpinfo->media_device);
     792                }
     793                pause_for_N_seconds(5, "Letting DVD drive settle");
     794                if (bkpinfo->media_device) {
     795                    mr_asprintf(sz_blank_disk, "dvd+rw-format -force %s", bkpinfo->media_device);
     796                } else {
     797                    mr_asprintf(sz_blank_disk, "dvd+rw-format");
     798                }
     799                log_msg(3, "sz_blank_disk = '%s'", sz_blank_disk);
     800                res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);
     801                if (res) {
     802                    log_to_screen("Warning - format failed. (Was it a DVD-R?) Sleeping for 5 seconds to take a breath...");
     803                    pause_for_N_seconds(5, "Letting DVD drive settle... and trying again.");
     804                    res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);
     805                    if (res) {
     806                        log_to_screen("Format failed a second time.");
     807                    }
     808                } else {
     809                    log_to_screen
     810                        ("Format succeeded. Sleeping for 5 seconds to take a breath...");
     811                }
     812                mr_free(sz_blank_disk);
     813                pause_for_N_seconds(5, "Letting DVD drive settle");
     814                if (!bkpinfo->please_dont_eject) {
     815                    log_to_screen("Ejecting media to clear drive status.");
     816                    eject_device(bkpinfo->media_device);
     817                    inject_device(bkpinfo->media_device);
     818                }
     819                pause_for_N_seconds(5, "Letting DVD drive settle");
     820                res = eval_call_to_make_ISO(bkpinfo->call_make_iso, bkpinfo->scratchdir, g_current_media_number, message_to_screen);
     821                retval += res;
     822                if (!bkpinfo->please_dont_eject) {
     823                    log_to_screen("Ejecting media.");
     824                    eject_device(bkpinfo->media_device);
     825                }
     826                if (res) {
     827                    log_to_screen("Dagnabbit. It still failed.");
     828                } else {
     829                    log_to_screen
     830                        ("OK, this time I successfully backed up to DVD.");
     831                }
     832            }
     833            mr_free(tmp);
     834#endif
     835            if (g_backup_media_type == dvd && !bkpinfo->please_dont_eject) {
     836                eject_device(bkpinfo->media_device);
     837            }
     838        }
     839        paranoid_free(message_to_screen);
     840    } else {
     841        mds = media_descriptor_string(bkpinfo->backup_media_type);
     842        mr_asprintf(message_to_screen, "Running mkisofs to make %s #%d", mds, g_current_media_number);
     843        log_msg(1, message_to_screen);
     844        mr_asprintf(result_sz, "Call to mkisofs to make ISO (%s #%d) ", mds,  g_current_media_number);
     845        mr_free(mds);
     846        if ((tmp = find_home_of_exe("xorriso")) != NULL) {
     847            mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_XORRISO_OPT);
     848        } else if ((tmp = find_home_of_exe("genisoimage")) != NULL) {
     849            mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_GENISOIMAGE_OPT);
     850        } else if ((tmp = find_home_of_exe("mkisofs")) != NULL) {
     851            mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_MKISOFS_OPT);
     852        } else if ((tmp = find_home_of_exe("wodim")) != NULL) {
     853            mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_WODIM_OPT);
     854        } else {
     855            fatal_error("Unable to find a command to create ISO among xorriso, genisoimage, mksiofs or wodim, please install one");
     856        }
     857        mr_free(tmp);
     858        if (bkpinfo->nonbootable_backup) {
     859            log_msg(1, "Making nonbootable backup");
     860            mr_asprintf(full_isofs_cmd, "%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS);
     861            res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);
     862            mr_free(full_isofs_cmd);
     863        } else {
     864            log_msg(1, "Making bootable backup");
     865
     866#ifdef __FreeBSD__
     867            bkpinfo->make_cd_use_lilo = TRUE;
     868#endif
     869
     870
     871            log_msg(1, "make_cd_use_lilo is actually %d", bkpinfo->make_cd_use_lilo);
     872            if (bkpinfo->make_cd_use_lilo) {
     873                log_msg(1, "make_cd_use_lilo = TRUE");
     874#ifdef __IA64__
     875                log_msg(1, "IA64 --> elilo");
     876                mr_asprintf(full_isofs_cmd, "%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS_REGULAR_ELILO);
     877                res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);
     878                mr_free(full_isofs_cmd);
     879#else
     880                log_msg(1, "Non-ia64 --> lilo");
     881                mr_asprintf(full_isofs_cmd, "%s%s-b images/mindi-bootroot.img -c images/boot.cat -o '_ISO_' .",isofs_cmd,MONDO_MKISOFS);
     882                // FIXME: fixed boot size probably wrong. lilo to be removed
     883                res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);
     884                mr_free(full_isofs_cmd);
     885#endif
     886            } else {
     887                log_msg(1, "make_cd_use_lilo = FALSE");
     888                log_msg(1, "Isolinux");
     889                if (bkpinfo->boot_type == UEFI) {
     890                    if (strstr(isofs_cmd,"xorriso")) {
     891                        /*  xorriso needs another '-' before efi-boot */
     892                        mr_asprintf(uefistr, "%s -%s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI);
     893                    } else {
     894                        mr_asprintf(uefistr, "%s %s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI);
     895                    }
     896                } else {
     897                    mr_asprintf(uefistr, "%s",MONDO_MKISOFS_CMS);
     898                }
     899                mr_asprintf(full_isofs_cmd, "%s%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS_REGULAR_SYSLINUX,uefistr);
     900                mr_free(uefistr);
     901
     902                res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);
     903                mr_free(full_isofs_cmd);
     904            }
     905        }
     906        mr_free(isofs_cmd);
     907        paranoid_free(message_to_screen);
     908
     909        if (res) {
     910            mr_strcat(result_sz, "...failed");
     911        } else {
     912            mr_strcat(result_sz, "...OK");
     913        }
     914        log_to_screen(result_sz);
     915        paranoid_free(result_sz);
     916        retval += res;
     917    }
     918
     919    if (bkpinfo->backup_media_type == cdr) {
     920        if (is_this_device_mounted(bkpinfo->media_device)) {
     921            log_msg(2, "Warning - %s mounted. I'm unmounting it before I burn to it.", bkpinfo->media_device);
     922            mr_asprintf(tmp, "umount %s", bkpinfo->media_device);
     923            run_program_and_log_output(tmp, FALSE);
     924            mr_free(tmp);
     925        }
     926    }
     927
     928    if (bkpinfo->call_burn_iso != NULL) {
     929        log_msg(2, "bkpinfo->call_burn_iso = %s", bkpinfo->call_burn_iso);
     930        mds = media_descriptor_string(bkpinfo->backup_media_type);
     931        mr_asprintf(message_to_screen, "Burning %s #%d", mds, g_current_media_number);
     932        mr_free(mds);
     933        pause_and_ask_for_cdr(2, &cd_is_mountable);
     934        res = eval_call_to_make_ISO(bkpinfo->call_burn_iso, destfile, g_current_media_number, message_to_screen);
     935        if (res) {
     936            mr_strcat(message_to_screen, "...failed");
     937        } else {
     938            mr_strcat(message_to_screen, "...OK");
     939        }
     940        log_to_screen(message_to_screen);
     941        paranoid_free(message_to_screen);
     942
     943        retval += res;
     944    }
     945
     946    if (bkpinfo->call_after_iso != NULL) {
     947        mds = media_descriptor_string(bkpinfo->backup_media_type);
     948        mr_asprintf(message_to_screen, "Running post-ISO call (%s #%d)", mds, g_current_media_number);
     949        mr_free(mds);
     950        res = eval_call_to_make_ISO(bkpinfo->call_after_iso, destfile, g_current_media_number, message_to_screen);
     951        if (res) {
     952            mr_strcat(message_to_screen, "...failed");
     953        } else {
     954            mr_strcat(message_to_screen, "...OK");
     955        }
     956        log_to_screen(message_to_screen);
     957        paranoid_free(message_to_screen);
     958
     959        retval += res;
     960    }
     961
     962    if (chdir(old_pwd)) {
     963        // FIXME
     964    }
     965    mr_free(old_pwd);
     966    if (retval) {
     967        log_msg(1, "WARNING - make_iso_fs returned an error");
     968    }
     969    return (retval);
     970}
     971
     972
     973bool is_dev_an_NTFS_dev(char *bigfile_fname)
     974{
     975    char *tmp = NULL;
     976    char *command = NULL;
     977    bool ret = TRUE;
     978
     979    mr_asprintf(command, "dd if=%s bs=512 count=1 2> /dev/null | strings | head -n1", bigfile_fname);
     980    log_msg(1, "command = '%s'", command);
     981    tmp = call_program_and_get_last_line_of_output(command);
     982    mr_free(command);
     983
     984    log_msg(1, "--> tmp = '%s'", tmp);
     985    if (strstr(tmp, "NTFS")) {
     986        log_it("TRUE");
     987        ret = TRUE;
     988    } else {
     989        log_it("FALSE");
     990        ret = FALSE;
     991    }
     992    mr_free(tmp);
     993    return(ret);
     994}
     995
     996
    357997
    358998/**
     
    6011241        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    6021242    }
     1243
     1244    return (retval);
     1245}
     1246
     1247/**
     1248 * Copy some files to tape.
     1249 * This function copies the files specified as parameters into the tape stream.
     1250 *
     1251 * @param bkpinfo The backup information structure. Used only in the call to
     1252 * @c write_file_to_stream_from_file().
     1253 *
     1254 * @param files_to_add The files to copy to the tape stream.
     1255 * @warning The list of @c files_to_add must be terminated with @c NULL.
     1256 * @note Files may be split across multiple tapes if necessary.
     1257 *
     1258 * @return The number of errors encountered (0 for success)
     1259 */
     1260int
     1261_move_files_to_stream(char *files_to_add, ...)
     1262{
     1263
     1264    /*@ int ************************************************************ */
     1265    int retval = 0;
     1266    int res = 0;
     1267    /*@ buffers ******************************************************** */
     1268
     1269    /*@ char *********************************************************** */
     1270    char start_chr;
     1271    char stop_chr;
     1272    char *curr_file = NULL;
     1273    char *cf;
     1274    /*@ long long ****************************************************** */
     1275    off_t length_of_incoming_file = (off_t)0;
     1276    va_list ap;
     1277
     1278    assert(bkpinfo != NULL);
     1279    va_start(ap, files_to_add);
     1280    for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {
     1281        if (!cf) {
     1282            continue;
     1283        }
     1284        mr_asprintf(curr_file, "%s", cf);
     1285        if (!does_file_exist(curr_file)) {
     1286            log_msg(1,
     1287                    "Warning - you're trying to add a non-existent file - '%s' to the tape",
     1288                    curr_file);
     1289        }
     1290        /* create header chars */
     1291        start_chr = BLK_START_AN_AFIO_OR_SLICE;
     1292        stop_chr = BLK_STOP_AN_AFIO_OR_SLICE;
     1293        /* ask for new tape if necessary */
     1294        length_of_incoming_file = length_of_file(curr_file);
     1295        write_header_block_to_stream(length_of_incoming_file, curr_file, start_chr);
     1296        res = write_file_to_stream_from_file(curr_file);
     1297        retval += res;
     1298        unlink(curr_file);
     1299        mr_free(curr_file);
     1300        /* write closing header */
     1301        write_header_block_to_stream((off_t)0, "finished-writing-file", stop_chr);
     1302    }
     1303    va_end(ap);
     1304
     1305    if (retval) {
     1306        log_msg(1,
     1307                "Warning - errors occurred while I was adding file to tape");
     1308    }
     1309    return (retval);
     1310}
     1311
     1312/**
     1313 * Move some files to the ISO scratch directory.
     1314 * This function moves files specified as parameters, into the directory
     1315 * @c bkpinfo->scratchdir, where the files that will be stored on the next
     1316 * CD are waiting.
     1317 *
     1318 * @param bkpinfo The backup information structure. Fields used:
     1319 * - @c media_size
     1320 * - @c scratchdir
     1321 * @param files_to_add The files to add to the scratchdir.
     1322 * @warning The list of @c files_to_add must be terminated with @c NULL.
     1323 * @note If and when the space occupied by the scratchdir would exceed
     1324 * the capacity of the current CD,
     1325 * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the
     1326 * scratchdir is emptied.
     1327 *
     1328 * @return The number of errors encountered (0 for success)
     1329 */
     1330int _move_files_to_cd(char *files_to_add, ...)
     1331{
     1332
     1333    /*@ int ************************************************************ */
     1334    int retval = 0;
     1335    int res = 0;
     1336
     1337    /*@ buffers ******************************************************** */
     1338    char *tmp = NULL;
     1339    char *curr_file = NULL;
     1340    char *cf;
     1341
     1342    /*@ long ************************************************************ */
     1343    va_list ap;
     1344    long long would_occupy;
     1345
     1346    assert(bkpinfo != NULL);
     1347    would_occupy = space_occupied_by_cd(bkpinfo->scratchdir);
     1348    va_start(ap, files_to_add); // initialize the variable arguments
     1349    for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {
     1350        if (!cf) {
     1351            continue;
     1352        }
     1353        mr_asprintf(curr_file, "%s", cf);
     1354        if (!does_file_exist(curr_file)) {
     1355            log_msg(1, "Warning - you're trying to add a non-existent file - '%s' to the CD", curr_file);
     1356        } else {
     1357            log_msg(8, "Trying to add file %s to CD", curr_file);
     1358            would_occupy += length_of_file(curr_file) / 1024;
     1359        }
     1360        mr_free(curr_file);
     1361    }
     1362    va_end(ap);
     1363
     1364    if (bkpinfo->media_size <= 0) {
     1365        fatal_error("move_files_to_cd() - unknown media size");
     1366    }
     1367    if (would_occupy / 1024 > bkpinfo->media_size) {
     1368        res = write_iso_and_go_on(FALSE);   /* FALSE because this is not the last CD we'll write */
     1369        retval += res;
     1370        if (res) {
     1371            log_msg(1, "WARNING - write_iso_and_go_on returned an error");
     1372        }
     1373    }
     1374
     1375    va_start(ap, files_to_add); // initialize the variable arguments
     1376    for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {
     1377        if (!cf) {
     1378            continue;
     1379        }
     1380        mr_asprintf(curr_file, "%s", cf);
     1381
     1382        mr_asprintf(tmp, "mv -f %s %s/archives/", curr_file, bkpinfo->scratchdir);
     1383        mr_free(curr_file);
     1384        res = run_program_and_log_output(tmp, 5);
     1385        retval += res;
     1386        if (res) {
     1387            log_msg(1, "(move_files_to_cd) '%s' failed", tmp);
     1388        } else {
     1389            log_msg(8, "Moved %s to CD OK", tmp);
     1390        }
     1391        mr_free(tmp);
     1392    }
     1393    va_end(ap);
     1394
     1395    if (retval) {
     1396        log_msg(1,
     1397                "Warning - errors occurred while I was adding files to CD dir");
     1398    }
     1399    return (retval);
     1400}
     1401
     1402
     1403
     1404/**
     1405 * @addtogroup LLarchiveGroup
     1406 * @{
     1407 */
     1408/**
     1409 * Function pointer to an appropriate @c move_files_to_stream routine.
     1410 * You can set this to your own function (for example, one to
     1411 * transfer files over the network) or leave it as is.
     1412 */
     1413int (*move_files_to_stream) (char *, ...) =
     1414    _move_files_to_stream;
     1415
     1416
     1417/**
     1418 * Function pointer to an appropriate @c move_files_to_cd routine.
     1419 * You can set this to your own function (for example, one to
     1420 * transfer files over the network) or leave it as is.
     1421 */
     1422int (*move_files_to_cd) (char *, ...) =
     1423    _move_files_to_cd;
     1424
     1425
     1426/**
     1427 * Set the <tt>N</tt>th bit of @c array to @c true_or_false.
     1428 * @param array The bit array (as a @c char pointer).
     1429 * @param N The bit number to set or reset.
     1430 * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N.
     1431 * @see get_bit_N_of_array
     1432 */
     1433void set_bit_N_of_array(char *array, int N, bool true_or_false)
     1434{
     1435    int bit_number;
     1436    int mask, orig_val, to_add;
     1437    int element_number;
     1438
     1439    assert(array != NULL);
     1440
     1441    element_number = N / 8;
     1442    bit_number = N % 8;
     1443    to_add = (1 << bit_number);
     1444    mask = 255 - to_add;
     1445    orig_val = array[element_number] & mask;
     1446    //  log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val);
     1447    if (true_or_false) {
     1448        array[element_number] = orig_val | to_add;
     1449    }
     1450}
     1451
     1452
     1453/**
     1454 * Get the <tt>N</tt>th bit of @c array.
     1455 * @param array The bit-array (as a @c char pointer).
     1456 * @param N The number of the bit you want.
     1457 * @return TRUE (bit is set) or FALSE (bit is not set).
     1458 * @see set_bit_N_of_array
     1459 * @ingroup utilityGroup
     1460 */
     1461bool get_bit_N_of_array(char *array, int N)
     1462{
     1463    int element_number;
     1464    int bit_number;
     1465    int mask;
     1466
     1467    element_number = N / 8;
     1468    bit_number = N % 8;
     1469    mask = 1 << bit_number;
     1470    if (array[element_number] & mask) {
     1471        return (TRUE);
     1472    } else {
     1473        return (FALSE);
     1474    }
     1475}
     1476
     1477
     1478
     1479/**
     1480 * Chop up @c filename.
     1481 * @param bkpinfo The backup information structure. Fields used:
     1482 * - @c backup_media_type
     1483 * - @c compression_level
     1484 * - @c optimal_set_size
     1485 * - @c tmpdir
     1486 * - @c use_lzo
     1487 * - @c zip_exe
     1488 * - @c zip_suffix
     1489 *
     1490 * @param biggie_filename The file to chop up.
     1491 * @param ntfsprog_fifo The FIFO to ntfsclone if this is an imagedev, NULL otherwise.
     1492 * @param biggie_file_number The sequence number of this biggie file (starting from 0).
     1493 * @param noof_biggie_files The number of biggie files there are total.
     1494 * @return The number of errors encountered (0 for success)
     1495 * @see make_slices_and_images
     1496 * @ingroup LLarchiveGroup
     1497 */
     1498int slice_up_file_etc(char *biggie_filename, char *ntfsprog_fifo, long biggie_file_number, long noof_biggie_files, bool use_ntfsprog) {
     1499
     1500    /*@ buffers ************************************************** */
     1501    char *tmp = NULL;
     1502    char *checksum_line = NULL;
     1503    char *command = NULL;
     1504    char *tempblock = NULL;
     1505    char *curr_slice_fname_uncompressed = NULL;
     1506    char *curr_slice_fname_compressed = NULL;
     1507    char *file_to_archive = NULL;
     1508    char *file_to_openin = NULL;
     1509    /*@ pointers ************************************************** */
     1510    char *pB = NULL;
     1511    FILE *fin = NULL;
     1512    FILE *fout = NULL;
     1513
     1514    /*@ bool ****************************************************** */
     1515    bool finished = FALSE;
     1516
     1517    /*@ long ****************************************************** */
     1518    size_t blksize = (size_t)0;
     1519    long slice_num = 0L;
     1520    long i = 0L;
     1521    bool should_I_compress_slices = TRUE;
     1522    char *suffix = NULL;                // for compressed slices
     1523
     1524    /*@ long long ************************************************** */
     1525    off_t totalread = (off_t)0;
     1526    off_t totallength = (off_t)0;
     1527
     1528    /*@ int ******************************************************** */
     1529    int retval = 0;
     1530    int res = 0;
     1531
     1532    /*@ structures ************************************************** */
     1533    struct s_filename_and_lstat_info biggiestruct;
     1534
     1535    assert(bkpinfo != NULL);
     1536    assert_string_is_neither_NULL_nor_zerolength(biggie_filename);
     1537
     1538    biggiestruct.for_backward_compatibility = '\n';
     1539    biggiestruct.use_ntfsprog = use_ntfsprog;
     1540    if (is_this_file_compressed(biggie_filename) || bkpinfo->compression_level == 0) {
     1541        mr_asprintf(suffix, "%s", "");
     1542        should_I_compress_slices = FALSE;
     1543    } else {
     1544        mr_asprintf(suffix, "%s", bkpinfo->zip_suffix);
     1545        should_I_compress_slices = TRUE;
     1546    }
     1547
     1548    if (bkpinfo->optimal_set_size < 999L) {
     1549        fatal_error("bkpinfo->optimal_set_size is insanely small");
     1550    }
     1551
     1552    if (ntfsprog_fifo) {
     1553        file_to_openin = ntfsprog_fifo;
     1554        mr_asprintf(checksum_line, "IGNORE");
     1555        log_msg(2, "Not calculating checksum for %s: it would take too long", biggie_filename);
     1556        if ((tmp = find_home_of_exe("ntfsresize")) == NULL) {
     1557            fatal_error("ntfsresize not found");
     1558        }
     1559        mr_asprintf(command, "%s --force --info %s|grep '^You might resize at '|cut -d' ' -f5", tmp, biggie_filename);
     1560        mr_free(tmp);
     1561        log_it("command = %s", command);
     1562        tmp = call_program_and_get_last_line_of_output(command);
     1563        mr_free(command);
     1564        log_it("res of it = %s", tmp);
     1565        totallength = (off_t)atoll(tmp);
     1566        mr_free(tmp);
     1567    } else {
     1568        file_to_openin = biggie_filename;
     1569        if (strchr(biggie_filename,'\'') != NULL) {
     1570            mr_asprintf(command, "md5sum \"%s\"", biggie_filename);
     1571        } else {
     1572            mr_asprintf(command, "md5sum '%s'", biggie_filename);
     1573        }
     1574        if (!(fin = popen(command, "r"))) {
     1575            log_OS_error("Unable to popen-in command");
     1576            mr_free(suffix);
     1577            return (1);
     1578        }
     1579        mr_free(command);
     1580        mr_getline(checksum_line, fin);
     1581        pclose(fin);
     1582        totallength = length_of_file(biggie_filename);
     1583    }
     1584    lstat(biggie_filename, &biggiestruct.properties);
     1585    strcpy(biggiestruct.filename, biggie_filename);
     1586    pB = strchr(checksum_line, ' ');
     1587    if (!pB) {
     1588        pB = strchr(checksum_line, '\t');
     1589    }
     1590    if (pB) {
     1591        *pB = '\0';
     1592    }
     1593    strcpy(biggiestruct.checksum, checksum_line);
     1594    mr_free(checksum_line);
     1595
     1596    mr_asprintf(tmp, "%s", slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""));
     1597    fout = fopen(tmp, "w");
     1598    if (fout == NULL) {
     1599        log_msg(1, "Unable to open and write to %s", tmp);
     1600        mr_free(tmp);
     1601        mr_free(suffix);
     1602        return (1);
     1603    }
     1604    res = fwrite((void *) &biggiestruct, 1, sizeof(biggiestruct), fout);
     1605    paranoid_fclose(fout);
     1606    mr_free(tmp);
     1607
     1608    log_msg(1, "Opening in %s; slicing it and writing to CD/tape", file_to_openin);
     1609    if (!(fin = fopen(file_to_openin, "r"))) {
     1610        log_OS_error("Unable to openin biggie_filename");
     1611        log_to_screen("Cannot archive bigfile '%s': not found", biggie_filename);
     1612
     1613        mr_free(suffix);
     1614        return (1);
     1615    }
     1616    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     1617        res = move_files_to_stream(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);
     1618    } else {
     1619        res = move_files_to_cd(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);
     1620    }
     1621    i = bkpinfo->optimal_set_size / 256L;
     1622    if (!(tempblock = (char *) malloc(256 * 1024))) {
     1623        fatal_error("malloc error 256*1024");
     1624    }
     1625    for (slice_num = 1; !finished; slice_num++) {
     1626        mr_asprintf(curr_slice_fname_uncompressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, ""));
     1627        mr_asprintf(curr_slice_fname_compressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, suffix));
     1628
     1629        tmp = percent_media_full_comment();
     1630        update_progress_form(tmp);
     1631        mr_free(tmp);
     1632
     1633        if (!(fout = fopen(curr_slice_fname_uncompressed, "w"))) {
     1634            log_OS_error(curr_slice_fname_uncompressed);
     1635            mr_free(suffix);
     1636            return (1);
     1637        }
     1638        if ((i == bkpinfo->optimal_set_size / 256L) && (totalread < (off_t)1.1 * totallength)) {
     1639            for (i = 0L; i < (bkpinfo->optimal_set_size / 256L); i++) {
     1640                blksize = fread(tempblock, 1, 256 * 1024, fin);
     1641                if (blksize > (size_t)0) {
     1642                    totalread = totalread + (off_t)blksize;
     1643                    res = fwrite(tempblock, 1, blksize, fout);
     1644                } else {
     1645                    break;
     1646                }
     1647            }
     1648        } else {
     1649            i = 0L;
     1650        }
     1651        paranoid_fclose(fout);
     1652        if (i > 0L)             // length_of_file (curr_slice_fname_uncompressed)
     1653        {
     1654            if (!does_file_exist(curr_slice_fname_uncompressed)) {
     1655                log_msg(2, "Warning - '%s' doesn't exist. How can I compress slice?", curr_slice_fname_uncompressed);
     1656            }
     1657            if (should_I_compress_slices && bkpinfo->compression_level > 0) {
     1658                mr_asprintf(command, "%s -%d %s", bkpinfo->zip_exe, bkpinfo->compression_level, curr_slice_fname_uncompressed);
     1659                log_msg(2, command);
     1660                if ((res = system(command))) {
     1661                    log_OS_error(command);
     1662                }
     1663                //          did_I_compress_slice = TRUE;
     1664            } else {
     1665                mr_asprintf(command, "mv %s %s 2>> %s", curr_slice_fname_uncompressed, curr_slice_fname_compressed, MONDO_LOGFILE);
     1666                res = 0;        // don't do it :)
     1667                //          did_I_compress_slice = FALSE;
     1668            }
     1669            mr_free(command);
     1670
     1671            retval += res;
     1672            if (res) {
     1673                log_msg(2, "Failed to compress the slice");
     1674            }
     1675            if (bkpinfo->use_lzo && strcmp(curr_slice_fname_compressed, curr_slice_fname_uncompressed)) {
     1676                unlink(curr_slice_fname_uncompressed);
     1677            }
     1678            if (res) {
     1679                mr_asprintf(tmp, "Problem with slice # %ld", slice_num);
     1680            } else {
     1681                mr_asprintf(tmp, "%s - Bigfile #%ld, slice #%ld compressed OK          ", biggie_filename, biggie_file_number + 1, slice_num);
     1682            }
     1683            if (!g_text_mode) {
     1684                newtDrawRootText(0, g_noof_rows - 2, tmp);
     1685                newtRefresh();
     1686            } else {
     1687                log_msg(2, tmp);
     1688            }
     1689            mr_free(tmp);
     1690
     1691            mr_asprintf(file_to_archive, "%s", curr_slice_fname_compressed);
     1692            g_current_progress++;
     1693        } else {                /* if i==0 then ... */
     1694            finished = TRUE;
     1695            mr_asprintf(file_to_archive, "%s", curr_slice_fname_uncompressed);
     1696            if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     1697                break;
     1698            }
     1699        }
     1700        mr_free(curr_slice_fname_uncompressed);
     1701        mr_free(curr_slice_fname_compressed);
     1702
     1703        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     1704            register_in_tape_catalog(biggieslice, biggie_file_number, slice_num, file_to_archive);
     1705            maintain_collection_of_recent_archives(bkpinfo->tmpdir, file_to_archive);
     1706            res = move_files_to_stream(file_to_archive, NULL);
     1707        } else {
     1708            res = move_files_to_cd(file_to_archive, NULL);
     1709        }
     1710        mr_free(file_to_archive);
     1711
     1712        retval += res;
     1713        if (res) {
     1714            log_to_screen("Failed to add slice %ld of bigfile %ld to scratchdir", slice_num, biggie_file_number + 1);
     1715            fatal_error("Hard disk full. You should have bought a bigger one.");
     1716        }
     1717    }
     1718    mr_free(tempblock);
     1719    mr_free(suffix);
     1720    paranoid_fclose(fin);
     1721    mr_asprintf(tmp, "Sliced bigfile #%ld", biggie_file_number + 1);
     1722    if (retval) {
     1723        mr_strcat(tmp, "...FAILED");
     1724    } else {
     1725        mr_strcat(tmp, "...OK!");
     1726    }
     1727    log_msg(1, tmp);
     1728    mr_free(tmp);
    6031729
    6041730    return (retval);
     
    7081834                    mr_free(sz_devfile);
    7091835                    fatal_error("Fork failure");
     1836                    break;
    7101837                case 0:
    7111838                    log_msg(2, "CHILD - fip - calling feed_into_ntfsprog(%s, %s)", bigfile_fname, sz_devfile);
     
    8551982    return (retval);
    8561983}
     1984/* @} - end of LLarchiveGroup */
     1985
     1986/**
     1987 * Main function for each @c afio thread.
     1988 * @param inbuf A transfer block containing:
     1989 * - @c p_last_set_archived: [offset 0] pointer to an @c int
     1990 *   containing the last set archived.
     1991 * - @c p_archival_threads_running: [offset 4] pointer to an @c int
     1992 *   containing the number of archival threads currently running.
     1993 * - @c p_next_set_to_archive: [offset 8] pointer to an @c int containing
     1994 *   the next set that should be archived.
     1995 * - @c p_list_of_fileset_flags: [offset 12] @c char pointer pointing to a
     1996 *   bit array, where each bit corresponds to a filelist (1=needs
     1997 *   to be archived, 0=archived).
     1998 * - @c bkpinfo: [offset BKPINFO_LOC_OFFSET] pointer to backup information
     1999 *   structure. Fields used:
     2000 *   - @c tmpdir
     2001 *   - @c zip_suffix
     2002 *
     2003 * Any of the above may be modified by the caller at any time.
     2004 *
     2005 * @bug Assumes @c int pointers are 4 bytes.
     2006 * @see archive_this_fileset
     2007 * @see make_afioballs_and_images
     2008 * @return NULL, always.
     2009 * @ingroup LLarchiveGroup
     2010 */
     2011void *create_afio_files_in_background(void *inbuf)
     2012{
     2013    long int archiving_set_no = 0L;
     2014    char *archiving_filelist_fname = NULL;
     2015    char *archiving_afioball_fname = NULL;
     2016    char *curr_xattr_list_fname = NULL;
     2017    char *curr_acl_list_fname = NULL;
     2018
     2019    char *tmp = NULL;
     2020    int res = 0, retval = 0;
     2021    int *p_archival_threads_running;
     2022    int *p_last_set_archived;
     2023    int *p_next_set_to_archive;
     2024    char *p_list_of_fileset_flags;
     2025    int this_thread_no = g_current_thread_no++;
     2026
     2027    p_last_set_archived = (int *) inbuf;
     2028    p_archival_threads_running = (int *) (inbuf + 4);
     2029    p_next_set_to_archive = (int *) (inbuf + 8);
     2030    p_list_of_fileset_flags = (char *) (inbuf + 12);
     2031
     2032    mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L);
     2033
     2034    while (does_file_exist(archiving_filelist_fname)) {
     2035        if (g_exiting) {
     2036            mr_free(archiving_filelist_fname);
     2037            fatal_error("Execution run aborted (pthread)");
     2038        }
     2039        if (archiving_set_no >= MAX_NOOF_SETS_HERE) {
     2040            mr_free(archiving_filelist_fname);
     2041            fatal_error("Maximum number of filesets exceeded. Adjust MAX_NOOF_SETS_HERE, please.");
     2042        }
     2043        if (!semaphore_p()) {
     2044            log_msg(3, "P sem failed (pid=%d)", (int) getpid());
     2045            mr_free(archiving_filelist_fname);
     2046            fatal_error("Cannot get semaphore P");
     2047        }
     2048        if (archiving_set_no < *p_next_set_to_archive) {
     2049            archiving_set_no = *p_next_set_to_archive;
     2050        }
     2051        *p_next_set_to_archive = *p_next_set_to_archive + 1;
     2052        if (!semaphore_v()) {
     2053            mr_free(archiving_filelist_fname);
     2054            fatal_error("Cannot get semaphore V");
     2055        }
     2056
     2057        /* backup this set of files */
     2058        mr_asprintf(archiving_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no, bkpinfo->zip_suffix);
     2059        mr_free(archiving_filelist_fname);
     2060        mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
     2061        if (!does_file_exist(archiving_filelist_fname)) {
     2062            log_msg(3, "%s[%d:%d] - well, I would archive %d, except that it doesn't exist. I'll stop now.", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
     2063            mr_free(archiving_afioball_fname);
     2064            break;
     2065        }
     2066
     2067        mr_asprintf(tmp, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no - ARCH_BUFFER_NUM, bkpinfo->zip_suffix);
     2068        if (does_file_exist(tmp)) {
     2069            log_msg(4, "%s[%d:%d] - waiting for storer", FORTY_SPACES, getpid(), this_thread_no);
     2070            while (does_file_exist(tmp)) {
     2071                sleep(1);
     2072            }
     2073            log_msg(4, "[%d] - continuing", getpid());
     2074        }
     2075        mr_free(tmp);
     2076
     2077        log_msg(4, "%s[%d:%d] - EXATing %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
     2078
     2079        if (g_getfattr) {
     2080            mr_asprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
     2081            get_fattr_list(archiving_filelist_fname, curr_xattr_list_fname);
     2082            mr_free(curr_xattr_list_fname);
     2083        }
     2084        if (g_getfacl) {
     2085            mr_asprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
     2086            get_acl_list(archiving_filelist_fname, curr_acl_list_fname);
     2087            mr_free(curr_acl_list_fname);
     2088        }
     2089
     2090        log_msg(4, "%s[%d:%d] - archiving %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
     2091        res = archive_this_fileset(archiving_filelist_fname, archiving_afioball_fname, archiving_set_no);
     2092        mr_free(archiving_afioball_fname);
     2093
     2094        retval += res;
     2095
     2096        if (res) {
     2097            log_to_screen("Errors occurred while archiving set %ld. Please review logs.", archiving_set_no);
     2098        }
     2099
     2100        if (!semaphore_p()) {
     2101            mr_free(archiving_filelist_fname);
     2102            fatal_error("Cannot get semaphore P");
     2103        }
     2104
     2105        set_bit_N_of_array(p_list_of_fileset_flags, archiving_set_no, 5);
     2106
     2107        if (*p_last_set_archived < archiving_set_no) {
     2108            *p_last_set_archived = archiving_set_no;
     2109        }                       // finished archiving this one
     2110
     2111        if (!semaphore_v()) {
     2112            mr_free(archiving_filelist_fname);
     2113            fatal_error("Cannot get semaphore V");
     2114        }
     2115        log_msg(4, "%s[%d:%d] - archived %d OK", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
     2116        archiving_set_no++;
     2117
     2118        mr_free(archiving_filelist_fname);
     2119        mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
     2120    }
     2121    mr_free(archiving_filelist_fname);
     2122
     2123    if (!semaphore_p()) {
     2124        fatal_error("Cannot get semaphore P");
     2125    }
     2126    (*p_archival_threads_running)--;
     2127    if (!semaphore_v()) {
     2128        fatal_error("Cannot get semaphore V");
     2129    }
     2130    log_msg(3, "%s[%d:%d] - exiting", FORTY_SPACES, getpid(), this_thread_no);
     2131    pthread_exit(NULL);
     2132}
     2133
    8572134
    8582135/**
     
    18593136
    18603137
    1861 
    1862 /**
    1863  * Set the <tt>N</tt>th bit of @c array to @c true_or_false.
    1864  * @param array The bit array (as a @c char pointer).
    1865  * @param N The bit number to set or reset.
    1866  * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N.
    1867  * @see get_bit_N_of_array
    1868  */
    1869 void set_bit_N_of_array(char *array, int N, bool true_or_false)
    1870 {
    1871     int bit_number;
    1872     int mask, orig_val, to_add;
    1873     int element_number;
    1874 
    1875     assert(array != NULL);
    1876 
    1877     element_number = N / 8;
    1878     bit_number = N % 8;
    1879     to_add = (1 << bit_number);
    1880     mask = 255 - to_add;
    1881     orig_val = array[element_number] & mask;
    1882     //  log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val);
    1883     if (true_or_false) {
    1884         array[element_number] = orig_val | to_add;
    1885     }
    1886 }
    1887 
    1888 
    1889 
    1890 /**
    1891  * Maximum number of filesets allowed in this function.
    1892  */
    1893 #define MAX_NOOF_SETS_HERE 32767
    1894 
    1895 /**
    1896  * Offset of the bkpinfo pointer (in bytes) from the
    1897  * buffer passed to create_afio_files_in_background.
    1898  */
    1899 #define BKPINFO_LOC_OFFSET (16+MAX_NOOF_SETS_HERE/8+16)
    1900 
    1901 /**
    1902  * Main function for each @c afio thread.
    1903  * @param inbuf A transfer block containing:
    1904  * - @c p_last_set_archived: [offset 0] pointer to an @c int
    1905  *   containing the last set archived.
    1906  * - @c p_archival_threads_running: [offset 4] pointer to an @c int
    1907  *   containing the number of archival threads currently running.
    1908  * - @c p_next_set_to_archive: [offset 8] pointer to an @c int containing
    1909  *   the next set that should be archived.
    1910  * - @c p_list_of_fileset_flags: [offset 12] @c char pointer pointing to a
    1911  *   bit array, where each bit corresponds to a filelist (1=needs
    1912  *   to be archived, 0=archived).
    1913  * - @c bkpinfo: [offset BKPINFO_LOC_OFFSET] pointer to backup information
    1914  *   structure. Fields used:
    1915  *   - @c tmpdir
    1916  *   - @c zip_suffix
    1917  *
    1918  * Any of the above may be modified by the caller at any time.
    1919  *
    1920  * @bug Assumes @c int pointers are 4 bytes.
    1921  * @see archive_this_fileset
    1922  * @see make_afioballs_and_images
    1923  * @return NULL, always.
    1924  * @ingroup LLarchiveGroup
    1925  */
    1926 void *create_afio_files_in_background(void *inbuf)
    1927 {
    1928     long int archiving_set_no = 0L;
    1929     char *archiving_filelist_fname = NULL;
    1930     char *archiving_afioball_fname = NULL;
    1931     char *curr_xattr_list_fname = NULL;
    1932     char *curr_acl_list_fname = NULL;
    1933 
    1934     char *tmp = NULL;
    1935     int res = 0, retval = 0;
    1936     int *p_archival_threads_running;
    1937     int *p_last_set_archived;
    1938     int *p_next_set_to_archive;
    1939     char *p_list_of_fileset_flags;
    1940     int this_thread_no = g_current_thread_no++;
    1941 
    1942     p_last_set_archived = (int *) inbuf;
    1943     p_archival_threads_running = (int *) (inbuf + 4);
    1944     p_next_set_to_archive = (int *) (inbuf + 8);
    1945     p_list_of_fileset_flags = (char *) (inbuf + 12);
    1946 
    1947     mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, 0L);
    1948 
    1949     while (does_file_exist(archiving_filelist_fname)) {
    1950         if (g_exiting) {
    1951             mr_free(archiving_filelist_fname);
    1952             fatal_error("Execution run aborted (pthread)");
    1953         }
    1954         if (archiving_set_no >= MAX_NOOF_SETS_HERE) {
    1955             mr_free(archiving_filelist_fname);
    1956             fatal_error("Maximum number of filesets exceeded. Adjust MAX_NOOF_SETS_HERE, please.");
    1957         }
    1958         if (!semaphore_p()) {
    1959             log_msg(3, "P sem failed (pid=%d)", (int) getpid());
    1960             mr_free(archiving_filelist_fname);
    1961             fatal_error("Cannot get semaphore P");
    1962         }
    1963         if (archiving_set_no < *p_next_set_to_archive) {
    1964             archiving_set_no = *p_next_set_to_archive;
    1965         }
    1966         *p_next_set_to_archive = *p_next_set_to_archive + 1;
    1967         if (!semaphore_v()) {
    1968             mr_free(archiving_filelist_fname);
    1969             fatal_error("Cannot get semaphore V");
    1970         }
    1971 
    1972         /* backup this set of files */
    1973         mr_asprintf(archiving_afioball_fname, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no, bkpinfo->zip_suffix);
    1974         mr_free(archiving_filelist_fname);
    1975         mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
    1976         if (!does_file_exist(archiving_filelist_fname)) {
    1977             log_msg(3, "%s[%d:%d] - well, I would archive %d, except that it doesn't exist. I'll stop now.", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
    1978             mr_free(archiving_afioball_fname);
    1979             break;
    1980         }
    1981 
    1982         mr_asprintf(tmp, AFIOBALL_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no - ARCH_BUFFER_NUM, bkpinfo->zip_suffix);
    1983         if (does_file_exist(tmp)) {
    1984             log_msg(4, "%s[%d:%d] - waiting for storer", FORTY_SPACES, getpid(), this_thread_no);
    1985             while (does_file_exist(tmp)) {
    1986                 sleep(1);
    1987             }
    1988             log_msg(4, "[%d] - continuing", getpid());
    1989         }
    1990         mr_free(tmp);
    1991 
    1992         log_msg(4, "%s[%d:%d] - EXATing %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
    1993 
    1994         if (g_getfattr) {
    1995             mr_asprintf(curr_xattr_list_fname, XATTR_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
    1996             get_fattr_list(archiving_filelist_fname, curr_xattr_list_fname);
    1997             mr_free(curr_xattr_list_fname);
    1998         }
    1999         if (g_getfacl) {
    2000             mr_asprintf(curr_acl_list_fname, ACL_LIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
    2001             get_acl_list(archiving_filelist_fname, curr_acl_list_fname);
    2002             mr_free(curr_acl_list_fname);
    2003         }
    2004 
    2005         log_msg(4, "%s[%d:%d] - archiving %d...", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
    2006         res = archive_this_fileset(archiving_filelist_fname, archiving_afioball_fname, archiving_set_no);
    2007         mr_free(archiving_afioball_fname);
    2008 
    2009         retval += res;
    2010 
    2011         if (res) {
    2012             log_to_screen("Errors occurred while archiving set %ld. Please review logs.", archiving_set_no);
    2013         }
    2014 
    2015         if (!semaphore_p()) {
    2016             mr_free(archiving_filelist_fname);
    2017             fatal_error("Cannot get semaphore P");
    2018         }
    2019 
    2020         set_bit_N_of_array(p_list_of_fileset_flags, archiving_set_no, 5);
    2021 
    2022         if (*p_last_set_archived < archiving_set_no) {
    2023             *p_last_set_archived = archiving_set_no;
    2024         }                       // finished archiving this one
    2025 
    2026         if (!semaphore_v()) {
    2027             mr_free(archiving_filelist_fname);
    2028             fatal_error("Cannot get semaphore V");
    2029         }
    2030         log_msg(4, "%s[%d:%d] - archived %d OK", FORTY_SPACES, getpid(), this_thread_no, archiving_set_no);
    2031         archiving_set_no++;
    2032 
    2033         mr_free(archiving_filelist_fname);
    2034         mr_asprintf(archiving_filelist_fname, FILELIST_FNAME_RAW_SZ, bkpinfo->tmpdir, archiving_set_no);
    2035     }
    2036     mr_free(archiving_filelist_fname);
    2037 
    2038     if (!semaphore_p()) {
    2039         fatal_error("Cannot get semaphore P");
    2040     }
    2041     (*p_archival_threads_running)--;
    2042     if (!semaphore_v()) {
    2043         fatal_error("Cannot get semaphore V");
    2044     }
    2045     log_msg(3, "%s[%d:%d] - exiting", FORTY_SPACES, getpid(), this_thread_no);
    2046     pthread_exit(NULL);
    2047 }
    2048 
    2049 
    2050 /**
    2051  * Get the <tt>N</tt>th bit of @c array.
    2052  * @param array The bit-array (as a @c char pointer).
    2053  * @param N The number of the bit you want.
    2054  * @return TRUE (bit is set) or FALSE (bit is not set).
    2055  * @see set_bit_N_of_array
    2056  * @ingroup utilityGroup
    2057  */
    2058 bool get_bit_N_of_array(char *array, int N)
    2059 {
    2060     int element_number;
    2061     int bit_number;
    2062     int mask;
    2063 
    2064     element_number = N / 8;
    2065     bit_number = N % 8;
    2066     mask = 1 << bit_number;
    2067     if (array[element_number] & mask) {
    2068         return (TRUE);
    2069     } else {
    2070         return (FALSE);
    2071     }
    2072 }
    2073 
    2074 
    2075 /**
    2076  * Move some files to the ISO scratch directory.
    2077  * This function moves files specified as parameters, into the directory
    2078  * @c bkpinfo->scratchdir, where the files that will be stored on the next
    2079  * CD are waiting.
    2080  *
    2081  * @param bkpinfo The backup information structure. Fields used:
    2082  * - @c media_size
    2083  * - @c scratchdir
    2084  * @param files_to_add The files to add to the scratchdir.
    2085  * @warning The list of @c files_to_add must be terminated with @c NULL.
    2086  * @note If and when the space occupied by the scratchdir would exceed
    2087  * the capacity of the current CD,
    2088  * <tt>write_iso_and_go_on(bkpinfo, FALSE)</tt> is called and the
    2089  * scratchdir is emptied.
    2090  *
    2091  * @return The number of errors encountered (0 for success)
    2092  */
    2093 int _move_files_to_cd(char *files_to_add, ...)
    2094 {
    2095 
    2096     /*@ int ************************************************************ */
    2097     int retval = 0;
    2098     int res = 0;
    2099 
    2100     /*@ buffers ******************************************************** */
    2101     char *tmp = NULL;
    2102     char *curr_file = NULL;
    2103     char *cf;
    2104 
    2105     /*@ long ************************************************************ */
    2106     va_list ap;
    2107     long long would_occupy;
    2108 
    2109     assert(bkpinfo != NULL);
    2110     would_occupy = space_occupied_by_cd(bkpinfo->scratchdir);
    2111     va_start(ap, files_to_add); // initialize the variable arguments
    2112     for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {
    2113         if (!cf) {
    2114             continue;
    2115         }
    2116         mr_asprintf(curr_file, "%s", cf);
    2117         if (!does_file_exist(curr_file)) {
    2118             log_msg(1, "Warning - you're trying to add a non-existent file - '%s' to the CD", curr_file);
    2119         } else {
    2120             log_msg(8, "Trying to add file %s to CD", curr_file);
    2121             would_occupy += length_of_file(curr_file) / 1024;
    2122         }
    2123         mr_free(curr_file);
    2124     }
    2125     va_end(ap);
    2126 
    2127     if (bkpinfo->media_size <= 0) {
    2128         fatal_error("move_files_to_cd() - unknown media size");
    2129     }
    2130     if (would_occupy / 1024 > bkpinfo->media_size) {
    2131         res = write_iso_and_go_on(FALSE);   /* FALSE because this is not the last CD we'll write */
    2132         retval += res;
    2133         if (res) {
    2134             log_msg(1, "WARNING - write_iso_and_go_on returned an error");
    2135         }
    2136     }
    2137 
    2138     va_start(ap, files_to_add); // initialize the variable arguments
    2139     for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {
    2140         if (!cf) {
    2141             continue;
    2142         }
    2143         mr_asprintf(curr_file, "%s", cf);
    2144 
    2145         mr_asprintf(tmp, "mv -f %s %s/archives/", curr_file, bkpinfo->scratchdir);
    2146         mr_free(curr_file);
    2147         res = run_program_and_log_output(tmp, 5);
    2148         retval += res;
    2149         if (res) {
    2150             log_msg(1, "(move_files_to_cd) '%s' failed", tmp);
    2151         } else {
    2152             log_msg(8, "Moved %s to CD OK", tmp);
    2153         }
    2154         mr_free(tmp);
    2155     }
    2156     va_end(ap);
    2157 
    2158     if (retval) {
    2159         log_msg(1,
    2160                 "Warning - errors occurred while I was adding files to CD dir");
    2161     }
    2162     return (retval);
    2163 }
    2164 
    2165 /* @} - end of LLarchiveGroup */
    2166 
    2167 /**
    2168  * Copy some files to tape.
    2169  * This function copies the files specified as parameters into the tape stream.
    2170  *
    2171  * @param bkpinfo The backup information structure. Used only in the call to
    2172  * @c write_file_to_stream_from_file().
    2173  *
    2174  * @param files_to_add The files to copy to the tape stream.
    2175  * @warning The list of @c files_to_add must be terminated with @c NULL.
    2176  * @note Files may be split across multiple tapes if necessary.
    2177  *
    2178  * @return The number of errors encountered (0 for success)
    2179  */
    2180 int
    2181 _move_files_to_stream(char *files_to_add, ...)
    2182 {
    2183 
    2184     /*@ int ************************************************************ */
    2185     int retval = 0;
    2186     int res = 0;
    2187     /*@ buffers ******************************************************** */
    2188 
    2189     /*@ char *********************************************************** */
    2190     char start_chr;
    2191     char stop_chr;
    2192     char *curr_file = NULL;
    2193     char *cf;
    2194     /*@ long long ****************************************************** */
    2195     off_t length_of_incoming_file = (off_t)0;
    2196     va_list ap;
    2197 
    2198     assert(bkpinfo != NULL);
    2199     va_start(ap, files_to_add);
    2200     for (cf = files_to_add; cf != NULL; cf = va_arg(ap, char *)) {
    2201         if (!cf) {
    2202             continue;
    2203         }
    2204         mr_asprintf(curr_file, "%s", cf);
    2205         if (!does_file_exist(curr_file)) {
    2206             log_msg(1,
    2207                     "Warning - you're trying to add a non-existent file - '%s' to the tape",
    2208                     curr_file);
    2209         }
    2210         /* create header chars */
    2211         start_chr = BLK_START_AN_AFIO_OR_SLICE;
    2212         stop_chr = BLK_STOP_AN_AFIO_OR_SLICE;
    2213         /* ask for new tape if necessary */
    2214         length_of_incoming_file = length_of_file(curr_file);
    2215         write_header_block_to_stream(length_of_incoming_file, curr_file, start_chr);
    2216         res = write_file_to_stream_from_file(curr_file);
    2217         retval += res;
    2218         unlink(curr_file);
    2219         mr_free(curr_file);
    2220         /* write closing header */
    2221         write_header_block_to_stream((off_t)0, "finished-writing-file", stop_chr);
    2222     }
    2223     va_end(ap);
    2224 
    2225     if (retval) {
    2226         log_msg(1,
    2227                 "Warning - errors occurred while I was adding file to tape");
    2228     }
    2229     return (retval);
    2230 }
    2231 
    2232 
    2233 /**
    2234  * @addtogroup LLarchiveGroup
    2235  * @{
    2236  */
    2237 /**
    2238  * Function pointer to an appropriate @c move_files_to_stream routine.
    2239  * You can set this to your own function (for example, one to
    2240  * transfer files over the network) or leave it as is.
    2241  */
    2242 int (*move_files_to_stream) (char *, ...) =
    2243     _move_files_to_stream;
    2244 
    2245 
    2246 /**
    2247  * Function pointer to an appropriate @c move_files_to_cd routine.
    2248  * You can set this to your own function (for example, one to
    2249  * transfer files over the network) or leave it as is.
    2250  */
    2251 int (*move_files_to_cd) (char *, ...) =
    2252     _move_files_to_cd;
    2253 
    2254 
    2255 
    2256 /**
    2257  * @addtogroup LLarchiveGroup
    2258  * @{
    2259  */
    2260 
    2261 void pause_for_N_seconds(int how_long, char *msg)
    2262 {
    2263     int i;
    2264     open_evalcall_form(msg);
    2265     for (i = 0; i < how_long; i++) {
    2266         update_evalcall_form((int) ((100.0 / (float) (how_long) * i)));
    2267         sleep(1);
    2268     }
    2269     close_evalcall_form();
    2270 }
    2271 
    2272 
    2273 
    2274 
    2275 /**
    2276  * Create a USB image in @c destfile, from files in @c bkpinfo->scratchdir.
    2277  *
    2278  * @param bkpinfo The backup information structure. Fields used:
    2279  * - @c backup_media_type
    2280  * - @c nonbootable_backup
    2281  * - @c scratchdir
    2282  *
    2283  * @param destfile Where to put the generated USB image.
    2284  * @return The number of errors encountered (0 for success)
    2285  */
    2286 int make_usb_fs()
    2287 {
    2288     /*@ int ********************************************** */
    2289     int retval = 0;
    2290     int res;
    2291 
    2292     /*@ buffers ****************************************** */
    2293     char *tmp = NULL;
    2294     char *tmp1 = NULL;
    2295     char *result_sz = NULL;
    2296     char *message_to_screen = NULL;
    2297     char *old_pwd = NULL;
    2298     char *mds = NULL;
    2299 
    2300     assert(bkpinfo != NULL);
    2301 
    2302     log_msg(2, "make_usb_fs --- scratchdir=%s", bkpinfo->scratchdir);
    2303     old_pwd = mr_getcwd();
    2304     mr_asprintf(tmp, "chmod 700 %s", bkpinfo->scratchdir);
    2305     run_program_and_log_output(tmp, FALSE);
    2306     mr_free(tmp);
    2307     if (chdir(bkpinfo->scratchdir)) {
    2308         // FIXME
    2309     }
    2310 
    2311     mds = media_descriptor_string(bkpinfo->backup_media_type);
    2312     mr_asprintf(message_to_screen, "Copying data to make %s #%d",mds, g_current_media_number);
    2313     mr_free(mds);
    2314     log_msg(1, message_to_screen);
    2315 
    2316     if (bkpinfo->media_device) {
    2317         mr_asprintf(tmp1, "%s1", bkpinfo->media_device);
    2318     } else {
    2319         mr_asprintf(tmp1, "");
    2320     }
    2321     if (is_this_device_mounted(tmp1)) {
    2322         log_msg(1, "USB device mounted. Remounting it at the right place");
    2323         mr_asprintf(tmp, "umount %s", tmp1);
    2324         run_program_and_log_output(tmp, FALSE);
    2325         mr_free(tmp);
    2326     }
    2327     mr_free(tmp1);
    2328 
    2329     log_msg(1, "Mounting USB device.");
    2330     mr_asprintf(tmp1, "%s/usb", bkpinfo->tmpdir);
    2331     mr_asprintf(tmp, "mkdir -p %s", tmp1);
    2332     run_program_and_log_output(tmp, FALSE);
    2333     mr_free(tmp);
    2334 
    2335 
    2336     /* Mindi always create one single parition on the USB dev */
    2337     mr_asprintf(tmp, "mount %s1 %s", bkpinfo->media_device, tmp1);
    2338     run_program_and_log_output(tmp, FALSE);
    2339     mr_free(tmp);
    2340 
    2341     if (bkpinfo->nonbootable_backup) {
    2342         log_msg(1, "Making nonbootable USB backup not implemented yet");
    2343     } else {
    2344         log_msg(1, "Making bootable backup");
    2345 
    2346         /* Command to execute */
    2347         mr_asprintf(tmp,"cd %s ; rm -fr %s/syslinux ; mv * %s", bkpinfo->scratchdir, tmp1, tmp1);
    2348         res = eval_call_to_make_USB(tmp, message_to_screen);
    2349         if (res) {
    2350             mr_asprintf(result_sz, "%s ...failed",tmp);
    2351         } else {
    2352             mr_asprintf(result_sz, "%s ...OK",tmp);
    2353         }
    2354         log_to_screen(result_sz);
    2355         mr_free(result_sz);
    2356         mr_free(tmp);
    2357         retval += res;
    2358 
    2359         /* Recreate the required structure under the scratch dir */
    2360         mr_asprintf(tmp,"mkdir %s/archive", bkpinfo->scratchdir);
    2361         run_program_and_log_output(tmp, FALSE);
    2362         mr_free(tmp);
    2363     }
    2364     paranoid_free(message_to_screen);
    2365 
    2366     /*  Copy the current logfile - of course incomplete to the media */
    2367     mr_system("gzip -c9 %s > %s/archives/%s", MONDO_LOGFILE, tmp1, MONDO_LOGFILENAME);
    2368     paranoid_free(tmp1);
    2369 
    2370     if (is_this_device_mounted(bkpinfo->media_device)) {
    2371         mr_asprintf(tmp, "umount %s1", bkpinfo->media_device);
    2372         run_program_and_log_output(tmp, FALSE);
    2373         mr_free(tmp);
    2374     }
    2375 
    2376     if (chdir(old_pwd)) {
    2377         // FIXME
    2378     }
    2379     mr_free(old_pwd);
    2380     if (retval) {
    2381         log_msg(1, "WARNING - make_usb_fs returned an error");
    2382     }
    2383     return(retval);
    2384 }
    2385 
    2386 /**
    2387  * Make sure the user has a valid CD-R(W) in the CD drive.
    2388  * @param cd_dev Set to the CD-R(W) device checked.
    2389  * @param keep_looping If TRUE, keep pestering user until they insist
    2390  * or insert a correct CD; if FALSE, only check once.
    2391  * @return 0 (there was an OK CD in the drive) or 1 (there wasn't).
    2392  */
    2393 int interrogate_disk_currently_in_cddrive(char *cd_dev,
    2394                                              bool keep_looping)
    2395 {
    2396     int res = 0;
    2397     char *bkp = NULL;
    2398     char *cdrecord = NULL;
    2399 
    2400     mr_asprintf(bkp, "%s", cd_dev);
    2401     if ((cd_dev = find_optical_device()) != NULL) {
    2402         if (!system("which cdrecord > /dev/null 2> /dev/null")) {
    2403             mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev);
    2404         } else if (!system("which dvdrecord > /dev/null 2> /dev/null")) {
    2405             mr_asprintf(cdrecord, "cdrecord dev=%s -atip", cd_dev);
    2406         } else {
    2407             log_msg(2, "Oh well. I guess I'll just pray then.");
    2408         }
    2409         if (cdrecord != NULL) {
    2410             if (!keep_looping) {
    2411                 retract_CD_tray_and_defeat_autorun();
    2412                 res = run_program_and_log_output(cdrecord, 5);
    2413             } else {
    2414                 while ((res = run_program_and_log_output(cdrecord, 5))) {
    2415                     retract_CD_tray_and_defeat_autorun();
    2416                     if (ask_me_yes_or_no
    2417                         ("Unable to examine CD. Are you sure this is a valid CD-R(W) CD?"))
    2418                     {
    2419                         log_msg(1, "Well, he insisted...");
    2420                         break;
    2421                     }
    2422                 }
    2423             }
    2424         }
    2425     }
    2426     mr_free(bkp);
    2427 
    2428     mr_free(cdrecord);
    2429     return (res);
    2430 }
    2431 
    2432 
    2433 /**
    2434  * Asks the user to put a CD-R(W) in the drive.
    2435  * @param ask_for_one_if_more_than_this (unused)
    2436  * @param pmountable If non-NULL, pointed-to value is set to TRUE if the CD is mountable, FALSE otherwise.
    2437  */
    2438 void pause_and_ask_for_cdr(int ask_for_one_if_more_than_this, bool * pmountable) {
    2439 
    2440     /*@ buffers ********************************************* */
    2441     char *tmp = NULL;
    2442     char *cdrom_dev = NULL;
    2443     char *cd_dev = NULL;
    2444     char *our_serial_str = NULL;
    2445     bool ok_go_ahead_burn_it;
    2446     int cd_number = -1;
    2447     int attempt_to_mount_returned_this = 999;
    2448     char *mtpt = NULL;
    2449     char *szcdno = NULL;
    2450     char *szserfname = NULL;
    2451     char *szunmount = NULL;
    2452     char *mds = NULL;
    2453 
    2454     malloc_string(cd_dev);
    2455 
    2456     mds = media_descriptor_string(g_backup_media_type);
    2457     log_to_screen("I am about to burn %s #%d", mds, g_current_media_number);
    2458     mr_free(mds);
    2459     if (g_current_media_number < ask_for_one_if_more_than_this) {
    2460         return;
    2461     }
    2462     log_to_screen("Scanning CD-ROM drive...");
    2463     mr_asprintf(mtpt, "%s/cd.mtpt", bkpinfo->tmpdir);
    2464     make_hole_for_dir(mtpt);
    2465 
    2466   gotos_make_me_puke:
    2467     ok_go_ahead_burn_it = TRUE;
    2468     mr_free(cdrom_dev);
    2469     if ((cdrom_dev = find_optical_device()) != NULL) {
    2470         /* When enabled, it made CD eject-and-retract when wrong CD inserted.. Weird
    2471         log_msg(2, "paafcd: Retracting CD-ROM drive if possible" );
    2472         retract_CD_tray_and_defeat_autorun();
    2473         */
    2474         mr_asprintf(tmp, "umount %s", cdrom_dev);
    2475         run_program_and_log_output(tmp, 1);
    2476         mr_asprintf(szcdno, "%s/archives/THIS-CD-NUMBER", mtpt);
    2477         mr_asprintf(szserfname, "%s/archives/SERIAL-STRING", mtpt);
    2478         mr_asprintf(szunmount, "umount %s", mtpt);
    2479         cd_number = -1;
    2480         mr_asprintf(tmp, "mount %s %s", cdrom_dev, mtpt);
    2481         mr_asprintf(our_serial_str, "%s", "");
    2482         attempt_to_mount_returned_this = run_program_and_log_output(tmp, 1);
    2483         mr_free(tmp);
    2484 
    2485         if (attempt_to_mount_returned_this) {
    2486             log_msg(4, "Failed to mount %s at %s", cdrom_dev, mtpt);
    2487             log_to_screen("If there's a CD/DVD in the drive, it's blank.");
    2488         } else if (!does_file_exist(szcdno) || !does_file_exist(szserfname)) {
    2489             mds = media_descriptor_string(g_backup_media_type);
    2490             log_to_screen("%s has data on it but it's probably not a Mondo CD.", mds);
    2491             mr_free(mds);
    2492         } else {
    2493             mds = media_descriptor_string(g_backup_media_type);
    2494             log_to_screen("%s found in drive. It's a Mondo disk.", mds);
    2495             mr_free(mds);
    2496 
    2497             cd_number = atoi(last_line_of_file(szcdno));
    2498             mr_asprintf(tmp, "cat %s 2> /dev/null", szserfname);
    2499             mr_free(our_serial_str);
    2500             our_serial_str = call_program_and_get_last_line_of_output(tmp);
    2501             mr_free(tmp);
    2502             // FIXME - should be able to use last_line_of_file(), surely?
    2503         }
    2504         mr_free(szcdno);
    2505         mr_free(szserfname);
    2506 
    2507         run_program_and_log_output(szunmount, 1);
    2508         mr_free(szunmount);
    2509 
    2510         log_msg(2, "paafcd: cd_number = %d", cd_number);
    2511         log_msg(2, "our serial str = %s; bkpinfo->serial_string = %s", our_serial_str, bkpinfo->serial_string);
    2512         if (cd_number > 0 && !strcmp(our_serial_str, bkpinfo->serial_string)) {
    2513             mds = media_descriptor_string(g_backup_media_type);
    2514             log_msg(2, "This %s is part of this backup set!", mds);
    2515             ok_go_ahead_burn_it = FALSE;
    2516             if (cd_number == g_current_media_number - 1) {
    2517                 log_to_screen("I think you've left the previous %s in the drive.", mds);
    2518             } else {
    2519                 log_to_screen("Please remove this %s. It is part of the backup set you're making now.", mds);
    2520             }
    2521             mr_free(mds);
    2522 
    2523         } else {
    2524             log_to_screen("...but not part of _our_ backup set.");
    2525         }
    2526         mr_free(our_serial_str);
    2527     } else {
    2528         mds = media_descriptor_string(g_backup_media_type);
    2529         log_msg(2,
    2530                 "paafcd: Can't find CD-ROM drive. Perhaps it has a blank %s in it?", mds);
    2531         if (interrogate_disk_currently_in_cddrive(cd_dev, FALSE)) {
    2532             ok_go_ahead_burn_it = FALSE;
    2533             log_to_screen("There isn't a writable %s in the drive.", mds);
    2534         }
    2535         mr_free(mds);
    2536     }
    2537 
    2538     if (!ok_go_ahead_burn_it) {
    2539         if (!bkpinfo->please_dont_eject) {
    2540             eject_device(cdrom_dev);
    2541         }
    2542         mds = media_descriptor_string(g_backup_media_type);
    2543         mr_asprintf(tmp, "I am about to burn %s #%d of the backup set. Please insert %s and press Enter.", mds, g_current_media_number, mds);
    2544         mr_free(mds);
    2545 
    2546         popup_and_OK(tmp);
    2547         mr_free(tmp);
    2548         goto gotos_make_me_puke;
    2549     } else {
    2550         log_msg(2, "paafcd: OK, going ahead and burning it.");
    2551     }
    2552 
    2553     mds = media_descriptor_string(g_backup_media_type);
    2554     log_msg(2, "paafcd: OK, I assume I have a blank/reusable %s in the drive...", mds);
    2555 
    2556     log_to_screen("Proceeding w/ %s in drive.", mds);
    2557     mr_free(mds);
    2558 
    2559     mr_free(cdrom_dev);
    2560     paranoid_free(cd_dev);
    2561     mr_free(mtpt);
    2562     if (pmountable) {
    2563         if (attempt_to_mount_returned_this) {
    2564             *pmountable = FALSE;
    2565         } else {
    2566             *pmountable = TRUE;
    2567         }
    2568     }
    2569 
    2570 }
    2571 
    2572 
    2573 /**
    2574  * Create an ISO image in @c destfile, from files in @c bkpinfo->scratchdir.
    2575  *
    2576  * @param bkpinfo The backup information structure. Fields used:
    2577  * - @c backup_media_type
    2578  * - @c call_after_iso
    2579  * - @c call_before_iso
    2580  * - @c call_burn_iso
    2581  * - @c call_make_iso
    2582  * - @c make_cd_use_lilo
    2583  * - @c manual_cd_tray
    2584  * - @c nonbootable_backup
    2585  * - @c scratchdir
    2586  *
    2587  * @param destfile Where to put the generated ISO image.
    2588  * @return The number of errors encountered (0 for success)
    2589  */
    2590 int make_iso_fs(char *destfile) {
    2591     /*@ int ********************************************** */
    2592     int retval = 0;
    2593     int res;
    2594 
    2595     /*@ buffers ****************************************** */
    2596     char *tmp = NULL;
    2597     char *old_pwd = NULL;
    2598     char *result_sz = NULL;
    2599     char *message_to_screen = NULL;
    2600     char *sz_blank_disk = NULL;
    2601     char *isofs_cmd = NULL;
    2602     char *full_isofs_cmd = NULL;
    2603     char *mds = NULL;
    2604     char *uefistr = NULL;
    2605     bool cd_is_mountable;
    2606 
    2607     assert(bkpinfo != NULL);
    2608     assert_string_is_neither_NULL_nor_zerolength(destfile);
    2609 
    2610     if (bkpinfo->backup_media_type == iso && bkpinfo->manual_cd_tray) {
    2611         popup_and_OK("Please insert new media and press Enter.");
    2612     }
    2613 
    2614     log_msg(2, "make_iso_fs --- scratchdir=%s --- destfile=%s", bkpinfo->scratchdir, destfile);
    2615     old_pwd = mr_getcwd();
    2616     mr_asprintf(tmp, "chmod 700 %s", bkpinfo->scratchdir);
    2617     run_program_and_log_output(tmp, FALSE);
    2618     mr_free(tmp);
    2619 
    2620     if (chdir(bkpinfo->scratchdir)) {
    2621         // FIXME
    2622     }
    2623 
    2624     if (bkpinfo->call_before_iso != NULL) {
    2625         mr_asprintf(message_to_screen, "Running pre-ISO call for CD#%d", g_current_media_number);
    2626         res = eval_call_to_make_ISO(bkpinfo->call_before_iso, destfile, g_current_media_number, message_to_screen);
    2627         if (res) {
    2628             mr_strcat(message_to_screen, "...failed");
    2629         } else {
    2630             mr_strcat(message_to_screen, "...OK");
    2631         }
    2632         log_to_screen(message_to_screen);
    2633         paranoid_free(message_to_screen);
    2634 
    2635         retval += res;
    2636     }
    2637 
    2638     if (bkpinfo->call_make_iso != NULL) {
    2639         log_msg(2, "bkpinfo->call_make_iso = %s", bkpinfo->call_make_iso);
    2640         mds = media_descriptor_string(bkpinfo->backup_media_type);
    2641         mr_asprintf(message_to_screen, "Making an ISO (%s #%d)", mds, g_current_media_number);
    2642         mr_free(mds);
    2643 
    2644         pause_and_ask_for_cdr(2, &cd_is_mountable); /* if g_current_media_number >= 2 then pause & ask */
    2645         if (retval) {
    2646             log_to_screen
    2647                 ("Serious error(s) occurred already. I shan't try to write to media.");
    2648         } else {
    2649             res =
    2650                 eval_call_to_make_ISO(bkpinfo->call_make_iso, bkpinfo->scratchdir, g_current_media_number, message_to_screen);
    2651             if (res) {
    2652                 log_to_screen("%s...failed to write", message_to_screen);
    2653             } else {
    2654                 log_to_screen("%s...OK", message_to_screen);
    2655                 mr_asprintf(tmp, "tail -n10 %s | grep -F ':-('", MONDO_LOGFILE);
    2656                 if (!run_program_and_log_output(tmp, 1)) {
    2657                     log_to_screen
    2658                         ("Despite nonfatal errors, growisofs confirms the write was successful.");
    2659                 }
    2660                 mr_free(tmp);
    2661             }
    2662             retval += res;
    2663 #ifdef DVDRWFORMAT
    2664             mr_asprintf(tmp, "tail -n8 %s | grep 'blank=full.*dvd-compat.*DAO'", MONDO_LOGFILE);
    2665             if (g_backup_media_type == dvd
    2666                 && (res || !run_program_and_log_output(tmp, 1))) {
    2667                 log_to_screen
    2668                     ("Failed to write to disk. I shall blank it and then try again.");
    2669                 sleep(5);
    2670                 /* reset error counter before trying to blank DVD */
    2671                 retval -= res;
    2672                 sync();
    2673                 pause_for_N_seconds(5, "Letting DVD drive settle");
    2674 
    2675 // dvd+rw-format --- OPTION 2
    2676                 if (!bkpinfo->please_dont_eject) {
    2677                     log_to_screen("Ejecting media to clear drive status.");
    2678                     eject_device(bkpinfo->media_device);
    2679                     inject_device(bkpinfo->media_device);
    2680                 }
    2681                 pause_for_N_seconds(5, "Letting DVD drive settle");
    2682                 if (bkpinfo->media_device) {
    2683                     mr_asprintf(sz_blank_disk, "dvd+rw-format -force %s", bkpinfo->media_device);
    2684                 } else {
    2685                     mr_asprintf(sz_blank_disk, "dvd+rw-format");
    2686                 }
    2687                 log_msg(3, "sz_blank_disk = '%s'", sz_blank_disk);
    2688                 res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);
    2689                 if (res) {
    2690                     log_to_screen("Warning - format failed. (Was it a DVD-R?) Sleeping for 5 seconds to take a breath...");
    2691                     pause_for_N_seconds(5, "Letting DVD drive settle... and trying again.");
    2692                     res = run_external_binary_with_percentage_indicator_NEW("Blanking DVD disk", sz_blank_disk);
    2693                     if (res) {
    2694                         log_to_screen("Format failed a second time.");
    2695                     }
    2696                 } else {
    2697                     log_to_screen
    2698                         ("Format succeeded. Sleeping for 5 seconds to take a breath...");
    2699                 }
    2700                 mr_free(sz_blank_disk);
    2701                 pause_for_N_seconds(5, "Letting DVD drive settle");
    2702                 if (!bkpinfo->please_dont_eject) {
    2703                     log_to_screen("Ejecting media to clear drive status.");
    2704                     eject_device(bkpinfo->media_device);
    2705                     inject_device(bkpinfo->media_device);
    2706                 }
    2707                 pause_for_N_seconds(5, "Letting DVD drive settle");
    2708                 res = eval_call_to_make_ISO(bkpinfo->call_make_iso, bkpinfo->scratchdir, g_current_media_number, message_to_screen);
    2709                 retval += res;
    2710                 if (!bkpinfo->please_dont_eject) {
    2711                     log_to_screen("Ejecting media.");
    2712                     eject_device(bkpinfo->media_device);
    2713                 }
    2714                 if (res) {
    2715                     log_to_screen("Dagnabbit. It still failed.");
    2716                 } else {
    2717                     log_to_screen
    2718                         ("OK, this time I successfully backed up to DVD.");
    2719                 }
    2720             }
    2721             mr_free(tmp);
    2722 #endif
    2723             if (g_backup_media_type == dvd && !bkpinfo->please_dont_eject) {
    2724                 eject_device(bkpinfo->media_device);
    2725             }
    2726         }
    2727         paranoid_free(message_to_screen);
    2728     } else {
    2729         mds = media_descriptor_string(bkpinfo->backup_media_type);
    2730         mr_asprintf(message_to_screen, "Running mkisofs to make %s #%d", mds, g_current_media_number);
    2731         log_msg(1, message_to_screen);
    2732         mr_asprintf(result_sz, "Call to mkisofs to make ISO (%s #%d) ", mds,  g_current_media_number);
    2733         mr_free(mds);
    2734         if ((tmp = find_home_of_exe("xorriso")) != NULL) {
    2735             mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_XORRISO_OPT);
    2736         } else if ((tmp = find_home_of_exe("genisoimage")) != NULL) {
    2737             mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_GENISOIMAGE_OPT);
    2738         } else if ((tmp = find_home_of_exe("mkisofs")) != NULL) {
    2739             mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_MKISOFS_OPT);
    2740         } else if ((tmp = find_home_of_exe("wodim")) != NULL) {
    2741             mr_asprintf(isofs_cmd, "%s %s", tmp, MONDO_WODIM_OPT);
    2742         } else {
    2743             fatal_error("Unable to find a command to create ISO among xorriso, genisoimage, mksiofs or wodim, please install one");
    2744         }
    2745         mr_free(tmp);
    2746         if (bkpinfo->nonbootable_backup) {
    2747             log_msg(1, "Making nonbootable backup");
    2748             mr_asprintf(full_isofs_cmd, "%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS);
    2749             res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);
    2750             mr_free(full_isofs_cmd);
    2751         } else {
    2752             log_msg(1, "Making bootable backup");
    2753 
    2754 #ifdef __FreeBSD__
    2755             bkpinfo->make_cd_use_lilo = TRUE;
    2756 #endif
    2757 
    2758 
    2759             log_msg(1, "make_cd_use_lilo is actually %d", bkpinfo->make_cd_use_lilo);
    2760             if (bkpinfo->make_cd_use_lilo) {
    2761                 log_msg(1, "make_cd_use_lilo = TRUE");
    2762 #ifdef __IA64__
    2763                 log_msg(1, "IA64 --> elilo");
    2764                 mr_asprintf(full_isofs_cmd, "%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS_REGULAR_ELILO);
    2765                 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);
    2766                 mr_free(full_isofs_cmd);
    2767 #else
    2768                 log_msg(1, "Non-ia64 --> lilo");
    2769                 mr_asprintf(full_isofs_cmd, "%s%s-b images/mindi-bootroot.img -c images/boot.cat -o '_ISO_' .",isofs_cmd,MONDO_MKISOFS);
    2770                 // FIXME: fixed boot size probably wrong. lilo to be removed
    2771                 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);
    2772                 mr_free(full_isofs_cmd);
    2773 #endif
    2774             } else {
    2775                 log_msg(1, "make_cd_use_lilo = FALSE");
    2776                 log_msg(1, "Isolinux");
    2777                 if (bkpinfo->boot_type == UEFI) {
    2778                     if (strstr(isofs_cmd,"xorriso")) {
    2779                         /*  xorriso needs another '-' before efi-boot */
    2780                         mr_asprintf(uefistr, "%s -%s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI);
    2781                     } else {
    2782                         mr_asprintf(uefistr, "%s %s", MONDO_UEFI_PREFIX, MONDO_MKISOFS_UEFI);
    2783                     }
    2784                 } else {
    2785                     mr_asprintf(uefistr, "%s",MONDO_MKISOFS_CMS);
    2786                 }
    2787                 mr_asprintf(full_isofs_cmd, "%s%s%s-o '_ISO_' .",isofs_cmd,MONDO_MKISOFS_REGULAR_SYSLINUX,uefistr);
    2788                 mr_free(uefistr);
    2789 
    2790                 res = eval_call_to_make_ISO(full_isofs_cmd, destfile, g_current_media_number, message_to_screen);
    2791                 mr_free(full_isofs_cmd);
    2792             }
    2793         }
    2794         mr_free(isofs_cmd);
    2795         paranoid_free(message_to_screen);
    2796 
    2797         if (res) {
    2798             mr_strcat(result_sz, "...failed");
    2799         } else {
    2800             mr_strcat(result_sz, "...OK");
    2801         }
    2802         log_to_screen(result_sz);
    2803         paranoid_free(result_sz);
    2804         retval += res;
    2805     }
    2806 
    2807     if (bkpinfo->backup_media_type == cdr) {
    2808         if (is_this_device_mounted(bkpinfo->media_device)) {
    2809             log_msg(2, "Warning - %s mounted. I'm unmounting it before I burn to it.", bkpinfo->media_device);
    2810             mr_asprintf(tmp, "umount %s", bkpinfo->media_device);
    2811             run_program_and_log_output(tmp, FALSE);
    2812             mr_free(tmp);
    2813         }
    2814     }
    2815 
    2816     if (bkpinfo->call_burn_iso != NULL) {
    2817         log_msg(2, "bkpinfo->call_burn_iso = %s", bkpinfo->call_burn_iso);
    2818         mds = media_descriptor_string(bkpinfo->backup_media_type);
    2819         mr_asprintf(message_to_screen, "Burning %s #%d", mds, g_current_media_number);
    2820         mr_free(mds);
    2821         pause_and_ask_for_cdr(2, &cd_is_mountable);
    2822         res = eval_call_to_make_ISO(bkpinfo->call_burn_iso, destfile, g_current_media_number, message_to_screen);
    2823         if (res) {
    2824             mr_strcat(message_to_screen, "...failed");
    2825         } else {
    2826             mr_strcat(message_to_screen, "...OK");
    2827         }
    2828         log_to_screen(message_to_screen);
    2829         paranoid_free(message_to_screen);
    2830 
    2831         retval += res;
    2832     }
    2833 
    2834     if (bkpinfo->call_after_iso != NULL) {
    2835         mds = media_descriptor_string(bkpinfo->backup_media_type);
    2836         mr_asprintf(message_to_screen, "Running post-ISO call (%s #%d)", mds, g_current_media_number);
    2837         mr_free(mds);
    2838         res = eval_call_to_make_ISO(bkpinfo->call_after_iso, destfile, g_current_media_number, message_to_screen);
    2839         if (res) {
    2840             mr_strcat(message_to_screen, "...failed");
    2841         } else {
    2842             mr_strcat(message_to_screen, "...OK");
    2843         }
    2844         log_to_screen(message_to_screen);
    2845         paranoid_free(message_to_screen);
    2846 
    2847         retval += res;
    2848     }
    2849 
    2850     if (chdir(old_pwd)) {
    2851         // FIXME
    2852     }
    2853     mr_free(old_pwd);
    2854     if (retval) {
    2855         log_msg(1, "WARNING - make_iso_fs returned an error");
    2856     }
    2857     return (retval);
    2858 }
    2859 
    2860 
    2861 bool is_dev_an_NTFS_dev(char *bigfile_fname)
    2862 {
    2863     char *tmp = NULL;
    2864     char *command = NULL;
    2865     bool ret = TRUE;
    2866 
    2867     mr_asprintf(command, "dd if=%s bs=512 count=1 2> /dev/null | strings | head -n1", bigfile_fname);
    2868     log_msg(1, "command = '%s'", command);
    2869     tmp = call_program_and_get_last_line_of_output(command);
    2870     mr_free(command);
    2871 
    2872     log_msg(1, "--> tmp = '%s'", tmp);
    2873     if (strstr(tmp, "NTFS")) {
    2874         log_it("TRUE");
    2875         ret = TRUE;
    2876     } else {
    2877         log_it("FALSE");
    2878         ret = FALSE;
    2879     }
    2880     mr_free(tmp);
    2881     return(ret);
    2882 }
    2883 
    2884 
    2885 /**
    2886  * Chop up @c filename.
    2887  * @param bkpinfo The backup information structure. Fields used:
    2888  * - @c backup_media_type
    2889  * - @c compression_level
    2890  * - @c optimal_set_size
    2891  * - @c tmpdir
    2892  * - @c use_lzo
    2893  * - @c zip_exe
    2894  * - @c zip_suffix
    2895  *
    2896  * @param biggie_filename The file to chop up.
    2897  * @param ntfsprog_fifo The FIFO to ntfsclone if this is an imagedev, NULL otherwise.
    2898  * @param biggie_file_number The sequence number of this biggie file (starting from 0).
    2899  * @param noof_biggie_files The number of biggie files there are total.
    2900  * @return The number of errors encountered (0 for success)
    2901  * @see make_slices_and_images
    2902  * @ingroup LLarchiveGroup
    2903  */
    2904 int slice_up_file_etc(char *biggie_filename, char *ntfsprog_fifo, long biggie_file_number, long noof_biggie_files, bool use_ntfsprog) {
    2905 
    2906     /*@ buffers ************************************************** */
    2907     char *tmp = NULL;
    2908     char *checksum_line = NULL;
    2909     char *command = NULL;
    2910     char *tempblock = NULL;
    2911     char *curr_slice_fname_uncompressed = NULL;
    2912     char *curr_slice_fname_compressed = NULL;
    2913     char *file_to_archive = NULL;
    2914     char *file_to_openin = NULL;
    2915     /*@ pointers ************************************************** */
    2916     char *pB = NULL;
    2917     FILE *fin = NULL;
    2918     FILE *fout = NULL;
    2919 
    2920     /*@ bool ****************************************************** */
    2921     bool finished = FALSE;
    2922 
    2923     /*@ long ****************************************************** */
    2924     size_t blksize = (size_t)0;
    2925     long slice_num = 0L;
    2926     long i = 0L;
    2927     bool should_I_compress_slices = TRUE;
    2928     char *suffix = NULL;                // for compressed slices
    2929 
    2930     /*@ long long ************************************************** */
    2931     off_t totalread = (off_t)0;
    2932     off_t totallength = (off_t)0;
    2933 
    2934     /*@ int ******************************************************** */
    2935     int retval = 0;
    2936     int res = 0;
    2937 
    2938     /*@ structures ************************************************** */
    2939     struct s_filename_and_lstat_info biggiestruct;
    2940 
    2941     assert(bkpinfo != NULL);
    2942     assert_string_is_neither_NULL_nor_zerolength(biggie_filename);
    2943 
    2944     biggiestruct.for_backward_compatibility = '\n';
    2945     biggiestruct.use_ntfsprog = use_ntfsprog;
    2946     if (is_this_file_compressed(biggie_filename) || bkpinfo->compression_level == 0) {
    2947         mr_asprintf(suffix, "%s", "");
    2948         should_I_compress_slices = FALSE;
    2949     } else {
    2950         mr_asprintf(suffix, "%s", bkpinfo->zip_suffix);
    2951         should_I_compress_slices = TRUE;
    2952     }
    2953 
    2954     if (bkpinfo->optimal_set_size < 999L) {
    2955         fatal_error("bkpinfo->optimal_set_size is insanely small");
    2956     }
    2957 
    2958     if (ntfsprog_fifo) {
    2959         file_to_openin = ntfsprog_fifo;
    2960         mr_asprintf(checksum_line, "IGNORE");
    2961         log_msg(2, "Not calculating checksum for %s: it would take too long", biggie_filename);
    2962         if ((tmp = find_home_of_exe("ntfsresize")) == NULL) {
    2963             fatal_error("ntfsresize not found");
    2964         }
    2965         mr_asprintf(command, "%s --force --info %s|grep '^You might resize at '|cut -d' ' -f5", tmp, biggie_filename);
    2966         mr_free(tmp);
    2967         log_it("command = %s", command);
    2968         tmp = call_program_and_get_last_line_of_output(command);
    2969         mr_free(command);
    2970         log_it("res of it = %s", tmp);
    2971         totallength = (off_t)atoll(tmp);
    2972         mr_free(tmp);
    2973     } else {
    2974         file_to_openin = biggie_filename;
    2975         if (strchr(biggie_filename,'\'') != NULL) {
    2976             mr_asprintf(command, "md5sum \"%s\"", biggie_filename);
    2977         } else {
    2978             mr_asprintf(command, "md5sum '%s'", biggie_filename);
    2979         }
    2980         if (!(fin = popen(command, "r"))) {
    2981             log_OS_error("Unable to popen-in command");
    2982             mr_free(suffix);
    2983             return (1);
    2984         }
    2985         mr_free(command);
    2986         mr_getline(checksum_line, fin);
    2987         pclose(fin);
    2988         totallength = length_of_file(biggie_filename);
    2989     }
    2990     lstat(biggie_filename, &biggiestruct.properties);
    2991     strcpy(biggiestruct.filename, biggie_filename);
    2992     pB = strchr(checksum_line, ' ');
    2993     if (!pB) {
    2994         pB = strchr(checksum_line, '\t');
    2995     }
    2996     if (pB) {
    2997         *pB = '\0';
    2998     }
    2999     strcpy(biggiestruct.checksum, checksum_line);
    3000     mr_free(checksum_line);
    3001 
    3002     mr_asprintf(tmp, "%s", slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""));
    3003     fout = fopen(tmp, "w");
    3004     if (fout == NULL) {
    3005         log_msg(1, "Unable to open and write to %s", tmp);
    3006         mr_free(tmp);
    3007         mr_free(suffix);
    3008         return (1);
    3009     }
    3010     res = fwrite((void *) &biggiestruct, 1, sizeof(biggiestruct), fout);
    3011     paranoid_fclose(fout);
    3012     mr_free(tmp);
    3013 
    3014     log_msg(1, "Opening in %s; slicing it and writing to CD/tape", file_to_openin);
    3015     if (!(fin = fopen(file_to_openin, "r"))) {
    3016         log_OS_error("Unable to openin biggie_filename");
    3017         log_to_screen("Cannot archive bigfile '%s': not found", biggie_filename);
    3018 
    3019         mr_free(suffix);
    3020         return (1);
    3021     }
    3022     if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    3023         res = move_files_to_stream(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);
    3024     } else {
    3025         res = move_files_to_cd(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);
    3026     }
    3027     i = bkpinfo->optimal_set_size / 256L;
    3028     if (!(tempblock = (char *) malloc(256 * 1024))) {
    3029         fatal_error("malloc error 256*1024");
    3030     }
    3031     for (slice_num = 1; !finished; slice_num++) {
    3032         mr_asprintf(curr_slice_fname_uncompressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, ""));
    3033         mr_asprintf(curr_slice_fname_compressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, suffix));
    3034 
    3035         tmp = percent_media_full_comment();
    3036         update_progress_form(tmp);
    3037         mr_free(tmp);
    3038 
    3039         if (!(fout = fopen(curr_slice_fname_uncompressed, "w"))) {
    3040             log_OS_error(curr_slice_fname_uncompressed);
    3041             mr_free(suffix);
    3042             return (1);
    3043         }
    3044         if ((i == bkpinfo->optimal_set_size / 256L) && (totalread < (off_t)1.1 * totallength)) {
    3045             for (i = 0L; i < (bkpinfo->optimal_set_size / 256L); i++) {
    3046                 blksize = fread(tempblock, 1, 256 * 1024, fin);
    3047                 if (blksize > (size_t)0) {
    3048                     totalread = totalread + (off_t)blksize;
    3049                     res = fwrite(tempblock, 1, blksize, fout);
    3050                 } else {
    3051                     break;
    3052                 }
    3053             }
    3054         } else {
    3055             i = 0L;
    3056         }
    3057         paranoid_fclose(fout);
    3058         if (i > 0L)             // length_of_file (curr_slice_fname_uncompressed)
    3059         {
    3060             if (!does_file_exist(curr_slice_fname_uncompressed)) {
    3061                 log_msg(2, "Warning - '%s' doesn't exist. How can I compress slice?", curr_slice_fname_uncompressed);
    3062             }
    3063             if (should_I_compress_slices && bkpinfo->compression_level > 0) {
    3064                 mr_asprintf(command, "%s -%d %s", bkpinfo->zip_exe, bkpinfo->compression_level, curr_slice_fname_uncompressed);
    3065                 log_msg(2, command);
    3066                 if ((res = system(command))) {
    3067                     log_OS_error(command);
    3068                 }
    3069                 //          did_I_compress_slice = TRUE;
    3070             } else {
    3071                 mr_asprintf(command, "mv %s %s 2>> %s", curr_slice_fname_uncompressed, curr_slice_fname_compressed, MONDO_LOGFILE);
    3072                 res = 0;        // don't do it :)
    3073                 //          did_I_compress_slice = FALSE;
    3074             }
    3075             mr_free(command);
    3076 
    3077             retval += res;
    3078             if (res) {
    3079                 log_msg(2, "Failed to compress the slice");
    3080             }
    3081             if (bkpinfo->use_lzo && strcmp(curr_slice_fname_compressed, curr_slice_fname_uncompressed)) {
    3082                 unlink(curr_slice_fname_uncompressed);
    3083             }
    3084             if (res) {
    3085                 mr_asprintf(tmp, "Problem with slice # %ld", slice_num);
    3086             } else {
    3087                 mr_asprintf(tmp, "%s - Bigfile #%ld, slice #%ld compressed OK          ", biggie_filename, biggie_file_number + 1, slice_num);
    3088             }
    3089             if (!g_text_mode) {
    3090                 newtDrawRootText(0, g_noof_rows - 2, tmp);
    3091                 newtRefresh();
    3092             } else {
    3093                 log_msg(2, tmp);
    3094             }
    3095             mr_free(tmp);
    3096 
    3097             mr_asprintf(file_to_archive, "%s", curr_slice_fname_compressed);
    3098             g_current_progress++;
    3099         } else {                /* if i==0 then ... */
    3100             finished = TRUE;
    3101             mr_asprintf(file_to_archive, "%s", curr_slice_fname_uncompressed);
    3102             if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    3103                 break;
    3104             }
    3105         }
    3106         mr_free(curr_slice_fname_uncompressed);
    3107         mr_free(curr_slice_fname_compressed);
    3108 
    3109         if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    3110             register_in_tape_catalog(biggieslice, biggie_file_number, slice_num, file_to_archive);
    3111             maintain_collection_of_recent_archives(bkpinfo->tmpdir, file_to_archive);
    3112             res = move_files_to_stream(file_to_archive, NULL);
    3113         } else {
    3114             res = move_files_to_cd(file_to_archive, NULL);
    3115         }
    3116         mr_free(file_to_archive);
    3117 
    3118         retval += res;
    3119         if (res) {
    3120             log_to_screen("Failed to add slice %ld of bigfile %ld to scratchdir", slice_num, biggie_file_number + 1);
    3121             fatal_error("Hard disk full. You should have bought a bigger one.");
    3122         }
    3123     }
    3124     mr_free(tempblock);
    3125     mr_free(suffix);
    3126     paranoid_fclose(fin);
    3127     mr_asprintf(tmp, "Sliced bigfile #%ld", biggie_file_number + 1);
    3128     if (retval) {
    3129         mr_strcat(tmp, "...FAILED");
    3130     } else {
    3131         mr_strcat(tmp, "...OK!");
    3132     }
    3133     log_msg(1, tmp);
    3134     mr_free(tmp);
    3135 
    3136     return (retval);
    3137 }
    3138 
    3139 
    31403138/* @} - end of LLarchiveGroup */
    31413139
Note: See TracChangeset for help on using the changeset viewer.