Changeset 3879 in MondoRescue


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

Fix all remaining compiler errors

Location:
branches/3.3/mondo
Files:
8 deleted
24 edited

Legend:

Unmodified
Added
Removed
  • branches/3.3/mondo/bootstrap

    r3412 r3879  
    3030libtoolize -f -c --automake
    3131aclocal
    32 autoheader
     32#autoheader # to be used with AC_CONFIG_HEADER
    3333rm -f missing
    3434automake --add-missing --copy
  • branches/3.3/mondo/configure.ac

    r3848 r3879  
    1313AC_CONFIG_SRCDIR([src/mondoarchive/mondoarchive.c])
    1414AC_CONFIG_MACRO_DIR([m4])
    15 AC_CONFIG_HEADERS([config.h])
    1615
    17 AC_PREREQ([2.63])
     16AC_PREREQ([2.71])
    1817AC_CANONICAL_HOST
    1918AC_CANONICAL_TARGET
     
    7473        GCC_MAJ="`gcc -dumpversion 2>&1 | cut -d. -f1`"
    7574        GCC_MIN="`gcc -dumpversion 2>&1 | cut -d. -f2`"
    76         CFLAGS="$CFLAGS -Wall -Wextra -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wconversion -Wno-return-type -Wformat=2 -Werror=implicit-function-declaration -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -D_FORTIFY_SOURCE=2 -fstack-clash-protection -fstack-protector-strong -fcf-protection -fsanitize=undefined -Wl,-z,defs -Wl,-z,now -Wl,-z,relro" # -Wstrict-prototypes -Werror"
     75
     76        # Just test for dev machine on x86_64 ubsan used for option -fsanitize=undefined
     77        if [ -f /usr/lib64/libubsan.so ]; then
     78            CFLAGS="$CFLAGS -fsanitize=undefined"
     79            HAVE_UBSAN=1
     80        else
     81            HAVE_UBSAN=0
     82        fi
     83
     84        # Just test for dev machine on x86_64 asan used for option -fsanitize=address
     85        if [ -f /usr/lib64/libasan.so ]; then
     86            CFLAGS="$CFLAGS -fsanitize=address"
     87            HAVE_ASAN=1
     88        else
     89            HAVE_ASAN=0
     90        fi
     91
     92        CFLAGS="$CFLAGS -Wall -Wextra -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wno-return-type -Wformat=2 -Werror=implicit-function-declaration -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -D_FORTIFY_SOURCE=2 -fstack-clash-protection -fstack-protector-strong -fcf-protection -Wl,-z,defs -Wl,-z,now -Wl,-z,relro -Wno-discarded-qualifiers" # -Wconversion -Wstrict-prototypes -Werror"
    7793        ;;
    7894    *)
     
    103119
    104120# Checks for header files.
    105 AC_HEADER_STDC
     121AC_CHECK_INCLUDES_DEFAULT
     122AC_PROG_EGREP
     123
    106124AC_HEADER_SYS_WAIT
    107125AC_HEADER_STDBOOL
  • 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
  • branches/3.3/mondo/src/common/libmondo-cli.c

    r3875 r3879  
    1515#include "mr_str.h"
    1616#include "mondostructures.h"
    17 #include "libmondo-cli-EXT.h"
     17#include "libmondo-string-EXT.h"
     18#include "libmondo-files-EXT.h"
     19#include "libmondo-stream-EXT.h"
     20#include "libmondo-devices-EXT.h"
     21#include "libmondo-fork-EXT.h"
     22#include "libmondo-fifo-EXT.h"
    1823#include "newt-specific-EXT.h"
    19 #include "libmondo.h"
    2024
    2125extern int g_loglevel;
     
    6165
    6266long g_max_biggie_size = BIGGIEMAXSIZE;
    63 
    64 /**
    65  * @addtogroup cliGroup
    66  * @{
    67  */
    68 /**
    69  * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv.
    70  * @param argc The argument count, including the program name; @p argc passed to main().
    71  * @param argv The argument vector; @p argv passed to main().
    72  * @param bkpinfo The backup information structure to populate.
    73  * @return The number of problems with the command line (0 for success).
    74  */
    75 int
    76 handle_incoming_parameters(int argc, char *argv[])
    77 {
    78     /*@ int *** */
    79     int res = 0;
    80     int retval = 0;
    81     int i = 0;
    82 
    83     /*@ buffers *************** */
    84     char flag_val[128][MAX_STR_LEN];
    85     bool flag_set[128];
    86 
    87     for (i = 0; i < 128; i++) {
    88         flag_val[i][0] = '\0';
    89         flag_set[i] = FALSE;
    90     }
    91     bkpinfo->media_size = 650; /* default */
    92     res = retrieve_switches_from_command_line(argc, argv, flag_val, flag_set);
    93     retval += res;
    94     if (!retval) {
    95         res = process_switches(flag_val, flag_set);
    96         retval += res;
    97     }
    98 
    99     log_msg(3, "Switches:-");
    100     for (i = 0; i < 128; i++) {
    101         if (flag_set[i]) {
    102             log_msg(3, "-%c %s", i, flag_val[i]);
    103         }
    104     }
    105     bkpinfo->boot_type = mr_boot_type();
    106 
    107     return (retval);
    108 }
    10967
    11068
     
    13189}
    13290
     91
    13392/**
    134  * Process mondoarchive's command-line switches.
    135  * @param bkpinfo The backup information structure to populate.
    136  * @param flag_val An array of the argument passed to each switch (the letter is the index).
    137  * If a switch is not set or has no argument, the field in @p flag_val doesn't matter.
    138  * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set,
    139  * FALSE if it's not.
    140  * @return The number of problems with the switches, or 0 for success.
    141  * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here?
     93 * Print a not-so-helpful help message and exit.
    14294 */
    143 int
    144 process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128])
     95void help_screen()
    14596{
    146 
    147     /*@ ints *** */
    148     int i = 0;
    149     int retval = 0;
    150 
    151     /*@ buffers ** */
    152     char *tmp = NULL;
    153     char *tmp1 = NULL;
    154     char *tmp2 = NULL;
    155     char *psz = NULL;
    156     char *p = NULL;
    157     char *q = NULL;
    158     char *q2 = NULL;
    159 
    160     long itbs = 0L;
    161 
    162     struct stat buf;
    163 
    164     malloc_string(tmp);
    165 
    166     assert(bkpinfo != NULL);
    167     assert(flag_val != NULL);
    168     assert(flag_set != NULL);
    169 
    170     bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
    171 
    172     /* compulsory */
    173     i = flag_set['c'] + flag_set['i'] + flag_set['n'] +
    174         flag_set['t'] + flag_set['u'] + flag_set['r'] +
    175         flag_set['w'] + flag_set['C'] + flag_set['U'];
    176     if ((i == 0) && (! bkpinfo->restore_data)) {
    177         retval++;
    178         log_to_screen("You must specify the media type\n");
    179     }
    180     if (i > 1) {
    181         retval++;
    182         log_to_screen("Please specify only one media type\n");
    183     }
    184 
    185     if (flag_set['K']) {
    186         g_loglevel = atoi(flag_val['K']);
    187             log_msg(1,"Loglevel forced to %d",g_loglevel);
    188         if (g_loglevel < 3) {
    189             g_loglevel = 3;
    190         }
    191     }
    192 
    193     if ((flag_set['L'] && flag_set['0']) && (! bkpinfo->restore_data)) {
    194         retval++;
    195         log_to_screen("You cannot have 'no compression' _and_ LZOP.\n");
    196     }
    197     if (! bkpinfo->restore_data) {
    198         bkpinfo->backup_data = flag_set['O'];
    199     }
    200     bkpinfo->verify_data = flag_set['V'];
    201 
    202     if (flag_set['I'] && !bkpinfo->backup_data) {
    203         log_to_screen("-I switch is ignored if just verifying");
    204     }
    205     if (flag_set['E'] && !bkpinfo->backup_data) {
    206         log_to_screen("-E switch is ignored if just verifying");
    207     }
    208 
    209     if ((tmp = find_home_of_exe("afio")) == NULL) {
    210         mr_free(tmp);
    211         if ((tmp = find_home_of_exe("star")) != NULL) {
    212             mr_free(tmp);
    213             flag_set['R'] = TRUE;
    214             log_msg(1, "Using star instead of afio");
    215         } else {
    216             mr_free(tmp);
    217             fatal_error("Neither afio nor star is installed. Please install at least one.");
    218         }
    219     }
    220 
    221     if (flag_set['R']) {
    222         bkpinfo->use_star = TRUE;
    223         if (flag_set['L']) {
    224             fatal_error("You may not use star and lzop at the same time.");
    225         }
    226         if ((tmp = find_home_of_exe("star")) == NULL) {
    227             mr_free(tmp);
    228             fatal_error("Please install 'star' if you are going to use -R. Thanks.");
    229         }
    230         mr_free(tmp);
    231     }
    232 
    233     if ((flag_set['W']) && (! bkpinfo->restore_data)) {
    234         bkpinfo->nonbootable_backup = TRUE;
    235         log_to_screen("Warning - you have opted for non-bootable backup");
    236         if (flag_set['f'] || flag_set['l']) {
    237             log_to_screen
    238                 ("You don't need to specify bootloader or bootdevice");
    239         }
    240     }
    241 
    242     if (flag_set['I']) {
    243         if (flag_val['I'][0] == '-') {
    244             retval++;
    245             log_to_screen("Please supply a sensible value with '-I'\n");
    246         }
    247         if (!strcmp(flag_val['I'],"/")) {
    248             log_msg(2, "'/' is pleonastic.");
    249         }
    250         if (bkpinfo->include_paths && bkpinfo->include_paths[0]) {
    251             mr_strcat(bkpinfo->include_paths, "|");
    252         }
    253 
    254         mr_asprintf(tmp1, "%s", flag_val['I']);
    255         p = tmp1;
    256         q = tmp1;
    257 
    258         /* Cut the flag_val['I'] in parts containing all paths to test them */
    259         while (p != NULL) {
    260             q = strchr(p, '|');
    261             if (q != NULL) {
    262                 *q = '\0';
    263                 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
    264                     log_msg(1, "ERROR ! %s doesn't exist", p);
    265                     fatal_error("ERROR ! You specified a directory to include which doesn't exist");
    266                 }
    267                 p = q+1 ;
    268             } else {
    269                 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
    270                     log_msg(1, "ERROR ! %s doesn't exist", p);
    271                     fatal_error("ERROR ! You specified a directory to include which doesn't exist");
    272                 }
    273                 p = NULL;
    274             }
    275         }
    276         mr_free(tmp1);
    277         mr_make_devlist_from_pathlist(flag_val['I'], 'I');
    278         log_msg(4, "Finished with the -I option");
    279     }
    280 
    281     if (g_kernel_version >= 2.6 && !flag_set['d'] && (flag_set['c'] || flag_set['w']) && (! bkpinfo->restore_data)) {
    282         fatal_error("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
    283     }
    284 
    285 
    286     if (flag_set['J']) {
    287         if (flag_set['I']) {
    288             retval++;
    289             log_to_screen("Please do not use -J in combination with -I. If you want to make a list of files to backup, that's fine, use -J <filename> but please don't muddy the waters by combining -J with -I. Thanks. :-)");
    290         }
    291         bkpinfo->make_filelist = FALSE;
    292         mr_asprintf(bkpinfo->include_paths, "%s", flag_val['J']);
    293     }
    294 
    295     if ((flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) && (! bkpinfo->restore_data)) {
    296         if (system("which cdrecord > /dev/null 2> /dev/null") && system("which dvdrecord > /dev/null 2> /dev/null")) {
    297             fatal_error("Please install dvdrecord/cdrecord and try again.");
    298         }
    299         if (flag_set['C']) {
    300             bkpinfo->cdrw_speed = atoi(flag_val['C']);
    301             if (bkpinfo->cdrw_speed < 1) {
    302                 fatal_error("You specified a silly speed for a CD-R[W] drive");
    303             }
    304             if (!flag_set['L']) {
    305                 log_to_screen("You must use -L with -C. Therefore I am setting it for you.");
    306                 flag_set['L'] = 1;
    307                 flag_val['L'][0] = '\0';
    308             }
    309         } else {
    310             log_msg(3, "flag_val['c'] = %s", flag_val['c']);
    311             log_msg(3, "flag_val['w'] = %s", flag_val['w']);
    312             if (flag_set['c']) {
    313                 bkpinfo->cdrw_speed = atoi(flag_val['c']);
    314             } else if (flag_set['w']) {
    315                 bkpinfo->cdrw_speed = atoi(flag_val['w']);
    316             } else if (flag_set['r']) {
    317                 bkpinfo->cdrw_speed = 1;    /*atoi(flag_val['r']); */
    318             }
    319 
    320             if (bkpinfo->cdrw_speed < 1) {
    321                 fatal_error("You specified a silly speed for a CD-R[W] drive");
    322             }
    323         }
    324     }
    325 
    326     if ((flag_set['t'] && !flag_set['d']) && (! bkpinfo->restore_data)) {
    327         log_it("Hmm! No tape drive specified. Let's see what we can do.");
    328         if ((bkpinfo->media_device = find_tape_device()) == NULL) {
    329             fatal_error("Tape device not specified and I couldn't find it either. Please use option -d");
    330         }
    331         flag_set['d'] = TRUE;
    332         log_to_screen("You didn't specify a tape streamer device. I'm assuming %s", bkpinfo->media_device);
    333     }
    334 
    335     if (flag_set['U'])          // USB
    336     {
    337         if (! flag_set['d']) {
    338             fatal_error("You need to specify a device file with -d for bootable USB device usage");
    339         }
    340         if ((!flag_set['s']) && (! bkpinfo->restore_data)) {
    341             fatal_error("You did not specify a size (-s) for your USB device. Aborting");
    342         }
    343     }
    344 
    345     if (flag_set['r'])          // DVD
    346     {
    347         if (flag_set['m']) {
    348             fatal_error("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m.");
    349         }
    350         if (!flag_set['d']) {
    351             if ((bkpinfo->media_device = find_optical_device()) != NULL) {
    352                 flag_set['d'] = TRUE;
    353                 log_to_screen("I guess DVD drive is at %s", bkpinfo->media_device);
    354             }
    355         }
    356         if (strchr(bkpinfo->media_device, ',')) {
    357             fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
    358         }
    359         if (! bkpinfo->restore_data) {
    360             if (!flag_set['s']) {
    361                 sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE);    // 4.7 salesman's GB = 4.482 real GB = 4582 MB
    362                 strcat(flag_val['s'], "m");
    363                 log_to_screen("You did not specify a size (-s) for DVD. I'm guessing %s.", flag_val['s']);
    364                 flag_set['s'] = 1;
    365             }
    366         }
    367     }
    368 
    369     if (flag_set['t'] || flag_set['u']) {   /* tape size */
    370         if (strchr(flag_val['d'], ',')) {
    371             fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
    372         }
    373         if ((flag_set['O']) && (! bkpinfo->restore_data)) {
    374             if (flag_set['s']) {
    375                 if (flag_set['t']) {
    376                     fatal_error("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway.");
    377                 }
    378                 if (process_the_s_switch(flag_val['s'])) {
    379                     fatal_error("Bad -s switch");
    380                 }
    381             } else if (flag_set['u'] || flag_set['t']) {
    382                 bkpinfo->media_size = 0;
    383             } else {
    384                 retval++;
    385                 log_to_screen("Tape size not specified.\n");
    386             }
    387         }
    388     } else if (! bkpinfo->restore_data) {           /* CD|USB size */
    389         if (flag_set['s']) {
    390             if (process_the_s_switch(flag_val['s'])) {
    391                 fatal_error("Bad -s switch");
    392             }
    393         }
    394         if (flag_set['w']) {
    395             bkpinfo->wipe_media_first = TRUE;
    396         }                       /* CD-RW */
    397     }
    398 
    399     if (flag_set['n']) {
    400         mr_asprintf(bkpinfo->netfs_mount, "%s", flag_val['n']);
    401         if (!flag_set['d']) {
    402             mr_asprintf(bkpinfo->netfs_remote_dir, "/");
    403             mr_asprintf(bkpinfo->isodir, "%s", ".");
    404         }
    405         /* test for protocol */
    406         p = strstr(bkpinfo->netfs_mount, "://");
    407         if (p == NULL) {
    408             /* protocol not found assuming NFS for compatibility */
    409             mr_asprintf(q,"nfs");
    410 
    411             p = strchr(bkpinfo->netfs_mount, ':');
    412             if (p == NULL) {
    413                 fatal_error("No protocol specified for remote share mount, nor any old NFS syntax found.\nPlease do man mondoarchive as syntax changed");
    414             }
    415             /* p points on to the string server:/path */
    416             p = bkpinfo->netfs_mount;
    417 
    418         } else {
    419             /* Isolate the protocol */
    420             *p = '\0';
    421             mr_asprintf(q,"%s",bkpinfo->netfs_mount);
    422 
    423             /* Skip proto now */
    424             p++;
    425             p++;
    426             p++;
    427         }
    428         /* whatever done before proto is pointed to by q */
    429         bkpinfo->netfs_proto = q;
    430 
    431         /* p points on to the string server:/path */
    432         /* Store the 2 values */
    433         q2 = bkpinfo->netfs_mount;
    434         mr_asprintf(bkpinfo->netfs_mount, "%s", p);
    435         mr_free(q2);
    436 
    437         /* test if we specified a user */
    438         p = strchr(bkpinfo->netfs_mount, '@');
    439         if (p != NULL) {
    440             /* User found. Store the 2 values */
    441             mr_asprintf(bkpinfo->netfs_user, "%s", bkpinfo->netfs_mount);
    442             p = strchr(bkpinfo->netfs_user, '@');
    443             *p = '\0';
    444             p = strchr(bkpinfo->netfs_mount, '@');
    445             p++;
    446             /* new netfs mount */
    447             q2 = bkpinfo->netfs_mount;
    448             mr_asprintf(bkpinfo->netfs_mount, "%s", p);
    449             mr_free(q2);
    450         }
    451         if (bkpinfo->netfs_user != NULL) {
    452             mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount);
    453         } else {
    454             mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount);
    455         }
    456         mr_free(bkpinfo->isodir);
    457         bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1);
    458         mr_free(tmp1);
    459 
    460         log_msg(3, "proto = %s", bkpinfo->netfs_proto);
    461         log_msg(3, "mount = %s", bkpinfo->netfs_mount);
    462         if (bkpinfo->netfs_user) {
    463             log_msg(3, "user = %s", bkpinfo->netfs_user);
    464         }
    465         log_msg(3, "isodir= %s", bkpinfo->isodir);
    466 
    467         if (strlen(bkpinfo->isodir) < 3) {
    468             log_to_screen("Network share %s is not mounted. Trying to mount it for you.\n",bkpinfo->netfs_mount);
    469             if (bkpinfo->netfs_user) {
    470                 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
    471                     mr_asprintf(tmp1, "sshfs %s@%s", bkpinfo->netfs_user, bkpinfo->netfs_mount);
    472                 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) {
    473                     mr_asprintf(tmp1, "mount -t cifs %s -o user=%s", bkpinfo->netfs_mount, bkpinfo->netfs_user);
    474                 } else if (strstr(bkpinfo->netfs_proto, "nfs")) {
    475                     mr_asprintf(tmp1, "mount -t %s %s@%s", bkpinfo->netfs_proto, bkpinfo->netfs_user, bkpinfo->netfs_mount);
    476                 } else {
    477                     log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto);
    478                     fatal_error("Bad Protocol\n");
    479                 }
    480             } else {
    481                 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
    482                     mr_asprintf(tmp1, "sshfs %s", bkpinfo->netfs_mount);
    483                 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) {
    484                     mr_asprintf(tmp1, "mount -t cifs %s", bkpinfo->netfs_mount);
    485                 } else if (strstr(bkpinfo->netfs_proto, "nfs")) {
    486                     mr_asprintf(tmp1, "mount -t %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount);
    487                 } else {
    488                     log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto);
    489                     fatal_error("Bad Protocol\n");
    490                 }
    491             }
    492             i = system(tmp1);
    493             mr_free(tmp1);
    494 
    495             if (i) {
    496                 log_to_screen("Unable to mount Network share %s. Please mount manually.\n", bkpinfo->netfs_mount);
    497                 retval++;
    498             } else {
    499                 if (bkpinfo->netfs_user) {
    500                     mr_asprintf(tmp1, "mount | grep -E \"^[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount);
    501                 } else {
    502                     mr_asprintf(tmp1, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount);
    503                 }
    504                 mr_free(bkpinfo->isodir);
    505                 bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1);
    506                 if (strlen(bkpinfo->isodir) < 3) {
    507                     retval++;
    508                     log_to_screen("Network share %s is strangely not mounted. Please mount manually...\n", bkpinfo->netfs_mount);
    509                 }
    510             }
    511         }
    512     }
    513 
    514     if (flag_set['c']) {
    515         bkpinfo->backup_media_type = cdr;
    516     }
    517     if (flag_set['C']) {
    518         bkpinfo->backup_media_type = cdstream;
    519     }
    520     if (flag_set['i']) {
    521         bkpinfo->backup_media_type = iso;
    522     }
    523     if (flag_set['n']) {
    524         bkpinfo->backup_media_type = netfs;
    525         /* Never try to eject a Network device */
    526         bkpinfo->please_dont_eject = TRUE;
    527     }
    528     if (flag_set['r']) {
    529         bkpinfo->backup_media_type = dvd;
    530     }
    531     if (flag_set['t']) {
    532         bkpinfo->backup_media_type = tape;
    533     }
    534     if (flag_set['u']) {
    535         bkpinfo->backup_media_type = udev;
    536     }
    537     if (flag_set['U']) {
    538         bkpinfo->backup_media_type = usb;
    539         /* Never try to eject a USB device */
    540         bkpinfo->please_dont_eject = TRUE;
    541     }
    542     if (flag_set['z']) {
    543         if ((tmp = find_home_of_exe("getfattr")) != NULL) {
    544             mr_asprintf(g_getfattr,"getfattr");
    545         }
    546         mr_free(tmp);
    547         if ((tmp = find_home_of_exe("getfacl")) != NULL) {
    548             mr_asprintf(g_getfattr,"getfaacl");
    549         }
    550         mr_free(tmp);
    551     }
    552 
    553     /* optional, popular */
    554     if (flag_set['g']) {
    555         g_text_mode = FALSE;
    556     }
    557 
    558     if (flag_set['E']) {
    559         if ((flag_val['E'][0] == '-')) {
    560             retval++;
    561             log_to_screen("Please supply a sensible value with '-E'\n");
    562         }
    563         mr_asprintf(tmp1, "%s", flag_val['E']);
    564 
    565         p = tmp1;
    566         q = tmp1;
    567 
    568         /* Cut the flag_val['E'] in parts containing all paths to test them */
    569         while (p != NULL) {
    570             q = strchr(p, '|');
    571             if (q != NULL) {
    572                 *q = '\0';
    573                 /* Fix bug 14 where ending / cause a problem later
    574                 * so handled here for the moment */
    575                 q--;
    576                 if (*q == '/') {
    577                     *q = '\0';
    578                 }
    579                 q++;
    580                 /* End of bug fix */
    581                 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
    582                     log_msg(1, "WARNING ! %s doesn't exist", p);
    583                 }
    584                 p = q+1 ;
    585             } else {
    586                 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
    587                     log_msg(1, "WARNING ! %s doesn't exist", p);
    588                 }
    589                 p = NULL;
    590             }
    591         }
    592         mr_free(tmp1);
    593 
    594         mr_make_devlist_from_pathlist(flag_val['E'], 'E');
    595         log_msg(4, "Finished with the -E option");
    596     }
    597 
    598     if (flag_set['e']) {
    599         bkpinfo->please_dont_eject = TRUE;
    600     }
    601 
    602     if (flag_set['M']) {
    603         g_max_biggie_size = atol(flag_val['M']);
    604         log_msg(1, "Max size for biggie file is now %ld KB", g_max_biggie_size);
    605     }
    606 
    607     if ((flag_set['N']) && (! bkpinfo->restore_data))       // exclude Network mounts & devices
    608     {
    609         psz = list_of_NETFS_mounts_only();
    610         log_msg(5, "-N means we'll exclude %s", psz);
    611         if (bkpinfo->exclude_paths) {
    612             mr_strcat(bkpinfo->exclude_paths, "|%s", psz);
    613             mr_free(psz);
    614         } else {
    615             bkpinfo->exclude_paths = psz;
    616         }
    617 
    618         if (bkpinfo->exclude_paths != NULL) {
    619             log_msg(3, "-N means we're now excluding %s", bkpinfo->exclude_paths);
    620         }
    621     }
    622 
    623     if (flag_set['b']) {
    624         mr_asprintf(psz, "%s", flag_val['b']);
    625         log_msg(1, "psz = '%s'", psz);
    626         if (psz[strlen(psz) - 1] == 'k') {
    627             psz[strlen(psz) - 1] = '\0';
    628             itbs = atol(psz) * 1024L;
    629         } else {
    630             itbs = atol(psz);
    631         }
    632         mr_free(psz);
    633         log_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
    634         log_msg(1, "Internal tape block size is now %ld bytes", itbs);
    635         if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
    636             fatal_error("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
    637         }
    638         bkpinfo->internal_tape_block_size = itbs;
    639     }
    640 
    641     if ((flag_set['D']) && (! bkpinfo->restore_data)) {
    642         bkpinfo->differential = 1;
    643 //      bkpinfo->differential = atoi (flag_val['D']);
    644         if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) {
    645             fatal_error("The D option should be between 1 and 9 inclusive");
    646         }
    647     }
    648 
    649     if (flag_set['x']) {
    650         mr_asprintf(bkpinfo->image_devs, "%s", flag_val['x']);
    651         if ((run_program_and_log_output("which ntfsclone", 2)) && (! bkpinfo->restore_data)) {
    652             fatal_error("Please install ntfsprogs package/tarball.");
    653         }
    654     }
    655 
    656     if (flag_set['m']) {
    657         bkpinfo->manual_cd_tray = TRUE;
    658     }
    659 
    660     if ((flag_set['k']) && (! bkpinfo->restore_data)) {
    661         mr_asprintf(bkpinfo->kernel_path, "%s", flag_val['k']);
    662         if (!does_file_exist(bkpinfo->kernel_path)) {
    663             retval++;
    664             log_to_screen("You specified kernel '%s', which does not exist\n", bkpinfo->kernel_path);
    665         }
    666     }
    667 
    668     if (flag_set['p']) {
    669         mr_asprintf(bkpinfo->prefix, "%s", flag_val['p']);
    670         log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
    671     }
    672 
    673     if (flag_set['d']) {        /* backup directory (if ISO/NETFS) */
    674         if (flag_set['i']) {
    675             // what is flag_val['d'] is NULL/undefined
    676             mr_asprintf(bkpinfo->isodir, "%s", flag_val['d']);
    677             mr_asprintf(tmp1, "ls -l %s", bkpinfo->isodir);
    678             if (run_program_and_log_output(tmp1, 2)) {
    679                 mr_free(tmp1);
    680                 fatal_error("output folder does not exist - please create it");
    681             }
    682             mr_free(tmp1);
    683         } else if (flag_set['n']) {
    684             mr_free(bkpinfo->netfs_remote_dir);
    685             // what is flag_val['d'] is NULL/undefined
    686             mr_asprintf(bkpinfo->netfs_remote_dir, "%s", flag_val['d']);
    687         } else {                /* backup device (if tape/CD-R/CD-RW) */
    688             /* bkpinfo-> media_device already setup upper */
    689         }
    690     }
    691 
    692     if ((flag_set['n']) && (! bkpinfo->restore_data)) {
    693         mr_asprintf(tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->netfs_remote_dir);
    694         if ((bkpinfo->netfs_user) && (strstr(bkpinfo->netfs_proto,"nfs"))) {
    695             mr_asprintf(tmp2, "su - %s -c \"echo hi > %s\"", bkpinfo->netfs_user, tmp1);
    696         } else {
    697             mr_asprintf(tmp2, "echo hi > %s", tmp1);
    698         }
    699         i = run_program_and_log_output(tmp2, 2);
    700         mr_free(tmp2);
    701 
    702         if (i) {
    703             retval++;
    704             log_to_screen("Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n", bkpinfo->netfs_remote_dir, bkpinfo->netfs_mount);
    705         }
    706         unlink(tmp1);
    707         mr_free(tmp1);
    708     }
    709 
    710     if (!flag_set['d'] && (flag_set['c'] || flag_set['w'] || flag_set['C'])) {
    711             tmp1 = mr_popup_and_get_string("Device", "Please specify the device", bkpinfo->media_device);
    712             if (tmp1 == NULL) {
    713                 retval++;
    714                 log_to_screen("User opted to cancel.");
    715             } else {
    716                 mr_free(bkpinfo->media_device);
    717                 bkpinfo->media_device = tmp1;
    718             }
    719         } else {
    720     }
    721 
    722     if ((!flag_set['d'] && !flag_set['n'] && !flag_set['C']) && (! bkpinfo->restore_data)) {
    723         retval++;
    724         log_to_screen("Please specify the backup device/directory.\n");
    725         fatal_error("You didn't use -d to specify the backup device/directory.");
    726     }
    727 
    728     for (i = '0'; i <= '9'; i++) {
    729         if (flag_set[i]) {
    730             bkpinfo->compression_level = i - '0';
    731         }                       /* not '\0' but '0' */
    732     }
    733 
    734     if (flag_set['S']) {
    735         setup_scratchdir(flag_val['S']);
    736         mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->scratchdir);
    737         if (run_program_and_log_output(tmp1, 1)) {
    738             retval++;
    739             mr_free(tmp1);
    740             log_to_screen("Please specify a scratchdir which I can write to. :)");
    741             fatal_error("I cannot write to the scratchdir you specified.");
    742         }
    743         mr_free(tmp1);
    744 
    745         mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->scratchdir, bkpinfo->scratchdir);
    746         if (run_program_and_log_output(tmp1, 1)) {
    747             retval++;
    748             mr_free(tmp1);
    749             log_to_screen("Please don't specify a SAMBA or VFAT or NFS scratchdir.");
    750             fatal_error("I cannot write to the scratchdir you specified.");
    751         }
    752         mr_free(tmp1);
    753     }
    754 
    755     if (flag_set['T']) {
    756         setup_tmpdir(flag_val['T']);
    757         mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->tmpdir);
    758         i = run_program_and_log_output(tmp1, 1);
    759         mr_free(tmp1);
    760 
    761         if (i) {
    762             retval++;
    763             log_to_screen("Please specify a tempdir which I can write to. :)");
    764             fatal_error("I cannot write to the tempdir you specified.");
    765         }
    766         mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir);
    767         i = run_program_and_log_output(tmp1, 1);
    768         mr_free(tmp1);
    769 
    770         if (i) {
    771             retval++;
    772             log_to_screen("Please don't specify a SAMBA or VFAT or NFS tmpdir.");
    773             fatal_error("I cannot write to the tempdir you specified.");
    774         }
    775     }
    776 
    777     if ((flag_set['A']) && (! bkpinfo->restore_data)) {
    778         mr_asprintf(bkpinfo->call_after_iso, "%s", flag_val['A']);
    779     }
    780 
    781     if ((flag_set['B']) && (! bkpinfo->restore_data)) {
    782         mr_asprintf(bkpinfo->call_before_iso, "%s", flag_val['B']);
    783     }
    784 
    785     if ((flag_set['H']) && (! bkpinfo->restore_data)) {
    786         g_cd_recovery = TRUE;
    787     }
    788 
    789     if ((flag_set['l']) && (! bkpinfo->restore_data)) {
    790 #ifdef __FreeBSD__
    791 #  define BOOT_LOADER_CHARS "GLBMR"
    792 #else
    793 #  ifdef __IA64__
    794 #    define BOOT_LOADER_CHARS "GER"
    795 #  else
    796 #    define BOOT_LOADER_CHARS "GLR"
    797 #  endif
    798 #endif
    799         if (!strchr(BOOT_LOADER_CHARS, (bkpinfo->boot_loader = flag_val['l'][0]))) {
    800             log_msg(1, "%c? What is %c? I need G, L, E or R.", bkpinfo->boot_loader, bkpinfo->boot_loader);
    801             fatal_error("Please specify GRUB, LILO, ELILO  or RAW with the -l switch");
    802         }
    803 #undef BOOT_LOADER_CHARS
    804     }
    805 
    806     if (flag_set['f']) {
    807         mr_free(bkpinfo->boot_device);
    808         mr_asprintf(bkpinfo->boot_device, "%s", resolve_softlinks_to_get_to_actual_device_file(flag_val['f']));
    809     }
    810 
    811     if ((flag_set['P']) && (! bkpinfo->restore_data)) {
    812         mr_asprintf(bkpinfo->postnuke_tarball, "%s", flag_val['P']);
    813     }
    814 
    815     if (flag_set['Q']) {
    816         i = which_boot_loader(tmp);
    817         log_msg(3, "boot loader is %c, residing at %s", i, tmp);
    818         printf("boot loader is %c, residing at %s\n", i, tmp);
    819         finish(0);
    820     }
    821 
    822     if ((flag_set['L']) && (! bkpinfo->restore_data)) {
    823         bkpinfo->use_lzo = TRUE;
    824         if (run_program_and_log_output("which lzop", 2)) {
    825             retval++;
    826             log_to_screen("Please install LZOP. You can't use '-L' until you do.\n");
    827         }
    828     }
    829 
    830     if (flag_set['F']) {
    831         log_msg(3, "-F means we will fail immediately at the first interaction request");
    832         g_fail_immediately = TRUE;
    833     }
    834 
    835     if ((flag_set['G']) && (! bkpinfo->restore_data)) {
    836         bkpinfo->use_gzip = TRUE;
    837         if (run_program_and_log_output("which gzip", 2)) {
    838             retval++;
    839             log_to_screen("Please install gzip. You can't use '-G' until you do.\n");
    840         }
    841     }
    842 
    843     if ((flag_set['Y']) && (! bkpinfo->restore_data)) {
    844         bkpinfo->use_lzma = TRUE;
    845         if (run_program_and_log_output("which lzma", 2)) {
    846             retval++;
    847             log_to_screen("Please install lzma. You can't use '-Y' until you do.\n");
    848         }
    849     }
    850 
    851     bkpinfo->use_obdr = FALSE;
    852     if (flag_set['o']) {
    853         if ((!flag_set['t']) && (! bkpinfo->restore_data)) {
    854             log_to_screen("OBDR support is only available for tapes. Use the -t option");
    855             fatal_error("Aborting");
    856         }
    857         bkpinfo->use_obdr = TRUE;
    858     }
    859 
    860 #ifndef __FreeBSD__
    861     if ((!is_this_a_valid_disk_format("vfat")) && (! bkpinfo->restore_data)) {
    862         bkpinfo->make_cd_use_lilo = TRUE;
    863         log_to_screen("Your kernel appears not to support vfat filesystems. I am therefore");
    864         log_to_screen("using LILO instead of SYSLINUX as the media boot loader.");
    865     }
    866     if ((run_program_and_log_output("which mkfs.vfat", 2)) && (! bkpinfo->restore_data)) {
    867         bkpinfo->make_cd_use_lilo = TRUE;
    868 #ifdef __IA32__
    869         log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as");
    870         log_to_screen("your boot loader. I shall therefore use LILO instead.");
    871 #endif
    872 #ifdef __IA64__
    873         log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI");
    874         log_to_screen("environment correctly. Please install it.");
    875         fatal_error("Aborting");
    876 #endif
    877     }
    878 #ifdef __IA64__
    879     /* We force ELILO usage on IA64 */
    880     bkpinfo->make_cd_use_lilo = TRUE;
    881 #endif
    882 #endif
    883 
    884     if (! bkpinfo->restore_data) {
    885         i = flag_set['O'] + flag_set['V'];
    886         if (i == 0) {
    887             retval++;
    888             log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n");
    889         }
    890     }
    891 
    892     if ((! bkpinfo->restore_data) && (flag_set['Z'])) {
    893             fatal_error("The -Z switch is only valid in restore mode");
    894     }
    895 
    896     if (flag_set['Z']) {
    897         if (! strcmp(flag_val['Z'], "nuke")) {
    898             bkpinfo->restore_mode = nuke;
    899         } else if (! strcmp(flag_val['Z'], "interactive")) {
    900             bkpinfo->restore_mode = interactive;
    901         } else if (! strcmp(flag_val['Z'], "compare")) {
    902             bkpinfo->restore_mode = compare;
    903         } else if (! strcmp(flag_val['Z'], "mbr")) {
    904             bkpinfo->restore_mode = mbr;
    905         } else if (! strcmp(flag_val['Z'], "iso")) {
    906             bkpinfo->restore_mode = isoonly;
    907         } else if (! strcmp(flag_val['Z'], "isonuke")) {
    908             bkpinfo->restore_mode = isonuke;
    909         } else {
    910             bkpinfo->restore_mode = interactive;
    911         }
    912     }
    913 
    914 /* and finally... */
    915 
    916     paranoid_free(tmp);
    917     return (retval);
     97    log_msg(1, "Type 'man mondoarchive' for more information");
     98    exit(1);
    91899}
    919 
    920100
    921101
     
    983163
    984164
    985 
    986 
    987165/**
    988  * Print a not-so-helpful help message and exit.
     166 * Process mondoarchive's command-line switches.
     167 * @param bkpinfo The backup information structure to populate.
     168 * @param flag_val An array of the argument passed to each switch (the letter is the index).
     169 * If a switch is not set or has no argument, the field in @p flag_val doesn't matter.
     170 * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set,
     171 * FALSE if it's not.
     172 * @return The number of problems with the switches, or 0 for success.
     173 * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here?
    989174 */
    990 void help_screen()
     175int
     176process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128])
    991177{
    992     log_msg(1, "Type 'man mondoarchive' for more information");
    993     exit(1);
     178
     179    /*@ ints *** */
     180    int i = 0;
     181    int retval = 0;
     182
     183    /*@ buffers ** */
     184    char *tmp = NULL;
     185    char *tmp1 = NULL;
     186    char *tmp2 = NULL;
     187    char *psz = NULL;
     188    char *p = NULL;
     189    char *q = NULL;
     190    char *q2 = NULL;
     191
     192    long itbs = 0L;
     193
     194    struct stat buf;
     195
     196    malloc_string(tmp);
     197
     198    assert(bkpinfo != NULL);
     199    assert(flag_val != NULL);
     200    assert(flag_set != NULL);
     201
     202    bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
     203
     204    /* compulsory */
     205    i = flag_set['c'] + flag_set['i'] + flag_set['n'] +
     206        flag_set['t'] + flag_set['u'] + flag_set['r'] +
     207        flag_set['w'] + flag_set['C'] + flag_set['U'];
     208    if ((i == 0) && (! bkpinfo->restore_data)) {
     209        retval++;
     210        log_to_screen("You must specify the media type\n");
     211    }
     212    if (i > 1) {
     213        retval++;
     214        log_to_screen("Please specify only one media type\n");
     215    }
     216
     217    if (flag_set['K']) {
     218        g_loglevel = atoi(flag_val['K']);
     219            log_msg(1,"Loglevel forced to %d",g_loglevel);
     220        if (g_loglevel < 3) {
     221            g_loglevel = 3;
     222        }
     223    }
     224
     225    if ((flag_set['L'] && flag_set['0']) && (! bkpinfo->restore_data)) {
     226        retval++;
     227        log_to_screen("You cannot have 'no compression' _and_ LZOP.\n");
     228    }
     229    if (! bkpinfo->restore_data) {
     230        bkpinfo->backup_data = flag_set['O'];
     231    }
     232    bkpinfo->verify_data = flag_set['V'];
     233
     234    if (flag_set['I'] && !bkpinfo->backup_data) {
     235        log_to_screen("-I switch is ignored if just verifying");
     236    }
     237    if (flag_set['E'] && !bkpinfo->backup_data) {
     238        log_to_screen("-E switch is ignored if just verifying");
     239    }
     240
     241    if ((tmp = find_home_of_exe("afio")) == NULL) {
     242        mr_free(tmp);
     243        if ((tmp = find_home_of_exe("star")) != NULL) {
     244            mr_free(tmp);
     245            flag_set['R'] = TRUE;
     246            log_msg(1, "Using star instead of afio");
     247        } else {
     248            mr_free(tmp);
     249            fatal_error("Neither afio nor star is installed. Please install at least one.");
     250        }
     251    }
     252
     253    if (flag_set['R']) {
     254        bkpinfo->use_star = TRUE;
     255        if (flag_set['L']) {
     256            fatal_error("You may not use star and lzop at the same time.");
     257        }
     258        if ((tmp = find_home_of_exe("star")) == NULL) {
     259            mr_free(tmp);
     260            fatal_error("Please install 'star' if you are going to use -R. Thanks.");
     261        }
     262        mr_free(tmp);
     263    }
     264
     265    if ((flag_set['W']) && (! bkpinfo->restore_data)) {
     266        bkpinfo->nonbootable_backup = TRUE;
     267        log_to_screen("Warning - you have opted for non-bootable backup");
     268        if (flag_set['f'] || flag_set['l']) {
     269            log_to_screen
     270                ("You don't need to specify bootloader or bootdevice");
     271        }
     272    }
     273
     274    if (flag_set['I']) {
     275        if (flag_val['I'][0] == '-') {
     276            retval++;
     277            log_to_screen("Please supply a sensible value with '-I'\n");
     278        }
     279        if (!strcmp(flag_val['I'],"/")) {
     280            log_msg(2, "'/' is pleonastic.");
     281        }
     282        if (bkpinfo->include_paths && bkpinfo->include_paths[0]) {
     283            mr_strcat(bkpinfo->include_paths, "|");
     284        }
     285
     286        mr_asprintf(tmp1, "%s", flag_val['I']);
     287        p = tmp1;
     288        q = tmp1;
     289
     290        /* Cut the flag_val['I'] in parts containing all paths to test them */
     291        while (p != NULL) {
     292            q = strchr(p, '|');
     293            if (q != NULL) {
     294                *q = '\0';
     295                if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
     296                    log_msg(1, "ERROR ! %s doesn't exist", p);
     297                    fatal_error("ERROR ! You specified a directory to include which doesn't exist");
     298                }
     299                p = q+1 ;
     300            } else {
     301                if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
     302                    log_msg(1, "ERROR ! %s doesn't exist", p);
     303                    fatal_error("ERROR ! You specified a directory to include which doesn't exist");
     304                }
     305                p = NULL;
     306            }
     307        }
     308        mr_free(tmp1);
     309        mr_make_devlist_from_pathlist(flag_val['I'], 'I');
     310        log_msg(4, "Finished with the -I option");
     311    }
     312
     313    if (g_kernel_version >= 2.6 && !flag_set['d'] && (flag_set['c'] || flag_set['w']) && (! bkpinfo->restore_data)) {
     314        fatal_error("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
     315    }
     316
     317
     318    if (flag_set['J']) {
     319        if (flag_set['I']) {
     320            retval++;
     321            log_to_screen("Please do not use -J in combination with -I. If you want to make a list of files to backup, that's fine, use -J <filename> but please don't muddy the waters by combining -J with -I. Thanks. :-)");
     322        }
     323        bkpinfo->make_filelist = FALSE;
     324        mr_asprintf(bkpinfo->include_paths, "%s", flag_val['J']);
     325    }
     326
     327    if ((flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) && (! bkpinfo->restore_data)) {
     328        if (system("which cdrecord > /dev/null 2> /dev/null") && system("which dvdrecord > /dev/null 2> /dev/null")) {
     329            fatal_error("Please install dvdrecord/cdrecord and try again.");
     330        }
     331        if (flag_set['C']) {
     332            bkpinfo->cdrw_speed = atoi(flag_val['C']);
     333            if (bkpinfo->cdrw_speed < 1) {
     334                fatal_error("You specified a silly speed for a CD-R[W] drive");
     335            }
     336            if (!flag_set['L']) {
     337                log_to_screen("You must use -L with -C. Therefore I am setting it for you.");
     338                flag_set['L'] = 1;
     339                flag_val['L'][0] = '\0';
     340            }
     341        } else {
     342            log_msg(3, "flag_val['c'] = %s", flag_val['c']);
     343            log_msg(3, "flag_val['w'] = %s", flag_val['w']);
     344            if (flag_set['c']) {
     345                bkpinfo->cdrw_speed = atoi(flag_val['c']);
     346            } else if (flag_set['w']) {
     347                bkpinfo->cdrw_speed = atoi(flag_val['w']);
     348            } else if (flag_set['r']) {
     349                bkpinfo->cdrw_speed = 1;    /*atoi(flag_val['r']); */
     350            }
     351
     352            if (bkpinfo->cdrw_speed < 1) {
     353                fatal_error("You specified a silly speed for a CD-R[W] drive");
     354            }
     355        }
     356    }
     357
     358    if ((flag_set['t'] && !flag_set['d']) && (! bkpinfo->restore_data)) {
     359        log_it("Hmm! No tape drive specified. Let's see what we can do.");
     360        if ((bkpinfo->media_device = find_tape_device()) == NULL) {
     361            fatal_error("Tape device not specified and I couldn't find it either. Please use option -d");
     362        }
     363        flag_set['d'] = TRUE;
     364        log_to_screen("You didn't specify a tape streamer device. I'm assuming %s", bkpinfo->media_device);
     365    }
     366
     367    if (flag_set['U'])          // USB
     368    {
     369        if (! flag_set['d']) {
     370            fatal_error("You need to specify a device file with -d for bootable USB device usage");
     371        }
     372        if ((!flag_set['s']) && (! bkpinfo->restore_data)) {
     373            fatal_error("You did not specify a size (-s) for your USB device. Aborting");
     374        }
     375    }
     376
     377    if (flag_set['r'])          // DVD
     378    {
     379        if (flag_set['m']) {
     380            fatal_error("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m.");
     381        }
     382        if (!flag_set['d']) {
     383            if ((bkpinfo->media_device = find_optical_device()) != NULL) {
     384                flag_set['d'] = TRUE;
     385                log_to_screen("I guess DVD drive is at %s", bkpinfo->media_device);
     386            }
     387        }
     388        if (strchr(bkpinfo->media_device, ',')) {
     389            fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
     390        }
     391        if (! bkpinfo->restore_data) {
     392            if (!flag_set['s']) {
     393                sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE);    // 4.7 salesman's GB = 4.482 real GB = 4582 MB
     394                strcat(flag_val['s'], "m");
     395                log_to_screen("You did not specify a size (-s) for DVD. I'm guessing %s.", flag_val['s']);
     396                flag_set['s'] = 1;
     397            }
     398        }
     399    }
     400
     401    if (flag_set['t'] || flag_set['u']) {   /* tape size */
     402        if (strchr(flag_val['d'], ',')) {
     403            fatal_error("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
     404        }
     405        if ((flag_set['O']) && (! bkpinfo->restore_data)) {
     406            if (flag_set['s']) {
     407                if (flag_set['t']) {
     408                    fatal_error("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway.");
     409                }
     410                if (process_the_s_switch(flag_val['s'])) {
     411                    fatal_error("Bad -s switch");
     412                }
     413            } else if (flag_set['u'] || flag_set['t']) {
     414                bkpinfo->media_size = 0;
     415            } else {
     416                retval++;
     417                log_to_screen("Tape size not specified.\n");
     418            }
     419        }
     420    } else if (! bkpinfo->restore_data) {           /* CD|USB size */
     421        if (flag_set['s']) {
     422            if (process_the_s_switch(flag_val['s'])) {
     423                fatal_error("Bad -s switch");
     424            }
     425        }
     426        if (flag_set['w']) {
     427            bkpinfo->wipe_media_first = TRUE;
     428        }                       /* CD-RW */
     429    }
     430
     431    if (flag_set['n']) {
     432        mr_asprintf(bkpinfo->netfs_mount, "%s", flag_val['n']);
     433        if (!flag_set['d']) {
     434            mr_asprintf(bkpinfo->netfs_remote_dir, "/");
     435            mr_asprintf(bkpinfo->isodir, "%s", ".");
     436        }
     437        /* test for protocol */
     438        p = strstr(bkpinfo->netfs_mount, "://");
     439        if (p == NULL) {
     440            /* protocol not found assuming NFS for compatibility */
     441            mr_asprintf(q,"nfs");
     442
     443            p = strchr(bkpinfo->netfs_mount, ':');
     444            if (p == NULL) {
     445                fatal_error("No protocol specified for remote share mount, nor any old NFS syntax found.\nPlease do man mondoarchive as syntax changed");
     446            }
     447            /* p points on to the string server:/path */
     448            p = bkpinfo->netfs_mount;
     449
     450        } else {
     451            /* Isolate the protocol */
     452            *p = '\0';
     453            mr_asprintf(q,"%s",bkpinfo->netfs_mount);
     454
     455            /* Skip proto now */
     456            p++;
     457            p++;
     458            p++;
     459        }
     460        /* whatever done before proto is pointed to by q */
     461        bkpinfo->netfs_proto = q;
     462
     463        /* p points on to the string server:/path */
     464        /* Store the 2 values */
     465        q2 = bkpinfo->netfs_mount;
     466        mr_asprintf(bkpinfo->netfs_mount, "%s", p);
     467        mr_free(q2);
     468
     469        /* test if we specified a user */
     470        p = strchr(bkpinfo->netfs_mount, '@');
     471        if (p != NULL) {
     472            /* User found. Store the 2 values */
     473            mr_asprintf(bkpinfo->netfs_user, "%s", bkpinfo->netfs_mount);
     474            p = strchr(bkpinfo->netfs_user, '@');
     475            *p = '\0';
     476            p = strchr(bkpinfo->netfs_mount, '@');
     477            p++;
     478            /* new netfs mount */
     479            q2 = bkpinfo->netfs_mount;
     480            mr_asprintf(bkpinfo->netfs_mount, "%s", p);
     481            mr_free(q2);
     482        }
     483        if (bkpinfo->netfs_user != NULL) {
     484            mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount);
     485        } else {
     486            mr_asprintf(tmp1, "mount | grep -E \"^[a-z]*#*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount);
     487        }
     488        mr_free(bkpinfo->isodir);
     489        bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1);
     490        mr_free(tmp1);
     491
     492        log_msg(3, "proto = %s", bkpinfo->netfs_proto);
     493        log_msg(3, "mount = %s", bkpinfo->netfs_mount);
     494        if (bkpinfo->netfs_user) {
     495            log_msg(3, "user = %s", bkpinfo->netfs_user);
     496        }
     497        log_msg(3, "isodir= %s", bkpinfo->isodir);
     498
     499        if (strlen(bkpinfo->isodir) < 3) {
     500            log_to_screen("Network share %s is not mounted. Trying to mount it for you.\n",bkpinfo->netfs_mount);
     501            if (bkpinfo->netfs_user) {
     502                if (strstr(bkpinfo->netfs_proto, "sshfs")) {
     503                    mr_asprintf(tmp1, "sshfs %s@%s", bkpinfo->netfs_user, bkpinfo->netfs_mount);
     504                } else if (strstr(bkpinfo->netfs_proto, "smbfs")) {
     505                    mr_asprintf(tmp1, "mount -t cifs %s -o user=%s", bkpinfo->netfs_mount, bkpinfo->netfs_user);
     506                } else if (strstr(bkpinfo->netfs_proto, "nfs")) {
     507                    mr_asprintf(tmp1, "mount -t %s %s@%s", bkpinfo->netfs_proto, bkpinfo->netfs_user, bkpinfo->netfs_mount);
     508                } else {
     509                    log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto);
     510                    fatal_error("Bad Protocol\n");
     511                }
     512            } else {
     513                if (strstr(bkpinfo->netfs_proto, "sshfs")) {
     514                    mr_asprintf(tmp1, "sshfs %s", bkpinfo->netfs_mount);
     515                } else if (strstr(bkpinfo->netfs_proto, "smbfs")) {
     516                    mr_asprintf(tmp1, "mount -t cifs %s", bkpinfo->netfs_mount);
     517                } else if (strstr(bkpinfo->netfs_proto, "nfs")) {
     518                    mr_asprintf(tmp1, "mount -t %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount);
     519                } else {
     520                    log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto);
     521                    fatal_error("Bad Protocol\n");
     522                }
     523            }
     524            i = system(tmp1);
     525            mr_free(tmp1);
     526
     527            if (i) {
     528                log_to_screen("Unable to mount Network share %s. Please mount manually.\n", bkpinfo->netfs_mount);
     529                retval++;
     530            } else {
     531                if (bkpinfo->netfs_user) {
     532                    mr_asprintf(tmp1, "mount | grep -E \"^[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user, bkpinfo->netfs_mount);
     533                } else {
     534                    mr_asprintf(tmp1, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount);
     535                }
     536                mr_free(bkpinfo->isodir);
     537                bkpinfo->isodir = call_program_and_get_last_line_of_output(tmp1);
     538                if (strlen(bkpinfo->isodir) < 3) {
     539                    retval++;
     540                    log_to_screen("Network share %s is strangely not mounted. Please mount manually...\n", bkpinfo->netfs_mount);
     541                }
     542            }
     543        }
     544    }
     545
     546    if (flag_set['c']) {
     547        bkpinfo->backup_media_type = cdr;
     548    }
     549    if (flag_set['C']) {
     550        bkpinfo->backup_media_type = cdstream;
     551    }
     552    if (flag_set['i']) {
     553        bkpinfo->backup_media_type = iso;
     554    }
     555    if (flag_set['n']) {
     556        bkpinfo->backup_media_type = netfs;
     557        /* Never try to eject a Network device */
     558        bkpinfo->please_dont_eject = TRUE;
     559    }
     560    if (flag_set['r']) {
     561        bkpinfo->backup_media_type = dvd;
     562    }
     563    if (flag_set['t']) {
     564        bkpinfo->backup_media_type = tape;
     565    }
     566    if (flag_set['u']) {
     567        bkpinfo->backup_media_type = udev;
     568    }
     569    if (flag_set['U']) {
     570        bkpinfo->backup_media_type = usb;
     571        /* Never try to eject a USB device */
     572        bkpinfo->please_dont_eject = TRUE;
     573    }
     574    if (flag_set['z']) {
     575        if ((tmp = find_home_of_exe("getfattr")) != NULL) {
     576            mr_asprintf(g_getfattr,"getfattr");
     577        }
     578        mr_free(tmp);
     579        if ((tmp = find_home_of_exe("getfacl")) != NULL) {
     580            mr_asprintf(g_getfattr,"getfaacl");
     581        }
     582        mr_free(tmp);
     583    }
     584
     585    /* optional, popular */
     586    if (flag_set['g']) {
     587        g_text_mode = FALSE;
     588    }
     589
     590    if (flag_set['E']) {
     591        if ((flag_val['E'][0] == '-')) {
     592            retval++;
     593            log_to_screen("Please supply a sensible value with '-E'\n");
     594        }
     595        mr_asprintf(tmp1, "%s", flag_val['E']);
     596
     597        p = tmp1;
     598        q = tmp1;
     599
     600        /* Cut the flag_val['E'] in parts containing all paths to test them */
     601        while (p != NULL) {
     602            q = strchr(p, '|');
     603            if (q != NULL) {
     604                *q = '\0';
     605                /* Fix bug 14 where ending / cause a problem later
     606                * so handled here for the moment */
     607                q--;
     608                if (*q == '/') {
     609                    *q = '\0';
     610                }
     611                q++;
     612                /* End of bug fix */
     613                if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
     614                    log_msg(1, "WARNING ! %s doesn't exist", p);
     615                }
     616                p = q+1 ;
     617            } else {
     618                if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
     619                    log_msg(1, "WARNING ! %s doesn't exist", p);
     620                }
     621                p = NULL;
     622            }
     623        }
     624        mr_free(tmp1);
     625
     626        mr_make_devlist_from_pathlist(flag_val['E'], 'E');
     627        log_msg(4, "Finished with the -E option");
     628    }
     629
     630    if (flag_set['e']) {
     631        bkpinfo->please_dont_eject = TRUE;
     632    }
     633
     634    if (flag_set['M']) {
     635        g_max_biggie_size = atol(flag_val['M']);
     636        log_msg(1, "Max size for biggie file is now %ld KB", g_max_biggie_size);
     637    }
     638
     639    if ((flag_set['N']) && (! bkpinfo->restore_data))       // exclude Network mounts & devices
     640    {
     641        psz = list_of_NETFS_mounts_only();
     642        log_msg(5, "-N means we'll exclude %s", psz);
     643        if (bkpinfo->exclude_paths) {
     644            mr_strcat(bkpinfo->exclude_paths, "|%s", psz);
     645            mr_free(psz);
     646        } else {
     647            bkpinfo->exclude_paths = psz;
     648        }
     649
     650        if (bkpinfo->exclude_paths != NULL) {
     651            log_msg(3, "-N means we're now excluding %s", bkpinfo->exclude_paths);
     652        }
     653    }
     654
     655    if (flag_set['b']) {
     656        mr_asprintf(psz, "%s", flag_val['b']);
     657        log_msg(1, "psz = '%s'", psz);
     658        if (psz[strlen(psz) - 1] == 'k') {
     659            psz[strlen(psz) - 1] = '\0';
     660            itbs = atol(psz) * 1024L;
     661        } else {
     662            itbs = atol(psz);
     663        }
     664        mr_free(psz);
     665        log_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
     666        log_msg(1, "Internal tape block size is now %ld bytes", itbs);
     667        if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
     668            fatal_error("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
     669        }
     670        bkpinfo->internal_tape_block_size = itbs;
     671    }
     672
     673    if ((flag_set['D']) && (! bkpinfo->restore_data)) {
     674        bkpinfo->differential = 1;
     675//      bkpinfo->differential = atoi (flag_val['D']);
     676        if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) {
     677            fatal_error("The D option should be between 1 and 9 inclusive");
     678        }
     679    }
     680
     681    if (flag_set['x']) {
     682        mr_asprintf(bkpinfo->image_devs, "%s", flag_val['x']);
     683        if ((run_program_and_log_output("which ntfsclone", 2)) && (! bkpinfo->restore_data)) {
     684            fatal_error("Please install ntfsprogs package/tarball.");
     685        }
     686    }
     687
     688    if (flag_set['m']) {
     689        bkpinfo->manual_cd_tray = TRUE;
     690    }
     691
     692    if ((flag_set['k']) && (! bkpinfo->restore_data)) {
     693        mr_asprintf(bkpinfo->kernel_path, "%s", flag_val['k']);
     694        if (!does_file_exist(bkpinfo->kernel_path)) {
     695            retval++;
     696            log_to_screen("You specified kernel '%s', which does not exist\n", bkpinfo->kernel_path);
     697        }
     698    }
     699
     700    if (flag_set['p']) {
     701        mr_asprintf(bkpinfo->prefix, "%s", flag_val['p']);
     702        log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
     703    }
     704
     705    if (flag_set['d']) {        /* backup directory (if ISO/NETFS) */
     706        if (flag_set['i']) {
     707            // what is flag_val['d'] is NULL/undefined
     708            mr_asprintf(bkpinfo->isodir, "%s", flag_val['d']);
     709            mr_asprintf(tmp1, "ls -l %s", bkpinfo->isodir);
     710            if (run_program_and_log_output(tmp1, 2)) {
     711                mr_free(tmp1);
     712                fatal_error("output folder does not exist - please create it");
     713            }
     714            mr_free(tmp1);
     715        } else if (flag_set['n']) {
     716            mr_free(bkpinfo->netfs_remote_dir);
     717            // what is flag_val['d'] is NULL/undefined
     718            mr_asprintf(bkpinfo->netfs_remote_dir, "%s", flag_val['d']);
     719        } else {                /* backup device (if tape/CD-R/CD-RW) */
     720            /* bkpinfo-> media_device already setup upper */
     721        }
     722    }
     723
     724    if ((flag_set['n']) && (! bkpinfo->restore_data)) {
     725        mr_asprintf(tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->netfs_remote_dir);
     726        if ((bkpinfo->netfs_user) && (strstr(bkpinfo->netfs_proto,"nfs"))) {
     727            mr_asprintf(tmp2, "su - %s -c \"echo hi > %s\"", bkpinfo->netfs_user, tmp1);
     728        } else {
     729            mr_asprintf(tmp2, "echo hi > %s", tmp1);
     730        }
     731        i = run_program_and_log_output(tmp2, 2);
     732        mr_free(tmp2);
     733
     734        if (i) {
     735            retval++;
     736            log_to_screen("Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n", bkpinfo->netfs_remote_dir, bkpinfo->netfs_mount);
     737        }
     738        unlink(tmp1);
     739        mr_free(tmp1);
     740    }
     741
     742    if (!flag_set['d'] && (flag_set['c'] || flag_set['w'] || flag_set['C'])) {
     743            tmp1 = mr_popup_and_get_string("Device", "Please specify the device", bkpinfo->media_device);
     744            if (tmp1 == NULL) {
     745                retval++;
     746                log_to_screen("User opted to cancel.");
     747            } else {
     748                mr_free(bkpinfo->media_device);
     749                bkpinfo->media_device = tmp1;
     750            }
     751        } else {
     752    }
     753
     754    if ((!flag_set['d'] && !flag_set['n'] && !flag_set['C']) && (! bkpinfo->restore_data)) {
     755        retval++;
     756        log_to_screen("Please specify the backup device/directory.\n");
     757        fatal_error("You didn't use -d to specify the backup device/directory.");
     758    }
     759
     760    for (i = '0'; i <= '9'; i++) {
     761        if (flag_set[i]) {
     762            bkpinfo->compression_level = i - '0';
     763        }                       /* not '\0' but '0' */
     764    }
     765
     766    if (flag_set['S']) {
     767        setup_scratchdir(flag_val['S']);
     768        mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->scratchdir);
     769        if (run_program_and_log_output(tmp1, 1)) {
     770            retval++;
     771            mr_free(tmp1);
     772            log_to_screen("Please specify a scratchdir which I can write to. :)");
     773            fatal_error("I cannot write to the scratchdir you specified.");
     774        }
     775        mr_free(tmp1);
     776
     777        mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->scratchdir, bkpinfo->scratchdir);
     778        if (run_program_and_log_output(tmp1, 1)) {
     779            retval++;
     780            mr_free(tmp1);
     781            log_to_screen("Please don't specify a SAMBA or VFAT or NFS scratchdir.");
     782            fatal_error("I cannot write to the scratchdir you specified.");
     783        }
     784        mr_free(tmp1);
     785    }
     786
     787    if (flag_set['T']) {
     788        setup_tmpdir(flag_val['T']);
     789        mr_asprintf(tmp1, "touch %s/.foo.dat", bkpinfo->tmpdir);
     790        i = run_program_and_log_output(tmp1, 1);
     791        mr_free(tmp1);
     792
     793        if (i) {
     794            retval++;
     795            log_to_screen("Please specify a tempdir which I can write to. :)");
     796            fatal_error("I cannot write to the tempdir you specified.");
     797        }
     798        mr_asprintf(tmp1, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir);
     799        i = run_program_and_log_output(tmp1, 1);
     800        mr_free(tmp1);
     801
     802        if (i) {
     803            retval++;
     804            log_to_screen("Please don't specify a SAMBA or VFAT or NFS tmpdir.");
     805            fatal_error("I cannot write to the tempdir you specified.");
     806        }
     807    }
     808
     809    if ((flag_set['A']) && (! bkpinfo->restore_data)) {
     810        mr_asprintf(bkpinfo->call_after_iso, "%s", flag_val['A']);
     811    }
     812
     813    if ((flag_set['B']) && (! bkpinfo->restore_data)) {
     814        mr_asprintf(bkpinfo->call_before_iso, "%s", flag_val['B']);
     815    }
     816
     817    if ((flag_set['H']) && (! bkpinfo->restore_data)) {
     818        g_cd_recovery = TRUE;
     819    }
     820
     821    if ((flag_set['l']) && (! bkpinfo->restore_data)) {
     822#ifdef __FreeBSD__
     823#  define BOOT_LOADER_CHARS "GLBMR"
     824#else
     825#  ifdef __IA64__
     826#    define BOOT_LOADER_CHARS "GER"
     827#  else
     828#    define BOOT_LOADER_CHARS "GLR"
     829#  endif
     830#endif
     831        if (!strchr(BOOT_LOADER_CHARS, (bkpinfo->boot_loader = flag_val['l'][0]))) {
     832            log_msg(1, "%c? What is %c? I need G, L, E or R.", bkpinfo->boot_loader, bkpinfo->boot_loader);
     833            fatal_error("Please specify GRUB, LILO, ELILO  or RAW with the -l switch");
     834        }
     835#undef BOOT_LOADER_CHARS
     836    }
     837
     838    if (flag_set['f']) {
     839        mr_free(bkpinfo->boot_device);
     840        mr_asprintf(bkpinfo->boot_device, "%s", resolve_softlinks_to_get_to_actual_device_file(flag_val['f']));
     841    }
     842
     843    if ((flag_set['P']) && (! bkpinfo->restore_data)) {
     844        mr_asprintf(bkpinfo->postnuke_tarball, "%s", flag_val['P']);
     845    }
     846
     847    if (flag_set['Q']) {
     848        i = which_boot_loader(tmp);
     849        log_msg(3, "boot loader is %c, residing at %s", i, tmp);
     850        printf("boot loader is %c, residing at %s\n", i, tmp);
     851        finish(0);
     852    }
     853
     854    if ((flag_set['L']) && (! bkpinfo->restore_data)) {
     855        bkpinfo->use_lzo = TRUE;
     856        if (run_program_and_log_output("which lzop", 2)) {
     857            retval++;
     858            log_to_screen("Please install LZOP. You can't use '-L' until you do.\n");
     859        }
     860    }
     861
     862    if (flag_set['F']) {
     863        log_msg(3, "-F means we will fail immediately at the first interaction request");
     864        g_fail_immediately = TRUE;
     865    }
     866
     867    if ((flag_set['G']) && (! bkpinfo->restore_data)) {
     868        bkpinfo->use_gzip = TRUE;
     869        if (run_program_and_log_output("which gzip", 2)) {
     870            retval++;
     871            log_to_screen("Please install gzip. You can't use '-G' until you do.\n");
     872        }
     873    }
     874
     875    if ((flag_set['Y']) && (! bkpinfo->restore_data)) {
     876        bkpinfo->use_lzma = TRUE;
     877        if (run_program_and_log_output("which lzma", 2)) {
     878            retval++;
     879            log_to_screen("Please install lzma. You can't use '-Y' until you do.\n");
     880        }
     881    }
     882
     883    bkpinfo->use_obdr = FALSE;
     884    if (flag_set['o']) {
     885        if ((!flag_set['t']) && (! bkpinfo->restore_data)) {
     886            log_to_screen("OBDR support is only available for tapes. Use the -t option");
     887            fatal_error("Aborting");
     888        }
     889        bkpinfo->use_obdr = TRUE;
     890    }
     891
     892#ifndef __FreeBSD__
     893    if ((!is_this_a_valid_disk_format("vfat")) && (! bkpinfo->restore_data)) {
     894        bkpinfo->make_cd_use_lilo = TRUE;
     895        log_to_screen("Your kernel appears not to support vfat filesystems. I am therefore");
     896        log_to_screen("using LILO instead of SYSLINUX as the media boot loader.");
     897    }
     898    if ((run_program_and_log_output("which mkfs.vfat", 2)) && (! bkpinfo->restore_data)) {
     899        bkpinfo->make_cd_use_lilo = TRUE;
     900#ifdef __IA32__
     901        log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as");
     902        log_to_screen("your boot loader. I shall therefore use LILO instead.");
     903#endif
     904#ifdef __IA64__
     905        log_to_screen("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI");
     906        log_to_screen("environment correctly. Please install it.");
     907        fatal_error("Aborting");
     908#endif
     909    }
     910#ifdef __IA64__
     911    /* We force ELILO usage on IA64 */
     912    bkpinfo->make_cd_use_lilo = TRUE;
     913#endif
     914#endif
     915
     916    if (! bkpinfo->restore_data) {
     917        i = flag_set['O'] + flag_set['V'];
     918        if (i == 0) {
     919            retval++;
     920            log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n");
     921        }
     922    }
     923
     924    if ((! bkpinfo->restore_data) && (flag_set['Z'])) {
     925            fatal_error("The -Z switch is only valid in restore mode");
     926    }
     927
     928    if (flag_set['Z']) {
     929        if (! strcmp(flag_val['Z'], "nuke")) {
     930            bkpinfo->restore_mode = nuke;
     931        } else if (! strcmp(flag_val['Z'], "interactive")) {
     932            bkpinfo->restore_mode = interactive;
     933        } else if (! strcmp(flag_val['Z'], "compare")) {
     934            bkpinfo->restore_mode = compare;
     935        } else if (! strcmp(flag_val['Z'], "mbr")) {
     936            bkpinfo->restore_mode = mbr;
     937        } else if (! strcmp(flag_val['Z'], "iso")) {
     938            bkpinfo->restore_mode = isoonly;
     939        } else if (! strcmp(flag_val['Z'], "isonuke")) {
     940            bkpinfo->restore_mode = isonuke;
     941        } else {
     942            bkpinfo->restore_mode = interactive;
     943        }
     944    }
     945
     946/* and finally... */
     947
     948    paranoid_free(tmp);
     949    return (retval);
     950}
     951
     952
     953
     954/**
     955 * @addtogroup cliGroup
     956 * @{
     957 */
     958/**
     959 * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv.
     960 * @param argc The argument count, including the program name; @p argc passed to main().
     961 * @param argv The argument vector; @p argv passed to main().
     962 * @param bkpinfo The backup information structure to populate.
     963 * @return The number of problems with the command line (0 for success).
     964 */
     965int
     966handle_incoming_parameters(int argc, char *argv[])
     967{
     968    /*@ int *** */
     969    int res = 0;
     970    int retval = 0;
     971    int i = 0;
     972
     973    /*@ buffers *************** */
     974    char flag_val[128][MAX_STR_LEN];
     975    bool flag_set[128];
     976
     977    for (i = 0; i < 128; i++) {
     978        flag_val[i][0] = '\0';
     979        flag_set[i] = FALSE;
     980    }
     981    bkpinfo->media_size = 650; /* default */
     982    res = retrieve_switches_from_command_line(argc, argv, flag_val, flag_set);
     983    retval += res;
     984    if (!retval) {
     985        res = process_switches(flag_val, flag_set);
     986        retval += res;
     987    }
     988
     989    log_msg(3, "Switches:-");
     990    for (i = 0; i < 128; i++) {
     991        if (flag_set[i]) {
     992            log_msg(3, "-%c %s", i, flag_val[i]);
     993        }
     994    }
     995    bkpinfo->boot_type = mr_boot_type();
     996
     997    return (retval);
    994998}
    995999
     
    10581062
    10591063
    1060 /**
    1061  * Turn signal-trapping on or off.
    1062  * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
    1063  */
    1064 void set_signals(int on)
    1065 {
    1066     int signals[] = { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
    1067     int i;
    1068 
    1069     signal(SIGPIPE, sigpipe_occurred);
    1070     for (i = 0; signals[i]; i++) {
    1071         if (on) {
    1072             signal(signals[i], terminate_daemon);
    1073         } else {
    1074             signal(signals[i], termination_in_progress);
    1075         }
    1076     }
    1077 }
    1078 
    1079 
    1080 
    10811064
    10821065/**
     
    10911074}
    10921075
     1076
     1077
     1078/**
     1079 * Turn signal-trapping on or off.
     1080 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
     1081 */
     1082void set_signals(int on)
     1083{
     1084    int signals[] = { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
     1085    int i;
     1086
     1087    signal(SIGPIPE, sigpipe_occurred);
     1088    for (i = 0; signals[i]; i++) {
     1089        if (on) {
     1090            signal(signals[i], terminate_daemon);
     1091        } else {
     1092            signal(signals[i], termination_in_progress);
     1093        }
     1094    }
     1095}
     1096
    10931097/* @} - end of cliGroup */
  • branches/3.3/mondo/src/common/libmondo-devices.c

    r3878 r3879  
    8080
    8181/**
    82  * Retract all CD trays and wait for autorun to complete.
    83  * @ingroup deviceGroup
    84  */
    85 void retract_CD_tray_and_defeat_autorun(void)
    86 {
    87 //  log_it("rctada: Retracting optical tray", __LINE__);
    88     if (!bkpinfo->please_dont_eject) {
    89         if (bkpinfo->media_device != NULL) {
    90             inject_device(bkpinfo->media_device);
    91     }
    92     if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
    93         log_it("autorun detected; sleeping for 2 seconds");
    94         sleep(2);
    95     }
    96 }
    97 
    98 
    99 
    100 /**
    101  * Find out what device is mounted as root (/).
    102  * @return Root device.
    103  * @note The returned string points to storage that needs to be freed by
    104  * caller
    105  * @bug A bit of a misnomer; it's actually finding out the root device.
    106  * The mountpoint (where it's mounted) will obviously be '/'.
    107  */
    108 char *where_is_root_mounted(void) {
    109 
    110 /*@ buffers **************** */
    111 char *tmp = NULL;
    112 
    113 #ifdef __FreeBSD__
    114     tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");
    115 #else
    116     tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//");
    117     if (strstr(tmp, "/dev/cciss/")) {
    118         mr_free(tmp);
    119         tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1");
    120     }
    121     if (strstr(tmp, "/dev/md")) {
    122         mr_free(tmp);
    123         tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");
    124     }
    125 #endif
    126 
    127 return (tmp);
    128 }
    129 
    130 
    131 
    132 /**
    133  * Determine whether we're booted off a ramdisk.
    134  * @return @c TRUE (we are) or @c FALSE (we aren't).
    135  * @ingroup utilityGroup
    136  */
    137 bool am_I_in_disaster_recovery_mode(void)
    138 {
    139     char *tmp = NULL;
    140     bool is_this_a_ramdisk = FALSE;
    141 
    142     tmp = where_is_root_mounted();
    143     log_msg(0, "root is mounted at %s", tmp);
    144     log_msg(0, "That doesn't mean %s is the root partition. It's just a debugging message. Relax. It's part of am_I_in_disaster_recovery_mode().", tmp);
    145 
    146 #ifdef __FreeBSD__
    147     if (strstr(tmp, "/dev/md")) {
    148         is_this_a_ramdisk = TRUE;
    149     }
    150 #else
    151     if (!strncmp(tmp, "/dev/ram", 8)
    152         || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
    153             && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
    154         || !strcmp(tmp, "/dev/root")) {
    155         is_this_a_ramdisk = TRUE;
    156     } else {
    157         is_this_a_ramdisk = FALSE;
    158     }
    159 #endif
    160     mr_free(tmp);
    161 
    162     if (is_this_a_ramdisk) {
    163         if (!does_file_exist("/THIS-IS-A-RAMDISK")) {
    164             log_to_screen("Using /dev/root is stupid of you but I'll forgive you.");
    165             is_this_a_ramdisk = FALSE;
    166         }
    167     }
    168     if (does_file_exist("/THIS-IS-A-RAMDISK")) {
    169         is_this_a_ramdisk = TRUE;
    170     }
    171 
    172     log_msg(1, "Is this a ramdisk? result = %s", (is_this_a_ramdisk) ? "TRUE" : "FALSE");
    173     return (is_this_a_ramdisk);
    174 }
    175 
    176 
    177 
    178 
    179 
    180 /**
    181  * Turn @c bkpinfo->backup_media_type into a human-readable string.
    182  * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
    183  * @note The returned string points to static storage that will be overwritten with each call.
    184  * @ingroup stringGroup
    185  */
    186 static char *bkptype_to_string(t_bkptype bt)
    187 {
    188     static char output[MAX_STR_LEN / 4];
    189     switch (bt) {
    190     case none:
    191         strcpy(output, "none");
    192         break;
    193     case iso:
    194         strcpy(output, "iso");
    195         break;
    196     case cdr:
    197         strcpy(output, "cdr");
    198         break;
    199     case cdstream:
    200         strcpy(output, "cdstream");
    201         break;
    202     case netfs:
    203         strcpy(output, "netfs");
    204         break;
    205     case tape:
    206         strcpy(output, "tape");
    207         break;
    208     case udev:
    209         strcpy(output, "udev");
    210         break;
    211     case usb:
    212         strcpy(output, "usb");
    213         break;
    214     default:
    215         strcpy(output, "default");
    216     }
    217     return (output);
    218 }
    219 
    220 
    221 
    222 /**
    223  * @addtogroup deviceGroup
    224  * @{
    225  */
    226 /**
    227  * Eject the tray of the specified CD device.
    228  * @param dev The device to eject.
    229  * @return the return value of the @c eject command. (0=success, nonzero=failure)
    230  */
    231 int eject_device(char *dev)
    232 {
    233     char *command = NULL;
    234     int res1 = 0, res2 = 0;
    235 
    236     if (dev == NULL) {
    237         return (1);
    238     }
    239 
    240     if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
    241         && g_backup_media_type != udev) {
    242         mr_asprintf(command, "mt -f %s offline", dev);
    243         res1 = run_program_and_log_output(command, 1);
    244         mr_free(command);
    245     } else {
    246         res1 = 0;
    247     }
    248 
    249 #ifdef __FreeBSD__
    250     if (strstr(dev, "acd")) {
    251         mr_asprintf(command, "cdcontrol -f %s eject", dev);
    252     } else {
    253         mr_asprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`", dev);
    254     }
    255 #else
    256     mr_asprintf(command, "eject %s", dev);
    257 #endif
    258 
    259     log_msg(3, "Ejecting %s", dev);
    260     res2 = run_program_and_log_output(command, 1);
    261     mr_free(command);
    262     if (res1 && res2) {
    263         return (1);
    264     } else {
    265         return (0);
    266     }
    267 }
    268 
    269 /**
    270  * Load (inject) the tray of the specified CD device.
    271  * @param dev The device to load/inject.
    272  * @return 0 for success, nonzero for failure.
    273  */
    274 int inject_device(char *dev)
    275 {
    276     char *command = NULL;
    277     int i;
    278 
    279     if (dev == NULL) {
    280         return (1);
    281     }
    282 
    283 #ifdef __FreeBSD__
    284     if (strstr(dev, "acd")) {
    285         mr_asprintf(command, "cdcontrol -f %s close", dev);
    286     } else {
    287         mr_asprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`", dev);
    288     }
    289 #else
    290     mr_asprintf(command, "eject -t %s", dev);
    291 #endif
    292     i = run_program_and_log_output(command, FALSE);
    293     mr_free(command);
    294     return (i);
    295 }
    296 
    297 
    298 /**
    299  * Determine whether the specified @p device (really, you can use any file)
    300  * exists.
    301  * @return TRUE if it exists, FALSE if it doesn't.
    302  */
    303 bool does_device_exist(char *device)
    304 {
    305 
    306     /*@ buffers *********************************************************** */
    307     char *tmp = NULL;
    308     bool ret;
    309 
    310     assert_string_is_neither_NULL_nor_zerolength(device);
    311 
    312     mr_asprintf(tmp, "ls %s > /dev/null 2> /dev/null", device);
    313 
    314     if (system(tmp)) {
    315         ret = FALSE;
    316     } else {
    317         ret = TRUE;
    318     }
    319     mr_free(tmp);
    320     return (ret);
    321 }
    322 
    323 
    324 /**
    325  * Determine whether a non-Microsoft partition exists on any connected hard drive.
    326  * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent machine).
    327  */
    328 bool does_nonMS_partition_exist(void)
    329 {
    330 #if __FreeBSD__
    331     return
    332         !system("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
    333 #else
    334     return
    335         !system("mr-parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|EFI|FAT|NTFS)'");
    336 #endif
    337 }
    338 
    339 /**
    340  * Determine whether the specified @p partno exists on the specified @p drive.
    341  * @param drive The drive to search for the partition in.
    342  * @param partno The partition number to look for.
    343  * @return 0 if it exists, nonzero otherwise.
    344  */
    345 int does_partition_exist(const char *drive, int partno)
    346 {
    347     /*@ buffers **************************************************** */
    348     char *program = NULL;
    349     char *incoming = NULL;
    350     char *searchstr = NULL;
    351 
    352     /*@ ints ******************************************************* */
    353     int res = 0;
    354 
    355     /*@ pointers *************************************************** */
    356     FILE *fin;
    357 
    358     /*@ end vars *************************************************** */
    359     assert_string_is_neither_NULL_nor_zerolength(drive);
    360     assert(partno >= 0 && partno < 999);
    361 
    362 #ifdef __FreeBSD__
    363     // We assume here that this is running from mondorestore. (It is.)
    364     tmp = build_partition_name(drive, partno);
    365     mr_asprintf(program, "ls %s %s >/dev/null 2>&1", drive, tmp);
    366     mr_free(tmp);
    367     res = system(program);
    368     mr_free(program);
    369     return(res);
    370 #endif
    371 
    372     mr_asprintf(program, "mr-parted2fdisk -l %s 2> /dev/null", drive);
    373     fin = popen(program, "r");
    374     if (!fin) {
    375         log_it("program=%s", program);
    376         log_OS_error("Cannot popen-in program");
    377         mr_free(program);
    378         return (0);
    379     }
    380     mr_free(program);
    381 
    382     searchstr = build_partition_name(drive, partno);
    383     mr_strcat(searchstr, " ");
    384     for (res = 0, mr_getline(incoming, fin); !res && !feof(fin) ; mr_getline(incoming, fin)) {
    385         if (strstr(incoming, searchstr)) {
    386             res = 1;
    387         }
    388         mr_free(incoming);
    389     }
    390     mr_free(searchstr);
    391     mr_free(incoming);
    392 
    393     if (pclose(fin)) {
    394         log_OS_error("Cannot pclose fin");
    395     }
    396     return (res);
    397 }
    398 
    399 
    400 
    401 
    402 
    403 /**
    404  * Determine whether given NULL-terminated @p str exists in the begining of @p dev.
    405  * @param dev The device to look in.
    406  * @param str The string to look for.
    407  * @return TRUE if it exists, FALSE if it doesn't.
    408  */
    409 bool does_string_exist_in_boot_block(char *dev, char *str)
    410 {
    411     /*@ buffers **************************************************** */
    412     char *command = NULL;
    413 
    414     /*@ end vars *************************************************** */
    415     int i;
    416 
    417     assert_string_is_neither_NULL_nor_zerolength(dev);
    418     assert_string_is_neither_NULL_nor_zerolength(str);
    419 
    420     /* For UEFI detection, this should be extended to count=1000 ! */
    421     if (bkpinfo->boot_type == UEFI) {
    422         mr_asprintf(command, "dd if=%s bs=446 count=1000 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, str);
    423     } else {
    424         mr_asprintf(command, "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, str);
    425     }
    426     i = system(command);
    427     mr_free(command);
    428     if (i) {
    429         return (FALSE);
    430     } else {
    431         return (TRUE);
    432     }
    433 }
    434 
    435 /**
    436  * Determine whether specified @p str exists in the first @p n sectors of
    437  * @p dev.
    438  * @param dev The device to look in.
    439  * @param str The string to look for.
    440  * @param n The number of 512-byte sectors to search.
    441  */
    442 bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)
    443 {
    444     /*@ buffers **************************************************** */
    445     char *command = NULL;
    446     /*@ end vars *************************************************** */
    447     int i;
    448 
    449     mr_asprintf(command, "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, n, str);
    450     i = system(command);
    451     mr_free(command);
    452     if (i) {
    453         return (FALSE);
    454     } else {
    455         return (TRUE);
    456     }
    457 }
    458 
    459 
    460 /*
    461  * This function tries to find an optical media device
    462  * and return it's device file to the caller that needs to free it
    463  */
    464 char *find_optical_device(void) {
    465     char *dev = NULL;
    466     char *tmp1 = NULL;
    467     char *command = NULL;
    468 
    469     log_to_screen("I am looking for your optical burner. Please wait.");
    470 
    471     if (bkpinfo->media_device != NULL) {
    472         log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device);
    473         return (bkpinfo->media_device);
    474     }
    475 
    476     mr_asprintf(tmp1, "cdrecord -inq 2> /dev/null | grep -E '^Detected '  | cut -d':' -f2");
    477     dev = call_program_and_get_last_line_of_output(tmp1);
    478     mr_free(tmp1);
    479 
    480     if ((dev != NULL) && does_file_exist(dev)) {
    481         log_msg(2, "find_optical_device found %s automatically", dev);
    482     } else {
    483         mr_free(dev);
    484         tmp1 = find_home_of_exe("lsscsi");
    485         if (tmp1 != NULL) {
    486             mr_asprintf(command, "%s | grep ' cd' | awk '{print $NF}' | head -1", tmp1);
    487             dev = call_program_and_get_last_line_of_output(command);
    488             mr_free(command);
    489         }
    490         mr_free(tmp1);
    491 
    492         if ((dev == NULL) || !does_file_exist(dev)) {
    493             /* trying something else then */
    494             mr_asprintf(dev, "%s", VANILLA_SCSI_CDROM);
    495             if (!does_file_exist(dev)) {
    496                 mr_asprintf(dev, "%s", ALT_CDROM);
    497                 if (!does_file_exist(dev)) {
    498                     mr_asprintf(dev, "%s", "/dev/cdrom");
    499                     if (!does_file_exist(dev)) {
    500                         mr_asprintf(dev, "%s", "/dev/dvd");
    501                         if (!does_file_exist(dev)) {
    502                             log_it("Unable to find a tape device on this system");
    503                         }
    504                     }
    505                 }
    506             }
    507         }
    508         if (dev != NULL) {
    509             log_it("find_optical_device found %s manually", dev);
    510         }
    511     }
    512 
    513     if ((dev != NULL) && does_file_exist(dev)) {
    514         log_it("find_optical_device returns %s", dev);
    515     } else {
    516         mr_free(dev);
    517         log_it("find_optical_device found no optical burner on your system returning NULL");
    518     }
    519     return(dev);
    520 }
    521 /**
    522 * Mount the CD-ROM or USB device at /mnt/cdrom.
    523 * @param bkpinfo The backup information structure. Fields used:
    524 * - @c bkpinfo->backup_media_type
    525 * - @c bkpinfo->disaster_recovery
    526 * - @c bkpinfo->isodir
    527 * - @c bkpinfo->media_device
    528 * @return TRUE for success, FALSE for failure.
    529 */
    530 bool mount_media(const char *mountpoint) {
    531 
    532     char *mount_cmd = NULL;
    533     char *mountdir = NULL;
    534     char *tmp = NULL;
    535     int i = 0, res = 0;
    536 #ifdef __FreeBSD__
    537     char mdd[32];
    538     char *mddev = mdd;
    539     char *dev;
    540 #endif
    541 
    542     if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
    543         log_msg(8, "Tape/udev. Therefore, no need to mount a media.");
    544         return(TRUE);
    545     }
    546 
    547     assert_string_is_neither_NULL_nor_zerolength(mountpoint);
    548 
    549     mr_asprintf(tmp, "mount | grep -F %s", mountpoint);
    550     if (!run_program_and_log_output(tmp, FALSE)) {
    551         log_msg(2, "mount_media() - media already mounted. Fair enough.");
    552         mr_free(tmp);
    553         return (TRUE);
    554     }
    555     mr_free(tmp);
    556 
    557     make_hole_for_dir(mountpoint);
    558 
    559     if (bkpinfo->backup_media_type == netfs) {
    560         log_msg(2, "Mounting for Network thingy");
    561         log_msg(2, "isodir = %s", bkpinfo->isodir);
    562         if (((bkpinfo->isodir == NULL) || !strcmp(bkpinfo->isodir, "/")) && am_I_in_disaster_recovery_mode()) {
    563             mr_asprintf(bkpinfo->isodir, "%s", "/tmp/isodir");
    564             log_msg(1, "isodir is being set to %s", bkpinfo->isodir);
    565         }
    566 #ifdef __FreeBSD__
    567         if (bkpinfo->netfs_remote_dir != NULL) {
    568             // NETFS
    569             mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);
    570         } else {
    571             // ISO
    572             mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number);
    573         }
    574         mddev = make_vn(mount_cmd);
    575         mr_free(mount_cmd);
    576 
    577         mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint);
    578 #else
    579         if (bkpinfo->netfs_remote_dir != NULL) {
    580             // NETFS
    581             mr_asprintf(mount_cmd, "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number, mountpoint);
    582         } else {
    583             // ISO
    584             mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number, mountpoint);
    585         }
    586 #endif
    587 
    588     } else if (bkpinfo->backup_media_type == iso) {
    589         if (bkpinfo->subdir) {
    590             mr_asprintf(mountdir, "%s/%s", bkpinfo->isodir, bkpinfo->subdir);
    591         } else {
    592             mr_asprintf(mountdir, "%s", bkpinfo->isodir);
    593         }
    594 #ifdef __FreeBSD__
    595         mr_asprintf(mount_cmd, "%s/%s-%d.iso", mountdir, bkpinfo->prefix, g_current_media_number);
    596         mddev = make_vn(mount_cmd);
    597         mr_free(mount_cmd);
    598 
    599         mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint);
    600 #else
    601         mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", mountdir, bkpinfo->prefix, g_current_media_number, mountpoint);
    602 #endif
    603         mr_free(mountdir);
    604     } else if (bkpinfo->backup_media_type == usb) {
    605         mr_asprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, mountpoint);
    606     } else {    //  optical
    607         if (bkpinfo->disaster_recovery
    608             && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
    609             mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE"));
    610         } else {
    611             if (bkpinfo->media_device == NULL) {
    612                 bkpinfo->media_device = find_optical_device();
    613             }
    614         }
    615 
    616 #ifdef __FreeBSD__
    617         if (g_ISO_restore_mode) {
    618             mr_asprintf(dev, "%s", make_vn(bkpinfo->media_device));
    619             if (!dev) {
    620                 mr_asprintf(command, "Unable to mount ISO (make_vn(%s) failed)", bkpinfo->media_device);
    621                 fatal_error(command);
    622             }
    623             mr_free(bkpinfo->media_device);
    624             bkpinfo->media_device = dev
    625         }
    626 
    627         mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE);
    628 #else
    629         mr_asprintf(mount_cmd, "mount %s -o loop,ro -t iso9660 %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE);
    630 #endif
    631         log_msg(2, "(mount_media) --- command = %s", mount_cmd);
    632         // usefull ??
    633         if (strncmp(bkpinfo->media_device, "/dev/", 5) == 0) {
    634             retract_CD_tray_and_defeat_autorun();
    635         }
    636     }
    637 
    638     for (i = 0; i < 2; i++) {
    639         res = run_program_and_log_output(mount_cmd, FALSE);
    640         if (!res) {
    641             break;
    642         } else {
    643             log_msg(2, "Failed to mount device.");
    644             sleep(5);
    645             sync();
    646         }
    647     }
    648     mr_free(mount_cmd);
    649 
    650     if (res) {
    651         log_msg(2, "Failed, despite %d attempts", i);
    652         return(FALSE);
    653     } else {
    654         log_msg(2, "Mounted media drive OK");
    655         return(TRUE);
    656     }
    657 }
    658 /**************************************************************************
    659 *END_MOUNT_MEDIA                                                         *
    660 **************************************************************************/
    661 
    662 
    663 
    664 
    665 /**
    666  * Try to mount CD/DVD at @p mountpoint. If the CD/DVD is not found or has
    667  * not been specified, call find_optical_device() to find it.
    668  * @param mountpoint Where to mount the CD-ROM.
    669  * @return TRUE for success, FALSE for failure.
    670  * @see mount_media
    671  */
    672 bool find_and_mount_actual_cd(char *mountpoint) {
    673 
    674     /*@ buffers ***************************************************** */
    675 
    676     /*@ int's  ****************************************************** */
    677     bool res;
    678 
    679     /*@ end vars **************************************************** */
    680 
    681     assert(bkpinfo != NULL);
    682     assert_string_is_neither_NULL_nor_zerolength(mountpoint);
    683 
    684     if (bkpinfo->media_device == NULL) {
    685         bkpinfo->media_device = find_optical_device();
    686     }
    687 
    688     if (bkpinfo->backup_media_type != iso) {
    689         retract_CD_tray_and_defeat_autorun();
    690     }
    691 
    692     if ((bkpinfo->media_device == NULL) || (res = mount_media(mountpoint))) {
    693         mr_free(bkpinfo->media_device);
    694         if ((bkpinfo->media_device = mr_popup_and_get_string("CD-ROM device", "Please enter your CD-ROM's /dev device", "/dev/cdrom")) == NULL) {
    695             res = TRUE;
    696         } else {
    697             res = mount_media(mountpoint);
    698         }
    699     }
    700     if (res) {
    701         log_msg(1, "mount failed");
    702     } else {
    703         log_msg(1, "mount succeeded with %s", bkpinfo->media_device);
    704     }
    705     return (res);
    706 }
    707 /*
    708  * This function tries to find a USB media device
    709  * and return it's device file to the caller that needs to free it
    710  */
    711 char *find_usb_device(void)
    712 {
    713     char *dev = NULL;
    714     char *tmp1 = NULL;
    715     char *command = NULL;
    716 
    717     log_to_screen("I am looking for your USB key. Please wait.");
    718 
    719     if (bkpinfo->media_device != NULL) {
    720         log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device);
    721         return (bkpinfo->media_device);
    722     }
    723 
    724     tmp1 = find_home_of_exe("lsscsi");
    725     if (tmp1 != NULL) {
    726         mr_asprintf(command, "%s | grep ' disk' | grep USB | awk '{print $NF}' | head -1", tmp1);
    727         dev = call_program_and_get_last_line_of_output(command);
    728         mr_free(command);
    729     }
    730     mr_free(tmp1);
    731 
    732     if ((dev == NULL) || !does_file_exist(dev)) {
    733         tmp1 = find_home_of_exe("lsblk");
    734         if (tmp1 != NULL) {
    735             mr_asprintf(command, "%s --noheadings --raw --output rm,tran,type,path --sort path | awk '/^1 usb disk/ {d=$4} END {print d}'", tmp1);
    736             dev = call_program_and_get_last_line_of_output(command);
    737             mr_free(command);
    738         }
    739         mr_free(tmp1);
    740         log_it("Unable to find a tape device on this system");
    741     }
    742     if (dev != NULL) {
    743         log_it("find_usb_device found %s manually", dev);
    744     }
    745 
    746     if ((dev != NULL) && does_file_exist(dev)) {
    747         log_it("find_usb_device returns %s", dev);
    748     } else {
    749         mr_free(dev);
    750         log_it("find_usb_device found no USB key on your system returning NULL");
    751     }
    752     return(dev);
    753 }
    754 
    755 
    756 
    757 /* Generic fund to find a media
    758  * Return a dynamically allocted string that caller needs to free
    759  * @media_type is the type of media to look for
    760  */
    761 
    762 char *find_device(t_bkptype media_type) {
    763 
    764     if (media_type == usb) {
    765         return(find_usb_device());
    766     } else if (media_type == tape) {
    767         return(find_tape_device());
    768     } else if ((media_type == dvd) || (media_type == cdr)) {
    769         return(find_optical_device());
    770     } else {
    771         return(NULL);
    772     }
    773 }
    774 
    775 
    776 
    777 
    778 #include <sys/ioctl.h>
    779 
    780 /**
    781  * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls
    782  * and @c dmesg.
    783  * @param drive The device to find the size of.
    784  * @return size in megabytes.
    785  */
    786 long get_phys_size_of_drive(char *drive)
    787 {
    788     int fd;
    789 #if linux
    790     unsigned long long s = 0;
    791     int fileid, cylinders = 0;
    792     int cylindersize = 0;
    793     int gotgeo = 0;
    794 
    795 
    796     struct hd_geometry hdgeo;
    797 #elif __FreeBSD__
    798     off_t s;
    799 #endif
    800 
    801     long outvalA = -1;
    802     long outvalB = -1;
    803     long outvalC = -1;
    804 
    805     if ((fd = open(drive, O_RDONLY)) != -1) {
    806         if (ioctl(fd,
    807 #if linux
    808 #ifdef BLKGETSIZE64
    809                   BLKGETSIZE64,
    810 #else
    811                   BLKGETSIZE,
    812 #endif
    813 #elif __FreeBSD__
    814                   DIOCGMEDIASIZE,
    815 #endif
    816                   &s) != -1) {
    817             close(fd);
    818             // s>>11 works for older disks but not for newer ones
    819             outvalB =
    820 #if linux
    821 #ifdef BLKGETSIZE64
    822                 s >> 20
    823 #else
    824                 s >> 11
    825 #endif
    826 #else
    827                 s >> 20
    828 #endif
    829                 ;
    830         }
    831     }
    832 
    833     if (outvalB <= 0) {
    834         log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
    835 #if linux
    836         fileid = open(drive, O_RDONLY);
    837         if (fileid != -1) {
    838             if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {
    839                 if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
    840                     cylindersize = hdgeo.heads * hdgeo.sectors / 2;
    841                     outvalA = cylindersize * cylinders / 1024;
    842                     log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",
    843                             hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);
    844                     gotgeo = 1;
    845                 } else {
    846                     log_msg(1, "Harddisk geometry wrong");
    847                 }
    848             } else {
    849                 log_msg(1,
    850                         "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",
    851                         strerror(errno));
    852             }
    853             close(fileid);
    854         } else {
    855             log_msg(1, "Failed to open %s for reading: %s", drive,
    856                     strerror(errno));
    857         }
    858         if (!gotgeo) {
    859             log_msg(1, "Failed to get harddisk geometry, using old mode");
    860         }
    861 #endif
    862     }
    863 // OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
    864 // NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
    865 
    866     outvalC = (outvalA > outvalB) ? outvalA : outvalB;
    867 
    868 //  log_msg (5, "drive = %s, error = %s", drive, strerror (errno));
    869 //  fatal_error ("GPSOD: Unable to get size of drive");
    870     log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
    871             outvalC);
    872 
    873     return (outvalC);
    874 }
    875 
    876 /**
    877  * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
    878  * under Linux and @c lsvfs under FreeBSD.
    879  * @param format The format to test.
    880  * @return TRUE if the format is supported, FALSE if not.
    881  */
    882 bool is_this_a_valid_disk_format(char *format)
    883 {
    884     char *good_formats = NULL;
    885     char *command = NULL;
    886     char *format_sz = NULL;
    887     char *p = NULL;
    888 
    889     FILE *pin;
    890     int retval;
    891 
    892     assert_string_is_neither_NULL_nor_zerolength(format);
    893 
    894     mr_asprintf(format_sz, "%s ", format);
    895 
    896 #ifdef __FreeBSD__
    897     mr_asprintf(command, "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
    898 #else
    899     mr_asprintf(command, "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
    900 #endif
    901 
    902     pin = popen(command, "r");
    903     mr_free(command);
    904 
    905     if (!pin) {
    906         log_OS_error("Unable to read good formats");
    907         retval = 0;
    908     } else {
    909         mr_getline(p, pin);
    910         good_formats = mr_strip_spaces(p);
    911         mr_free(p);
    912         (void)pclose(pin);
    913         mr_strcat(good_formats, " swap lvm raid ntfs-3g ntfs 7 ");  // " ntfs 7 " -- um, cheating much? :)
    914         if (strstr(good_formats, format_sz)) {
    915             retval = 1;
    916         } else {
    917             retval = 0;
    918         }
    919     }
    920     mr_free(good_formats);
    921     mr_free(format_sz);
    922 
    923     return (retval);
    924 }
    925 
    926 
    927 /** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
    928 
    929 /**
    930  * Determine whether @p device_raw is currently mounted.
    931  * @param device_raw The device to check.
    932  * @return TRUE if it's mounted, FALSE if not.
    933  */
    934 bool is_this_device_mounted(char *device_raw)
    935 {
    936 
    937     char *tmp = NULL;
    938     bool retval = FALSE;
    939 
    940     mr_asprintf(tmp, "mr-device-mounted %s > /dev/null", device_raw);
    941     if (system(tmp) == 0) {
    942         retval = TRUE;
    943     }
    944     mr_free(tmp);
    945     return(retval);
    946 }
    947 
    948 /* previous C version replaced by a call to a perl script, fixing issues with symlinks between devices - RHEL7 e.g.
    949     FILE *fin;
    950 
    951     char *incoming = NULL;
    952     char *device_with_tab = NULL;
    953     char *device_with_space = NULL;
    954     char *tmp = NULL;
    955     bool retval = FALSE;
    956 
    957 #ifdef __FreeBSD__
    958 #define SWAPLIST_COMMAND "swapinfo"
    959 #else
    960 #define SWAPLIST_COMMAND "cat /proc/swaps"
    961 #endif
    962 
    963 
    964     if (device_raw == NULL) {
    965         return(FALSE);
    966     }
    967 
    968     if (device_raw[0] != '/' && !strstr(device_raw, ":/")) {
    969         log_msg(1, "%s needs to have a '/' prefixed - I'll do it", device_raw);
    970         mr_asprintf(tmp, "/%s", device_raw);
    971     } else {
    972         mr_asprintf(tmp, "%s", device_raw);
    973     }
    974     log_msg(1, "Is %s mounted?", tmp);
    975     if (!strcmp(tmp, "/proc") || !strcmp(tmp, "proc")) {
    976         log_msg(1, "I don't know how the heck /proc made it into the mountlist. I'll ignore it.");
    977         mr_free(tmp);
    978         return(FALSE);
    979     }
    980     mr_asprintf(device_with_tab, "%s\t", tmp);
    981     mr_asprintf(device_with_space, "%s ", tmp);
    982     mr_free(tmp);
    983 
    984     if (!(fin = popen("mount", "r"))) {
    985         log_OS_error("Cannot popen 'mount'");
    986         return(FALSE);
    987     }
    988 
    989     for (mr_getline(incoming, fin); !feof(fin); mr_getline(incoming, fin)) {
    990         if (strstr(incoming, device_with_space) || strstr(incoming, device_with_tab)) {
    991             paranoid_pclose(fin);
    992             mr_free(incoming);
    993             return(TRUE);
    994         }
    995         mr_free(incoming);
    996     }
    997     mr_free(incoming);
    998     mr_free(device_with_tab);
    999     paranoid_pclose(fin);
    1000 
    1001     mr_asprintf(tmp, "%s | grep -E \"^%s\" > /dev/null 2> /dev/null", SWAPLIST_COMMAND, device_with_space);
    1002     mr_free(device_with_space);
    1003     log_msg(4, "tmp (command) = '%s'", tmp);
    1004     if (!system(tmp)) {
    1005         retval = TRUE;
    1006     }
    1007     mr_free(tmp);
    1008     return(retval);
    1009 }
    1010 */
    1011 
    1012 #ifdef __FreeBSD__
    1013 //                       CODE IS FREEBSD-SPECIFIC
    1014 /**
    1015  * Create a loopback device for specified @p fname.
    1016  * @param fname The file to associate with a device.
    1017  * @return /dev entry for the device, or NULL if it couldn't be allocated.
    1018  */
    1019 char *make_vn(char *fname)
    1020 {
    1021     char *device = (char *) malloc(MAX_STR_LEN);
    1022     char *mddevice = NULL;
    1023     char *command = NULL;
    1024     char *tmp = NULL;
    1025     int vndev = 2;
    1026 
    1027     tmp = call_program_and_get_last_line_of_output("/sbin/sysctl -n kern.osreldate");
    1028     if (atoi(tmp) < 500000) {
    1029         do {
    1030             mr_asprintf(mddevice, "vn%ic", vndev++);
    1031             mr_free(command);
    1032             mr_asprintf(command, "vnconfig %s %s", mddevice, fname);
    1033             if (vndev > 10) {
    1034                 mr_free(tmp);
    1035                 mr_free(mddevice);
    1036                 mr_free(command);
    1037                 return NULL;
    1038             }
    1039         }
    1040         while (system(command));
    1041     } else {
    1042         mr_asprintf(command, "mdconfig -a -t vnode -f %s", fname);
    1043         mddevice = call_program_and_get_last_line_of_output(command);
    1044         if (!strstr(mddevice, "md")) {
    1045             mr_free(tmp);
    1046             mr_free(command);
    1047             mr_free(mddevice);
    1048             return NULL;
    1049         }
    1050     }
    1051     mr_free(tmp);
    1052     mr_free(command);
    1053     sprintf(device, "/dev/%s", mddevice);
    1054     mr_free(mddevice);
    1055     return device;
    1056 }
    1057 
    1058 
    1059 
    1060 //                       CODE IS FREEBSD-SPECIFIC
    1061 /**
    1062  * Deallocate specified @p dname.
    1063  * This should be called when you are done with the device created by make_vn(),
    1064  * so the system does not run out of @c vn devices.
    1065  * @param dname The device to deallocate.
    1066  * @return 0 for success, nonzero for failure.
    1067  */
    1068 int kick_vn(char *dname)
    1069 {
    1070     char *command = NULL;
    1071     char *tmp = NULL;
    1072     int res = 0;
    1073 
    1074     if (strncmp(dname, "/dev/", 5) == 0) {
    1075         dname += 5;
    1076     }
    1077 
    1078     tmp = call_program_and_get_last_line_of_output("/sbin/sysctl -n kern.osreldate");
    1079     if (atoi(tmp) < 500000) {
    1080         mr_asprintf(command, "vnconfig -d %s", dname);
    1081     } else {
    1082         mr_asprintf(command, "mdconfig -d -u %s", dname);
    1083     }
    1084     mr_free(tmp);
    1085     res = system(command);
    1086     mr_free(command);
    1087     return(res);
    1088 }
    1089 #endif
    1090 
    1091 
    1092 /**
    1093  * Mount the CD-ROM at @p mountpoint.
    1094  * @param device The device (or file if g_ISO_restore_mode) to mount.
    1095  * @param mountpoint The place to mount it.
    1096  * @return 0 for success, nonzero for failure.
    1097  */
    1098 int mount_USB_here(char *device, char *mountpoint)
    1099 {
    1100     /*@ buffer ****************************************************** */
    1101     char *command = NULL;
    1102     int retval;
    1103 
    1104     assert_string_is_neither_NULL_nor_zerolength(device);
    1105     assert_string_is_neither_NULL_nor_zerolength(mountpoint);
    1106 
    1107     make_hole_for_dir(mountpoint);
    1108     if (isdigit(device[0])) {
    1109         return(1);
    1110     }
    1111     log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device, mountpoint);
    1112 
    1113 #ifdef __FreeBSD__
    1114     mr_asprintf(command, "mount_vfat %s %s 2>> %s", device, mountpoint, MONDO_LOGFILE);
    1115 
    1116 #else
    1117     mr_asprintf(command, "mount %s -t vfat %s 2>> %s", device, mountpoint, MONDO_LOGFILE);
    1118 #endif
    1119 
    1120     log_msg(4, command);
    1121     retval = system(command);
    1122     log_msg(1, "system(%s) returned %d", command, retval);
    1123     mr_free(command);
    1124 
    1125     return (retval);
    1126 }
    1127 
    1128 /**
    1129  * Find out what number CD is in the drive.
    1130  * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
    1131  * @return The current CD number, or -1 if it could not be found.
    1132  * @note If the CD is not mounted, it will be mounted
    1133  * (and remain mounted after this function returns).
    1134  */
    1135 int what_number_cd_is_this(void) {
    1136 
    1137     int cd_number = -1;
    1138     char *mountdev = NULL;
    1139     char *tmp = NULL;
    1140 
    1141     assert(bkpinfo != NULL);
    1142 //  log_it("Asking what_number_cd_is_this");
    1143     if ((g_ISO_restore_mode) || (g_restoring_live_from_cd)) {
    1144         tmp = call_program_and_get_last_line_of_output("mount | grep iso9660 | awk '{print $3;}'");
    1145         mr_asprintf(mountdev, "%s%s", tmp, "/archives/THIS-CD-NUMBER");
    1146         mr_free(tmp);
    1147         cd_number = atoi(last_line_of_file(mountdev));
    1148         mr_free(mountdev);
    1149         return (cd_number);
    1150     }
    1151 
    1152     if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {
    1153         log_it("ERROR: bkpinfo->media_device shoulnd't be unaccessible here\n");
    1154         /* trying again ! */
    1155         bkpinfo->media_device = find_optical_device();
    1156     }
    1157     if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {
    1158         fatal_error("ERROR: bkpinfo->media_device shoulnd't really be unaccessible here\n");
    1159     }
    1160     if (!is_this_device_mounted(MNT_CDROM)) {
    1161         mount_media(MNT_CDROM);
    1162     }
    1163 
    1164     cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
    1165     return(cd_number);
    1166 }
    1167 
    1168 
    1169 
    1170 
    1171 /**
    1172  * Ask the user for CD number @p cd_number_i_want.
    1173  * Sets g_current_media_number once the correct CD is inserted.
    1174  * @param bkpinfo The backup information structure. Fields used:
    1175  * - @c bkpinfo->backup_media_type
    1176  * - @c bkpinfo->prefix
    1177  * - @c bkpinfo->isodir
    1178  * - @c bkpinfo->media_device
    1179  * - @c bkpinfo->please_dont_eject_when_restoring
    1180  * @param cd_number_i_want The CD number to ask for.
    1181  */
    1182 void
    1183 insist_on_this_cd_number(int cd_number_i_want)
    1184 {
    1185 
    1186     /*@ int ************************************************************* */
    1187     int res = 0;
    1188 
    1189 
    1190     /*@ buffers ********************************************************* */
    1191     char *tmp = NULL;
    1192     char *mds = NULL;
    1193     char *request = NULL;
    1194 
    1195     assert(bkpinfo != NULL);
    1196     assert(cd_number_i_want > 0);
    1197 
    1198 //  log_msg(3, "Insisting on CD number %d", cd_number_i_want);
    1199 
    1200     if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    1201         log_msg(3,
    1202                 "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
    1203         return;
    1204     }
    1205     if (!does_file_exist(MNT_CDROM)) {
    1206         mr_asprintf(tmp, "mkdir -p " MNT_CDROM);
    1207         run_program_and_log_output(tmp, 5);
    1208         mr_free(tmp);
    1209     }
    1210 
    1211     if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso || bkpinfo->backup_media_type == netfs) {
    1212         g_ISO_restore_mode = TRUE;
    1213     }
    1214     if ((res = what_number_cd_is_this()) != cd_number_i_want) {
    1215         log_msg(3, "Currently, we hold %d but we want %d", res, cd_number_i_want);
    1216 
    1217         /* Now we need to umount the current media to have the next mounted after */
    1218         run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
    1219         log_msg(3, "Mounting next media %d",cd_number_i_want);
    1220         g_current_media_number = cd_number_i_want;
    1221         mount_media(MNT_CDROM);
    1222 
    1223         mds = media_descriptor_string(bkpinfo->backup_media_type);
    1224         log_msg(3, "Insisting on %s #%d", mds, cd_number_i_want);
    1225         mr_asprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);
    1226         mr_free(mds);
    1227 
    1228         while (what_number_cd_is_this() != cd_number_i_want) {
    1229             sync();
    1230             if (is_this_device_mounted(MNT_CDROM)) {
    1231                 res =
    1232                     run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
    1233             } else {
    1234                 res = 0;
    1235             }
    1236             if (res) {
    1237                 log_to_screen("WARNING - failed to unmount CD-ROM drive");
    1238             }
    1239             if (!bkpinfo->please_dont_eject) {
    1240                 res = eject_device(bkpinfo->media_device);
    1241             } else {
    1242                 res = 0;
    1243             }
    1244             if (res) {
    1245                 log_to_screen("WARNING - failed to eject CD-ROM disk");
    1246             }
    1247             popup_and_OK(request);
    1248             if (!bkpinfo->please_dont_eject) {
    1249                 inject_device(bkpinfo->media_device);
    1250             }
    1251             sync();
    1252         }
    1253         mr_free(request);
    1254 
    1255         log_msg(1, "Thankyou. Proceeding...");
    1256         g_current_media_number = cd_number_i_want;
    1257     }
    1258 }
    1259 
    1260 /* @} - end of deviceGroup */
    1261 
    1262 
    1263 
    1264 /**
    1265  * Creates a singly linked list of all of the non-NETFS mounted file systems.
    1266  * @param DSFptr A pointer  to the structure MOUNTED_FS_STRUCT used to hold
    1267  * the list of mounted file systems.
    1268  * @return None.
    1269  */
    1270 static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
    1271 {
    1272     assert (DSFptr);
    1273     if (DSF_Head == NULL) {
    1274         DSF_Head = DSFptr;
    1275     } else {
    1276         DSF_Tail->next = DSFptr;
    1277     }
    1278     DSFptr->next = NULL;
    1279     DSF_Tail = DSFptr;
    1280 }
    1281 
    1282 /**
    1283  * Find the structure, in the singly linked list of all of the non-NETFS
    1284  * mounted file systems, that contains the specified device.
    1285  * @param device The device to find
    1286  * @return NULL if it didn't find the device, a pointer to the
    1287  * structure if it did.
    1288  */
    1289 static MOUNTED_FS_STRUCT *find_device_in_list (char *device)
    1290 {
    1291     MOUNTED_FS_STRUCT *DSFptr = NULL;
    1292 
    1293     DSFptr = DSF_Head;
    1294     while (DSFptr != NULL) {
    1295         if (!strcmp(DSFptr->device, device)) {
    1296             break;
    1297         }
    1298         DSFptr = DSFptr->next;
    1299     }
    1300     return (DSFptr);
    1301 }
    1302 
    1303 /**
    1304  * Find the structure, in the singly linked list of all of the non-NETFS
    1305  * mounted file systems, that contains the specified mount point.
    1306  * @param mount_point The mount point to find
    1307  * @return NULL is it didn't find the mount point, a pointer to the
    1308  * structure if it did.
    1309  */
    1310 static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
    1311 {
    1312     MOUNTED_FS_STRUCT *DSFptr = NULL;
    1313 
    1314     DSFptr = DSF_Head;
    1315     while (DSFptr != NULL) {
    1316         if (!strcmp(DSFptr->mount_point, mount_point)) {
    1317             break;
    1318         }
    1319         DSFptr = DSFptr->next;
    1320     }
    1321     return (DSFptr);
    1322 }
    1323 
    1324 /**
    132582 * Frees the memory for all of the structures on the linked list of
    132683 * all of the non-NETFS mounted file systems.
     
    133996    DSF_Tail = NULL;
    134097}
     98
     99
     100/**
     101 * Creates a singly linked list of all of the non-NETFS mounted file systems.
     102 * @param DSFptr A pointer  to the structure MOUNTED_FS_STRUCT used to hold
     103 * the list of mounted file systems.
     104 * @return None.
     105 */
     106static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
     107{
     108    assert (DSFptr);
     109    if (DSF_Head == NULL) {
     110        DSF_Head = DSFptr;
     111    } else {
     112        DSF_Tail->next = DSFptr;
     113    }
     114    DSFptr->next = NULL;
     115    DSF_Tail = DSFptr;
     116}
     117
    1341118
    1342119
     
    1415192}
    1416193
     194/**
     195 * Find the structure, in the singly linked list of all of the non-NETFS
     196 * mounted file systems, that contains the specified mount point.
     197 * @param mount_point The mount point to find
     198 * @return NULL is it didn't find the mount point, a pointer to the
     199 * structure if it did.
     200 */
     201static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
     202{
     203    MOUNTED_FS_STRUCT *DSFptr = NULL;
     204
     205    DSFptr = DSF_Head;
     206    while (DSFptr != NULL) {
     207        if (!strcmp(DSFptr->mount_point, mount_point)) {
     208            break;
     209        }
     210        DSFptr = DSFptr->next;
     211    }
     212    return (DSFptr);
     213}
     214
     215
     216/**
     217 * Find the structure, in the singly linked list of all of the non-NETFS
     218 * mounted file systems, that contains the specified device.
     219 * @param device The device to find
     220 * @return NULL if it didn't find the device, a pointer to the
     221 * structure if it did.
     222 */
     223static MOUNTED_FS_STRUCT *find_device_in_list(char *device) {
     224    MOUNTED_FS_STRUCT *DSFptr = NULL;
     225
     226    DSFptr = DSF_Head;
     227    while (DSFptr != NULL) {
     228        if (!strcmp(DSFptr->device, device)) {
     229            break;
     230        }
     231        DSFptr = DSFptr->next;
     232    }
     233    return (DSFptr);
     234}
    1417235
    1418236
     
    1749567
    1750568
     569/**
     570 * Load (inject) the tray of the specified CD device.
     571 * @param dev The device to load/inject.
     572 * @return 0 for success, nonzero for failure.
     573 */
     574int inject_device(char *dev)
     575{
     576    char *command = NULL;
     577    int i;
     578
     579    if (dev == NULL) {
     580        return (1);
     581    }
     582
     583#ifdef __FreeBSD__
     584    if (strstr(dev, "acd")) {
     585        mr_asprintf(command, "cdcontrol -f %s close", dev);
     586    } else {
     587        mr_asprintf(command, "camcontrol load `echo %s | sed 's|/dev/||'`", dev);
     588    }
     589#else
     590    mr_asprintf(command, "eject -t %s", dev);
     591#endif
     592    i = run_program_and_log_output(command, FALSE);
     593    mr_free(command);
     594    return (i);
     595}
     596
     597
     598/**
     599 * Retract all CD trays and wait for autorun to complete.
     600 * @ingroup deviceGroup
     601 */
     602void retract_CD_tray_and_defeat_autorun(void)
     603{
     604//  log_it("rctada: Retracting optical tray", __LINE__);
     605    if (!bkpinfo->please_dont_eject) {
     606        if (bkpinfo->media_device != NULL) {
     607            inject_device(bkpinfo->media_device);
     608        }
     609    }
     610    if (!run_program_and_log_output("ps | grep autorun | grep -v grep", 5)) {
     611        log_it("autorun detected; sleeping for 2 seconds");
     612        sleep(2);
     613    }
     614}
     615
     616
     617
     618/**
     619 * Find out what device is mounted as root (/).
     620 * @return Root device.
     621 * @note The returned string points to storage that needs to be freed by
     622 * caller
     623 * @bug A bit of a misnomer; it's actually finding out the root device.
     624 * The mountpoint (where it's mounted) will obviously be '/'.
     625 */
     626char *where_is_root_mounted(void) {
     627
     628/*@ buffers **************** */
     629char *tmp = NULL;
     630
     631#ifdef __FreeBSD__
     632    tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");
     633#else
     634    tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//");
     635    if (strstr(tmp, "/dev/cciss/")) {
     636        mr_free(tmp);
     637        tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1");
     638    }
     639    if (strstr(tmp, "/dev/md")) {
     640        mr_free(tmp);
     641        tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");
     642    }
     643#endif
     644
     645return (tmp);
     646}
     647
     648
     649
     650/**
     651 * Determine whether we're booted off a ramdisk.
     652 * @return @c TRUE (we are) or @c FALSE (we aren't).
     653 * @ingroup utilityGroup
     654 */
     655bool am_I_in_disaster_recovery_mode(void)
     656{
     657    char *tmp = NULL;
     658    bool is_this_a_ramdisk = FALSE;
     659
     660    tmp = where_is_root_mounted();
     661    log_msg(0, "root is mounted at %s", tmp);
     662    log_msg(0, "That doesn't mean %s is the root partition. It's just a debugging message. Relax. It's part of am_I_in_disaster_recovery_mode().", tmp);
     663
     664#ifdef __FreeBSD__
     665    if (strstr(tmp, "/dev/md")) {
     666        is_this_a_ramdisk = TRUE;
     667    }
     668#else
     669    if (!strncmp(tmp, "/dev/ram", 8)
     670        || (!strncmp(tmp, "/dev/rd", 7) && !strcmp(tmp, "/dev/rd/")
     671            && strncmp(tmp, "/dev/rd/cd", 10)) || strstr(tmp, "rootfs")
     672        || !strcmp(tmp, "/dev/root")) {
     673        is_this_a_ramdisk = TRUE;
     674    } else {
     675        is_this_a_ramdisk = FALSE;
     676    }
     677#endif
     678    mr_free(tmp);
     679
     680    if (is_this_a_ramdisk) {
     681        if (!does_file_exist("/THIS-IS-A-RAMDISK")) {
     682            log_to_screen("Using /dev/root is stupid of you but I'll forgive you.");
     683            is_this_a_ramdisk = FALSE;
     684        }
     685    }
     686    if (does_file_exist("/THIS-IS-A-RAMDISK")) {
     687        is_this_a_ramdisk = TRUE;
     688    }
     689
     690    log_msg(1, "Is this a ramdisk? result = %s", (is_this_a_ramdisk) ? "TRUE" : "FALSE");
     691    return (is_this_a_ramdisk);
     692}
     693
     694
     695
     696
     697
     698/**
     699 * Turn @c bkpinfo->backup_media_type into a human-readable string.
     700 * @return The human readable string (e.g. @c cdr becomes <tt>"cdr"</tt>).
     701 * @note The returned string points to static storage that will be overwritten with each call.
     702 * @ingroup stringGroup
     703 */
     704static char *bkptype_to_string(t_bkptype bt)
     705{
     706    char *output = NULL;
     707    switch (bt) {
     708    case none:
     709        mr_asprintf(output, "%s", "none");
     710        break;
     711    case iso:
     712        mr_asprintf(output, "%s", "iso");
     713        break;
     714    case cdr:
     715        mr_asprintf(output, "%s", "cdr");
     716        break;
     717    case cdstream:
     718        mr_asprintf(output, "%s", "cdstream");
     719        break;
     720    case netfs:
     721        mr_asprintf(output, "%s", "netfs");
     722        break;
     723    case tape:
     724        mr_asprintf(output, "%s", "tape");
     725        break;
     726    case udev:
     727        mr_asprintf(output, "%s", "udev");
     728        break;
     729    case usb:
     730        mr_asprintf(output, "%s", "usb");
     731        break;
     732    default:
     733        mr_asprintf(output, "%s", "default");
     734    }
     735    return (output);
     736}
     737
     738
     739
     740/**
     741 * @addtogroup deviceGroup
     742 * @{
     743 */
     744/**
     745 * Eject the tray of the specified CD device.
     746 * @param dev The device to eject.
     747 * @return the return value of the @c eject command. (0=success, nonzero=failure)
     748 */
     749int eject_device(char *dev)
     750{
     751    char *command = NULL;
     752    int res1 = 0, res2 = 0;
     753
     754    if (dev == NULL) {
     755        return (1);
     756    }
     757
     758    if (IS_THIS_A_STREAMING_BACKUP(g_backup_media_type)
     759        && g_backup_media_type != udev) {
     760        mr_asprintf(command, "mt -f %s offline", dev);
     761        res1 = run_program_and_log_output(command, 1);
     762        mr_free(command);
     763    } else {
     764        res1 = 0;
     765    }
     766
     767#ifdef __FreeBSD__
     768    if (strstr(dev, "acd")) {
     769        mr_asprintf(command, "cdcontrol -f %s eject", dev);
     770    } else {
     771        mr_asprintf(command, "camcontrol eject `echo %s | sed 's|/dev/||'`", dev);
     772    }
     773#else
     774    mr_asprintf(command, "eject %s", dev);
     775#endif
     776
     777    log_msg(3, "Ejecting %s", dev);
     778    res2 = run_program_and_log_output(command, 1);
     779    mr_free(command);
     780    if (res1 && res2) {
     781        return (1);
     782    } else {
     783        return (0);
     784    }
     785}
     786
     787/**
     788 * Determine whether a non-Microsoft partition exists on any connected hard drive.
     789 * @return TRUE (there's a Linux/FreeBSD partition) or FALSE (Microsoft has taken over yet another innocent machine).
     790 */
     791bool does_nonMS_partition_exist(void)
     792{
     793#if __FreeBSD__
     794    return
     795        !system("for drive in /dev/ad? /dev/da?; do fdisk $drive | grep -q FreeBSD && exit 0; done; false");
     796#else
     797    return
     798        !system("mr-parted2fdisk -l 2>/dev/null | grep '^/dev/' | grep -Eqv '(MS|DOS|EFI|FAT|NTFS)'");
     799#endif
     800}
     801
     802/**
     803 * Determine whether the specified @p partno exists on the specified @p drive.
     804 * @param drive The drive to search for the partition in.
     805 * @param partno The partition number to look for.
     806 * @return 0 if it exists, nonzero otherwise.
     807 */
     808int does_partition_exist(const char *drive, int partno)
     809{
     810    /*@ buffers **************************************************** */
     811    char *program = NULL;
     812    char *incoming = NULL;
     813    char *searchstr = NULL;
     814
     815    /*@ ints ******************************************************* */
     816    int res = 0;
     817
     818    /*@ pointers *************************************************** */
     819    FILE *fin;
     820
     821    /*@ end vars *************************************************** */
     822    assert_string_is_neither_NULL_nor_zerolength(drive);
     823    assert(partno >= 0 && partno < 999);
     824
     825#ifdef __FreeBSD__
     826    // We assume here that this is running from mondorestore. (It is.)
     827    tmp = build_partition_name(drive, partno);
     828    mr_asprintf(program, "ls %s %s >/dev/null 2>&1", drive, tmp);
     829    mr_free(tmp);
     830    res = system(program);
     831    mr_free(program);
     832    return(res);
     833#endif
     834
     835    mr_asprintf(program, "mr-parted2fdisk -l %s 2> /dev/null", drive);
     836    fin = popen(program, "r");
     837    if (!fin) {
     838        log_it("program=%s", program);
     839        log_OS_error("Cannot popen-in program");
     840        mr_free(program);
     841        return (0);
     842    }
     843    mr_free(program);
     844
     845    searchstr = build_partition_name(drive, partno);
     846    mr_strcat(searchstr, " ");
     847    for (res = 0, mr_getline(incoming, fin); !res && !feof(fin) ; mr_getline(incoming, fin)) {
     848        if (strstr(incoming, searchstr)) {
     849            res = 1;
     850        }
     851        mr_free(incoming);
     852    }
     853    mr_free(searchstr);
     854    mr_free(incoming);
     855
     856    if (pclose(fin)) {
     857        log_OS_error("Cannot pclose fin");
     858    }
     859    return (res);
     860}
     861
     862
     863
     864
     865
     866/**
     867 * Determine whether given NULL-terminated @p str exists in the begining of @p dev.
     868 * @param dev The device to look in.
     869 * @param str The string to look for.
     870 * @return TRUE if it exists, FALSE if it doesn't.
     871 */
     872bool does_string_exist_in_boot_block(char *dev, char *str)
     873{
     874    /*@ buffers **************************************************** */
     875    char *command = NULL;
     876
     877    /*@ end vars *************************************************** */
     878    int i;
     879
     880    assert_string_is_neither_NULL_nor_zerolength(dev);
     881    assert_string_is_neither_NULL_nor_zerolength(str);
     882
     883    /* For UEFI detection, this should be extended to count=1000 ! */
     884    if (bkpinfo->boot_type == UEFI) {
     885        mr_asprintf(command, "dd if=%s bs=446 count=1000 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, str);
     886    } else {
     887        mr_asprintf(command, "dd if=%s bs=446 count=1 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, str);
     888    }
     889    i = system(command);
     890    mr_free(command);
     891    if (i) {
     892        return (FALSE);
     893    } else {
     894        return (TRUE);
     895    }
     896}
     897
     898/**
     899 * Determine whether specified @p str exists in the first @p n sectors of
     900 * @p dev.
     901 * @param dev The device to look in.
     902 * @param str The string to look for.
     903 * @param n The number of 512-byte sectors to search.
     904 */
     905bool does_string_exist_in_first_N_blocks(char *dev, char *str, int n)
     906{
     907    /*@ buffers **************************************************** */
     908    char *command = NULL;
     909    /*@ end vars *************************************************** */
     910    int i;
     911
     912    mr_asprintf(command, "dd if=%s bs=512 count=%i 2> /dev/null | strings | grep \"%s\" > /dev/null 2> /dev/null", dev, n, str);
     913    i = system(command);
     914    mr_free(command);
     915    if (i) {
     916        return (FALSE);
     917    } else {
     918        return (TRUE);
     919    }
     920}
     921
     922
     923/*
     924 * This function tries to find an optical media device
     925 * and return it's device file to the caller that needs to free it
     926 */
     927char *find_optical_device(void) {
     928    char *dev = NULL;
     929    char *tmp1 = NULL;
     930    char *command = NULL;
     931
     932    log_to_screen("I am looking for your optical burner. Please wait.");
     933
     934    if (bkpinfo->media_device != NULL) {
     935        log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device);
     936        return (bkpinfo->media_device);
     937    }
     938
     939    mr_asprintf(tmp1, "cdrecord -inq 2> /dev/null | grep -E '^Detected '  | cut -d':' -f2");
     940    dev = call_program_and_get_last_line_of_output(tmp1);
     941    mr_free(tmp1);
     942
     943    if ((dev != NULL) && does_file_exist(dev)) {
     944        log_msg(2, "find_optical_device found %s automatically", dev);
     945    } else {
     946        mr_free(dev);
     947        tmp1 = find_home_of_exe("lsscsi");
     948        if (tmp1 != NULL) {
     949            mr_asprintf(command, "%s | grep ' cd' | awk '{print $NF}' | head -1", tmp1);
     950            dev = call_program_and_get_last_line_of_output(command);
     951            mr_free(command);
     952        }
     953        mr_free(tmp1);
     954
     955        if ((dev == NULL) || !does_file_exist(dev)) {
     956            /* trying something else then */
     957            mr_asprintf(dev, "%s", VANILLA_SCSI_CDROM);
     958            if (!does_file_exist(dev)) {
     959                mr_asprintf(dev, "%s", ALT_CDROM);
     960                if (!does_file_exist(dev)) {
     961                    mr_asprintf(dev, "%s", "/dev/cdrom");
     962                    if (!does_file_exist(dev)) {
     963                        mr_asprintf(dev, "%s", "/dev/dvd");
     964                        if (!does_file_exist(dev)) {
     965                            log_it("Unable to find a tape device on this system");
     966                        }
     967                    }
     968                }
     969            }
     970        }
     971        if (dev != NULL) {
     972            log_it("find_optical_device found %s manually", dev);
     973        }
     974    }
     975
     976    if ((dev != NULL) && does_file_exist(dev)) {
     977        log_it("find_optical_device returns %s", dev);
     978    } else {
     979        mr_free(dev);
     980        log_it("find_optical_device found no optical burner on your system returning NULL");
     981    }
     982    return(dev);
     983}
     984/**
     985* Mount the CD-ROM or USB device at /mnt/cdrom.
     986* @param bkpinfo The backup information structure. Fields used:
     987* - @c bkpinfo->backup_media_type
     988* - @c bkpinfo->disaster_recovery
     989* - @c bkpinfo->isodir
     990* - @c bkpinfo->media_device
     991* @return TRUE for success, FALSE for failure.
     992*/
     993bool mount_media(const char *mountpoint) {
     994
     995    char *mount_cmd = NULL;
     996    char *mountdir = NULL;
     997    char *tmp = NULL;
     998    int i = 0, res = 0;
     999#ifdef __FreeBSD__
     1000    char mdd[32];
     1001    char *mddev = mdd;
     1002    char *dev;
     1003#endif
     1004
     1005    if (bkpinfo->backup_media_type == tape || bkpinfo->backup_media_type == udev) {
     1006        log_msg(8, "Tape/udev. Therefore, no need to mount a media.");
     1007        return(TRUE);
     1008    }
     1009
     1010    assert_string_is_neither_NULL_nor_zerolength(mountpoint);
     1011
     1012    mr_asprintf(tmp, "mount | grep -F %s", mountpoint);
     1013    if (!run_program_and_log_output(tmp, FALSE)) {
     1014        log_msg(2, "mount_media() - media already mounted. Fair enough.");
     1015        mr_free(tmp);
     1016        return (TRUE);
     1017    }
     1018    mr_free(tmp);
     1019
     1020    make_hole_for_dir(mountpoint);
     1021
     1022    if (bkpinfo->backup_media_type == netfs) {
     1023        log_msg(2, "Mounting for Network thingy");
     1024        log_msg(2, "isodir = %s", bkpinfo->isodir);
     1025        if (((bkpinfo->isodir == NULL) || !strcmp(bkpinfo->isodir, "/")) && am_I_in_disaster_recovery_mode()) {
     1026            mr_asprintf(bkpinfo->isodir, "%s", "/tmp/isodir");
     1027            log_msg(1, "isodir is being set to %s", bkpinfo->isodir);
     1028        }
     1029#ifdef __FreeBSD__
     1030        if (bkpinfo->netfs_remote_dir != NULL) {
     1031            // NETFS
     1032            mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);
     1033        } else {
     1034            // ISO
     1035            mr_asprintf(mount_cmd, "/mnt/isodir/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number);
     1036        }
     1037        mddev = make_vn(mount_cmd);
     1038        mr_free(mount_cmd);
     1039
     1040        mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint);
     1041#else
     1042        if (bkpinfo->netfs_remote_dir != NULL) {
     1043            // NETFS
     1044            mr_asprintf(mount_cmd, "mount %s/%s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number, mountpoint);
     1045        } else {
     1046            // ISO
     1047            mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number, mountpoint);
     1048        }
     1049#endif
     1050
     1051    } else if (bkpinfo->backup_media_type == iso) {
     1052        if (bkpinfo->subdir) {
     1053            mr_asprintf(mountdir, "%s/%s", bkpinfo->isodir, bkpinfo->subdir);
     1054        } else {
     1055            mr_asprintf(mountdir, "%s", bkpinfo->isodir);
     1056        }
     1057#ifdef __FreeBSD__
     1058        mr_asprintf(mount_cmd, "%s/%s-%d.iso", mountdir, bkpinfo->prefix, g_current_media_number);
     1059        mddev = make_vn(mount_cmd);
     1060        mr_free(mount_cmd);
     1061
     1062        mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s", mddev, mountpoint);
     1063#else
     1064        mr_asprintf(mount_cmd, "mount %s/%s-%d.iso -t iso9660 -o loop,ro %s", mountdir, bkpinfo->prefix, g_current_media_number, mountpoint);
     1065#endif
     1066        mr_free(mountdir);
     1067    } else if (bkpinfo->backup_media_type == usb) {
     1068        mr_asprintf(mount_cmd, "mount -t vfat %s %s", bkpinfo->media_device, mountpoint);
     1069    } else {    //  optical
     1070        if (bkpinfo->disaster_recovery
     1071            && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
     1072            mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE"));
     1073        } else {
     1074            if (bkpinfo->media_device == NULL) {
     1075                bkpinfo->media_device = find_optical_device();
     1076            }
     1077        }
     1078
     1079#ifdef __FreeBSD__
     1080        if (g_ISO_restore_mode) {
     1081            mr_asprintf(dev, "%s", make_vn(bkpinfo->media_device));
     1082            if (!dev) {
     1083                mr_asprintf(command, "Unable to mount ISO (make_vn(%s) failed)", bkpinfo->media_device);
     1084                fatal_error(command);
     1085            }
     1086            mr_free(bkpinfo->media_device);
     1087            bkpinfo->media_device = dev
     1088        }
     1089
     1090        mr_asprintf(mount_cmd, "mount_cd9660 -r %s %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE);
     1091#else
     1092        mr_asprintf(mount_cmd, "mount %s -o loop,ro -t iso9660 %s 2>> %s", bkpinfo->media_device, mountpoint, MONDO_LOGFILE);
     1093#endif
     1094        log_msg(2, "(mount_media) --- command = %s", mount_cmd);
     1095        // usefull ??
     1096        if (strncmp(bkpinfo->media_device, "/dev/", 5) == 0) {
     1097            retract_CD_tray_and_defeat_autorun();
     1098        }
     1099    }
     1100
     1101    for (i = 0; i < 2; i++) {
     1102        res = run_program_and_log_output(mount_cmd, FALSE);
     1103        if (!res) {
     1104            break;
     1105        } else {
     1106            log_msg(2, "Failed to mount device.");
     1107            sleep(5);
     1108            sync();
     1109        }
     1110    }
     1111    mr_free(mount_cmd);
     1112
     1113    if (res) {
     1114        log_msg(2, "Failed, despite %d attempts", i);
     1115        return(FALSE);
     1116    } else {
     1117        log_msg(2, "Mounted media drive OK");
     1118        return(TRUE);
     1119    }
     1120}
     1121/**************************************************************************
     1122*END_MOUNT_MEDIA                                                         *
     1123**************************************************************************/
     1124
     1125
     1126
     1127
     1128/**
     1129 * Try to mount CD/DVD at @p mountpoint. If the CD/DVD is not found or has
     1130 * not been specified, call find_optical_device() to find it.
     1131 * @param mountpoint Where to mount the CD-ROM.
     1132 * @return TRUE for success, FALSE for failure.
     1133 * @see mount_media
     1134 */
     1135bool find_and_mount_actual_cd(char *mountpoint) {
     1136
     1137    /*@ buffers ***************************************************** */
     1138
     1139    /*@ int's  ****************************************************** */
     1140    bool res;
     1141
     1142    /*@ end vars **************************************************** */
     1143
     1144    assert(bkpinfo != NULL);
     1145    assert_string_is_neither_NULL_nor_zerolength(mountpoint);
     1146
     1147    if (bkpinfo->media_device == NULL) {
     1148        bkpinfo->media_device = find_optical_device();
     1149    }
     1150
     1151    if (bkpinfo->backup_media_type != iso) {
     1152        retract_CD_tray_and_defeat_autorun();
     1153    }
     1154
     1155    if ((bkpinfo->media_device == NULL) || (res = mount_media(mountpoint))) {
     1156        mr_free(bkpinfo->media_device);
     1157        if ((bkpinfo->media_device = mr_popup_and_get_string("CD-ROM device", "Please enter your CD-ROM's /dev device", "/dev/cdrom")) == NULL) {
     1158            res = TRUE;
     1159        } else {
     1160            res = mount_media(mountpoint);
     1161        }
     1162    }
     1163    if (res) {
     1164        log_msg(1, "mount failed");
     1165    } else {
     1166        log_msg(1, "mount succeeded with %s", bkpinfo->media_device);
     1167    }
     1168    return (res);
     1169}
     1170/*
     1171 * This function tries to find a USB media device
     1172 * and return it's device file to the caller that needs to free it
     1173 */
     1174char *find_usb_device(void)
     1175{
     1176    char *dev = NULL;
     1177    char *tmp1 = NULL;
     1178    char *command = NULL;
     1179
     1180    log_to_screen("I am looking for your USB key. Please wait.");
     1181
     1182    if (bkpinfo->media_device != NULL) {
     1183        log_msg(3, "Been there, done that. Returning %s", bkpinfo->media_device);
     1184        return (bkpinfo->media_device);
     1185    }
     1186
     1187    tmp1 = find_home_of_exe("lsscsi");
     1188    if (tmp1 != NULL) {
     1189        mr_asprintf(command, "%s | grep ' disk' | grep USB | awk '{print $NF}' | head -1", tmp1);
     1190        dev = call_program_and_get_last_line_of_output(command);
     1191        mr_free(command);
     1192    }
     1193    mr_free(tmp1);
     1194
     1195    if ((dev == NULL) || !does_file_exist(dev)) {
     1196        tmp1 = find_home_of_exe("lsblk");
     1197        if (tmp1 != NULL) {
     1198            mr_asprintf(command, "%s --noheadings --raw --output rm,tran,type,path --sort path | awk '/^1 usb disk/ {d=$4} END {print d}'", tmp1);
     1199            dev = call_program_and_get_last_line_of_output(command);
     1200            mr_free(command);
     1201        }
     1202        mr_free(tmp1);
     1203        log_it("Unable to find a tape device on this system");
     1204    }
     1205    if (dev != NULL) {
     1206        log_it("find_usb_device found %s manually", dev);
     1207    }
     1208
     1209    if ((dev != NULL) && does_file_exist(dev)) {
     1210        log_it("find_usb_device returns %s", dev);
     1211    } else {
     1212        mr_free(dev);
     1213        log_it("find_usb_device found no USB key on your system returning NULL");
     1214    }
     1215    return(dev);
     1216}
     1217
     1218
     1219
     1220/* Generic fund to find a media
     1221 * Return a dynamically allocted string that caller needs to free
     1222 * @media_type is the type of media to look for
     1223 */
     1224
     1225char *find_device(t_bkptype media_type) {
     1226
     1227    if (media_type == usb) {
     1228        return(find_usb_device());
     1229    } else if (media_type == tape) {
     1230        return(find_tape_device());
     1231    } else if ((media_type == dvd) || (media_type == cdr)) {
     1232        return(find_optical_device());
     1233    } else {
     1234        return(NULL);
     1235    }
     1236}
     1237
     1238
     1239
     1240
     1241#include <sys/ioctl.h>
     1242
     1243/**
     1244 * Find the size of the specified @p drive, in megabytes. Uses @c ioctl calls
     1245 * and @c dmesg.
     1246 * @param drive The device to find the size of.
     1247 * @return size in megabytes.
     1248 */
     1249long get_phys_size_of_drive(char *drive)
     1250{
     1251    int fd;
     1252#if linux
     1253    unsigned long long s = 0;
     1254    int fileid, cylinders = 0;
     1255    int cylindersize = 0;
     1256    int gotgeo = 0;
     1257
     1258
     1259    struct hd_geometry hdgeo;
     1260#elif __FreeBSD__
     1261    off_t s;
     1262#endif
     1263
     1264    long outvalA = -1;
     1265    long outvalB = -1;
     1266    long outvalC = -1;
     1267
     1268    if ((fd = open(drive, O_RDONLY)) != -1) {
     1269        if (ioctl(fd,
     1270#if linux
     1271#ifdef BLKGETSIZE64
     1272                  BLKGETSIZE64,
     1273#else
     1274                  BLKGETSIZE,
     1275#endif
     1276#elif __FreeBSD__
     1277                  DIOCGMEDIASIZE,
     1278#endif
     1279                  &s) != -1) {
     1280            close(fd);
     1281            // s>>11 works for older disks but not for newer ones
     1282            outvalB =
     1283#if linux
     1284#ifdef BLKGETSIZE64
     1285                s >> 20
     1286#else
     1287                s >> 11
     1288#endif
     1289#else
     1290                s >> 20
     1291#endif
     1292                ;
     1293        }
     1294    }
     1295
     1296    if (outvalB <= 0) {
     1297        log_msg(1, "Error getting size of %s: %s", drive, strerror(errno));
     1298#if linux
     1299        fileid = open(drive, O_RDONLY);
     1300        if (fileid != -1) {
     1301            if (ioctl(fileid, HDIO_GETGEO, &hdgeo) != -1) {
     1302                if (hdgeo.cylinders && hdgeo.heads && hdgeo.sectors) {
     1303                    cylindersize = hdgeo.heads * hdgeo.sectors / 2;
     1304                    outvalA = cylindersize * cylinders / 1024;
     1305                    log_msg(2, "Got Harddisk geometry, C:%d, H:%d, S:%d",
     1306                            hdgeo.cylinders, hdgeo.heads, hdgeo.sectors);
     1307                    gotgeo = 1;
     1308                } else {
     1309