Changeset 3879 in MondoRescue


Ignore:
Timestamp:
Mar 9, 2024, 3:10:04 AM (4 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                    log_msg(1, "Harddisk geometry wrong");
     1310                }
     1311            } else {
     1312                log_msg(1,
     1313                        "Error in ioctl() getting new hard disk geometry (%s), resizing in unsafe mode",
     1314                        strerror(errno));
     1315            }
     1316            close(fileid);
     1317        } else {
     1318            log_msg(1, "Failed to open %s for reading: %s", drive,
     1319                    strerror(errno));
     1320        }
     1321        if (!gotgeo) {
     1322            log_msg(1, "Failed to get harddisk geometry, using old mode");
     1323        }
     1324#endif
     1325    }
     1326// OLDER DISKS will give ridiculously low value for outvalB (so outvalA is returned) :)
     1327// NEWER DISKS will give sane value for outvalB (close to outvalA, in other words) :)
     1328
     1329    outvalC = (outvalA > outvalB) ? outvalA : outvalB;
     1330
     1331//  log_msg (5, "drive = %s, error = %s", drive, strerror (errno));
     1332//  fatal_error ("GPSOD: Unable to get size of drive");
     1333    log_msg(1, "%s --> %ld or %ld --> %ld", drive, outvalA, outvalB,
     1334            outvalC);
     1335
     1336    return (outvalC);
     1337}
     1338
     1339/**
     1340 * Determine whether @p format is supported by the kernel. Uses /proc/filesystems
     1341 * under Linux and @c lsvfs under FreeBSD.
     1342 * @param format The format to test.
     1343 * @return TRUE if the format is supported, FALSE if not.
     1344 */
     1345bool is_this_a_valid_disk_format(char *format)
     1346{
     1347    char *good_formats = NULL;
     1348    char *command = NULL;
     1349    char *format_sz = NULL;
     1350    char *p = NULL;
     1351
     1352    FILE *pin;
     1353    int retval;
     1354
     1355    assert_string_is_neither_NULL_nor_zerolength(format);
     1356
     1357    mr_asprintf(format_sz, "%s ", format);
     1358
     1359#ifdef __FreeBSD__
     1360    mr_asprintf(command, "lsvfs | tr -s '\t' ' ' | grep -v Filesys | grep -v -- -- | cut -d' ' -f1 | tr -s '\n' ' '");
     1361#else
     1362    mr_asprintf(command, "grep -v nodev /proc/filesystems | tr -s '\t' ' ' | cut -d' ' -f2 | tr -s '\n' ' '");
     1363#endif
     1364
     1365    pin = popen(command, "r");
     1366    mr_free(command);
     1367
     1368    if (!pin) {
     1369        log_OS_error("Unable to read good formats");
     1370        retval = 0;
     1371    } else {
     1372        mr_getline(p, pin);
     1373        good_formats = mr_strip_spaces(p);
     1374        mr_free(p);
     1375        (void)pclose(pin);
     1376        mr_strcat(good_formats, " swap lvm raid ntfs-3g ntfs 7 ");  // " ntfs 7 " -- um, cheating much? :)
     1377        if (strstr(good_formats, format_sz)) {
     1378            retval = 1;
     1379        } else {
     1380            retval = 0;
     1381        }
     1382    }
     1383    mr_free(good_formats);
     1384    mr_free(format_sz);
     1385
     1386    return (retval);
     1387}
     1388
     1389
     1390/** @def SWAPLIST_COMMAND The command to list the swap files/partitions in use. */
     1391
     1392/**
     1393 * Determine whether @p device_raw is currently mounted.
     1394 * @param device_raw The device to check.
     1395 * @return TRUE if it's mounted, FALSE if not.
     1396 */
     1397bool is_this_device_mounted(char *device_raw)
     1398{
     1399
     1400    char *tmp = NULL;
     1401    bool retval = FALSE;
     1402
     1403    mr_asprintf(tmp, "mr-device-mounted %s > /dev/null", device_raw);
     1404    if (system(tmp) == 0) {
     1405        retval = TRUE;
     1406    }
     1407    mr_free(tmp);
     1408    return(retval);
     1409}
     1410
     1411#ifdef __FreeBSD__
     1412//                       CODE IS FREEBSD-SPECIFIC
     1413/**
     1414 * Create a loopback device for specified @p fname.
     1415 * @param fname The file to associate with a device.
     1416 * @return /dev entry for the device, or NULL if it couldn't be allocated.
     1417 */
     1418char *make_vn(char *fname)
     1419{
     1420    char *device = (char *) malloc(MAX_STR_LEN);
     1421    char *mddevice = NULL;
     1422    char *command = NULL;
     1423    char *tmp = NULL;
     1424    int vndev = 2;
     1425
     1426    tmp = call_program_and_get_last_line_of_output("/sbin/sysctl -n kern.osreldate");
     1427    if (atoi(tmp) < 500000) {
     1428        do {
     1429            mr_asprintf(mddevice, "vn%ic", vndev++);
     1430            mr_free(command);
     1431            mr_asprintf(command, "vnconfig %s %s", mddevice, fname);
     1432            if (vndev > 10) {
     1433                mr_free(tmp);
     1434                mr_free(mddevice);
     1435                mr_free(command);
     1436                return NULL;
     1437            }
     1438        }
     1439        while (system(command));
     1440    } else {
     1441        mr_asprintf(command, "mdconfig -a -t vnode -f %s", fname);
     1442        mddevice = call_program_and_get_last_line_of_output(command);
     1443        if (!strstr(mddevice, "md")) {
     1444            mr_free(tmp);
     1445            mr_free(command);
     1446            mr_free(mddevice);
     1447            return NULL;
     1448        }
     1449    }
     1450    mr_free(tmp);
     1451    mr_free(command);
     1452    sprintf(device, "/dev/%s", mddevice);
     1453    mr_free(mddevice);
     1454    return device;
     1455}
     1456
     1457
     1458
     1459//                       CODE IS FREEBSD-SPECIFIC
     1460/**
     1461 * Deallocate specified @p dname.
     1462 * This should be called when you are done with the device created by make_vn(),
     1463 * so the system does not run out of @c vn devices.
     1464 * @param dname The device to deallocate.
     1465 * @return 0 for success, nonzero for failure.
     1466 */
     1467int kick_vn(char *dname)
     1468{
     1469    char *command = NULL;
     1470    char *tmp = NULL;
     1471    int res = 0;
     1472
     1473    if (strncmp(dname, "/dev/", 5) == 0) {
     1474        dname += 5;
     1475    }
     1476
     1477    tmp = call_program_and_get_last_line_of_output("/sbin/sysctl -n kern.osreldate");
     1478    if (atoi(tmp) < 500000) {
     1479        mr_asprintf(command, "vnconfig -d %s", dname);
     1480    } else {
     1481        mr_asprintf(command, "mdconfig -d -u %s", dname);
     1482    }
     1483    mr_free(tmp);
     1484    res = system(command);
     1485    mr_free(command);
     1486    return(res);
     1487}
     1488#endif
     1489
     1490
     1491/**
     1492 * Mount the CD-ROM at @p mountpoint.
     1493 * @param device The device (or file if g_ISO_restore_mode) to mount.
     1494 * @param mountpoint The place to mount it.
     1495 * @return 0 for success, nonzero for failure.
     1496 */
     1497int mount_USB_here(char *device, char *mountpoint)
     1498{
     1499    /*@ buffer ****************************************************** */
     1500    char *command = NULL;
     1501    int retval;
     1502
     1503    assert_string_is_neither_NULL_nor_zerolength(device);
     1504    assert_string_is_neither_NULL_nor_zerolength(mountpoint);
     1505
     1506    make_hole_for_dir(mountpoint);
     1507    if (isdigit(device[0])) {
     1508        return(1);
     1509    }
     1510    log_msg(4, "(mount_USB_here --- device=%s, mountpoint=%s", device, mountpoint);
     1511
     1512#ifdef __FreeBSD__
     1513    mr_asprintf(command, "mount_vfat %s %s 2>> %s", device, mountpoint, MONDO_LOGFILE);
     1514
     1515#else
     1516    mr_asprintf(command, "mount %s -t vfat %s 2>> %s", device, mountpoint, MONDO_LOGFILE);
     1517#endif
     1518
     1519    log_msg(4, command);
     1520    retval = system(command);
     1521    log_msg(1, "system(%s) returned %d", command, retval);
     1522    mr_free(command);
     1523
     1524    return (retval);
     1525}
     1526
     1527/**
     1528 * Find out what number CD is in the drive.
     1529 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
     1530 * @return The current CD number, or -1 if it could not be found.
     1531 * @note If the CD is not mounted, it will be mounted
     1532 * (and remain mounted after this function returns).
     1533 */
     1534int what_number_cd_is_this(void) {
     1535
     1536    int cd_number = -1;
     1537    char *mountdev = NULL;
     1538    char *tmp = NULL;
     1539
     1540    assert(bkpinfo != NULL);
     1541//  log_it("Asking what_number_cd_is_this");
     1542    if ((g_ISO_restore_mode) || (g_restoring_live_from_cd)) {
     1543        tmp = call_program_and_get_last_line_of_output("mount | grep iso9660 | awk '{print $3;}'");
     1544        mr_asprintf(mountdev, "%s%s", tmp, "/archives/THIS-CD-NUMBER");
     1545        mr_free(tmp);
     1546        cd_number = atoi(last_line_of_file(mountdev));
     1547        mr_free(mountdev);
     1548        return (cd_number);
     1549    }
     1550
     1551    if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {
     1552        log_it("ERROR: bkpinfo->media_device shoulnd't be unaccessible here\n");
     1553        /* trying again ! */
     1554        bkpinfo->media_device = find_optical_device();
     1555    }
     1556    if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {
     1557        fatal_error("ERROR: bkpinfo->media_device shoulnd't really be unaccessible here\n");
     1558    }
     1559    if (!is_this_device_mounted(MNT_CDROM)) {
     1560        mount_media(MNT_CDROM);
     1561    }
     1562
     1563    cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
     1564    return(cd_number);
     1565}
     1566
     1567
     1568
     1569
     1570/**
     1571 * Ask the user for CD number @p cd_number_i_want.
     1572 * Sets g_current_media_number once the correct CD is inserted.
     1573 * @param bkpinfo The backup information structure. Fields used:
     1574 * - @c bkpinfo->backup_media_type
     1575 * - @c bkpinfo->prefix
     1576 * - @c bkpinfo->isodir
     1577 * - @c bkpinfo->media_device
     1578 * - @c bkpinfo->please_dont_eject_when_restoring
     1579 * @param cd_number_i_want The CD number to ask for.
     1580 */
     1581void
     1582insist_on_this_cd_number(int cd_number_i_want)
     1583{
     1584
     1585    /*@ int ************************************************************* */
     1586    int res = 0;
     1587
     1588
     1589    /*@ buffers ********************************************************* */
     1590    char *tmp = NULL;
     1591    char *mds = NULL;
     1592    char *request = NULL;
     1593
     1594    assert(bkpinfo != NULL);
     1595    assert(cd_number_i_want > 0);
     1596
     1597//  log_msg(3, "Insisting on CD number %d", cd_number_i_want);
     1598
     1599    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     1600        log_msg(3,
     1601                "No need to insist_on_this_cd_number when the backup type isn't CD-R(W) or NFS or ISO");
     1602        return;
     1603    }
     1604    if (!does_file_exist(MNT_CDROM)) {
     1605        mr_asprintf(tmp, "mkdir -p " MNT_CDROM);
     1606        run_program_and_log_output(tmp, 5);
     1607        mr_free(tmp);
     1608    }
     1609
     1610    if (g_ISO_restore_mode || bkpinfo->backup_media_type == iso || bkpinfo->backup_media_type == netfs) {
     1611        g_ISO_restore_mode = TRUE;
     1612    }
     1613    if ((res = what_number_cd_is_this()) != cd_number_i_want) {
     1614        log_msg(3, "Currently, we hold %d but we want %d", res, cd_number_i_want);
     1615
     1616        /* Now we need to umount the current media to have the next mounted after */
     1617        run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
     1618        log_msg(3, "Mounting next media %d",cd_number_i_want);
     1619        g_current_media_number = cd_number_i_want;
     1620        mount_media(MNT_CDROM);
     1621
     1622        mds = media_descriptor_string(bkpinfo->backup_media_type);
     1623        log_msg(3, "Insisting on %s #%d", mds, cd_number_i_want);
     1624        mr_asprintf(request, "Please insert %s #%d and press Enter.", mds, cd_number_i_want);
     1625        mr_free(mds);
     1626
     1627        while (what_number_cd_is_this() != cd_number_i_want) {
     1628            sync();
     1629            if (is_this_device_mounted(MNT_CDROM)) {
     1630                res =
     1631                    run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
     1632            } else {
     1633                res = 0;
     1634            }
     1635            if (res) {
     1636                log_to_screen("WARNING - failed to unmount CD-ROM drive");
     1637            }
     1638            if (!bkpinfo->please_dont_eject) {
     1639                res = eject_device(bkpinfo->media_device);
     1640            } else {
     1641                res = 0;
     1642            }
     1643            if (res) {
     1644                log_to_screen("WARNING - failed to eject CD-ROM disk");
     1645            }
     1646            popup_and_OK(request);
     1647            if (!bkpinfo->please_dont_eject) {
     1648                inject_device(bkpinfo->media_device);
     1649            }
     1650            sync();
     1651        }
     1652        mr_free(request);
     1653
     1654        log_msg(1, "Thankyou. Proceeding...");
     1655        g_current_media_number = cd_number_i_want;
     1656    }
     1657}
     1658
     1659
    17511660/* Update the bkpinfo structure for exclude & include paths
    17521661 * in order to handle correctly paths corresponding to devices */
     
    21082017    // Tape, CD, NETFS, ...?
    21092018    srandom(getpid());
    2110     bkpinfo->backup_media_type =
    2111         (g_restoring_live_from_cd) ? cdr :
    2112         which_backup_media_type(bkpinfo->restore_data);
     2019    bkpinfo->backup_media_type = (g_restoring_live_from_cd) ? cdr : which_backup_media_type(bkpinfo->restore_data);
    21132020    if (bkpinfo->backup_media_type == none) {
    21142021        log_to_screen("User has chosen not to backup the machine");
    21152022        finish(1);
    21162023    }
    2117     log_msg(3, "media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
     2024    tmp = bkptype_to_string(bkpinfo->backup_media_type);
     2025    log_msg(3, "media type = %s", tmp);
     2026    mr_free(tmp);
    21182027
    21192028    /* Why asking to remove the media with tape ?
     
    27552664    log_it("media device = %s", bkpinfo->media_device);
    27562665    log_it("media size = %ld", bkpinfo->media_size);
    2757     log_it("media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
     2666    tmp = bkptype_to_string(bkpinfo->backup_media_type);
     2667    log_it("media type = %s", tmp);
     2668    mr_free(tmp);
    27582669    if (bkpinfo->prefix != NULL) {
    27592670        log_it("prefix = %s", bkpinfo->prefix);
  • branches/3.3/mondo/src/common/libmondo-fifo.c

    r3865 r3879  
    2323#include "mr_mem.h"
    2424#include "mondostructures.h"
    25 #include "libmondo.h"
     25#include "libmondo-devices-EXT.h"
     26#include "libmondo-fork-EXT.h"
     27#include "newt-specific-EXT.h"
     28
    2629
    2730/**
  • branches/3.3/mondo/src/common/libmondo-filelist.c

    r3878 r3879  
    6060extern char *g_getfacl;
    6161extern char *g_getfattr;
     62
     63
     64int sort_file(char *orig_fname)
     65{
     66    char *tmp_fname = NULL;
     67    char *command = NULL;
     68    int retval = 0;
     69
     70    log_msg(5, "Sorting file %s", orig_fname);
     71
     72    if (!does_file_exist(orig_fname)) {
     73        log_msg(2, "file %s empty", orig_fname);
     74        return (0);
     75    }                           // no sense in trying to sort an empty file
     76
     77    mr_asprintf(tmp_fname, "%s/sortfile", bkpinfo->tmpdir);
     78    mr_asprintf(command, "sort %s > %s 2>> %s", orig_fname, tmp_fname, MONDO_LOGFILE);
     79    retval = system(command);
     80    mr_free(command);
     81
     82    if (retval) {
     83        log_msg(2, "Failed to sort %s - oh dear", orig_fname);
     84    } else {
     85        log_msg(5, "Sorted %s --> %s OK. Copying it back to %s now", orig_fname, tmp_fname, orig_fname);
     86        mr_asprintf(command, "mv -f %s %s", tmp_fname, orig_fname);
     87        retval += run_program_and_log_output(command, 5);
     88        mr_free(command);
     89
     90        if (retval) {
     91            log_msg(2, "Failed to copy %s back to %s - oh dear", tmp_fname, orig_fname);
     92        } else {
     93            log_msg(5, "%s was sorted OK.", orig_fname);
     94        }
     95    }
     96    mr_free(tmp_fname);
     97    log_msg(5, "Finished sorting file %s", orig_fname);
     98    return (retval);
     99}
     100
    62101
    63102
     
    310349    return (retval);
    311350}
    312 
    313 
    314 
    315 int sort_file(char *orig_fname)
    316 {
    317     char *tmp_fname = NULL;
    318     char *command = NULL;
    319     int retval = 0;
    320 
    321     log_msg(5, "Sorting file %s", orig_fname);
    322 
    323     if (!does_file_exist(orig_fname)) {
    324         log_msg(2, "file %s empty", orig_fname);
    325         return (0);
    326     }                           // no sense in trying to sort an empty file
    327 
    328     mr_asprintf(tmp_fname, "%s/sortfile", bkpinfo->tmpdir);
    329     mr_asprintf(command, "sort %s > %s 2>> %s", orig_fname, tmp_fname, MONDO_LOGFILE);
    330     retval = system(command);
    331     mr_free(command);
    332 
    333     if (retval) {
    334         log_msg(2, "Failed to sort %s - oh dear", orig_fname);
    335     } else {
    336         log_msg(5, "Sorted %s --> %s OK. Copying it back to %s now", orig_fname, tmp_fname, orig_fname);
    337         mr_asprintf(command, "mv -f %s %s", tmp_fname, orig_fname);
    338         retval += run_program_and_log_output(command, 5);
    339         mr_free(command);
    340 
    341         if (retval) {
    342             log_msg(2, "Failed to copy %s back to %s - oh dear", tmp_fname, orig_fname);
    343         } else {
    344             log_msg(5, "%s was sorted OK.", orig_fname);
    345         }
    346     }
    347     mr_free(tmp_fname);
    348     log_msg(5, "Finished sorting file %s", orig_fname);
    349     return (retval);
    350 }
    351 
    352351
    353352
  • branches/3.3/mondo/src/common/libmondo-raid-EXT.h

    r3855 r3879  
    2222extern void process_raidtab_line(FILE *, struct raid_device_record *,
    2323                                 char *, char *);
    24 extern int save_raidlist_to_raidtab(struct raidlist_itself *raidlist,
    25                                     char *fname);
    2624extern void save_raidrec_to_file(struct raid_device_record *raidrec,
    2725                                 FILE * fout);
  • branches/3.3/mondo/src/common/libmondo-raid.c

    r3878 r3879  
    245245}
    246246#endif
     247
     248
     249/**
     250 * Save a disklist to a stream in raidtab format.
     251 * @param listname One of "raid-disk", "spare-disk", "parity-disk", or "failed-disk".
     252 * @param disklist The disklist to save to @p fout.
     253 * @param fout The stream to write to.
     254 */
     255void save_disklist_to_file(const char *listname, struct list_of_disks *disklist, FILE * fout)
     256{
     257    int i;
     258
     259    assert_string_is_neither_NULL_nor_zerolength(listname);
     260    assert(disklist != NULL);
     261    assert(fout != NULL);
     262
     263    for (i = 0; i < disklist->entries; i++) {
     264        fprintf(fout, "    device                %s\n", disklist->el[i].device);
     265        fprintf(fout, "    %-21s %d\n", listname, disklist->el[i].index);
     266    }
     267}
     268/**
     269 * Retrieve the next line from a raidtab stream.
     270 * @param fin The file to read the input from.
     271 * @param label Where to put the line's label.
     272 * @param value Where to put the line's value.
     273 * @return 0 if the line was read and stored successfully, 1 if we're at end of file.
     274 */
     275static int get_next_raidtab_line(FILE * fin, char **label, char **value)
     276{
     277    char *incoming = NULL;
     278    char *p = NULL;
     279    char *res = NULL;
     280
     281    assert(fin != NULL);
     282
     283    if (feof(fin)) {
     284        return (1);
     285    }
     286
     287    for (mr_getline(res, fin); !feof(fin); mr_getline(res, fin)) {
     288        log_msg(10,"Found in raidtab line: %s",res);
     289        incoming = mr_strip_spaces(res);
     290        mr_free(res);
     291        p = strchr(incoming, ' ');
     292        if (strlen(incoming) < 3 || incoming[0] == '#' || !p) {
     293            mr_free(incoming);
     294            continue;
     295        }
     296        *(p++) = '\0';
     297        while (*p == ' ') {
     298            p++;
     299        }
     300        *label = incoming;
     301        *value = p;
     302        log_msg(10,"Found in raidtab pair: %s|%s",*label,*value);
     303        return (0);
     304    }
     305    return (1);
     306}
     307
     308
     309/**
     310 * Save the additional RAID variables to a stream.
     311 * @param vars The RAID variable list to save.
     312 * @param fout The FILE pointer to save them to.
     313 */
     314void
     315save_additional_vars_to_file(struct additional_raid_variables *vars,
     316                             FILE * fout)
     317{
     318    int i;
     319
     320    assert(vars != NULL);
     321    assert(fout != NULL);
     322
     323    for (i = 0; i < vars->entries; i++) {
     324        fprintf(fout, "    %-21s %s\n", vars->el[i].label,
     325                vars->el[i].value);
     326    }
     327}
     328
     329
    247330
    248331
     
    341424}
    342425
    343 
    344 /**
    345  * Save the additional RAID variables to a stream.
    346  * @param vars The RAID variable list to save.
    347  * @param fout The FILE pointer to save them to.
    348  */
    349 void
    350 save_additional_vars_to_file(struct additional_raid_variables *vars,
    351                              FILE * fout)
    352 {
    353     int i;
    354 
    355     assert(vars != NULL);
    356     assert(fout != NULL);
    357 
    358     for (i = 0; i < vars->entries; i++) {
    359         fprintf(fout, "    %-21s %s\n", vars->el[i].label,
    360                 vars->el[i].value);
    361     }
    362 }
    363 
    364 
    365426/**
    366427 * Save a raidlist structure to disk in raidtab format.
     
    412473    paranoid_fclose(fout);
    413474    return (0);
    414 }
    415 
    416 
    417 /**
    418  * Save a disklist to a stream in raidtab format.
    419  * @param listname One of "raid-disk", "spare-disk", "parity-disk", or "failed-disk".
    420  * @param disklist The disklist to save to @p fout.
    421  * @param fout The stream to write to.
    422  */
    423 void save_disklist_to_file(const char *listname, struct list_of_disks *disklist, FILE * fout)
    424 {
    425     int i;
    426 
    427     assert_string_is_neither_NULL_nor_zerolength(listname);
    428     assert(disklist != NULL);
    429     assert(fout != NULL);
    430 
    431     for (i = 0; i < disklist->entries; i++) {
    432         fprintf(fout, "    device                %s\n", disklist->el[i].device);
    433         fprintf(fout, "    %-21s %d\n", listname, disklist->el[i].index);
    434     }
    435 }
    436 /**
    437  * Retrieve the next line from a raidtab stream.
    438  * @param fin The file to read the input from.
    439  * @param label Where to put the line's label.
    440  * @param value Where to put the line's value.
    441  * @return 0 if the line was read and stored successfully, 1 if we're at end of file.
    442  */
    443 static int get_next_raidtab_line(FILE * fin, char **label, char **value)
    444 {
    445     char *incoming = NULL;
    446     char *p = NULL;
    447     char *res = NULL;
    448 
    449     assert(fin != NULL);
    450 
    451     if (feof(fin)) {
    452         return (1);
    453     }
    454 
    455     for (mr_getline(res, fin); !feof(fin); mr_getline(res, fin)) {
    456         log_msg(10,"Found in raidtab line: %s",res);
    457         incoming = mr_strip_spaces(res);
    458         mr_free(res);
    459         p = strchr(incoming, ' ');
    460         if (strlen(incoming) < 3 || incoming[0] == '#' || !p) {
    461             mr_free(incoming);
    462             continue;
    463         }
    464         *(p++) = '\0';
    465         while (*p == ' ') {
    466             p++;
    467         }
    468         *label = incoming;
    469         *value = p;
    470         log_msg(10,"Found in raidtab pair: %s|%s",*label,*value);
    471         return (0);
    472     }
    473     return (1);
    474475}
    475476
  • branches/3.3/mondo/src/common/libmondo-stream.c

    r3878 r3879  
    8080
    8181
     82
     83
     84/**
     85 * Log (to screen) an erroneous marker, along with what it should have been.
     86 * @param should_be What we were expecting.
     87 * @param it_is What we got.
     88 */
     89void wrong_marker(int should_be, int it_is)
     90{
     91    char *tmp1 = NULL;
     92    char *tmp2 = NULL;
     93    tmp1 =  marker_to_string(should_be);
     94    tmp2 =  marker_to_string(it_is);
     95    log_to_screen("Wrong marker! (Should be %s, is actually %s)", tmp1, tmp2);
     96    mr_free(tmp1);
     97    mr_free(tmp2);
     98}
     99
     100
     101
     102
     103/**
     104 * Read a header block from the currently opened stream (CD or tape).
     105 * This block indicates the length of the following file (if it's file-related)
     106 * the filename (if it's file-related), and the block type.
     107 * @param plen Where to put the length of the file. Valid only for file-related header blocks.
     108 * @param filename Where to put the name of the file. Valid only for file-related header blocks.
     109 * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...)
     110 * @return 0 for success, nonzero for failure.
     111 * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker().
     112 */
     113int
     114read_header_block_from_stream(long long *plen, char *filename,
     115                              int *pcontrol_char)
     116{
     117
     118    /*@ buffers ***************************************************** */
     119    char *tempblock;
     120    char *tmp = NULL;
     121
     122    /*@ int ********************************************************* */
     123    int i, retval;
     124
     125    /*@ end vars *************************************************** */
     126
     127    tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE);
     128
     129    for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) {
     130        tempblock[i] = 0;
     131    }
     132    while (!(*pcontrol_char = tempblock[7000])) {
     133        g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024;
     134    }
     135    memcpy((char *) plen, tempblock + 7001, sizeof(long long));
     136    if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) {
     137        log_it("Bad header block at %ld K", (long) g_tape_posK);
     138    }
     139    strcpy(filename, tempblock + 1000);
     140    if (*pcontrol_char == BLK_ABORTED_BACKUP) {
     141        log_to_screen("I can't verify an aborted backup.");
     142        retval = 1;
     143    } else {
     144        retval = 0;
     145    }
     146    for (i = 1000; i < 1020; i++) {
     147        if (tempblock[i] < 32 || tempblock[i] > 126) {
     148            tempblock[i] = ' ';
     149        }
     150    }
     151    tempblock[i] = '\0';
     152    tmp = marker_to_string(*pcontrol_char);
     153    log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10);
     154    mr_free(tmp);
     155    paranoid_free(tempblock);
     156    return (retval);
     157}
    82158
    83159
     
    206282}
    207283
    208 
    209 
    210 
    211 /**
    212  * Log (to screen) an erroneous marker, along with what it should have been.
    213  * @param should_be What we were expecting.
    214  * @param it_is What we got.
    215  */
    216 void wrong_marker(int should_be, int it_is)
    217 {
    218     char *tmp1 = NULL;
    219     char *tmp2 = NULL;
    220     tmp1 =  marker_to_string(should_be);
    221     tmp2 =  marker_to_string(it_is);
    222     log_to_screen("Wrong marker! (Should be %s, is actually %s)", tmp1, tmp2);
    223     mr_free(tmp1);
    224     mr_free(tmp2);
    225 }
    226 
    227 
    228 
    229 /**
    230  * Read a header block from the currently opened stream (CD or tape).
    231  * This block indicates the length of the following file (if it's file-related)
    232  * the filename (if it's file-related), and the block type.
    233  * @param plen Where to put the length of the file. Valid only for file-related header blocks.
    234  * @param filename Where to put the name of the file. Valid only for file-related header blocks.
    235  * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...)
    236  * @return 0 for success, nonzero for failure.
    237  * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker().
    238  */
    239 int
    240 read_header_block_from_stream(long long *plen, char *filename,
    241                               int *pcontrol_char)
    242 {
    243 
    244     /*@ buffers ***************************************************** */
    245     char *tempblock;
    246     char *tmp = NULL;
    247 
    248     /*@ int ********************************************************* */
    249     int i, retval;
    250 
    251     /*@ end vars *************************************************** */
    252 
    253     tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE);
    254 
    255     for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) {
    256         tempblock[i] = 0;
    257     }
    258     while (!(*pcontrol_char = tempblock[7000])) {
    259         g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024;
    260     }
    261     memcpy((char *) plen, tempblock + 7001, sizeof(long long));
    262     if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) {
    263         log_it("Bad header block at %ld K", (long) g_tape_posK);
    264     }
    265     strcpy(filename, tempblock + 1000);
    266     if (*pcontrol_char == BLK_ABORTED_BACKUP) {
    267         log_to_screen("I can't verify an aborted backup.");
    268         retval = 1;
    269     } else {
    270         retval = 0;
    271     }
    272     for (i = 1000; i < 1020; i++) {
    273         if (tempblock[i] < 32 || tempblock[i] > 126) {
    274             tempblock[i] = ' ';
    275         }
    276     }
    277     tempblock[i] = '\0';
    278     tmp = marker_to_string(*pcontrol_char);
    279     log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10);
    280     mr_free(tmp);
    281     paranoid_free(tempblock);
    282     return (retval);
    283 }
    284284
    285285
     
    561561    return (dev);
    562562}
     563
     564
     565/**
     566 * Seek through the stream until we find a header block where the NAME field matches
     567 * @p the_file_I_was_reading. This is useful if you've just started reading from
     568 * a new tape and want to find the file you were reading when the tape ended.
     569 * @param the_file_I_was_reading File name to look for.
     570 * @return 0 for success, nonzero for failure.
     571 */
     572int skip_incoming_files_until_we_find_this_one(char
     573                                               *the_file_I_was_reading)
     574{
     575    char *pA;
     576    char *pB;
     577    int res;
     578    int ctrl_chr;
     579    char *temp_fname;
     580    char *datablock;
     581    long long temp_size, size;
     582    long bytes_to_write;
     583
     584    datablock = malloc(TAPE_BLOCK_SIZE);
     585    malloc_string(temp_fname);
     586    pB = strrchr(the_file_I_was_reading, '/');
     587    if (pB) {
     588        pB++;
     589    } else {
     590        pB = the_file_I_was_reading;
     591    }
     592    log_msg(1, "skip_incoming_..(%s)", pB);
     593    log_msg(2, "Looking for initial START_AN_AFIO_OR_SLICE");
     594    ctrl_chr = -1;
     595    while (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
     596        res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
     597        if (res) {
     598            // FIXME
     599        }
     600        if (ctrl_chr == BLK_START_AN_AFIO_OR_SLICE) {
     601            break;
     602        }
     603        log_msg(1, "%lld %s %c", temp_size, temp_fname, ctrl_chr);
     604        wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
     605        log_msg(3, "Still trying to re-sync w/ tape");
     606    }
     607    while (ctrl_chr != BLK_START_FILE) {
     608        res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
     609        if (res) {
     610            //FIXME
     611        }
     612        if (ctrl_chr == BLK_START_FILE) {
     613            break;
     614        }
     615        log_msg(1, "%lld %s %c", temp_size, temp_fname, ctrl_chr);
     616        wrong_marker(BLK_START_FILE, ctrl_chr);
     617        log_msg(3, "Still trying to re-sync w/ tape");
     618    }
     619    pA = strrchr(temp_fname, '/');
     620    if (pA) {
     621        pA++;
     622    } else {
     623        pA = temp_fname;
     624    }
     625    pB = strrchr(the_file_I_was_reading, '/');
     626    if (pB) {
     627        pB++;
     628    } else {
     629        pB = the_file_I_was_reading;
     630    }
     631    while (strcmp(pA, pB)) {
     632        log_msg(6, "Skipping %s (it's not %s)", temp_fname, the_file_I_was_reading);
     633        for (size = temp_size; size > 0; size -= bytes_to_write) {
     634            bytes_to_write =
     635                (size < TAPE_BLOCK_SIZE) ? (long) size : TAPE_BLOCK_SIZE;
     636            if (fread(datablock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream)) {
     637                // FIXME - needs error-checking and -catching
     638            }
     639        }
     640        res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
     641        if (ctrl_chr != BLK_STOP_FILE) {
     642            wrong_marker(BLK_STOP_FILE, ctrl_chr);
     643        }
     644        res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
     645        if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
     646            wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
     647        }
     648        res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
     649        if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
     650            wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
     651        }
     652        res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
     653        if (ctrl_chr != BLK_START_FILE) {
     654            wrong_marker(BLK_START_FILE, ctrl_chr);
     655        }
     656        pA = strrchr(temp_fname, '/');
     657        if (pA) {
     658            pA++;
     659        } else {
     660            pA = temp_fname;
     661        }
     662        pB = strrchr(the_file_I_was_reading, '/');
     663        if (pB) {
     664            pB++;
     665        } else {
     666            pB = the_file_I_was_reading;
     667        }
     668    }
     669    log_msg(2, "Reading %s (it matches %s)", temp_fname, the_file_I_was_reading);
     670    paranoid_free(temp_fname);
     671    paranoid_free(datablock);
     672    return (0);
     673}
     674
     675
     676/**
     677 * Start to read from the next tape. Assumes the user has already inserted it.
     678 * @param bkpinfo The backup information structure. @c bkpinfo->media_device is the only field used.
     679 * @return 0 for success, nonzero for failure.
     680 */
     681int start_to_read_from_next_tape()
     682{
     683    /*@ int ********************************************************* */
     684    int res = 0;
     685    char *sz_msg;
     686    int ctrlchr;
     687    long long temp_size;
     688    malloc_string(sz_msg);
     689    /*@ end vars *************************************************** */
     690
     691    if (bkpinfo->media_device == NULL) {
     692        log_it("Unable to open in from NULL device");
     693        return (1);
     694    }
     695
     696    paranoid_pclose(g_tape_stream);
     697    sync();
     698    sync();
     699    sync();
     700    log_it("Next tape requested.");
     701    insist_on_this_tape_number(g_current_media_number + 1); // will increment it, too
     702    log_it("Opening IN the next tape");
     703    if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'r', bkpinfo->internal_tape_block_size))) {
     704        log_OS_error(g_tape_fifo);
     705        log_to_screen("Cannot openin stream device");
     706        return (1);
     707    }
     708    g_tape_posK = 0;
     709    g_sigpipe = FALSE;
     710    res += read_header_block_from_stream(&temp_size, sz_msg, &ctrlchr); /* just in case */
     711    if (ctrlchr != BLK_START_OF_TAPE) {
     712        wrong_marker(BLK_START_OF_TAPE, ctrlchr);
     713    }
     714    res += read_header_block_from_stream(&temp_size, sz_msg, &ctrlchr); /* just in case */
     715    if (ctrlchr != BLK_START_OF_BACKUP) {
     716        wrong_marker(BLK_START_OF_BACKUP, ctrlchr);
     717    } else {
     718        log_msg(3, "Next tape opened OK. Whoopee!");
     719    }
     720    paranoid_free(sz_msg);
     721    return (res);
     722}
     723
    563724
    564725
     
    14041565
    14051566/**
    1406  * Seek through the stream until we find a header block where the NAME field matches
    1407  * @p the_file_I_was_reading. This is useful if you've just started reading from
    1408  * a new tape and want to find the file you were reading when the tape ended.
    1409  * @param the_file_I_was_reading File name to look for.
    1410  * @return 0 for success, nonzero for failure.
    1411  */
    1412 int skip_incoming_files_until_we_find_this_one(char
    1413                                                *the_file_I_was_reading)
    1414 {
    1415     char *pA;
    1416     char *pB;
    1417     int res;
    1418     int ctrl_chr;
    1419     char *temp_fname;
    1420     char *datablock;
    1421     long long temp_size, size;
    1422     long bytes_to_write;
    1423 
    1424     datablock = malloc(TAPE_BLOCK_SIZE);
    1425     malloc_string(temp_fname);
    1426     pB = strrchr(the_file_I_was_reading, '/');
    1427     if (pB) {
    1428         pB++;
    1429     } else {
    1430         pB = the_file_I_was_reading;
    1431     }
    1432     log_msg(1, "skip_incoming_..(%s)", pB);
    1433     log_msg(2, "Looking for initial START_AN_AFIO_OR_SLICE");
    1434     ctrl_chr = -1;
    1435     while (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
    1436         res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
    1437         if (res) {
    1438             // FIXME
    1439         }
    1440         if (ctrl_chr == BLK_START_AN_AFIO_OR_SLICE) {
    1441             break;
    1442         }
    1443         log_msg(1, "%lld %s %c", temp_size, temp_fname, ctrl_chr);
    1444         wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
    1445         log_msg(3, "Still trying to re-sync w/ tape");
    1446     }
    1447     while (ctrl_chr != BLK_START_FILE) {
    1448         res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
    1449         if (res) {
    1450             //FIXME
    1451         }
    1452         if (ctrl_chr == BLK_START_FILE) {
    1453             break;
    1454         }
    1455         log_msg(1, "%lld %s %c", temp_size, temp_fname, ctrl_chr);
    1456         wrong_marker(BLK_START_FILE, ctrl_chr);
    1457         log_msg(3, "Still trying to re-sync w/ tape");
    1458     }
    1459     pA = strrchr(temp_fname, '/');
    1460     if (pA) {
    1461         pA++;
    1462     } else {
    1463         pA = temp_fname;
    1464     }
    1465     pB = strrchr(the_file_I_was_reading, '/');
    1466     if (pB) {
    1467         pB++;
    1468     } else {
    1469         pB = the_file_I_was_reading;
    1470     }
    1471     while (strcmp(pA, pB)) {
    1472         log_msg(6, "Skipping %s (it's not %s)", temp_fname, the_file_I_was_reading);
    1473         for (size = temp_size; size > 0; size -= bytes_to_write) {
    1474             bytes_to_write =
    1475                 (size < TAPE_BLOCK_SIZE) ? (long) size : TAPE_BLOCK_SIZE;
    1476             if (fread(datablock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream)) {
    1477                 // FIXME - needs error-checking and -catching
    1478             }
    1479         }
    1480         res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
    1481         if (ctrl_chr != BLK_STOP_FILE) {
    1482             wrong_marker(BLK_STOP_FILE, ctrl_chr);
    1483         }
    1484         res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
    1485         if (ctrl_chr != BLK_STOP_AN_AFIO_OR_SLICE) {
    1486             wrong_marker(BLK_STOP_AN_AFIO_OR_SLICE, ctrl_chr);
    1487         }
    1488         res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
    1489         if (ctrl_chr != BLK_START_AN_AFIO_OR_SLICE) {
    1490             wrong_marker(BLK_START_AN_AFIO_OR_SLICE, ctrl_chr);
    1491         }
    1492         res = read_header_block_from_stream(&temp_size, temp_fname, &ctrl_chr);
    1493         if (ctrl_chr != BLK_START_FILE) {
    1494             wrong_marker(BLK_START_FILE, ctrl_chr);
    1495         }
    1496         pA = strrchr(temp_fname, '/');
    1497         if (pA) {
    1498             pA++;
    1499         } else {
    1500             pA = temp_fname;
    1501         }
    1502         pB = strrchr(the_file_I_was_reading, '/');
    1503         if (pB) {
    1504             pB++;
    1505         } else {
    1506             pB = the_file_I_was_reading;
    1507         }
    1508     }
    1509     log_msg(2, "Reading %s (it matches %s)", temp_fname, the_file_I_was_reading);
    1510     paranoid_free(temp_fname);
    1511     paranoid_free(datablock);
    1512     return (0);
    1513 }
    1514 
    1515 
    1516 /**
    1517  * Start to read from the next tape. Assumes the user has already inserted it.
    1518  * @param bkpinfo The backup information structure. @c bkpinfo->media_device is the only field used.
    1519  * @return 0 for success, nonzero for failure.
    1520  */
    1521 int start_to_read_from_next_tape()
    1522 {
    1523     /*@ int ********************************************************* */
    1524     int res = 0;
    1525     char *sz_msg;
    1526     int ctrlchr;
    1527     long long temp_size;
    1528     malloc_string(sz_msg);
    1529     /*@ end vars *************************************************** */
    1530 
    1531     if (bkpinfo->media_device == NULL) {
    1532         log_it("Unable to open in from NULL device");
    1533         return (1);
    1534     }
    1535 
    1536     paranoid_pclose(g_tape_stream);
    1537     sync();
    1538     sync();
    1539     sync();
    1540     log_it("Next tape requested.");
    1541     insist_on_this_tape_number(g_current_media_number + 1); // will increment it, too
    1542     log_it("Opening IN the next tape");
    1543     if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'r', bkpinfo->internal_tape_block_size))) {
    1544         log_OS_error(g_tape_fifo);
    1545         log_to_screen("Cannot openin stream device");
    1546         return (1);
    1547     }
    1548     g_tape_posK = 0;
    1549     g_sigpipe = FALSE;
    1550     res += read_header_block_from_stream(&temp_size, sz_msg, &ctrlchr); /* just in case */
    1551     if (ctrlchr != BLK_START_OF_TAPE) {
    1552         wrong_marker(BLK_START_OF_TAPE, ctrlchr);
    1553     }
    1554     res += read_header_block_from_stream(&temp_size, sz_msg, &ctrlchr); /* just in case */
    1555     if (ctrlchr != BLK_START_OF_BACKUP) {
    1556         wrong_marker(BLK_START_OF_BACKUP, ctrlchr);
    1557     } else {
    1558         log_msg(3, "Next tape opened OK. Whoopee!");
    1559     }
    1560     paranoid_free(sz_msg);
    1561     return (res);
    1562 }
    1563 
    1564 
    1565 
    1566 /**
    15671567 * Copy a file from the currently opened stream (CD or tape) to the stream indicated
    15681568 * by @p fout.
  • branches/3.3/mondo/src/common/libmondo-tools-EXT.h

    r2470 r3879  
    44extern long get_time();
    55extern char *mr_date(void);
    6 extern void (*log_debug_msg) (int debug_level, const char *szFile,
    7                               const char *szFunction, int nLine,
    8                               const char *fmt, ...);
    9 extern void standard_log_debug_msg(int debug_level, const char *szFile,
    10                                    const char *szFunction, int nLine,
    11                                    const char *fmt, ...);
    126extern int read_cfg_var(char *config_file, char *label, char *value);
    137extern int write_cfg_var(char *config_file, char *label, char *value);
     
    4539extern char *get_uname_m();
    4640
    47 extern bool does_nonMS_partition_exist(void);
    48 
    49 
    5041extern void stop_magicdev_if_necessary(void);
    5142extern void restart_magicdev_if_necessary(void);
  • branches/3.3/mondo/src/common/libmondo-tools.c

    r3877 r3879  
    7474
    7575extern t_bkptype g_backup_media_type;
    76 
    77 extern bool am_I_in_disaster_recovery_mode(void);
    7876
    7977/*-----------------------------------------------------------*/
  • branches/3.3/mondo/src/include/my-stuff.h

    r3876 r3879  
    55#define HAVE_MALLOC 1
    66
    7 
    8 // Extra info for ACLs and SELINUX users
    9 #define STAR_ACL_SZ "-xattr -acl"
    10 
    117/**
    128 * @file
     
    2521#ifndef _MY_STUFF_H_
    2622#define _MY_STUFF_H_
    27 
    28 #ifdef HAVE_CONFIG_H
    29 #include <config.h>
    30 #endif
    3123
    3224#ifndef __FreeBSD__
     
    8375 */
    8476#define MONDO_CACHE "/var/cache/mondo"
     77#define ARCHIVES_PATH MNT_CDROM"/archives"
     78#define BIGGIELIST ARCHIVES_PATH"/biggielist.txt"
    8579
    8680/**
     
    109103#define assert(exp) ((exp)?((void)0):_mondo_assert_fail(__FILE__, __FUNCTION__, __LINE__, #exp))
    110104#endif
     105
     106// Extra info for ACLs and SELINUX users
     107#define STAR_ACL_SZ "-xattr -acl"
    111108
    112109#define CRC_M16 0xA001          ///< Mask for crc16.
     
    351348#define MONDO_MNTLISTCHG "/tmp/mountlist.changed"
    352349
     350extern void (*log_debug_msg) (int debug_level, const char *szFile,
     351                              const char *szFunction, int nLine,
     352                              const char *fmt, ...);
     353extern void standard_log_debug_msg(int debug_level, const char *szFile,
     354                                   const char *szFunction, int nLine,
     355                                   const char *fmt, ...);
    353356
    354357/**
  • branches/3.3/mondo/src/mondoarchive/mondoarchive.c

    r3875 r3879  
    1212#include "mr_str.h"
    1313#include "mr_msg.h"
    14 #include "../common/mondostructures.h"
    15 #include "../common/libmondo.h"
    16 #include "../common/libmondo-cli-EXT.h"
    17 #include "../common/libmondo-tools-EXT.h"
     14#include "mondostructures.h"
     15#include "libmondo-cli-EXT.h"
     16#include "libmondo-tools-EXT.h"
     17#include "libmondo-archive-EXT.h"
     18#include "libmondo-fork-EXT.h"
     19#include "libmondo-files-EXT.h"
     20#include "libmondo-filelist-EXT.h"
     21#include "libmondo-raid-EXT.h"
     22#include "libmondo-devices-EXT.h"
     23#include "newt-specific-EXT.h"
    1824#include "mondoarchive.h"
    1925
  • branches/3.3/mondo/src/mondorestore/Makefile.am

    r3564 r3879  
    77
    88## Headers
    9 noinst_HEADERS        = mondorestore.h mondo-rstr-compare.h mondo-rstr-newt.h mondo-rstr-tools.h \
    10                         mondorestore-EXT.h mr-externs.h \
    11                         mondo-rstr-compare-EXT.h mondo-rstr-tools-EXT.h mondoprep.h \
    12                         libmondo-mountlist.h libmondo-mountlist-EXT.h \
    13                         mondorestore.h
     9noinst_HEADERS        = mondorestore.h \
     10                        mondo-rstr-compare-EXT.h mondo-rstr-tools-EXT.h \
     11                        libmondo-mountlist-EXT.h
    1412
    1513## The program
  • branches/3.3/mondo/src/mondorestore/mondo-prep.c

    r3866 r3879  
    55
    66
    7 #include "my-stuff.h"
    8 #include "mr_mem.h"
    9 #include "../common/mondostructures.h"
    10 #include "mondoprep.h"
    11 #include "../common/libmondo.h"
    12 #include "../common/libmondo-tools-EXT.h"
    13 #include "mondo-rstr-tools-EXT.h"
    14 #include "libmondo-mountlist-EXT.h"
    157#include <sys/ioctl.h>
    168#include <linux/hdreg.h>
    179#include <math.h>
     10#include "my-stuff.h"
     11#include "mr_mem.h"
     12#include "mondostructures.h"
     13#include "mondo-rstr-tools-EXT.h"
     14#include "libmondo-mountlist-EXT.h"
     15#include "libmondo-tools-EXT.h"
     16#include "libmondo-gui-EXT.h"
     17#include "libmondo-devices-EXT.h"
     18#include "libmondo-fork-EXT.h"
     19#include "libmondo-string-EXT.h"
     20#include "libmondo-files-EXT.h"
     21#include "newt-specific-EXT.h"
    1822
    1923
     
    3236#endif
    3337
    34 #define ARCHIVES_PATH MNT_CDROM"/archives"
    3538#define MONDO_WAS_HERE "MONDOWOZEREMONDOWOZEREMONDOWOZEREhahahaMOJOJOJO"
    3639
     
    3942extern char *g_mountlist_fname;
    4043extern long g_current_progress, g_maximum_progress;
    41 
    4244extern bool g_text_mode;
     45extern int g_currentY;
     46
    4347
    4448extern void pause_for_N_seconds(int, char *);
     
    628632
    629633
     634
     635/**
     636 * Stop @p raid_device using @p raidstop.
     637 * @param raid_device The software RAID device to stop.
     638 * @return 0 for success, nonzero for failure.
     639 */
     640int stop_raid_device(char *raid_device) {
     641
     642/** int *************************************************************/
     643int res;
     644int retval = 0;
     645
     646/** buffers *********************************************************/
     647char *program = NULL;
     648
     649/** end *************************************************************/
     650
     651assert_string_is_neither_NULL_nor_zerolength(raid_device);
     652
     653#ifdef __FreeBSD__
     654if (is_this_device_mounted(raid_device)) {
     655    log_it("Can't stop %s when it's mounted!", raid_device);
     656    return 1;
     657}
     658mr_asprintf(program, "vinum stop -f %s", raid_device);
     659#else
     660// use raidstop if it exists, otherwise use mdadm
     661if (run_program_and_log_output("which raidstop", FALSE)) {
     662    mr_asprintf(program, "mdadm -S %s", raid_device);
     663} else {
     664    mr_asprintf(program, "raidstop %s", raid_device);
     665}
     666#endif
     667log_msg(1, "program = %s", program);
     668res = run_program_and_log_output(program, 1);
     669if (g_fprep) {
     670    fprintf(g_fprep, "%s\n", program);
     671}
     672mr_free(program);
     673
     674if (res) {
     675    log_msg(1, "Warning - failed to stop RAID device %s", raid_device);
     676}
     677retval += res;
     678return (retval);
     679}
     680
     681
     682
     683int start_raid_device(char *raid_device) {
     684
     685/** int *************************************************************/
     686int res;
     687int retval = 0;
     688
     689/** buffers *********************************************************/
     690char *program = NULL;
     691
     692/** end *************************************************************/
     693
     694assert_string_is_neither_NULL_nor_zerolength(raid_device);
     695
     696#ifdef __FreeBSD__
     697if (is_this_device_mounted(raid_device)) {
     698    log_it("Can't start %s when it's mounted!", raid_device);
     699    return 1;
     700}
     701mr_asprintf(program, "vinum start -f %s", raid_device);
     702#else
     703mr_asprintf(program, "raidstart %s", raid_device);
     704#endif
     705log_msg(1, "program = %s", program);
     706res = run_program_and_log_output(program, 1);
     707if (g_fprep) {
     708    fprintf(g_fprep, "%s\n", program);
     709}
     710mr_free(program);
     711
     712if (res) {
     713    log_msg(1, "Warning - failed to start RAID device %s", raid_device);
     714}
     715retval += res;
     716sleep(1);
     717return (retval);
     718}
     719
     720
     721/**
     722 * Decide which command we need to use to format a device of type @p format.
     723 * @param format The filesystem type we are about to format.
     724 * @param program Where to put the binary name for this format.
     725 * @return 0 for success, nonzero for failure.
     726 */
     727char *which_format_command_do_i_need(char *format) {
     728
     729char *program = NULL;
     730
     731assert_string_is_neither_NULL_nor_zerolength(format);
     732
     733if (strcmp(format, "swap") == 0) {
     734#ifdef __FreeBSD__
     735    mr_asprintf(program, "true");
     736#else
     737    mr_asprintf(program, "mkswap -f");
     738#endif
     739} else if (strcmp(format, "vfat") == 0) {
     740#ifdef __FreeBSD__
     741    mr_asprintf(program, "newfs_msdos -F 32");
     742#else
     743#ifdef __IA64__
     744    /* For EFI partitions on ia64 take fat16
     745     * as we want to make small ones */
     746    mr_asprintf(program, "mkfs.vfat -F 16");
     747#else
     748    /* mkfs.vfat will make the best possible choice itself */
     749    /* should avoid problems with mr-label later on when used */
     750    mr_asprintf(program, "mkfs.vfat");
     751#endif
     752#endif
     753#ifndef __FreeBSD__
     754} else if (strcmp(format, "reiserfs") == 0) {
     755    mr_asprintf(program, "mkreiserfs -ff");
     756} else if (strcmp(format, "xfs") == 0) {
     757    /*  Cf: https://bugzilla.redhat.com/show_bug.cgi?id=1309498 */
     758    mr_asprintf(program, "mkfs.xfs -f -q -m crc=0 -n ftype=0");
     759} else if (strcmp(format, "jfs") == 0) {
     760    mr_asprintf(program, "mkfs.jfs");
     761} else if (strcmp(format, "ext3") == 0) {
     762    mr_asprintf(program, "mkfs -t ext3 -F -q");
     763} else if (strcmp(format, "ext4") == 0) {
     764    mr_asprintf(program, "mkfs -t ext4 -F -q");
     765} else if (strcmp(format, "btrfs") == 0) {
     766    mr_asprintf(program, "mkfs.btrfs -f");
     767} else if (strcmp(format, "minix") == 0) {
     768    mr_asprintf(program, "mkfs.minix");
     769} else if (strcmp(format, "vmfs") == 0) {
     770    mr_asprintf(program, "mkfs -t vmfs");
     771} else if (strcmp(format, "ntfs") == 0) {
     772    /*
     773     * mkfs.ntfs treats the '-c' switch as 'specify cluster size'
     774     * so the default "mkfs -t %s -c" command structure fails
     775     */
     776    mr_asprintf(program, "mkfs -t ntfs");
     777} else if (strcmp(format, "ocfs2") == 0) {
     778    /*
     779     * For existing OCFS2 volumes, mkfs.ocfs2 ensures the volume is not mounted on any node in the cluster before formatting. For that to work, mkfs.ocfs2 expects the O2CB cluster service to be running. Specify this option to disable this check.
     780     *
     781     */
     782    mr_asprintf(program, "mkfs -t ocfs2 -F");
     783#endif
     784} else if (strcmp(format, "ext2") == 0) {
     785    mr_asprintf(program, "mke2fs -F -q");
     786} else {
     787#ifdef __FreeBSD__
     788    mr_asprintf(program, "newfs_%s", format);
     789#else
     790    mr_asprintf(program, "mkfs -t %s -c", format);  // -c checks for bad blocks
     791#endif
     792    log_it("Unknown format (%s) - assuming '%s' will do", format, program);
     793}
     794return(program);
     795}
     796
     797
     798
    630799/**
    631800 * Format @p device as a @p format filesystem.
     
    821990return (retval);
    822991}
     992
     993
     994/**
     995 * Stop all software RAID devices listed in @p mountlist.
     996 * @param mountlist The mountlist to stop the RAID devices in.
     997 * @return The number of errors encountered (0 for success).
     998 * @bug @p mountlist is not used.
     999 */
     1000int stop_all_raid_devices(struct mountlist_itself *mountlist) {
     1001
     1002/** int *************************************************************/
     1003int retval = 0;
     1004
     1005/** char ************************************************************/
     1006char *incoming;
     1007#ifndef __FreeBSD__
     1008char *dev;
     1009#endif
     1010/** pointers ********************************************************/
     1011#ifndef __FreeBSD__
     1012char *p;
     1013#endif
     1014FILE *fin;
     1015char *q;
     1016int i;
     1017
     1018/** end ****************************************************************/
     1019
     1020malloc_string(incoming);
     1021assert(mountlist != NULL);
     1022
     1023for (i = 0; i < 3; i++) {
     1024#ifdef __FreeBSD__
     1025    fin = popen("vinum list | grep '^[PVS]' | sed 's/S/1/;s/P/2/;s/V/3/' | sort | cut -d' ' -f2", "r");
     1026    if (!fin) {
     1027        paranoid_free(incoming);
     1028        return (1);
     1029    }
     1030    for (q = fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN - 1, fin)) {
     1031        retval += stop_raid_device(incoming);
     1032    }
     1033#else
     1034    fin = fopen("/proc/mdstat", "r");
     1035    if (!fin) {
     1036        log_OS_error("/proc/mdstat");
     1037        paranoid_free(incoming);
     1038        return (1);
     1039    }
     1040    for (q = fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN - 1, fin)) {
     1041        for (p = incoming; *p != '\0' && (*p != 'm' || *(p + 1) != 'd' || !isdigit(*(p + 2))); p++);
     1042        if (*p != '\0') {
     1043            malloc_string(dev);
     1044            sprintf(dev, "/dev/%s", p);
     1045            for (p = dev; *p > 32; p++);
     1046            *p = '\0';
     1047            retval += stop_raid_device(dev);
     1048            paranoid_free(dev);
     1049        }
     1050    }
     1051#endif
     1052}
     1053paranoid_fclose(fin);
     1054if (retval) {
     1055    log_msg(1, "Warning - unable to stop some RAID devices");
     1056}
     1057paranoid_free(incoming);
     1058paranoid_system("sync");
     1059paranoid_system("sync");
     1060paranoid_system("sync");
     1061sleep(1);
     1062return (retval);
     1063}
     1064
     1065
    8231066
    8241067
     
    9841227paranoid_system("clear");
    9851228newtResume();
     1229return (retval);
     1230}
     1231
     1232
     1233/**
     1234 * Set the type of partition number @p partno on @p drive to @p format.
     1235 * @param drive The drive to change the type of a partition on.
     1236 * @param partno The partition number on @p drive to change the type of.
     1237 * @param format The filesystem type this partition will eventually contain.
     1238 * @param partsize The size of this partition, in @e bytes (used for vfat
     1239 * type calculations).
     1240 * @return 0 for success, nonzero for failure.
     1241 */
     1242int set_partition_type(FILE * pout_to_fdisk, const char *drive, int partno, const char *format, long long partsize) {
     1243
     1244/** buffers *********************************************************/
     1245char *partition = NULL;
     1246char *command = NULL;
     1247char *output = NULL;
     1248char *tmp = NULL;
     1249char *partcode = NULL;
     1250
     1251/** pointers *********************************************************/
     1252FILE *fout;
     1253
     1254/** int **************************************************************/
     1255int res = 0;
     1256
     1257/** end **************************************************************/
     1258
     1259assert_string_is_neither_NULL_nor_zerolength(drive);
     1260assert(format != NULL);
     1261
     1262partition = build_partition_name(drive, partno);
     1263if (strcmp(format, "swap") == 0) {
     1264    mr_asprintf(partcode, "82");
     1265} else if (strcmp(format, "vfat") == 0) {
     1266    if (partsize / 1024 > 8192) {
     1267        mr_asprintf(partcode, "c");
     1268    } else {
     1269        mr_asprintf(partcode, "b");
     1270    }
     1271} else if (strcmp(format, "ext2") == 0
     1272             || strcmp(format, "reiserfs") == 0
     1273             || strcmp(format, "ext3") == 0
     1274             || strcmp(format, "ext4") == 0
     1275             || strcmp(format, "xfs") == 0
     1276             || strcmp(format, "jfs") == 0
     1277             || strcmp(format, "btrfs") == 0) {
     1278    mr_asprintf(partcode, "83");
     1279} else if (strcmp(format, "minix") == 0) {
     1280    mr_asprintf(partcode, "81");
     1281} else if (strcmp(format, "vmfs3") == 0) {
     1282    mr_asprintf(partcode, "fb");
     1283} else if (strcmp(format, "vmkcore") == 0) {
     1284    mr_asprintf(partcode, "fc");
     1285} else if (strcmp(format, "raid") == 0) {
     1286    mr_asprintf(partcode, "fd");
     1287} else if (strcmp(format, "ntfs") == 0) {
     1288    mr_asprintf(partcode, "7");
     1289} else if ((strcmp(format, "ufs") == 0)
     1290             || (strcmp(format, "ffs") == 0)) { /* raid autodetect */
     1291    mr_asprintf(partcode, "a5");
     1292} else if (strcmp(format, "lvm") == 0) {
     1293    mr_asprintf(partcode, "8e");
     1294} else if (format[0] == '\0') { /* LVM physical partition */
     1295    mr_asprintf(partcode, "");
     1296} else if (strlen(format) >= 1 && strlen(format) <= 2) {
     1297    mr_asprintf(partcode, "%s", format);
     1298} else {
     1299    /* probably an image */
     1300    mr_asprintf(tmp, "Unknown format ('%s') - using supplied string anyway", format);
     1301    mvaddstr_and_log_it(g_currentY++, 0, tmp);
     1302    mr_free(tmp);
     1303
     1304#ifdef __FreeBSD__
     1305    mr_asprintf(partcode, "%s", format);    // was a5
     1306#else
     1307    mr_asprintf(partcode, "%s", format);    // was 83
     1308#endif
     1309}
     1310log_msg(1, "Setting %s's type to %s (%s)", partition, format, partcode);
     1311mr_free(partition);
     1312
     1313if ((strcmp(partcode,"") != 0) && strcmp(partcode, "83")) { /* no need to set type if 83: 83 is default */
     1314
     1315    if (pout_to_fdisk) {
     1316        res = 0;
     1317        fput_string_one_char_at_a_time(pout_to_fdisk, "t\n");
     1318        if (partno > 1
     1319            || strstr(last_line_of_file(FDISK_LOG), " (1-4)")) {
     1320            log_msg(5, "Specifying partno (%d) - yay", partno);
     1321            mr_asprintf(tmp, "%d\n", partno);
     1322            fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
     1323            log_msg(5, "A - last line = '%s'", last_line_of_file(FDISK_LOG));
     1324            mr_free(tmp);
     1325        }
     1326
     1327        mr_asprintf(tmp, "%s\n", partcode);
     1328        fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
     1329        mr_free(tmp);
     1330
     1331        log_msg(5, "B - last line = '%s'",
     1332                last_line_of_file(FDISK_LOG));
     1333        fput_string_one_char_at_a_time(pout_to_fdisk, "\n");
     1334        log_msg(5, "C - last line = '%s'",
     1335                last_line_of_file(FDISK_LOG));
     1336
     1337        mr_asprintf(tmp, "%s", last_line_of_file(FDISK_LOG));
     1338        if (!strstr(tmp, " (m ")) {
     1339            log_msg(1, "last line = '%s'; part type set failed", tmp);
     1340            res++;
     1341            fput_string_one_char_at_a_time(pout_to_fdisk, "\n");
     1342        }
     1343        mr_free(tmp);
     1344
     1345        fput_string_one_char_at_a_time(pout_to_fdisk, "p\n");
     1346    } else {
     1347        mr_asprintf(output, "t\n%d\n%s\nw\n", partno, partcode);
     1348        mr_asprintf(command, "mr-parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE);
     1349        log_msg(5, "output = '%s'", output);
     1350        log_msg(5, "partno=%d; partcode=%s", partno, partcode);
     1351        log_msg(5, "command = '%s'", command);
     1352        fout = popen(command, "w");
     1353        if (!fout) {
     1354            log_OS_error(command);
     1355            res = 1;
     1356        } else {
     1357            res = 0;
     1358            fprintf(fout, "%s", output);
     1359            paranoid_pclose(fout);
     1360        }
     1361        mr_free(command);
     1362        paranoid_free(output);
     1363    }
     1364}
     1365mr_free(partcode);
     1366
     1367return (res);
     1368}
     1369
     1370
     1371/**
     1372 * Create partition number @p partno on @p drive with @p fdisk.
     1373 * @param drive The drive to create the partition on.
     1374//  * @param partno The partition number of the new partition (1-4 are primary, >=5 is logical).
     1375 * @param prev_partno The partition number of the most recently prepped partition.
     1376 * @param format The filesystem type of this partition (used to set the type).
     1377 * @param partsize The size of the partition in @e bytes.
     1378 * @return 0 for success, nonzero for failure.
     1379 */
     1380int partition_device(FILE * pout_to_fdisk, const char *drive, int partno, int prev_partno, const char *format, long long partsize) {
     1381
     1382/** int **************************************************************/
     1383int retval = 0;
     1384int res = 0;
     1385
     1386/** buffers **********************************************************/
     1387char *program = NULL;
     1388char *partition_name = NULL;
     1389char *tmp = NULL;
     1390char *output = NULL;
     1391
     1392/** pointers **********************************************************/
     1393char *part_table_fmt = NULL;
     1394FILE *fout;
     1395
     1396/** end ***************************************************************/
     1397
     1398assert_string_is_neither_NULL_nor_zerolength(drive);
     1399assert(format != NULL);
     1400
     1401log_it("partition_device('%s', %d, %d, '%s', %lld) --- starting", drive, partno, prev_partno, format, partsize);
     1402
     1403if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
     1404    log_it("Not partitioning %s - it is a virtual drive", drive);
     1405    return (0);
     1406}
     1407
     1408partition_name = build_partition_name(drive, partno);
     1409if (partsize <= 0) {
     1410    mr_asprintf(tmp, "Partitioning device %s (max size)", partition_name);
     1411} else {
     1412    mr_asprintf(tmp, "Partitioning device %s (%lld MB)", partition_name, (long long) partsize / 1024);
     1413}
     1414update_progress_form(tmp);
     1415log_it(tmp);
     1416mr_free(tmp);
     1417
     1418if (is_this_device_mounted(partition_name)) {
     1419    log_to_screen("%s is mounted, and should not be partitioned", partition_name);
     1420    mr_free(partition_name);
     1421    return (1);
     1422}
     1423
     1424
     1425mr_asprintf(program, "mr-parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE);
     1426
     1427/* TODO: should not be called each time */
     1428part_table_fmt = which_partition_format(drive);
     1429mr_asprintf(output, "");
     1430
     1431/* make it a primary/extended/logical */
     1432if (partno <= 4) {
     1433    mr_strcat(output, "n\np\n%d\n", partno);
     1434} else {
     1435    /* MBR needs an extended partition if more than 4 partitions */
     1436    if (strcmp(part_table_fmt, "MBR") == 0) {
     1437        if (partno == 5) {
     1438            if (prev_partno >= 4) {
     1439                log_to_screen("You need to leave at least one partition free, for 'extended/logical'");
     1440                mr_free(partition_name);
     1441                paranoid_free(output);
     1442                return (1);
     1443            } else {
     1444                mr_strcat(output, "n\ne\n%d\n\n\n", prev_partno + 1);
     1445            }
     1446        }
     1447        mr_strcat(output, "n\nl\n");
     1448    } else {
     1449        /* GPT allows more than 4 primary partitions */
     1450        mr_strcat(output, "n\np\n%d\n", partno);
     1451    }
     1452}
     1453mr_free(part_table_fmt);
     1454
     1455mr_strcat(output, "\n");    /*start block (ENTER for next free blk */
     1456if (partsize > 0) {
     1457    if (!strcmp(format, "7")) {
     1458        log_msg(1, "Adding 512K, just in case");
     1459        partsize += 512;
     1460    }
     1461    mr_strcat(output, "+%lldK", (long long) (partsize));
     1462}
     1463mr_strcat(output, "\n");
     1464#if 0
     1465/*
     1466#endif
     1467log_it("PARTSIZE = +%ld",(long)partsize);
     1468log_it("---fdisk command---");
     1469log_it(output);
     1470log_it("---end of fdisk---");
     1471#if 0
     1472*/
     1473#endif
     1474
     1475
     1476if (pout_to_fdisk) {
     1477    log_msg(1, "Doing the new all-in-one fdisk thing");
     1478    mr_strcat(output, "\n\np\n\n");
     1479    log_msg(1, "output = '%s'", output);
     1480    fput_string_one_char_at_a_time(pout_to_fdisk, output);
     1481    mr_asprintf(tmp, "%s", last_line_of_file(FDISK_LOG));
     1482    if (strstr(tmp, " (m ")) {
     1483        log_msg(1, "Successfully created partition %d on %s", partno, drive);
     1484    } else {
     1485        log_msg(1, "last line = %s", tmp);
     1486        log_msg(1, "Failed to create partition %d on %s; sending 'Enter'...", partno, drive);
     1487    }
     1488    mr_free(tmp);
     1489
     1490    if (!retval) {
     1491        log_msg(1, "Trying to set partition %d type now on %s", partno, drive);
     1492        retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);
     1493        if (retval) {
     1494            log_msg(1, "Failed. Trying again...");
     1495            retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);
     1496        }
     1497    }
     1498    if (retval) {
     1499        log_msg(1, "...but failed to set type");
     1500    }
     1501} else {
     1502    mr_strcat(output, "w\n\n");
     1503    if (g_fprep) {
     1504        fprintf(g_fprep, "echo \"%s\" | %s\n", output, program);
     1505    }
     1506    /* write to disk; close fdisk's stream */
     1507    if (!(fout = popen(program, "w"))) {
     1508        log_OS_error("can't popen-out to program");
     1509    } else {
     1510        fputs(output, fout);
     1511        paranoid_pclose(fout);
     1512    }
     1513
     1514    if (!does_partition_exist(drive, partno) && partsize > 0) {
     1515        log_it("Vaccum-packing");
     1516        g_current_progress--;
     1517        res = partition_device(pout_to_fdisk, drive, partno, prev_partno, format, -1);
     1518        if (res) {
     1519            log_it("Failed to vacuum-pack %s", partition_name);
     1520            retval++;
     1521        } else {
     1522            retval = 0;
     1523        }
     1524    }
     1525    if (does_partition_exist(drive, partno)) {
     1526        retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);
     1527        if (retval) {
     1528            log_it("Partitioned %s but failed to set its type", partition_name);
     1529        } else {
     1530            if (partsize > 0) {
     1531                log_to_screen("Partition %s created+configured OK", partition_name);
     1532            } else {
     1533                log_it("Returning from a successful vacuum-pack");
     1534            }
     1535        }
     1536    } else {
     1537        mr_asprintf(tmp, "Failed to partition %s", partition_name);
     1538        if (partsize > 0) {
     1539            log_to_screen(tmp);
     1540        } else {
     1541            log_it(tmp);
     1542        }
     1543        mr_free(tmp);
     1544        retval++;
     1545    }
     1546}
     1547mr_free(program);
     1548mr_free(output);
     1549mr_free(partition_name);
     1550
     1551g_current_progress++;
     1552log_it("partition_device() --- leaving");
    9861553return (retval);
    9871554}
     
    15322099}
    15332100
    1534 /**
    1535  * Create partition number @p partno on @p drive with @p fdisk.
    1536  * @param drive The drive to create the partition on.
    1537 //  * @param partno The partition number of the new partition (1-4 are primary, >=5 is logical).
    1538  * @param prev_partno The partition number of the most recently prepped partition.
    1539  * @param format The filesystem type of this partition (used to set the type).
    1540  * @param partsize The size of the partition in @e bytes.
    1541  * @return 0 for success, nonzero for failure.
    1542  */
    1543 int partition_device(FILE * pout_to_fdisk, const char *drive, int partno, int prev_partno, const char *format, long long partsize) {
    1544 
    1545 /** int **************************************************************/
    1546 int retval = 0;
    1547 int res = 0;
    1548 
    1549 /** buffers **********************************************************/
    1550 char *program = NULL;
    1551 char *partition_name = NULL;
    1552 char *tmp = NULL;
    1553 char *output = NULL;
    1554 
    1555 /** pointers **********************************************************/
    1556 char *part_table_fmt = NULL;
    1557 FILE *fout;
    1558 
    1559 /** end ***************************************************************/
    1560 
    1561 assert_string_is_neither_NULL_nor_zerolength(drive);
    1562 assert(format != NULL);
    1563 
    1564 log_it("partition_device('%s', %d, %d, '%s', %lld) --- starting", drive, partno, prev_partno, format, partsize);
    1565 
    1566 if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
    1567     log_it("Not partitioning %s - it is a virtual drive", drive);
    1568     return (0);
    1569 }
    1570 
    1571 partition_name = build_partition_name(drive, partno);
    1572 if (partsize <= 0) {
    1573     mr_asprintf(tmp, "Partitioning device %s (max size)", partition_name);
    1574 } else {
    1575     mr_asprintf(tmp, "Partitioning device %s (%lld MB)", partition_name, (long long) partsize / 1024);
    1576 }
    1577 update_progress_form(tmp);
    1578 log_it(tmp);
    1579 mr_free(tmp);
    1580 
    1581 if (is_this_device_mounted(partition_name)) {
    1582     log_to_screen("%s is mounted, and should not be partitioned", partition_name);
    1583     mr_free(partition_name);
    1584     return (1);
    1585 }
    1586 
    1587 
    1588 mr_asprintf(program, "mr-parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE);
    1589 
    1590 /* TODO: should not be called each time */
    1591 part_table_fmt = which_partition_format(drive);
    1592 mr_asprintf(output, "");
    1593 
    1594 /* make it a primary/extended/logical */
    1595 if (partno <= 4) {
    1596     mr_strcat(output, "n\np\n%d\n", partno);
    1597 } else {
    1598     /* MBR needs an extended partition if more than 4 partitions */
    1599     if (strcmp(part_table_fmt, "MBR") == 0) {
    1600         if (partno == 5) {
    1601             if (prev_partno >= 4) {
    1602                 log_to_screen("You need to leave at least one partition free, for 'extended/logical'");
    1603                 mr_free(partition_name);
    1604                 paranoid_free(output);
    1605                 return (1);
    1606             } else {
    1607                 mr_strcat(output, "n\ne\n%d\n\n\n", prev_partno + 1);
    1608             }
    1609         }
    1610         mr_strcat(output, "n\nl\n");
    1611     } else {
    1612         /* GPT allows more than 4 primary partitions */
    1613         mr_strcat(output, "n\np\n%d\n", partno);
    1614     }
    1615 }
    1616 mr_free(part_table_fmt);
    1617 
    1618 mr_strcat(output, "\n");    /*start block (ENTER for next free blk */
    1619 if (partsize > 0) {
    1620     if (!strcmp(format, "7")) {
    1621         log_msg(1, "Adding 512K, just in case");
    1622         partsize += 512;
    1623     }
    1624     mr_strcat(output, "+%lldK", (long long) (partsize));
    1625 }
    1626 mr_strcat(output, "\n");
    1627 #if 0
    1628 /*
    1629 #endif
    1630 log_it("PARTSIZE = +%ld",(long)partsize);
    1631 log_it("---fdisk command---");
    1632 log_it(output);
    1633 log_it("---end of fdisk---");
    1634 #if 0
    1635 */
    1636 #endif
    1637 
    1638 
    1639 if (pout_to_fdisk) {
    1640     log_msg(1, "Doing the new all-in-one fdisk thing");
    1641     mr_strcat(output, "\n\np\n\n");
    1642     log_msg(1, "output = '%s'", output);
    1643     fput_string_one_char_at_a_time(pout_to_fdisk, output);
    1644     mr_asprintf(tmp, "%s", last_line_of_file(FDISK_LOG));
    1645     if (strstr(tmp, " (m ")) {
    1646         log_msg(1, "Successfully created partition %d on %s", partno, drive);
    1647     } else {
    1648         log_msg(1, "last line = %s", tmp);
    1649         log_msg(1, "Failed to create partition %d on %s; sending 'Enter'...", partno, drive);
    1650     }
    1651     mr_free(tmp);
    1652 
    1653     if (!retval) {
    1654         log_msg(1, "Trying to set partition %d type now on %s", partno, drive);
    1655         retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);
    1656         if (retval) {
    1657             log_msg(1, "Failed. Trying again...");
    1658             retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);
    1659         }
    1660     }
    1661     if (retval) {
    1662         log_msg(1, "...but failed to set type");
    1663     }
    1664 } else {
    1665     mr_strcat(output, "w\n\n");
    1666     if (g_fprep) {
    1667         fprintf(g_fprep, "echo \"%s\" | %s\n", output, program);
    1668     }
    1669     /* write to disk; close fdisk's stream */
    1670     if (!(fout = popen(program, "w"))) {
    1671         log_OS_error("can't popen-out to program");
    1672     } else {
    1673         fputs(output, fout);
    1674         paranoid_pclose(fout);
    1675     }
    1676 
    1677     if (!does_partition_exist(drive, partno) && partsize > 0) {
    1678         log_it("Vaccum-packing");
    1679         g_current_progress--;
    1680         res = partition_device(pout_to_fdisk, drive, partno, prev_partno, format, -1);
    1681         if (res) {
    1682             log_it("Failed to vacuum-pack %s", partition_name);
    1683             retval++;
    1684         } else {
    1685             retval = 0;
    1686         }
    1687     }
    1688     if (does_partition_exist(drive, partno)) {
    1689         retval = set_partition_type(pout_to_fdisk, drive, partno, format, partsize);
    1690         if (retval) {
    1691             log_it("Partitioned %s but failed to set its type", partition_name);
    1692         } else {
    1693             if (partsize > 0) {
    1694                 log_to_screen("Partition %s created+configured OK", partition_name);
    1695             } else {
    1696                 log_it("Returning from a successful vacuum-pack");
    1697             }
    1698         }
    1699     } else {
    1700         mr_asprintf(tmp, "Failed to partition %s", partition_name);
    1701         if (partsize > 0) {
    1702             log_to_screen(tmp);
    1703         } else {
    1704             log_it(tmp);
    1705         }
    1706         mr_free(tmp);
    1707         retval++;
    1708     }
    1709 }
    1710 mr_free(program);
    1711 mr_free(output);
    1712 mr_free(partition_name);
    1713 
    1714 g_current_progress++;
    1715 log_it("partition_device() --- leaving");
    1716 return (retval);
    1717 }
    1718 
    1719 
    17202101
    17212102/**
     
    17892170
    17902171
    1791 
    17922172/**
    1793  * Set the type of partition number @p partno on @p drive to @p format.
    1794  * @param drive The drive to change the type of a partition on.
    1795  * @param partno The partition number on @p drive to change the type of.
    1796  * @param format The filesystem type this partition will eventually contain.
    1797  * @param partsize The size of this partition, in @e bytes (used for vfat
    1798  * type calculations).
    1799  * @return 0 for success, nonzero for failure.
     2173 * Create a mountlist_reference structure for @p drive_name in @p mountlist.
     2174 * @param mountlist The complete mountlist to get the drive references from.
     2175 * @param drive_name The drive to put in @p drivemntlist.
     2176 * @param drivemntlist The mountlist_reference structure to put the drive's entries in.
     2177 * @note @p drivemntlist and @p drivemntlist->el must be allocated by the caller.
     2178 * @author Ralph Grewe
    18002179 */
    1801 int set_partition_type(FILE * pout_to_fdisk, const char *drive, int partno, const char *format, long long partsize) {
    1802 
    1803 /** buffers *********************************************************/
    1804 char *partition = NULL;
    1805 char *command = NULL;
    1806 char *output = NULL;
    1807 char *tmp = NULL;
    1808 char *partcode = NULL;
    1809 
    1810 /** pointers *********************************************************/
    1811 FILE *fout;
    1812 
    1813 /** int **************************************************************/
    1814 int res = 0;
    1815 
    1816 /** end **************************************************************/
    1817 
    1818 assert_string_is_neither_NULL_nor_zerolength(drive);
    1819 assert(format != NULL);
    1820 
    1821 partition = build_partition_name(drive, partno);
    1822 if (strcmp(format, "swap") == 0) {
    1823     mr_asprintf(partcode, "82");
    1824 } else if (strcmp(format, "vfat") == 0) {
    1825     if (partsize / 1024 > 8192) {
    1826         mr_asprintf(partcode, "c");
    1827     } else {
    1828         mr_asprintf(partcode, "b");
    1829     }
    1830 } else if (strcmp(format, "ext2") == 0
    1831              || strcmp(format, "reiserfs") == 0
    1832              || strcmp(format, "ext3") == 0
    1833              || strcmp(format, "ext4") == 0
    1834              || strcmp(format, "xfs") == 0
    1835              || strcmp(format, "jfs") == 0
    1836              || strcmp(format, "btrfs") == 0) {
    1837     mr_asprintf(partcode, "83");
    1838 } else if (strcmp(format, "minix") == 0) {
    1839     mr_asprintf(partcode, "81");
    1840 } else if (strcmp(format, "vmfs3") == 0) {
    1841     mr_asprintf(partcode, "fb");
    1842 } else if (strcmp(format, "vmkcore") == 0) {
    1843     mr_asprintf(partcode, "fc");
    1844 } else if (strcmp(format, "raid") == 0) {
    1845     mr_asprintf(partcode, "fd");
    1846 } else if (strcmp(format, "ntfs") == 0) {
    1847     mr_asprintf(partcode, "7");
    1848 } else if ((strcmp(format, "ufs") == 0)
    1849              || (strcmp(format, "ffs") == 0)) { /* raid autodetect */
    1850     mr_asprintf(partcode, "a5");
    1851 } else if (strcmp(format, "lvm") == 0) {
    1852     mr_asprintf(partcode, "8e");
    1853 } else if (format[0] == '\0') { /* LVM physical partition */
    1854     mr_asprintf(partcode, "");
    1855 } else if (strlen(format) >= 1 && strlen(format) <= 2) {
    1856     mr_asprintf(partcode, "%s", format);
    1857 } else {
    1858     /* probably an image */
    1859     mr_asprintf(tmp, "Unknown format ('%s') - using supplied string anyway", format);
    1860     mvaddstr_and_log_it(g_currentY++, 0, tmp);
    1861     mr_free(tmp);
    1862 
    1863 #ifdef __FreeBSD__
    1864     mr_asprintf(partcode, "%s", format);    // was a5
    1865 #else
    1866     mr_asprintf(partcode, "%s", format);    // was 83
    1867 #endif
    1868 }
    1869 log_msg(1, "Setting %s's type to %s (%s)", partition, format, partcode);
    1870 mr_free(partition);
    1871 
    1872 if ((strcmp(partcode,"") != 0) && strcmp(partcode, "83")) { /* no need to set type if 83: 83 is default */
    1873 
    1874     if (pout_to_fdisk) {
    1875         res = 0;
    1876         fput_string_one_char_at_a_time(pout_to_fdisk, "t\n");
    1877         if (partno > 1
    1878             || strstr(last_line_of_file(FDISK_LOG), " (1-4)")) {
    1879             log_msg(5, "Specifying partno (%d) - yay", partno);
    1880             mr_asprintf(tmp, "%d\n", partno);
    1881             fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
    1882             log_msg(5, "A - last line = '%s'", last_line_of_file(FDISK_LOG));
    1883             mr_free(tmp);
    1884         }
    1885 
    1886         mr_asprintf(tmp, "%s\n", partcode);
    1887         fput_string_one_char_at_a_time(pout_to_fdisk, tmp);
    1888         mr_free(tmp);
    1889 
    1890         log_msg(5, "B - last line = '%s'",
    1891                 last_line_of_file(FDISK_LOG));
    1892         fput_string_one_char_at_a_time(pout_to_fdisk, "\n");
    1893         log_msg(5, "C - last line = '%s'",
    1894                 last_line_of_file(FDISK_LOG));
    1895 
    1896         mr_asprintf(tmp, "%s", last_line_of_file(FDISK_LOG));
    1897         if (!strstr(tmp, " (m ")) {
    1898             log_msg(1, "last line = '%s'; part type set failed", tmp);
    1899             res++;
    1900             fput_string_one_char_at_a_time(pout_to_fdisk, "\n");
    1901         }
    1902         mr_free(tmp);
    1903 
    1904         fput_string_one_char_at_a_time(pout_to_fdisk, "p\n");
    1905     } else {
    1906         mr_asprintf(output, "t\n%d\n%s\nw\n", partno, partcode);
    1907         mr_asprintf(command, "mr-parted2fdisk %s >> %s 2>> %s", drive, MONDO_LOGFILE, MONDO_LOGFILE);
    1908         log_msg(5, "output = '%s'", output);
    1909         log_msg(5, "partno=%d; partcode=%s", partno, partcode);
    1910         log_msg(5, "command = '%s'", command);
    1911         fout = popen(command, "w");
    1912         if (!fout) {
    1913             log_OS_error(command);
    1914             res = 1;
    1915         } else {
    1916             res = 0;
    1917             fprintf(fout, "%s", output);
    1918             paranoid_pclose(fout);
    1919         }
    1920         mr_free(command);
    1921         paranoid_free(output);
    1922     }
    1923 }
    1924 mr_free(partcode);
    1925 
    1926 return (res);
    1927 }
    1928 
    1929 
    1930 int start_raid_device(char *raid_device) {
    1931 
    1932 /** int *************************************************************/
    1933 int res;
    1934 int retval = 0;
    1935 
    1936 /** buffers *********************************************************/
    1937 char *program = NULL;
    1938 
    1939 /** end *************************************************************/
    1940 
    1941 assert_string_is_neither_NULL_nor_zerolength(raid_device);
    1942 
    1943 #ifdef __FreeBSD__
    1944 if (is_this_device_mounted(raid_device)) {
    1945     log_it("Can't start %s when it's mounted!", raid_device);
    1946     return 1;
    1947 }
    1948 mr_asprintf(program, "vinum start -f %s", raid_device);
    1949 #else
    1950 mr_asprintf(program, "raidstart %s", raid_device);
    1951 #endif
    1952 log_msg(1, "program = %s", program);
    1953 res = run_program_and_log_output(program, 1);
    1954 if (g_fprep) {
    1955     fprintf(g_fprep, "%s\n", program);
    1956 }
    1957 mr_free(program);
    1958 
    1959 if (res) {
    1960     log_msg(1, "Warning - failed to start RAID device %s", raid_device);
    1961 }
    1962 retval += res;
    1963 sleep(1);
    1964 return (retval);
    1965 }
    1966 
    1967 
    1968 
    1969 /**
    1970  * Stop @p raid_device using @p raidstop.
    1971  * @param raid_device The software RAID device to stop.
    1972  * @return 0 for success, nonzero for failure.
    1973  */
    1974 int stop_raid_device(char *raid_device) {
    1975 
    1976 /** int *************************************************************/
    1977 int res;
    1978 int retval = 0;
    1979 
    1980 /** buffers *********************************************************/
    1981 char *program = NULL;
    1982 
    1983 /** end *************************************************************/
    1984 
    1985 assert_string_is_neither_NULL_nor_zerolength(raid_device);
    1986 
    1987 #ifdef __FreeBSD__
    1988 if (is_this_device_mounted(raid_device)) {
    1989     log_it("Can't stop %s when it's mounted!", raid_device);
    1990     return 1;
    1991 }
    1992 mr_asprintf(program, "vinum stop -f %s", raid_device);
    1993 #else
    1994 // use raidstop if it exists, otherwise use mdadm
    1995 if (run_program_and_log_output("which raidstop", FALSE)) {
    1996     mr_asprintf(program, "mdadm -S %s", raid_device);
    1997 } else {
    1998     mr_asprintf(program, "raidstop %s", raid_device);
    1999 }
    2000 #endif
    2001 log_msg(1, "program = %s", program);
    2002 res = run_program_and_log_output(program, 1);
    2003 if (g_fprep) {
    2004     fprintf(g_fprep, "%s\n", program);
    2005 }
    2006 mr_free(program);
    2007 
    2008 if (res) {
    2009     log_msg(1, "Warning - failed to stop RAID device %s", raid_device);
    2010 }
    2011 retval += res;
    2012 return (retval);
    2013 }
    2014 
    2015 
    2016 int start_all_raid_devices(struct mountlist_itself *mountlist) {
    2017 
    2018 int i;
    2019 int retval = 0;
    2020 int res;
    2021 
    2022 for (i = 0; i < mountlist->entries; i++) {
    2023     if (!strncmp(mountlist->el[i].device, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
    2024         log_msg(1, "Starting %s", mountlist->el[i].device);
    2025         res = start_raid_device(mountlist->el[i].device);
    2026         retval += res;
    2027     }
    2028 }
    2029 if (retval) {
    2030     log_msg(1, "Started all s/w raid devices OK");
    2031 } else {
    2032     log_msg(1, "Failed to start some/all s/w raid devices");
    2033 }
    2034 return (retval);
    2035 }
    2036 
    2037 /**
    2038  * Stop all software RAID devices listed in @p mountlist.
    2039  * @param mountlist The mountlist to stop the RAID devices in.
    2040  * @return The number of errors encountered (0 for success).
    2041  * @bug @p mountlist is not used.
    2042  */
    2043 int stop_all_raid_devices(struct mountlist_itself *mountlist) {
    2044 
    2045 /** int *************************************************************/
    2046 int retval = 0;
    2047 
    2048 /** char ************************************************************/
    2049 char *incoming;
    2050 #ifndef __FreeBSD__
    2051 char *dev;
    2052 #endif
    2053 /** pointers ********************************************************/
    2054 #ifndef __FreeBSD__
    2055 char *p;
    2056 #endif
    2057 FILE *fin;
    2058 char *q;
    2059 int i;
    2060 
    2061 /** end ****************************************************************/
    2062 
    2063 malloc_string(incoming);
     2180void create_mountlist_for_drive(struct mountlist_itself *mountlist, char *drive_name, struct mountlist_reference *drivemntlist) {
     2181
     2182int partno;
     2183char *tmp_drive_name, *c;
     2184
    20642185assert(mountlist != NULL);
    2065 
    2066 for (i = 0; i < 3; i++) {
    2067 #ifdef __FreeBSD__
    2068     fin = popen("vinum list | grep '^[PVS]' | sed 's/S/1/;s/P/2/;s/V/3/' | sort | cut -d' ' -f2", "r");
    2069     if (!fin) {
    2070         paranoid_free(incoming);
    2071         return (1);
    2072     }
    2073     for (q = fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN - 1, fin)) {
    2074         retval += stop_raid_device(incoming);
    2075     }
    2076 #else
    2077     fin = fopen("/proc/mdstat", "r");
    2078     if (!fin) {
    2079         log_OS_error("/proc/mdstat");
    2080         paranoid_free(incoming);
    2081         return (1);
    2082     }
    2083     for (q = fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin) && (q != NULL); q = fgets(incoming, MAX_STR_LEN - 1, fin)) {
    2084         for (p = incoming; *p != '\0' && (*p != 'm' || *(p + 1) != 'd' || !isdigit(*(p + 2))); p++);
    2085         if (*p != '\0') {
    2086             malloc_string(dev);
    2087             sprintf(dev, "/dev/%s", p);
    2088             for (p = dev; *p > 32; p++);
    2089             *p = '\0';
    2090             retval += stop_raid_device(dev);
    2091             paranoid_free(dev);
    2092         }
    2093     }
    2094 #endif
    2095 }
    2096 paranoid_fclose(fin);
    2097 if (retval) {
    2098     log_msg(1, "Warning - unable to stop some RAID devices");
    2099 }
    2100 paranoid_free(incoming);
    2101 paranoid_system("sync");
    2102 paranoid_system("sync");
    2103 paranoid_system("sync");
    2104 sleep(1);
    2105 return (retval);
    2106 }
    2107 
    2108 
    2109 
    2110 /**
    2111  * Decide which command we need to use to format a device of type @p format.
    2112  * @param format The filesystem type we are about to format.
    2113  * @param program Where to put the binary name for this format.
    2114  * @return 0 for success, nonzero for failure.
    2115  */
    2116 char *which_format_command_do_i_need(char *format) {
    2117 
    2118 char *program = NULL;
    2119 
    2120 assert_string_is_neither_NULL_nor_zerolength(format);
    2121 
    2122 if (strcmp(format, "swap") == 0) {
    2123 #ifdef __FreeBSD__
    2124     mr_asprintf(program, "true");
    2125 #else
    2126     mr_asprintf(program, "mkswap -f");
    2127 #endif
    2128 } else if (strcmp(format, "vfat") == 0) {
    2129 #ifdef __FreeBSD__
    2130     mr_asprintf(program, "newfs_msdos -F 32");
    2131 #else
    2132 #ifdef __IA64__
    2133     /* For EFI partitions on ia64 take fat16
    2134      * as we want to make small ones */
    2135     mr_asprintf(program, "mkfs.vfat -F 16");
    2136 #else
    2137     /* mkfs.vfat will make the best possible choice itself */
    2138     /* should avoid problems with mr-label later on when used */
    2139     mr_asprintf(program, "mkfs.vfat");
    2140 #endif
    2141 #endif
    2142 #ifndef __FreeBSD__
    2143 } else if (strcmp(format, "reiserfs") == 0) {
    2144     mr_asprintf(program, "mkreiserfs -ff");
    2145 } else if (strcmp(format, "xfs") == 0) {
    2146     /*  Cf: https://bugzilla.redhat.com/show_bug.cgi?id=1309498 */
    2147     mr_asprintf(program, "mkfs.xfs -f -q -m crc=0 -n ftype=0");
    2148 } else if (strcmp(format, "jfs") == 0) {
    2149     mr_asprintf(program, "mkfs.jfs");
    2150 } else if (strcmp(format, "ext3") == 0) {
    2151     mr_asprintf(program, "mkfs -t ext3 -F -q");
    2152 } else if (strcmp(format, "ext4") == 0) {
    2153     mr_asprintf(program, "mkfs -t ext4 -F -q");
    2154 } else if (strcmp(format, "btrfs") == 0) {
    2155     mr_asprintf(program, "mkfs.btrfs -f");
    2156 } else if (strcmp(format, "minix") == 0) {
    2157     mr_asprintf(program, "mkfs.minix");
    2158 } else if (strcmp(format, "vmfs") == 0) {
    2159     mr_asprintf(program, "mkfs -t vmfs");
    2160 } else if (strcmp(format, "ntfs") == 0) {
    2161     /*
    2162      * mkfs.ntfs treats the '-c' switch as 'specify cluster size'
    2163      * so the default "mkfs -t %s -c" command structure fails
    2164      */
    2165     mr_asprintf(program, "mkfs -t ntfs");
    2166 } else if (strcmp(format, "ocfs2") == 0) {
    2167     /*
    2168      * For existing OCFS2 volumes, mkfs.ocfs2 ensures the volume is not mounted on any node in the cluster before formatting. For that to work, mkfs.ocfs2 expects the O2CB cluster service to be running. Specify this option to disable this check.
    2169      *
    2170      */
    2171     mr_asprintf(program, "mkfs -t ocfs2 -F");
    2172 #endif
    2173 } else if (strcmp(format, "ext2") == 0) {
    2174     mr_asprintf(program, "mke2fs -F -q");
    2175 } else {
    2176 #ifdef __FreeBSD__
    2177     mr_asprintf(program, "newfs_%s", format);
    2178 #else
    2179     mr_asprintf(program, "mkfs -t %s -c", format);  // -c checks for bad blocks
    2180 #endif
    2181     log_it("Unknown format (%s) - assuming '%s' will do", format, program);
    2182 }
    2183 return(program);
     2186assert(drive_name != NULL);
     2187assert(drivemntlist != NULL);
     2188
     2189log_msg(1, "Creating list of partitions for drive %s", drive_name);
     2190
     2191tmp_drive_name = strdup(drive_name);
     2192if (!tmp_drive_name)
     2193    fatal_error("Out of memory");
     2194
     2195/* devfs devices? */
     2196c = strrchr(tmp_drive_name, '/');
     2197if (c && strncmp(c, "/disc", 5) == 0) {
     2198    /* yup its devfs, change the "disc" to "part" so the existing code works */
     2199    strcpy(c + 1, "part");
     2200}
     2201drivemntlist->entries = 0;
     2202for (partno = 0; partno < mountlist->entries; partno++) {
     2203    if (strncmp(mountlist->el[partno].device, tmp_drive_name, strlen(tmp_drive_name)) == 0) {
     2204        drivemntlist->el[drivemntlist->entries] = &mountlist->el[partno];
     2205        drivemntlist->entries++;
     2206    }
     2207}
     2208if (tmp_drive_name)
     2209    free(tmp_drive_name);
    21842210}
    21852211
     
    23312357paranoid_free(drivelist);
    23322358}
    2333 
    2334 /**
    2335  * Create a mountlist_reference structure for @p drive_name in @p mountlist.
    2336  * @param mountlist The complete mountlist to get the drive references from.
    2337  * @param drive_name The drive to put in @p drivemntlist.
    2338  * @param drivemntlist The mountlist_reference structure to put the drive's entries in.
    2339  * @note @p drivemntlist and @p drivemntlist->el must be allocated by the caller.
    2340  * @author Ralph Grewe
    2341  */
    2342 void create_mountlist_for_drive(struct mountlist_itself *mountlist, char *drive_name, struct mountlist_reference *drivemntlist) {
    2343 
    2344 int partno;
    2345 char *tmp_drive_name, *c;
    2346 
    2347 assert(mountlist != NULL);
    2348 assert(drive_name != NULL);
    2349 assert(drivemntlist != NULL);
    2350 
    2351 log_msg(1, "Creating list of partitions for drive %s", drive_name);
    2352 
    2353 tmp_drive_name = strdup(drive_name);
    2354 if (!tmp_drive_name)
    2355     fatal_error("Out of memory");
    2356 
    2357 /* devfs devices? */
    2358 c = strrchr(tmp_drive_name, '/');
    2359 if (c && strncmp(c, "/disc", 5) == 0) {
    2360     /* yup its devfs, change the "disc" to "part" so the existing code works */
    2361     strcpy(c + 1, "part");
    2362 }
    2363 drivemntlist->entries = 0;
    2364 for (partno = 0; partno < mountlist->entries; partno++) {
    2365     if (strncmp(mountlist->el[partno].device, tmp_drive_name, strlen(tmp_drive_name)) == 0) {
    2366         drivemntlist->el[drivemntlist->entries] = &mountlist->el[partno];
    2367         drivemntlist->entries++;
    2368     }
    2369 }
    2370 if (tmp_drive_name)
    2371     free(tmp_drive_name);
    2372 }
    2373 
    23742359/* @} - end of prepGroup */
  • branches/3.3/mondo/src/mondorestore/mondo-rstr-compare.c

    r3875 r3879  
    77#include "mr_mem.h"
    88#include "mr_file.h"
    9 #include "../common/mondostructures.h"
    10 #include "../common/libmondo.h"
    11 //#include "../../config.h"
    12 #include "mr-externs.h"
    13 #include "mondo-rstr-compare.h"
    14 #include "mondorestore-EXT.h"
     9#include "mr_sys.h"
     10#include "mondostructures.h"
    1511#include "mondo-rstr-tools-EXT.h"
     12#include "libmondo-string-EXT.h"
     13#include "libmondo-verify-EXT.h"
     14#include "libmondo-files-EXT.h"
     15#include "libmondo-tools-EXT.h"
     16#include "libmondo-fork-EXT.h"
     17#include "libmondo-devices-EXT.h"
     18#include "libmondo-string-EXT.h"
     19#include "libmondo-mountlist-EXT.h"
     20#include "libmondo-raid-EXT.h"
     21#include "newt-specific-EXT.h"
    1622
    1723extern char *MONDO_LOGFILE;
     
    2127
    2228extern char *g_mountlist_fname;
     29extern int g_current_media_number;
     30extern bool g_text_mode;
     31extern int g_currentY;
     32extern long g_current_progress;
     33extern char *g_mondo_cfg_file;
     34
     35// in mondo-rstr-newt.c
     36extern int edit_mountlist(char *, struct mountlist_itself *, struct raidlist_itself *);
    2337
    2438//static char cvsid[] = "$Id$";
     
    6377
    6478    if (!does_file_exist(slice_fname(bigfileno, 0, ARCHIVES_PATH, ""))) {
    65         if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
     79        if (does_file_exist(ARCHIVES_PATH "/NOT-THE-LAST")) {
    6680            insist_on_this_cd_number((++g_current_media_number));
    6781        } else {
     
    368382        insist_on_this_cd_number(g_current_media_number);
    369383        update_progress_form(progress_str);
    370         mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.bz2", current_tarball_number);
     384        mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.bz2", current_tarball_number);
    371385
    372386        if (!does_file_exist(tarball_fname)) {
    373387            mr_free(tarball_fname);
    374             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.lzo", current_tarball_number);
     388            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.lzo", current_tarball_number);
    375389        }
    376390        if (!does_file_exist(tarball_fname)) {
    377391            mr_free(tarball_fname);
    378             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.lzma", current_tarball_number);
     392            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.lzma", current_tarball_number);
    379393        }
    380394        if (!does_file_exist(tarball_fname)) {
    381395            mr_free(tarball_fname);
    382             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.gz", current_tarball_number);
     396            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.gz", current_tarball_number);
    383397        }
    384398        if (!does_file_exist(tarball_fname)) {
    385399            mr_free(tarball_fname);
    386             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.afio.", current_tarball_number);
     400            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.afio.", current_tarball_number);
    387401        }
    388402        if (!does_file_exist(tarball_fname)) {
    389403            mr_free(tarball_fname);
    390             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.star.bz2", current_tarball_number);
     404            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.star.bz2", current_tarball_number);
    391405        }
    392406        if (!does_file_exist(tarball_fname)) {
    393407            mr_free(tarball_fname);
    394             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%d.star.", current_tarball_number);
     408            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%d.star.", current_tarball_number);
    395409        }
    396410        if (!does_file_exist(tarball_fname)) {
    397             if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST") ||
    398                 system("find " MNT_CDROM
    399                        "/archives/slice* > /dev/null 2> /dev/null")
     411            if (!does_file_exist(ARCHIVES_PATH "/NOT-THE-LAST") ||
     412                system("find " ARCHIVES_PATH "/slice* > /dev/null 2> /dev/null")
    400413                == 0) {
    401414                log_msg(2, "OK, I think I'm done with tarballs...");
     
    492505 **************************************************************************/
    493506
     507/**
     508 * Compare all data on a tape-based backup.
     509 * @param bkpinfo The backup information structure. Field used: @c bkpinfo->restore_path.
     510 * @return 0 for success, nonzero for failure.
     511 */
     512/**************************************************************************
     513 * F@COMPARE_TO_TAPE()                                                    *
     514 * compare_to_tape() -  gots me??                                         *
     515 *                                                                        *
     516 * returns: int                                                           *
     517 **************************************************************************/
     518int compare_to_tape()
     519{
     520    int res;
     521    char *dir;
     522    char *command = NULL;
     523
     524    assert(bkpinfo != NULL);
     525    malloc_string(dir);
     526
     527    if (getcwd(dir, MAX_STR_LEN)) {
     528        // FIXME
     529    }
     530    if (chdir(bkpinfo->restore_path)) {
     531        // FIXME
     532    }
     533    mr_asprintf(command, "cp -f /tmp/LAST-FILELIST-NUMBER %s/tmp", bkpinfo->restore_path);
     534    run_program_and_log_output(command, FALSE);
     535    mr_free(command);
     536
     537    mvaddstr_and_log_it(g_currentY, 0, "Verifying archives against filesystem");
     538    res = verify_tape_backups();
     539    if (chdir(dir)) {
     540        // FIXME
     541    }
     542    if (res) {
     543        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
     544    } else {
     545        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     546    }
     547    paranoid_free(dir);
     548    return (res);
     549}
     550
     551/**************************************************************************
     552 *END_COMPARE_TO_TAPE                                                     *
     553 **************************************************************************/
     554
     555
     556/**
     557 * Compare all data on a cdstream-based backup.
     558 * @param bkpinfo The backup information structure. Fields used:
     559 * - @c bkpinfo->disaster_recovery
     560 * - @c bkpinfo->media_device
     561 * - @c bkpinfo->restore_path
     562 * @return 0 for success, nonzero for failure.
     563 */
     564int compare_to_cdstream()
     565{
     566    int res;
     567
     568  /** needs malloc **/
     569    char *dir;
     570    char *command = NULL;
     571
     572    assert(bkpinfo != NULL);
     573    malloc_string(dir);
     574    if (getcwd(dir, MAX_STR_LEN)) {
     575        // FIXME
     576    }
     577    if (chdir(bkpinfo->restore_path)) {
     578        // FIXME
     579    }
     580
     581    mr_asprintf(command, "cp -f /tmp/LAST-FILELIST-NUMBER %s/tmp", bkpinfo->restore_path);
     582    run_program_and_log_output(command, FALSE);
     583    mr_free(command);
     584    mvaddstr_and_log_it(g_currentY, 0, "Verifying archives against filesystem");
     585
     586    if (bkpinfo->disaster_recovery
     587        && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
     588        mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE"));
     589    } else {
     590        bkpinfo->media_device = find_optical_device();
     591    }
     592    res = verify_tape_backups();
     593    if (chdir(dir)) {
     594        // FIXME
     595    }
     596    if (length_of_file(MONDO_CACHE"/changed.txt") > 2
     597        && length_of_file(MONDO_CACHE"/changed.files") > 2) {
     598        log_msg(0,
     599                "Type 'less "MONDO_CACHE"/changed.files' to see which files don't match the archives");
     600        log_msg(2, "Calling popup_changelist_from_file()");
     601        popup_changelist_from_file(MONDO_CACHE"/changed.files");
     602        log_msg(2, "Returned from popup_changelist_from_file()");
     603    }
     604
     605    mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     606    paranoid_free(dir);
     607    return (res);
     608}
     609
     610/**************************************************************************
     611 *END_COMPARE_CD_STREAM                                                   *
     612 **************************************************************************/
    494613
    495614
     
    620739 *END_COMPARE_MODE                                                        *
    621740 **************************************************************************/
    622 
    623 /**
    624  * Compare all data on a cdstream-based backup.
    625  * @param bkpinfo The backup information structure. Fields used:
    626  * - @c bkpinfo->disaster_recovery
    627  * - @c bkpinfo->media_device
    628  * - @c bkpinfo->restore_path
    629  * @return 0 for success, nonzero for failure.
    630  */
    631 int compare_to_cdstream()
    632 {
    633     int res;
    634 
    635   /** needs malloc **/
    636     char *dir;
    637     char *command = NULL;
    638 
    639     assert(bkpinfo != NULL);
    640     malloc_string(dir);
    641     if (getcwd(dir, MAX_STR_LEN)) {
    642         // FIXME
    643     }
    644     if (chdir(bkpinfo->restore_path)) {
    645         // FIXME
    646     }
    647 
    648     mr_asprintf(command, "cp -f /tmp/LAST-FILELIST-NUMBER %s/tmp", bkpinfo->restore_path);
    649     run_program_and_log_output(command, FALSE);
    650     mr_free(command);
    651     mvaddstr_and_log_it(g_currentY, 0, "Verifying archives against filesystem");
    652 
    653     if (bkpinfo->disaster_recovery
    654         && does_file_exist("/tmp/CDROM-LIVES-HERE")) {
    655         mr_asprintf(bkpinfo->media_device, "%s", last_line_of_file("/tmp/CDROM-LIVES-HERE"));
    656     } else {
    657         bkpinfo->media_device = find_optical_device();
    658     }
    659     res = verify_tape_backups();
    660     if (chdir(dir)) {
    661         // FIXME
    662     }
    663     if (length_of_file(MONDO_CACHE"/changed.txt") > 2
    664         && length_of_file(MONDO_CACHE"/changed.files") > 2) {
    665         log_msg(0,
    666                 "Type 'less "MONDO_CACHE"/changed.files' to see which files don't match the archives");
    667         log_msg(2, "Calling popup_changelist_from_file()");
    668         popup_changelist_from_file(MONDO_CACHE"/changed.files");
    669         log_msg(2, "Returned from popup_changelist_from_file()");
    670     }
    671 
    672     mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    673     paranoid_free(dir);
    674     return (res);
    675 }
    676 
    677 /**************************************************************************
    678  *END_COMPARE_CD_STREAM                                                   *
    679  **************************************************************************/
    680 
    681 
    682 /**
    683  * Compare all data on a tape-based backup.
    684  * @param bkpinfo The backup information structure. Field used: @c bkpinfo->restore_path.
    685  * @return 0 for success, nonzero for failure.
    686  */
    687 /**************************************************************************
    688  * F@COMPARE_TO_TAPE()                                                    *
    689  * compare_to_tape() -  gots me??                                         *
    690  *                                                                        *
    691  * returns: int                                                           *
    692  **************************************************************************/
    693 int compare_to_tape()
    694 {
    695     int res;
    696     char *dir;
    697     char *command = NULL;
    698 
    699     assert(bkpinfo != NULL);
    700     malloc_string(dir);
    701 
    702     if (getcwd(dir, MAX_STR_LEN)) {
    703         // FIXME
    704     }
    705     if (chdir(bkpinfo->restore_path)) {
    706         // FIXME
    707     }
    708     mr_asprintf(command, "cp -f /tmp/LAST-FILELIST-NUMBER %s/tmp", bkpinfo->restore_path);
    709     run_program_and_log_output(command, FALSE);
    710     mr_free(command);
    711 
    712     mvaddstr_and_log_it(g_currentY, 0, "Verifying archives against filesystem");
    713     res = verify_tape_backups();
    714     if (chdir(dir)) {
    715         // FIXME
    716     }
    717     if (res) {
    718         mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
    719     } else {
    720         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    721     }
    722     paranoid_free(dir);
    723     return (res);
    724 }
    725 
    726 /**************************************************************************
    727  *END_COMPARE_TO_TAPE                                                     *
    728  **************************************************************************/
    729 
    730741/* @} - end compareGroup */
  • branches/3.3/mondo/src/mondorestore/mondo-rstr-mountlist.c

    r3871 r3879  
    1212#include "mr_mem.h"
    1313#include "mondostructures.h"
    14 #include "libmondo-mountlist.h"
    15 
    1614#include "libmondo-raid-EXT.h"
    1715#include "libmondo-devices-EXT.h"
     
    535533
    536534/**
     535 * Make a list of the drives mentioned in the mountlist.
     536 * @param mountlist The mountlist to examine.
     537 * @param drivelist Where to put the list of drives found.
     538 * @return The number of physical (non-RAID non-LVM) drives found, or \<= 0 for error.
     539 */
     540int
     541make_list_of_drives_in_mountlist(struct mountlist_itself *mountlist,
     542                                 struct list_of_disks *drivelist)
     543{
     544
     545    /*@ int ************************************************************* */
     546    int lino;
     547    int noof_drives;
     548    int j;
     549
     550    /*@ buffers ********************************************************* */
     551    char *drive = NULL;
     552    char *truncdrive = NULL;
     553
     554    long long size;
     555
     556    assert(mountlist != NULL);
     557    assert(drivelist != NULL);
     558    log_it("Making list of drives");
     559    for (lino = 0, noof_drives = 0; lino < mountlist->entries; lino++) {
     560
     561        mr_asprintf(drive, "%s", mountlist->el[lino].device);
     562        if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
     563            log_msg(8, "Not putting %s in list of drives: it's a virtual drive", drive);
     564            mr_free(drive);
     565            continue;
     566        }
     567
     568        size = mountlist->el[lino].size;
     569        if (size == 0) {
     570            log_msg(8, "Not putting %s in list of drives: it has zero size (maybe an LVM volume)", drive);
     571            mr_free(drive);
     572            continue;
     573        }
     574
     575        log_msg(8, "Putting %s with size %lli in list of drives", drive, size);
     576
     577        /* memory allocation */
     578        truncdrive = truncate_to_drive_name(drive);
     579        mr_free(drive);
     580
     581        log_msg(8, "drive truncated to %s", truncdrive);
     582
     583        for (j = 0;
     584             j < noof_drives
     585             && strcmp(drivelist->el[j].device, truncdrive) != 0; j++) {
     586            continue;
     587        }
     588        if (j == noof_drives) {
     589            strncpy(drivelist->el[noof_drives].device, truncdrive, 63);
     590            drivelist->el[noof_drives].device[63] = '\0';
     591            log_msg(8,"Adding drive %s to list", drivelist->el[noof_drives].device);
     592            noof_drives++;
     593        }
     594        paranoid_free(truncdrive);
     595        if (noof_drives >= MAXIMUM_DISKS_PER_RAID_DEV) {
     596            log_msg(0, "Unable to handle mountlist with more than %d lines", MAXIMUM_DISKS_PER_RAID_DEV);
     597            log_to_screen("Unable to handle a so big mountlist");
     598            finish(1);
     599        }
     600    }
     601    drivelist->entries = noof_drives;
     602    log_msg(8, "Made list of %d drives",noof_drives);
     603
     604    return (noof_drives);
     605}
     606
     607
     608/**
    537609 * Evaluate a whole mountlist for flaws. Calls evaluate_drive_within_mountlist()
    538610 * for each drive, and then spreads the flaws across three lines.
     
    642714        return (i);
    643715    }
    644 }
    645 
    646 
    647 /**
    648  * Make a list of the drives mentioned in the mountlist.
    649  * @param mountlist The mountlist to examine.
    650  * @param drivelist Where to put the list of drives found.
    651  * @return The number of physical (non-RAID non-LVM) drives found, or \<= 0 for error.
    652  */
    653 int
    654 make_list_of_drives_in_mountlist(struct mountlist_itself *mountlist,
    655                                  struct list_of_disks *drivelist)
    656 {
    657 
    658     /*@ int ************************************************************* */
    659     int lino;
    660     int noof_drives;
    661     int j;
    662 
    663     /*@ buffers ********************************************************* */
    664     char *drive = NULL;
    665     char *truncdrive = NULL;
    666 
    667     long long size;
    668 
    669     assert(mountlist != NULL);
    670     assert(drivelist != NULL);
    671     log_it("Making list of drives");
    672     for (lino = 0, noof_drives = 0; lino < mountlist->entries; lino++) {
    673 
    674         mr_asprintf(drive, "%s", mountlist->el[lino].device);
    675         if (!strncmp(drive, RAID_DEVICE_STUB, strlen(RAID_DEVICE_STUB))) {
    676             log_msg(8, "Not putting %s in list of drives: it's a virtual drive", drive);
    677             mr_free(drive);
    678             continue;
    679         }
    680 
    681         size = mountlist->el[lino].size;
    682         if (size == 0) {
    683             log_msg(8, "Not putting %s in list of drives: it has zero size (maybe an LVM volume)", drive);
    684             mr_free(drive);
    685             continue;
    686         }
    687 
    688         log_msg(8, "Putting %s with size %lli in list of drives", drive, size);
    689 
    690         /* memory allocation */
    691         truncdrive = truncate_to_drive_name(drive);
    692         mr_free(drive);
    693 
    694         log_msg(8, "drive truncated to %s", truncdrive);
    695 
    696         for (j = 0;
    697              j < noof_drives
    698              && strcmp(drivelist->el[j].device, truncdrive) != 0; j++) {
    699             continue;
    700         }
    701         if (j == noof_drives) {
    702             strncpy(drivelist->el[noof_drives].device, truncdrive, 63);
    703             drivelist->el[noof_drives].device[63] = '\0';
    704             log_msg(8,"Adding drive %s to list", drivelist->el[noof_drives].device);
    705             noof_drives++;
    706         }
    707         paranoid_free(truncdrive);
    708         if (noof_drives >= MAXIMUM_DISKS_PER_RAID_DEV) {
    709             log_msg(0, "Unable to handle mountlist with more than %d lines", MAXIMUM_DISKS_PER_RAID_DEV);
    710             log_to_screen("Unable to handle a so big mountlist");
    711             finish(1);
    712         }
    713     }
    714     drivelist->entries = noof_drives;
    715     log_msg(8, "Made list of %d drives",noof_drives);
    716 
    717     return (noof_drives);
    718716}
    719717
     
    938936
    939937/**
     938 * Swap two entries in the mountlist in-place.
     939 * @param mountlist The mountlist to swap the entries in.
     940 * @param a The index number of the first entry.
     941 * @param b The index number of the second entry.
     942 */
     943void
     944swap_mountlist_entries(struct mountlist_itself *mountlist, int a, int b)
     945{
     946    /*@ mallocs *** */
     947    char *device = NULL;
     948    char *mountpoint = NULL;
     949    char *format = NULL;
     950
     951    long long size;
     952
     953    assert(mountlist != NULL);
     954    assert(a >= 0);
     955    assert(b >= 0);
     956
     957    mr_asprintf(device, "%s", mountlist->el[a].device);
     958    mr_asprintf(mountpoint, "%s", mountlist->el[a].mountpoint);
     959    mr_asprintf(format, "%s", mountlist->el[a].format);
     960
     961    size = mountlist->el[a].size;
     962
     963    strcpy(mountlist->el[a].device, mountlist->el[b].device);
     964    strcpy(mountlist->el[a].mountpoint, mountlist->el[b].mountpoint);
     965    strcpy(mountlist->el[a].format, mountlist->el[b].format);
     966
     967    mountlist->el[a].size = mountlist->el[b].size;
     968
     969    strcpy(mountlist->el[b].device, device);
     970    strcpy(mountlist->el[b].mountpoint, mountpoint);
     971    strcpy(mountlist->el[b].format, format);
     972
     973    mountlist->el[b].size = size;
     974    mr_free(device);
     975    mr_free(mountpoint);
     976    mr_free(format);
     977}
     978
     979
     980
     981/**
    940982 * Sort the mountlist alphabetically by device.
    941983 * The sorting is done in-place.
     
    9911033}
    9921034
    993 
    994 /**
    995  * Swap two entries in the mountlist in-place.
    996  * @param mountlist The mountlist to swap the entries in.
    997  * @param a The index number of the first entry.
    998  * @param b The index number of the second entry.
    999  */
    1000 void
    1001 swap_mountlist_entries(struct mountlist_itself *mountlist, int a, int b)
    1002 {
    1003     /*@ mallocs *** */
    1004     char *device = NULL;
    1005     char *mountpoint = NULL;
    1006     char *format = NULL;
    1007 
    1008     long long size;
    1009 
    1010     assert(mountlist != NULL);
    1011     assert(a >= 0);
    1012     assert(b >= 0);
    1013 
    1014     mr_asprintf(device, "%s", mountlist->el[a].device);
    1015     mr_asprintf(mountpoint, "%s", mountlist->el[a].mountpoint);
    1016     mr_asprintf(format, "%s", mountlist->el[a].format);
    1017 
    1018     size = mountlist->el[a].size;
    1019 
    1020     strcpy(mountlist->el[a].device, mountlist->el[b].device);
    1021     strcpy(mountlist->el[a].mountpoint, mountlist->el[b].mountpoint);
    1022     strcpy(mountlist->el[a].format, mountlist->el[b].format);
    1023 
    1024     mountlist->el[a].size = mountlist->el[b].size;
    1025 
    1026     strcpy(mountlist->el[b].device, device);
    1027     strcpy(mountlist->el[b].mountpoint, mountpoint);
    1028     strcpy(mountlist->el[b].format, format);
    1029 
    1030     mountlist->el[b].size = size;
    1031     mr_free(device);
    1032     mr_free(mountpoint);
    1033     mr_free(format);
    1034 }
    1035 
    10361035/* @} - end of mountlistGroup */
  • branches/3.3/mondo/src/mondorestore/mondo-rstr-newt.c

    r3856 r3879  
    1010#endif
    1111
    12 #include "mondo-rstr-newt.h"
     12#include "my-stuff.h"
     13#include "mondostructures.h"
    1314#include "mr_mem.h"
    1415#include "mr_str.h"
     16#include "libmondo-raid-EXT.h"
     17#include "libmondo-mountlist-EXT.h"
     18#include "libmondo-string-EXT.h"
     19#include "libmondo-tools-EXT.h"
     20#include "libmondo-files-EXT.h"
     21#include "libmondo-filelist-EXT.h"
     22#include "newt-specific-EXT.h"
    1523
    1624//static char cvsid[] = "$Id$";
     
    1826extern bool popup_with_buttons(char *p, char *button1, char *button2);
    1927extern char err_log_lines[NOOF_ERR_LINES][MAX_STR_LEN];
     28
     29static char g_strings_of_flist_window[ARBITRARY_MAXIMUM][MAX_STR_LEN];
     30static bool g_is_path_selected[ARBITRARY_MAXIMUM];
     31static bool g_is_path_expanded[ARBITRARY_MAXIMUM];
     32static char tmpnopath[MAX_STR_LEN + 2];
     33static char tmpprevpath[MAX_STR_LEN + 2];
     34
     35// from mondo-rstr-mountlist.c
     36extern void make_list_of_unallocated_raid_partitions(struct mountlist_itself *, struct mountlist_itself *, struct raidlist_itself *);
     37
     38extern bool g_text_mode;
     39
    2040
    2141/**
     
    3656
    3757/**
    38  * @addtogroup restoreGuiGroup
    39  * @{
    40  */
     58 * Redraw the list of unallocated RAID partitions.
     59 * @param unallocated_raid_partitions The mountlist containing unallocated RAID partitions.
     60 * @param keylist The list of keys for @p listbox.
     61 * @param listbox The Newt listbox component to redraw.
     62 * @ingroup restoreGuiDisklist
     63 */
     64void redraw_unallocpartnslist(struct mountlist_itself
     65                              *unallocated_raid_partitions,
     66                              void *keylist[ARBITRARY_MAXIMUM],
     67                              newtComponent listbox)
     68{
     69
     70    /** long *************************************************************/
     71    long i = 0;
     72
     73    /** buffers **********************************************************/
     74    char tmp[MAX_STR_LEN];
     75
     76    assert(unallocated_raid_partitions != NULL);
     77    assert(keylist != NULL);
     78    assert(listbox != NULL);
     79
     80    newtListboxClear(listbox);
     81    for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
     82        keylist[i] = (void *) i;
     83    }
     84    for (i = 0; i < unallocated_raid_partitions->entries; i++) {
     85        sprintf(tmp, "%-22s %8lld",
     86                unallocated_raid_partitions->el[i].device,
     87                unallocated_raid_partitions->el[i].size / 1024L);
     88        newtListboxAppendEntry(listbox, tmp, keylist[i]);
     89    }
     90}
     91
     92
     93/**
     94 * Find the next free location to place a disk in @p disklist.
     95 * @param disklist The disklist to operate on.
     96 * @return The next free location (starting from 0).
     97 * @ingroup restoreGuiDisklist
     98 */
     99int find_next_free_index_in_disklist(struct list_of_disks *disklist)
     100{
     101
     102    /** int ***************************************************************/
     103    int index = -1;
     104    int pos = 0;
     105
     106  /** bool **************************************************************/
     107    bool done;
     108
     109    assert(disklist != NULL);
     110
     111    for (done = FALSE; !done;) {
     112        for (pos = 0;
     113             pos < disklist->entries && disklist->el[pos].index <= index;
     114             pos++);
     115        if (pos >= disklist->entries) {
     116            done = TRUE;
     117        } else {
     118            index = disklist->el[pos].index;
     119        }
     120    }
     121    return (index + 1);
     122}
     123
     124
     125
    41126/**
    42127 * Add an entry in @p disklist from the list in @p unallocated_raid_partitions.
     
    118203
    119204
    120 
    121 
    122 /**
    123  * Add an entry to @p mountlist.
    124  * @param mountlist The mountlist to add an entry to.
    125  * @param raidlist The raidlist that accompanies @p mountlist.
    126  * @param listbox The listbox component in the mountlist editor.
    127  * @param currline The line selected in @p listbox.
     205/**
     206 * Locate @p device in @p raidlist.
     207 * @param raidlist The raidlist ot search in.
     208 * @param device The RAID device to search for.
     209 * @return The index of the device, or -1 if it could not be found.
     210 * @ingroup restoreGuiMountlist
     211 */
     212int
     213find_raid_device_in_raidlist(struct raidlist_itself *raidlist,
     214                             char *device)
     215{
     216
     217    /** int ***************************************************************/
     218    int i = 0;
     219#ifdef __FreeBSD__
     220    char *vdev = NULL;
     221    int res = 0;
     222#else
     223// Linux
     224#endif
     225
     226    assert(raidlist != NULL);
     227    assert_string_is_neither_NULL_nor_zerolength(device);
     228
     229#ifdef __FreeBSD__
     230    for (i = 0; i < raidlist->entries; i++) {
     231        mr_asprintf(vdev, "/dev/vinum/%s", raidlist->el[i].volname);
     232        res = strcmp(device, vdev);
     233        mr_free(vdev);
     234
     235        if (!res)
     236            break;
     237    }
     238#else
     239
     240    for (i = 0;
     241         strcmp(raidlist->el[i].raid_device, device)
     242         && i < raidlist->entries; i++);
     243#endif
     244    if (i == raidlist->entries) {
     245        return (-1);
     246    } else {
     247        return (i);
     248    }
     249}
     250
     251
     252/**
     253 * Redraw the disklist.
     254 * @param disklist The disklist to read from.
    128255 * @param keylist The list of keys for @p listbox.
     256 * @param listbox The Newt listbox component to redraw.
     257 * @ingroup restoreGuiDisklist
     258 */
     259void
     260redraw_disklist(struct list_of_disks *disklist,
     261                void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
     262{
     263
     264    /** long **************************************************************/
     265    long i = 0;
     266    char *tmp = NULL;
     267
     268    assert(disklist != NULL);
     269    assert(keylist != NULL);
     270    assert(listbox != NULL);
     271
     272    newtListboxClear(listbox);
     273
     274    for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
     275        keylist[i] = (void *) i;
     276    }
     277    for (i = 0; i < disklist->entries; i++) {
     278        tmp = disklist_entry_to_string(disklist, i);
     279        newtListboxAppendEntry(listbox, tmp, keylist[i]);
     280        mr_free(tmp);
     281    }
     282}
     283
     284
     285
     286/**
     287 * Delete entry number @p currline from @p disklist.
     288 * @param disklist The disklist to remove the entry from.
     289 * @param raid_device The RAID device containing the partition we're removing.
     290 * Used only in the popup "are you sure?" box.
     291 * @param currline The line number (starting from 0) of the item to delete.
     292 * @ingroup restoreGuiDisklist
     293 */
     294void
     295delete_disklist_entry(struct list_of_disks *disklist, char *raid_device,
     296                      int currline)
     297{
     298
     299    /** int ***************************************************************/
     300    int pos = 0;
     301    int res = 0;
     302
     303    /** buffers ***********************************************************/
     304    char *tmp = NULL;
     305
     306    assert(disklist != NULL);
     307    assert_string_is_neither_NULL_nor_zerolength(raid_device);
     308
     309    mr_asprintf(tmp, "Delete %s from RAID device %s - are you sure?", disklist->el[currline].device, raid_device);
     310    res = ask_me_yes_or_no(tmp);
     311    mr_free(tmp);
     312
     313    if (!res) {
     314        return;
     315    }
     316    for (pos = currline; pos < disklist->entries - 1; pos++) {
     317        strcpy(disklist->el[pos].device, disklist->el[pos + 1].device);
     318    }
     319    disklist->entries--;
     320}
     321
     322
     323
     324/**
     325 * Select the RAID disks to use in @p raidrec.
     326 * @param mountlist_dontedit The mountlist (will not be edited).
     327 * @param raidlist The raidlist to modify.
     328 * @param raidrec The RAID device record in @p raidlist to work on.
     329 * @param description_of_list The type of disks we're selecting (e.g. "data").
     330 * @param disklist The disklist to put the user-selected disks in.
    129331 * @ingroup restoreGuiMountlist
    130332 */
    131333void
    132 add_mountlist_entry(struct mountlist_itself *mountlist,
    133                     struct raidlist_itself *raidlist,
    134                     newtComponent listbox, int currline, void *keylist[])
     334select_raid_disks(struct mountlist_itself *mountlist_dontedit,
     335                  struct raidlist_itself *raidlist,
     336                  struct raid_device_record *raidrec,
     337                  char *description_of_list,
     338                  struct list_of_disks *disklist)
     339{
     340    void *curr_choice;
     341
     342    /** ??? ***************************************************************/
     343
     344    /** structures ********************************************************/
     345    struct raidlist_itself *bkp_raidlist;
     346    struct raid_device_record *bkp_raidrec;
     347    struct list_of_disks *bkp_disklist;
     348    struct mountlist_itself *unallocated_raid_partitions;
     349
     350    /** newt **************************************************************/
     351    newtComponent myForm = NULL;
     352    newtComponent bAdd = NULL;
     353    newtComponent bDelete = NULL;
     354    newtComponent bOK = NULL;
     355    newtComponent bCancel = NULL;
     356    newtComponent b_res = NULL;
     357    newtComponent partitionsListbox = NULL;
     358    newtComponent headerMsg = NULL;
     359
     360    /** buffers **********************************************************/
     361    void *keylist[ARBITRARY_MAXIMUM];
     362    char *tmp = NULL;
     363    char *help_text = NULL;
     364    char *title_of_window = NULL;
     365    char sz_res[MAX_STR_LEN];
     366    char *header_text = NULL;
     367
     368  /** int **************************************************************/
     369    int i = 0;
     370    int currline = 0;
     371
     372    assert(mountlist_dontedit != NULL);
     373    assert(raidlist != NULL);
     374    assert(raidrec != NULL);
     375    assert(description_of_list != NULL);
     376    assert(disklist != NULL);
     377
     378    log_it("malloc'ing");
     379    bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));
     380    bkp_disklist = mr_malloc(sizeof(struct list_of_disks));
     381    bkp_raidlist = mr_malloc(sizeof(struct raidlist_itself));
     382    unallocated_raid_partitions = mr_malloc(sizeof(struct mountlist_itself));
     383
     384    memcpy((void *) bkp_raidlist, (void *) raidlist, sizeof(struct raidlist_itself));
     385    memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));
     386    memcpy((void *) bkp_disklist, (void *) disklist, sizeof(struct list_of_disks));
     387
     388    log_it("Post-malloc");
     389    mr_asprintf(help_text, "   Edit this RAID device's list of partitions. Choose OK or Cancel when done.");
     390    mr_asprintf(header_text, "%-24s    %s", "Device", "Index");
     391    mr_asprintf(title_of_window, "%s contains...", raidrec->raid_device);
     392    newtPushHelpLine(help_text);
     393    for (b_res = (newtComponent) 12345; b_res != bOK && b_res != bCancel;) {
     394        headerMsg = newtLabel(1, 1, header_text);
     395        partitionsListbox =
     396            newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
     397        redraw_disklist(disklist, keylist, partitionsListbox);
     398        i = 1;
     399        bAdd = newtCompactButton(i, 9, " Add ");
     400        bDelete = newtCompactButton(i += 8, 9, "Delete");
     401        bOK = newtCompactButton(i += 9, 9, "  OK  ");
     402        bCancel = newtCompactButton(i += 9, 9, "Cancel");
     403        newtOpenWindow(21, 7, 38, 10, title_of_window);
     404        myForm = newtForm(NULL, NULL, 0);
     405        if (disklist->entries == 0) {
     406            newtFormAddComponents(myForm, headerMsg, bAdd, bDelete, bOK,
     407                                  bCancel, NULL);
     408        } else {
     409            newtFormAddComponents(myForm, headerMsg, partitionsListbox,
     410                                  bAdd, bDelete, bOK, bCancel, NULL);
     411        }
     412        b_res = newtRunForm(myForm);
     413        if (b_res == bOK || b_res == bCancel) { /* do nothing */
     414// That's OK. At the end of this subroutine (after this do/while loop),
     415// we'll throw away the changes if Cancel was pushed.
     416        } else {
     417            curr_choice = newtListboxGetCurrent(partitionsListbox);
     418            for (i = 0; i < disklist->entries && keylist[i] != curr_choice;
     419                 i++);
     420            if (i == disklist->entries && disklist->entries > 0) {
     421                log_to_screen("I don't know what that button does!");
     422            } else {
     423                currline = i;
     424                if (b_res == bAdd) {
     425                    log_it("Making list of unallocated RAID slices");
     426                    make_list_of_unallocated_raid_partitions
     427                        (unallocated_raid_partitions, mountlist_dontedit,
     428                         raidlist);
     429                    if (unallocated_raid_partitions->entries <= 0) {
     430                        popup_and_OK
     431                            ("There are no unallocated partitions marked for RAID.");
     432                    } else {
     433                        log_it
     434                            ("Done. The user may add one or more of the above to RAID device");
     435                        add_disklist_entry(disklist, raidrec->raid_device,
     436                                           unallocated_raid_partitions);
     437                        log_it("I have finished adding a disklist entry.");
     438                        redraw_disklist(disklist, keylist,
     439                                        partitionsListbox);
     440                    }
     441                } else if (b_res == bDelete) {
     442                    delete_disklist_entry(disklist, raidrec->raid_device,
     443                                          currline);
     444                    redraw_disklist(disklist, keylist, partitionsListbox);
     445                } else {
     446                    mr_asprintf(tmp, "%s's index is %d. What should it be?", raidrec->raid_device, disklist->el[currline].index);
     447                    sprintf(sz_res, "%d", disklist->el[currline].index);
     448                    if (popup_and_get_string("Set index", tmp, sz_res, 10)) {
     449                        disklist->el[currline].index = atoi(sz_res);
     450                    }
     451                    mr_free(tmp);
     452
     453                    redraw_disklist(disklist, keylist, partitionsListbox);
     454                }
     455            }
     456        }
     457        newtFormDestroy(myForm);
     458        newtPopWindow();
     459    }
     460    newtPopHelpLine();
     461    mr_free(help_text);
     462    mr_free(header_text);
     463    mr_free(title_of_window);
     464
     465    if (b_res == bCancel) {
     466        memcpy((void *) raidlist, (void *) bkp_raidlist, sizeof(struct raidlist_itself));
     467        memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));
     468        memcpy((void *) disklist, (void *) bkp_disklist, sizeof(struct list_of_disks));
     469    }
     470    mr_free(bkp_raidrec);
     471    mr_free(bkp_disklist);
     472    mr_free(bkp_raidlist);
     473    mr_free(unallocated_raid_partitions);
     474}
     475
     476
     477#ifndef __FreeBSD__
     478/**
     479 * Insert the RAID variables not stored in the "additional RAID variables" list there too.
     480 * @param raidrec The RAID device record to operate on.
     481 * @ingroup restoreGuiVarslist
     482 */
     483void insert_essential_additionalvars(struct raid_device_record *raidrec)
    135484{
    136485
    137486    /** int **************************************************************/
     487    int items = 0;
     488
     489    assert(raidrec != NULL);
     490
     491    items = raidrec->additional_vars.entries;
     492    write_variableINT_to_raid_var_line(raidrec, items++,
     493                                       "persistent-superblock",
     494                                       raidrec->persistent_superblock);
     495    write_variableINT_to_raid_var_line(raidrec, items++, "chunk-size",
     496                                       raidrec->chunk_size);
     497    raidrec->additional_vars.entries = items;
     498}
     499
     500#endif
     501
     502
     503#ifndef __FreeBSD__
     504/**
     505 * Redraw the list of additional RAID variables.
     506 * @param additional_vars The list of additional RAID varibals.
     507 * @param keylist The list of keys for @p listbox.
     508 * @param listbox The Newt listbox component to redraw.
     509 * @ingroup restoreGuiVarslist
     510 */
     511void
     512redraw_varslist(struct additional_raid_variables *additional_vars,
     513                void *keylist[], newtComponent listbox)
     514{
     515    /** long ************************************************************/
     516    long i = 0;
     517
     518    /** buffers *********************************************************/
     519    char tmp[MAX_STR_LEN];
     520
     521    assert(additional_vars != NULL);
     522    assert(keylist != NULL);
     523    assert(listbox != NULL);
     524
     525    newtListboxClear(listbox);
     526
     527    for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
     528        keylist[i] = (void *) i;
     529    }
     530    for (i = 0; i < additional_vars->entries; i++) {
     531        sprintf(tmp, "%-32s %-8s", additional_vars->el[i].label,
     532                additional_vars->el[i].value);
     533        newtListboxAppendEntry(listbox, tmp, keylist[i]);
     534    }
     535}
     536
     537#endif
     538
     539
     540#ifndef __FreeBSD__
     541/**
     542 * Remove variable @p label from the RAID variables list in @p raidrec.
     543 * @param raidrec The RAID device record to remove the variable from.
     544 * @param label The variable name to remove.
     545 * @return The value of the variable removed.
     546 * @ingroup restoreUtilityGroup
     547 */
     548int
     549read_variableINT_and_remove_from_raidvars(struct
     550                                          OSSWAP (raid_device_record,
     551                                                  vinum_volume) * raidrec,
     552                                          char *label)
     553{
     554    /** int ***************************************************************/
    138555    int i = 0;
    139 
    140     /** newt *************************************************************/
    141     newtComponent myForm;
     556    int res = 0;
     557
     558
     559    assert(raidrec != NULL);
     560    assert(label != NULL);
     561
     562    for (i = 0;
     563         i < raidrec->additional_vars.entries
     564         && strcmp(raidrec->additional_vars.el[i].label, label); i++);
     565    if (i == raidrec->additional_vars.entries) {
     566        res = -1;
     567    } else {
     568        res = atoi(raidrec->additional_vars.el[i].value);
     569        for (i++; i < raidrec->additional_vars.entries; i++) {
     570            memcpy((void *) &raidrec->additional_vars.el[i - 1],
     571                   (void *) &raidrec->additional_vars.el[i],
     572                   sizeof(struct raid_var_line));
     573        }
     574        raidrec->additional_vars.entries--;
     575    }
     576    return (res);
     577}
     578#endif
     579
     580#ifndef __FreeBSD__
     581/**
     582 * Remove the essential RAID variables from the "additional variables" section.
     583 * If they have been changed, set them in their normal locations too.
     584 * @param raidrec The RAID device record to operate on.
     585 * @ingroup restoreUtilityVarslist
     586 */
     587void remove_essential_additionalvars(struct raid_device_record *raidrec)
     588{
     589
     590    /** int **************************************************************/
     591    int res = 0;
     592
     593    assert(raidrec != NULL);
     594
     595    res =
     596        read_variableINT_and_remove_from_raidvars(raidrec,
     597                                                  "persistent-superblock");
     598    if (res > 0) {
     599        raidrec->persistent_superblock = res;
     600    }
     601    res = read_variableINT_and_remove_from_raidvars(raidrec, "chunk-size");
     602    if (res > 0) {
     603        raidrec->chunk_size = res;
     604    }
     605    res = read_variableINT_and_remove_from_raidvars(raidrec, "block-size");
     606}
     607
     608#endif
     609
     610
     611
     612/**
     613 * Choose the RAID level for the RAID device record in @p raidrec.
     614 * @param raidrec The RAID device record to set the RAID level of.
     615 * @ingroup restoreGuiMountlist
     616 */
     617void
     618choose_raid_level(struct OSSWAP (raid_device_record, vinum_plex) * raidrec)
     619{
     620
     621#ifdef __FreeBSD__
     622
     623    /** int ***************************************************************/
     624    int res = 0;
     625    int out = 0;
     626
     627    /** buffers ***********************************************************/
     628    char tmp[MAX_STR_LEN];
     629    char *prompt = NULL;
     630    char sz[MAX_STR_LEN];
     631
     632    mr_asprintf(prompt, "Please enter the RAID level you want. (concat, striped, raid5)");
     633    if (raidrec->raidlevel == -1) {
     634        strcpy(tmp, "concat");
     635    } else if (raidrec->raidlevel == 0) {
     636        strcpy(tmp, "striped");
     637    } else {
     638        sprintf(tmp, "raid%i", raidrec->raidlevel);
     639    }
     640    for (out = 999; out == 999;) {
     641        res = popup_and_get_string("Specify RAID level", prompt, tmp, 10);
     642        if (!res) {
     643            mr_free(prompt);
     644            return;
     645        }
     646        strip_spaces(tmp);
     647        if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') {
     648            strcpy(sz, tmp);
     649            strncpy(tmp, sz + 1, strlen(sz) - 2);
     650            tmp[strlen(sz) - 2] = '\0';
     651        }
     652        if (!strcmp(tmp, "concat")) {
     653            out = -1;
     654        } else if (!strcmp(tmp, "striped")) {
     655            out = 0;
     656        } else if (!strcmp(tmp, "raid5")) {
     657            out = 5;
     658        }
     659        log_it(tmp);
     660        if (is_this_raid_personality_registered(out)) {
     661            log_it("Groovy. You've picked a RAID personality which is registered.");
     662        } else {
     663            if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?"))
     664            {
     665                out = 999;
     666            }
     667        }
     668    }
     669    mr_free(prompt);
     670
     671    raidrec->raidlevel = out;
     672#else
     673    /** buffers ***********************************************************/
     674    char tmp[MAX_STR_LEN];
     675    char *personalities = NULL;
     676    char *prompt = NULL;
     677    char sz[MAX_STR_LEN];
     678    int out = 0;
     679    int res = 0;
     680
     681
     682    assert(raidrec != NULL);
     683    paranoid_system("grep Pers /proc/mdstat > /tmp/raid-personalities.txt 2> /dev/null");
     684    mr_asprintf(personalities, "%s", last_line_of_file("/tmp/raid-personalities.txt"));
     685    mr_asprintf(prompt, "Please enter the RAID level you want. %s", personalities);
     686    mr_free(personalities);
     687
     688    if (raidrec->raid_level == -1) {
     689        strcpy(tmp, "linear");
     690    } else {
     691        sprintf(tmp, "%d", raidrec->raid_level);
     692    }
     693    for (out = 999;
     694         out != -1 && out != 0 && out != 1 && out != 4 && out != 5
     695         && out != 10;) {
     696        res = popup_and_get_string("Specify RAID level", prompt, tmp, 10);
     697        if (!res) {
     698            return;
     699        }
     700        strip_spaces(tmp);
     701        if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') {
     702            strcpy(sz, tmp);
     703            strncpy(tmp, sz + 1, strlen(sz) - 2);
     704            tmp[strlen(sz) - 2] = '\0';
     705        }
     706        if (!strcmp(tmp, "linear")) {
     707            out = -1;
     708        } else if (!strncmp(tmp, "raid", 4)) {
     709            out = atoi(tmp + 4);
     710        } else {
     711            out = atoi(tmp);
     712        }
     713        log_it(tmp);
     714        if (is_this_raid_personality_registered(out)) {
     715            log_it("Groovy. You've picked a RAID personality which is registered.");
     716        } else {
     717            if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) {
     718                out = 999;
     719            }
     720        }
     721    }
     722    mr_free(prompt);
     723
     724    raidrec->raid_level = out;
     725#endif
     726}
     727
     728
     729#ifdef __FreeBSD__
     730
     731/**
     732 * Edit the plex @p raidrec in @p raidlist.
     733 * @param mountlist The mountlist to get some of the information from.
     734 * @param raidlist The raidlist containing information about RAID devices.
     735 * @param raidrec The plex to edit.
     736 * @param currline The line number (starting from 0) of the RAID device in @p mountlist.
     737 * @param currline2 The line number (starting from 0) of the plex within the RAID device.
     738 * @author Joshua Oreman
     739 * @ingroup restoreGuiMountlist
     740 */
     741void
     742edit_raidlist_plex(struct mountlist_itself *mountlist,
     743                   struct raidlist_itself *raidlist,
     744                   struct vinum_plex *raidrec, int currline, int currline2)
     745{
     746
     747    /** structures ********************************************************/
     748    struct vinum_plex bkp_raidrec;
     749
     750
     751    /** buffers ***********************************************************/
     752    char *title_of_editraidForm_window = NULL;
     753
     754    /** newt **************************************************************/
     755    newtComponent editraidForm;
    142756    newtComponent bOK;
    143757    newtComponent bCancel;
     758    newtComponent bEdit;
     759    newtComponent bAdd;
     760    newtComponent bDelete;
    144761    newtComponent b_res;
    145     newtComponent mountpointComp;
    146     newtComponent label0;
    147     newtComponent label1;
    148     newtComponent label2;
    149     newtComponent label3;
    150     newtComponent sizeComp;
    151     newtComponent deviceComp;
    152     newtComponent formatComp;
    153 
    154     /** buffers **********************************************************/
    155     char *drive_to_add = NULL;
    156     char *mountpoint_str = NULL;
    157     char *size_str = NULL;
    158     char *device_str = NULL;
    159     char *format_str = NULL;
    160 
    161     /** pointers *********************************************************/
    162     char *mountpoint_here;
    163     char *size_here;
    164     char *device_here;
    165     char *format_here;
    166 
    167     assert(mountlist != NULL);
    168     assert(raidlist != NULL);
    169     assert(listbox != NULL);
    170     assert(keylist != NULL);
    171 
    172     mr_asprintf(device_str, "/dev/");
    173     mr_asprintf(mountpoint_str, "/");
    174     mr_asprintf(size_str, "");
    175 #ifdef __FreeBSD__
    176     mr_asprintf(format_str, "ufs");
     762    newtComponent unallocListbox, allocListbox;
     763    newtComponent bLevel, sLevel;
     764    newtComponent bStripeSize, sStripeSize;
     765    newtComponent bAlloc, bUnalloc;
     766
     767    void *keylist[ARBITRARY_MAXIMUM];
     768    void *curr_choice_a, *curr_choice_u;
     769    int currline_a, currline_u;
     770
     771    char *p = NULL;
     772    char *tmp = NULL;
     773    char *entry = NULL;
     774
     775    struct mountlist_itself *unallocparts;
     776
     777    unallocparts = malloc(sizeof(struct mountlist_itself));
     778
     779    log_it("Started edit_raidlist_entry");
     780    memcpy((void *) &bkp_raidrec, (void *) raidrec,
     781           sizeof(struct vinum_plex));
     782    mr_asprintf(title_of_editraidForm_window, "%s.p%i", raidlist->el[currline].volname, currline2);
     783    newtPushHelpLine
     784        ("   Please select a subdisk to edit, or edit this plex's parameters");
     785    newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window);
     786    mr_free(title_of_editraidForm_window);
     787
     788    for (;;) {
     789        int i;
     790
     791        switch (raidrec->raidlevel) {
     792        case -1:
     793            mr_asprintf(tmp, "concat");
     794            break;
     795        case 0:
     796            mr_asprintf(tmp, "striped");
     797            break;
     798        case 5:
     799            mr_asprintf(tmp, "raid5");
     800            break;
     801        default:
     802            mr_asprintf(tmp, "unknown (%i)", raidrec->raidlevel);
     803            break;
     804        }
     805        bLevel = newtCompactButton(2, 2, " RAID level ");
     806        sLevel = newtLabel(19, 2, tmp);
     807        mr_free(tmp);
     808
     809        if (raidrec->raidlevel >= 0) {
     810            mr_asprintf(tmp, "%ik", raidrec->stripesize);
     811            bStripeSize = newtCompactButton(2, 4, " Stripe size ");
     812        } else {
     813            mr_asprintf(tmp, "N/A");
     814            bStripeSize = newtLabel(2, 4, "Stripe size:");
     815        }
     816        sStripeSize = newtLabel(19, 4, tmp);
     817        mr_free(tmp);
     818
     819        bOK = newtCompactButton(2, 16, "  OK  ");
     820        bCancel = newtCompactButton(12, 16, "Cancel");
     821        bAdd = newtCompactButton(22, 16, " Add ");
     822        bEdit = newtCompactButton(32, 16, " Edit ");
     823        bDelete = newtCompactButton(42, 16, "Delete");
     824
     825
     826        unallocListbox =
     827            newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
     828        allocListbox =
     829            newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
     830        bAlloc = newtButton(23, 7, " -> ");
     831        bUnalloc = newtButton(23, 11, " <- ");
     832
     833        editraidForm = newtForm(NULL, NULL, 0);
     834
     835        newtListboxClear(allocListbox);
     836        newtListboxClear(unallocListbox);
     837        bzero(unallocparts, sizeof(struct mountlist_itself));
     838        make_list_of_unallocated_raid_partitions(unallocparts, mountlist,
     839                                                 raidlist);
     840        for (i = 0; i < ARBITRARY_MAXIMUM; ++i) {
     841            keylist[i] = (void *) i;
     842            if (i < raidrec->subdisks) {
     843                mr_asprintf(entry, "%-17s", find_dev_entry_for_raid_device_name(raidlist, raidrec->sd[i].which_device));
     844                newtListboxAppendEntry(allocListbox, entry, keylist[i]);
     845                mr_free(entry);
     846            }
     847            if (i < unallocparts->entries) {
     848                mr_asprintf(entry, "%-17s", unallocparts->el[i].device);
     849                newtListboxAppendEntry(unallocListbox, entry, keylist[i]);
     850                mr_free(entry);
     851            }
     852        }
     853
     854#define COMP(x)  newtFormAddComponent (editraidForm, x)
     855#define UCOMP(x) if (unallocparts->entries > 0) COMP(x)
     856#define ACOMP(x) if (raidrec->subdisks > 0) COMP(x)
     857        editraidForm = newtForm(NULL, NULL, 0);
     858        UCOMP(unallocListbox);
     859        UCOMP(bAlloc);
     860        ACOMP(allocListbox);
     861        ACOMP(bUnalloc);
     862        COMP(bOK);
     863        COMP(bCancel);
     864        COMP(bLevel);
     865        COMP(sLevel);
     866        if (raidrec->raidlevel != -1) {
     867            COMP(bStripeSize);
     868            COMP(sStripeSize);
     869        }
     870#undef COMP
     871#undef UCOMP
     872#undef ACOMP
     873
     874        newtDrawForm(editraidForm);
     875        newtRefresh();
     876        b_res = newtRunForm(editraidForm);
     877        if (b_res == bOK || b_res == bCancel) {
     878            break;
     879        }
     880
     881        curr_choice_a = (raidrec->subdisks > 0) ?
     882            newtListboxGetCurrent(allocListbox) : (void *) 1234;
     883        curr_choice_u = (unallocparts->entries > 0) ?
     884            newtListboxGetCurrent(unallocListbox) : (void *) 1234;
     885        for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) {
     886            if (currline_a > ARBITRARY_MAXIMUM)
     887                break;
     888            if (keylist[currline_a] == curr_choice_a)
     889                break;
     890        }
     891        for (currline_u = 0; currline_u < unallocparts->entries;
     892             ++currline_u) {
     893            if (currline_u > ARBITRARY_MAXIMUM)
     894                break;
     895            if (keylist[currline_u] == curr_choice_u)
     896                break;
     897        }
     898        if (b_res == bLevel) {
     899            choose_raid_level(raidrec);
     900        } else if (b_res == bStripeSize) {
     901            char tmp1[64];
     902            sprintf(tmp1, "%i", raidrec->stripesize);
     903            if (popup_and_get_string
     904                ("Stripe size",
     905                 "Please enter the stripe size in kilobytes.", tmp1, 20)) {
     906                raidrec->stripesize = atoi(tmp1);
     907            }
     908        } else if ((b_res == bAlloc) || (b_res == unallocListbox)) {
     909            if (currline_u <= unallocparts->entries)
     910                add_raid_subdisk(raidlist, raidrec,
     911                                 unallocparts->el[currline_u].device);
     912        } else if ((b_res == bUnalloc) || (b_res == allocListbox)) {
     913            if (currline_a <= raidrec->subdisks) {
     914                memcpy((void *) &raidrec->sd[currline_a],
     915                       (void *) &raidrec->sd[raidrec->subdisks - 1],
     916                       sizeof(struct vinum_subdisk));
     917                raidrec->subdisks--;
     918            }
     919        }
     920    newtFormDestroy(editraidForm);
     921    newtRefresh();
     922}
     923
     924if (b_res == bCancel) {
     925    memcpy((void *) raidrec, (void *) &bkp_raidrec, sizeof(struct vinum_plex));
     926}
     927newtPopWindow();
     928newtPopHelpLine();
     929}
    177930#else
    178     mr_asprintf(format_str, "ext3");
     931/**
     932 * Edit additional RAID variable number @p lino.
     933 * @param raidrec The RAID device record to edit the variable in.
     934 * @param lino The line number (starting from 0) of the variable to edit.
     935 * @ingroup restoreGuiVarslist
     936 */
     937void edit_varslist_entry(struct raid_device_record *raidrec, int lino)
     938{
     939
     940    /** buffers ***********************************************************/
     941    char *header = NULL;
     942    char *comment = NULL;
     943    char sz_out[MAX_STR_LEN];
     944
     945    assert(raidrec != 0);
     946    assert(lino >= 0);
     947
     948    strcpy(sz_out, raidrec->additional_vars.el[lino].value);
     949    mr_asprintf(header, "Edit %s", raidrec->additional_vars.el[lino].label);
     950    mr_asprintf(comment, "Please set %s's value (currently '%s')", raidrec->additional_vars.el[lino].label, sz_out);
     951    if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) {
     952        strip_spaces(sz_out);
     953        strcpy(raidrec->additional_vars.el[lino].value, sz_out);
     954    }
     955    mr_free(header);
     956    mr_free(comment);
     957}
    179958#endif
    180     newtOpenWindow(20, 5, 48, 10, "Add entry");
    181     label0 = newtLabel(2, 1, "Device:    ");
    182     label1 = newtLabel(2, 2, "Mountpoint:");
    183     label2 = newtLabel(2, 3, "Size (MB): ");
    184     label3 = newtLabel(2, 4, "Format:    ");
    185     deviceComp = newtEntry(14, 1, device_str, 30, (void *) &device_here, 0);
    186     mountpointComp = newtEntry(14, 2, mountpoint_str, 30, (void *) &mountpoint_here, 0);
    187     formatComp = newtEntry(14, 4, format_str, 15, (void *) &format_here, 0);
    188     sizeComp = newtEntry(14, 3, size_str, 10, (void *) &size_here, 0);
    189     bOK = newtButton(5, 6, "  OK  ");
    190     bCancel = newtButton(17, 6, "Cancel");
    191     newtPushHelpLine
    192         ("To add an entry to the mountlist, please fill in these fields and then hit 'OK'");
    193     myForm = newtForm(NULL, NULL, 0);
    194     newtFormAddComponents(myForm, deviceComp, mountpointComp, sizeComp,
    195                           formatComp, label0, label1, label2, label3, bOK,
    196                           bCancel, NULL);
    197     for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
    198         b_res = newtRunForm(myForm);
    199         mr_free(device_str);
    200         device_str = mr_strip_spaces(device_here);
    201 
    202         mr_free(mountpoint_str);
    203         mountpoint_str = mr_strip_spaces(mountpoint_here);
    204 
    205         mr_free(format_str);
    206         format_str = mr_strip_spaces(format_here);
    207 
    208         mr_free(size_str);
    209         size_str = mr_strip_spaces(size_here);
    210 
    211         if (b_res == bOK) {
    212             if (device_str[strlen(device_str) - 1] == '/') {
    213                 popup_and_OK("You left the device nearly blank!");
    214                 b_res = NULL;
    215             }
    216             if (size_of_specific_device_in_mountlist(mountlist, device_str) >= 0) {
    217                 popup_and_OK("Can't add this - you've got one already!");
    218                 b_res = NULL;
    219             }
    220         }
    221     }
    222     newtFormDestroy(myForm);
    223     newtPopHelpLine();
    224     newtPopWindow();
    225     if (b_res == bCancel) {
    226         return;
    227     }
    228     mr_asprintf(drive_to_add, "%s", device_str);
    229     for (i = strlen(drive_to_add); isdigit(drive_to_add[i - 1]); i--);
    230     mr_free(drive_to_add);
    231 
    232     currline = mountlist->entries;
    233     strcpy(mountlist->el[currline].device, device_str);
    234     strcpy(mountlist->el[currline].mountpoint, mountpoint_str);
    235     mr_free(mountpoint_str);
    236 
    237     strcpy(mountlist->el[currline].format, format_str);
    238     mr_free(format_str);
    239 
    240     mountlist->el[currline].size = atol(size_str) * 1024L;
    241     mr_free(size_str);
    242 
    243     mountlist->entries++;
    244     if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
    245         initiate_new_raidlist_entry(raidlist, mountlist, currline, device_str);
    246     }
    247     mr_free(device_str);
    248 
    249     redraw_mountlist(mountlist, keylist, listbox);
    250 }
    251959
    252960
     
    289997}
    290998#endif
     999
     1000
     1001#ifndef __FreeBSD__
     1002/**
     1003 * Delete entry number @p lino in the additional RAID variables section of @p raidrec.
     1004 * @param raidrec The RAID device record containing the RAID variable to delete.
     1005 * @param lino The line number (starting from 0) of the variable to delete.
     1006 * @ingroup restoreGuiVarslist
     1007 */
     1008void delete_varslist_entry(struct raid_device_record *raidrec, int lino)
     1009{
     1010
     1011    /** buffers ************************************************************/
     1012    char *tmp = NULL;
     1013    int res = 0;
     1014
     1015    /** structures *********************************************************/
     1016    struct additional_raid_variables *av;
     1017
     1018    assert(raidrec != NULL);
     1019
     1020    av = &raidrec->additional_vars;
     1021    mr_asprintf(tmp, "Delete %s - are you sure?", av->el[lino].label);
     1022    res = ask_me_yes_or_no(tmp);
     1023    mr_free(tmp);
     1024
     1025    if (res) {
     1026        if (!strcmp(av->el[lino].label, "persistent-superblock")
     1027            || !strcmp(av->el[lino].label, "chunk-size")) {
     1028            mr_asprintf(tmp, "%s must not be deleted. It would be bad.", av->el[lino].label);
     1029            popup_and_OK(tmp);
     1030            mr_free(tmp);
     1031        } else {
     1032            memcpy((void *) &av->el[lino], (void *) &av->el[av->entries--],
     1033                   sizeof(struct raid_var_line));
     1034        }
     1035    }
     1036}
     1037#endif
     1038
     1039
     1040
     1041#ifndef __FreeBSD__
     1042/**
     1043 * Edit the additional RAID variables in @p raidrec.
     1044 * @param raidrec The RAID device record to edit the RAID variables in.
     1045 * @ingroup restoreGuiVarslist
     1046 */
     1047void edit_raidrec_additional_vars(struct raid_device_record *raidrec)
     1048{
     1049
     1050    /** structure *********************************************************/
     1051    struct raid_device_record bkp_raidrec;
     1052
     1053    /** newt **************************************************************/
     1054    newtComponent myForm;
     1055    newtComponent bAdd;
     1056    newtComponent bEdit;
     1057    newtComponent bDelete;
     1058    newtComponent bOK;
     1059    newtComponent bCancel;
     1060    newtComponent b_res;
     1061    newtComponent varsListbox;
     1062    newtComponent headerMsg;
     1063
     1064    /** ?? ***************************************************************/
     1065    void *keylist[ARBITRARY_MAXIMUM], *curr_choice;
     1066
     1067    /** buffers **********************************************************/
     1068    char title_of_window[MAX_STR_LEN];
     1069
     1070    /** int **************************************************************/
     1071    int i = 0;
     1072    int currline = 0;
     1073
     1074
     1075    assert(raidrec != NULL);
     1076
     1077    memcpy((void *) &bkp_raidrec, (void *) raidrec,
     1078           sizeof(struct raid_device_record));
     1079    sprintf(title_of_window, "Additional variables");
     1080    newtPushHelpLine
     1081        ("  Edit the additional fields to your heart's content, then click OK or Cancel.");
     1082    headerMsg = newtLabel(1, 1, "Label                            Value");
     1083    varsListbox =
     1084        newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
     1085    i = 1;
     1086    bAdd = newtCompactButton(i, 9, " Add ");
     1087    bEdit = newtCompactButton(i += 8, 9, " Edit ");
     1088    bDelete = newtCompactButton(i += 9, 9, "Delete");
     1089    bOK = newtCompactButton(i += 9, 9, "  OK  ");
     1090    bCancel = newtCompactButton(i += 9, 9, "Cancel");
     1091    newtOpenWindow(17, 7, 46, 10, title_of_window);
     1092    myForm = newtForm(NULL, NULL, 0);
     1093    newtFormAddComponents(myForm, headerMsg, varsListbox, bAdd, bEdit,
     1094                          bDelete, bOK, bCancel, NULL);
     1095    insert_essential_additionalvars(raidrec);
     1096    redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);
     1097    for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
     1098        b_res = newtRunForm(myForm);
     1099        curr_choice = newtListboxGetCurrent(varsListbox);
     1100        for (currline = 0;
     1101             currline < raidrec->additional_vars.entries
     1102             && keylist[currline] != curr_choice; currline++);
     1103        if (currline == raidrec->additional_vars.entries
     1104            && raidrec->additional_vars.entries > 0) {
     1105            log_it("Warning - I don't know what this button does");
     1106        }
     1107        if (b_res == bOK) {     /* do nothing */
     1108        } else if (b_res == bCancel) {  /* do nothing */
     1109        } else if (b_res == bAdd) {
     1110            add_varslist_entry(raidrec);
     1111        } else if (b_res == bDelete) {
     1112            delete_varslist_entry(raidrec, currline);
     1113        } else {
     1114            edit_varslist_entry(raidrec, currline);
     1115        }
     1116        redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);
     1117    }
     1118    remove_essential_additionalvars(raidrec);
     1119    newtFormDestroy(myForm);
     1120    newtPopWindow();
     1121    newtPopHelpLine();
     1122    if (b_res == bCancel) {
     1123        memcpy((void *) raidrec, (void *) &bkp_raidrec,
     1124               sizeof(struct raid_device_record));
     1125    }
     1126    return;
     1127}
     1128#endif
     1129
    2911130
    2921131/**
     
    4451284
    4461285/**
    447  * Choose the RAID level for the RAID device record in @p raidrec.
    448  * @param raidrec The RAID device record to set the RAID level of.
     1286 * Edit the entry for @p raidrec in @p raidlist.
     1287 * @param mountlist The mountlist to get some information from.
     1288 * @param raidlist The raidlist containing information about RAID devices.
     1289 * @param raidrec The RAID device record for this partition.
     1290 * @param currline The line number (starting from 0) in the mountlist of the RAID device.
    4491291 * @ingroup restoreGuiMountlist
    4501292 */
     1293void edit_raidlist_entry(struct mountlist_itself *mountlist,
     1294                    struct raidlist_itself *raidlist,
     1295                    struct OSSWAP (raid_device_record,
     1296                                   vinum_volume) * raidrec, int currline)
     1297{
     1298
     1299#ifdef __FreeBSD__
     1300    /** structures ********************************************************/
     1301    struct vinum_volume bkp_raidrec;
     1302
     1303
     1304    /** buffers ***********************************************************/
     1305    char title_of_editraidForm_window[MAX_STR_LEN];
     1306
     1307    /** newt **************************************************************/
     1308    newtComponent editraidForm;
     1309    newtComponent bOK;
     1310    newtComponent bCancel;
     1311    newtComponent bEdit;
     1312    newtComponent bAdd;
     1313    newtComponent bDelete;
     1314    newtComponent b_res;
     1315    newtComponent plexesListbox;
     1316    newtComponent plexesHeader;
     1317
     1318    void *keylist[10];
     1319    void *curr_choice;
     1320    char *raidlevel = NULL;
     1321    char *chunksize = NULL;
     1322    char *msg = NULL;
     1323
     1324    int currline2 = 0;
     1325    int res = 0;
     1326
     1327    log_it("Started edit_raidlist_entry");
     1328    memcpy((void *) &bkp_raidrec, (void *) raidrec,
     1329           sizeof(struct vinum_volume));
     1330    sprintf(title_of_editraidForm_window, "Plexes on %s",
     1331            raidrec->volname);
     1332    newtPushHelpLine("   Please select a plex to edit");
     1333    newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window);
     1334    for (;;) {
     1335        int i;
     1336        char *headerstr = NULL;
     1337        mr_asprintf(headerstr, "%-14s %-8s  %11s  %8s", "Plex", "Level", "Stripe Size", "Subdisks");
     1338
     1339        bOK = newtCompactButton(2, 13, "  OK  ");
     1340        bCancel = newtCompactButton(12, 13, "Cancel");
     1341        bAdd = newtCompactButton(22, 13, " Add ");
     1342        bEdit = newtCompactButton(32, 13, " Edit ");
     1343        bDelete = newtCompactButton(42, 13, "Delete");
     1344
     1345        plexesListbox =
     1346            newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
     1347        plexesHeader = newtLabel(2, 2, headerstr);
     1348        mr_free(headerstr);
     1349        editraidForm = newtForm(NULL, NULL, 0);
     1350
     1351        newtListboxClear(plexesListbox);
     1352        for (i = 0; i < 10; ++i) {
     1353            keylist[i] = (void *) i;
     1354            if (i < raidrec->plexes) {
     1355                char *pname;
     1356                char *entry;
     1357                switch (raidrec->plex[i].raidlevel) {
     1358                case -1:
     1359                    mr_asprintf(raidlevel, "concat");
     1360                    break;
     1361                case 0:
     1362                    mr_asprintf(raidlevel, "striped");
     1363                    break;
     1364                case 5:
     1365                    mr_asprintf(raidlevel, "raid5");
     1366                    break;
     1367                default:
     1368                    mr_asprintf(raidlevel, "raid%i", raidrec->plex[i].raidlevel);
     1369                    break;
     1370                }
     1371
     1372                if (raidrec->plex[i].raidlevel == -1) {
     1373                    mr_asprintf(chunksize, "N/A");
     1374                } else {
     1375                    mr_asprintf(chunksize, "%dk", raidrec->plex[i].stripesize);
     1376                }
     1377                mr_asprintf(pname, "%s.p%i", raidrec->volname, i);
     1378                mr_asprintf(entry, "%-14s %-8s  %11s  %8d", pname, raidlevel, chunksize, raidrec->plex[i].subdisks);
     1379                mr_free(pname);
     1380                mr_free(raidlevel);
     1381                mr_free(chunksize);
     1382
     1383                newtListboxAppendEntry(plexesListbox, entry, keylist[i]);
     1384                mr_free(entry);
     1385            }
     1386        }
     1387
     1388        newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit,
     1389                              bDelete, plexesListbox, plexesHeader, NULL);
     1390
     1391        b_res = newtRunForm(editraidForm);
     1392        if (b_res == bOK || b_res == bCancel) {
     1393            break;
     1394        }
     1395
     1396        curr_choice = newtListboxGetCurrent(plexesListbox);
     1397        for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) {
     1398            if (currline2 > 9)
     1399                break;
     1400            if (keylist[currline2] == curr_choice)
     1401                break;
     1402        }
     1403
     1404        if (b_res == bDelete) {
     1405            mr_asprintf(msg, "Are you sure you want to delete %s.p%i?", raidrec->volname, currline2);
     1406            res = ask_me_yes_or_no(msg);
     1407            mr_free(msg);
     1408
     1409            if (res) {
     1410                log_it("Deleting RAID plex");
     1411                memcpy((void *) &raidrec->plex[currline2],
     1412                       (void *) &raidrec->plex[raidrec->plexes - 1],
     1413                       sizeof(struct vinum_plex));
     1414                raidrec->plexes--;
     1415            }
     1416            continue;
     1417        }
     1418        if (b_res == bAdd) {
     1419            raidrec->plex[raidrec->plexes].raidlevel = 0;
     1420            raidrec->plex[raidrec->plexes].stripesize = 279;
     1421            raidrec->plex[raidrec->plexes].subdisks = 0;
     1422            currline2 = raidrec->plexes++;
     1423        }
     1424        edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2],
     1425                           currline, currline2);
     1426        newtFormDestroy(editraidForm);
     1427    }
     1428    if (b_res == bCancel) {
     1429        memcpy((void *) raidrec, (void *) &bkp_raidrec,
     1430               sizeof(struct vinum_volume));
     1431    }
     1432    newtPopHelpLine();
     1433    newtPopWindow();
     1434    mountlist->el[currline].size =
     1435        calculate_raid_device_size(mountlist, raidlist, raidrec->volname);
     1436#else
     1437    /** structures ********************************************************/
     1438    struct raid_device_record *bkp_raidrec;
     1439
     1440
     1441    /** buffers ***********************************************************/
     1442    char *title_of_editraidForm_window;
     1443    char *sz_raid_level = NULL;
     1444    char *sz_data_disks = NULL;
     1445    char *sz_spare_disks = NULL;
     1446    char *sz_parity_disks = NULL;
     1447    char *sz_failed_disks = NULL;
     1448
     1449    /** newt **************************************************************/
     1450    newtComponent editraidForm;
     1451    newtComponent bOK;
     1452    newtComponent bCancel;
     1453    newtComponent bAdditional;
     1454    newtComponent bChangeRaid;
     1455    newtComponent bSelectData;
     1456    newtComponent bSelectSpare;
     1457    newtComponent bSelectParity;
     1458    newtComponent bSelectFailed;
     1459    newtComponent b_res;
     1460
     1461    assert(mountlist != NULL);
     1462    assert(raidlist != NULL);
     1463    assert(raidrec != NULL);
     1464
     1465    bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));
     1466    log_it("Started edit_raidlist_entry");
     1467
     1468    memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));
     1469    mr_asprintf(title_of_editraidForm_window, "%s", raidrec->raid_device);
     1470    log_msg(2, "Opening newt window");
     1471    newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window);
     1472    for (;;) {
     1473        log_msg(2, "Main loop");
     1474        mr_free(title_of_editraidForm_window);
     1475        mr_asprintf(title_of_editraidForm_window, "Edit %s", raidrec->raid_device);
     1476        sz_raid_level = turn_raid_level_number_to_string(raidrec->raid_level);
     1477        sz_data_disks = number_of_disks_as_string(raidrec->data_disks.entries, "data");
     1478        sz_spare_disks = number_of_disks_as_string(raidrec->spare_disks.entries, "spare");
     1479        sz_parity_disks = number_of_disks_as_string(raidrec->parity_disks.entries, "parity");
     1480        sz_failed_disks = number_of_disks_as_string(raidrec->failed_disks.entries, "failed");
     1481        bSelectData = newtButton(1, 1, sz_data_disks);
     1482        bSelectSpare = newtButton(20, 1, sz_spare_disks);
     1483        bSelectParity = newtButton(1, 5, sz_parity_disks);
     1484        bSelectFailed = newtButton(20, 5, sz_failed_disks);
     1485        bChangeRaid = newtButton(1, 9, sz_raid_level);
     1486        bOK = newtButton(16 + (raidrec->raid_level == -1), 9, "  OK  ");
     1487        bCancel = newtButton(28, 9, "Cancel");
     1488        bAdditional =
     1489            newtCompactButton(1, 13,
     1490                              "Additional settings and information");
     1491        newtPushHelpLine
     1492            ("  Edit the RAID device's settings to your heart's content, then hit OK/Cancel.");
     1493        editraidForm = newtForm(NULL, NULL, 0);
     1494        newtFormAddComponents(editraidForm, bSelectData, bSelectParity,
     1495                              bChangeRaid, bSelectSpare, bSelectFailed,
     1496                              bOK, bCancel, bAdditional);
     1497        b_res = newtRunForm(editraidForm);
     1498        if (b_res == bChangeRaid) {
     1499            choose_raid_level(raidrec);
     1500        } else if (b_res == bSelectData) {
     1501            select_raid_disks(mountlist, raidlist, raidrec, "data", &raidrec->data_disks);
     1502        } else if (b_res == bSelectSpare) {
     1503            select_raid_disks(mountlist, raidlist, raidrec, "spare", &raidrec->spare_disks);
     1504        } else if (b_res == bSelectParity) {
     1505            select_raid_disks(mountlist, raidlist, raidrec, "parity", &raidrec->parity_disks);
     1506        } else if (b_res == bSelectFailed) {
     1507            select_raid_disks(mountlist, raidlist, raidrec, "failed", &raidrec->failed_disks);
     1508        } else if (b_res == bAdditional) {
     1509            edit_raidrec_additional_vars(raidrec);
     1510        }
     1511        newtFormDestroy(editraidForm);
     1512        if (b_res == bOK || b_res == bCancel) {
     1513            break;
     1514        }
     1515        mr_free(sz_data_disks);
     1516        mr_free(sz_spare_disks);
     1517        mr_free(sz_parity_disks);
     1518        mr_free(sz_failed_disks);
     1519    }
     1520    if (b_res == bCancel) {
     1521        memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));
     1522    }
     1523    newtPopHelpLine();
     1524    newtPopWindow();
     1525    mountlist->el[currline].size = calculate_raid_device_size(mountlist, raidlist, raidrec->raid_device);
     1526    mr_free(title_of_editraidForm_window);
     1527    mr_free(sz_raid_level);
     1528    paranoid_free(bkp_raidrec);
     1529#endif
     1530}
     1531
     1532
     1533/**
     1534 * Create a new raidtab entry for @p device in @p raidlist.
     1535 * @param raidlist The raidlist to add the device to.
     1536 * @param mountlist The mountlist containing information about the user's partitions.
     1537 * @param currline The selected line in the mountlist.
     1538 * @param device The RAID device (e.g. /dev/md0) to use.
     1539 * @ingroup restoreGuiMountlist
     1540 */
    4511541void
    452 choose_raid_level(struct OSSWAP (raid_device_record, vinum_plex) * raidrec)
    453 {
    454 
     1542initiate_new_raidlist_entry(struct raidlist_itself *raidlist,
     1543                            struct mountlist_itself *mountlist,
     1544                            int currline, char *device)
     1545{
     1546
     1547    /** structure *********************************************************/
     1548    struct OSSWAP (raid_device_record, vinum_volume) * raidrec;
     1549
     1550    /** int ***************************************************************/
     1551    int pos_in_raidlist = 0;
     1552
     1553    assert(raidlist != NULL);
     1554    assert(mountlist != NULL);
     1555    assert_string_is_neither_NULL_nor_zerolength(device);
     1556
     1557    pos_in_raidlist =
     1558        find_raid_device_in_raidlist(raidlist,
     1559                                     mountlist->el[currline].device);
     1560    if (pos_in_raidlist >= 0) {
     1561        fatal_error("Sorry, that RAID device already exists. Weird.");
     1562    }
     1563    pos_in_raidlist = raidlist->entries++;
     1564    raidrec = &raidlist->el[pos_in_raidlist];
     1565    initialize_raidrec(raidrec);
     1566    strcpy(raidrec->OSSWAP(raid_device, volname), OSSWAP(device, basename(device)));
     1567#ifndef __FreeBSD__
     1568    choose_raid_level(raidrec);
     1569    select_raid_disks(mountlist, raidlist, raidrec, "data",
     1570                      &raidrec->data_disks);
     1571#endif
     1572    edit_raidlist_entry(mountlist, raidlist, raidrec, currline);
     1573}
     1574
     1575
     1576/**
     1577 * Redraw the mountlist.
     1578 * @param mountlist The mountlist to read from.
     1579 * @param keylist The list of keys for @p listbox.
     1580 * @param listbox The Newt listbox component to redraw.
     1581 * @ingroup restoreGuiMountlist
     1582 */
     1583void
     1584redraw_mountlist(struct mountlist_itself *mountlist,
     1585                 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
     1586{
     1587
     1588    /** long **************************************************************/
     1589    long i = 0;
     1590    char * tmp = NULL;
     1591
     1592    assert(mountlist != NULL);
     1593    assert(keylist != NULL);
     1594    assert(listbox != NULL);
     1595
     1596    newtListboxClear(listbox);
     1597//  sort_mountlist_by_device (mountlist);
     1598    for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
     1599        keylist[i] = (void *) i;
     1600    }
     1601    for (i = 0; i < mountlist->entries; i++) {
     1602        tmp = mountlist_entry_to_string(mountlist, i);
     1603        newtListboxAppendEntry(listbox, tmp, keylist[i]);
     1604        mr_free(tmp);
     1605    }
     1606}
     1607
     1608
     1609
     1610
     1611/**
     1612 * Add an entry to @p mountlist.
     1613 * @param mountlist The mountlist to add an entry to.
     1614 * @param raidlist The raidlist that accompanies @p mountlist.
     1615 * @param listbox The listbox component in the mountlist editor.
     1616 * @param currline The line selected in @p listbox.
     1617 * @param keylist The list of keys for @p listbox.
     1618 * @ingroup restoreGuiMountlist
     1619 */
     1620void
     1621add_mountlist_entry(struct mountlist_itself *mountlist,
     1622                    struct raidlist_itself *raidlist,
     1623                    newtComponent listbox, int currline, void *keylist[])
     1624{
     1625
     1626    /** int **************************************************************/
     1627    int i = 0;
     1628
     1629    /** newt *************************************************************/
     1630    newtComponent myForm;
     1631    newtComponent bOK;
     1632    newtComponent bCancel;
     1633    newtComponent b_res;
     1634    newtComponent mountpointComp;
     1635    newtComponent label0;
     1636    newtComponent label1;
     1637    newtComponent label2;
     1638    newtComponent label3;
     1639    newtComponent sizeComp;
     1640    newtComponent deviceComp;
     1641    newtComponent formatComp;
     1642
     1643    /** buffers **********************************************************/
     1644    char *drive_to_add = NULL;
     1645    char *mountpoint_str = NULL;
     1646    char *size_str = NULL;
     1647    char *device_str = NULL;
     1648    char *format_str = NULL;
     1649
     1650    /** pointers *********************************************************/
     1651    char *mountpoint_here;
     1652    char *size_here;
     1653    char *device_here;
     1654    char *format_here;
     1655
     1656    assert(mountlist != NULL);
     1657    assert(raidlist != NULL);
     1658    assert(listbox != NULL);
     1659    assert(keylist != NULL);
     1660
     1661    mr_asprintf(device_str, "/dev/");
     1662    mr_asprintf(mountpoint_str, "/");
     1663    mr_asprintf(size_str, "");
    4551664#ifdef __FreeBSD__
    456 
    457     /** int ***************************************************************/
    458     int res = 0;
    459     int out = 0;
    460 
    461     /** buffers ***********************************************************/
    462     char tmp[MAX_STR_LEN];
    463     char *prompt = NULL;
    464     char sz[MAX_STR_LEN];
    465 
    466     mr_asprintf(prompt, "Please enter the RAID level you want. (concat, striped, raid5)");
    467     if (raidrec->raidlevel == -1) {
    468         strcpy(tmp, "concat");
    469     } else if (raidrec->raidlevel == 0) {
    470         strcpy(tmp, "striped");
    471     } else {
    472         sprintf(tmp, "raid%i", raidrec->raidlevel);
    473     }
    474     for (out = 999; out == 999;) {
    475         res = popup_and_get_string("Specify RAID level", prompt, tmp, 10);
    476         if (!res) {
    477             mr_free(prompt);
    478             return;
    479         }
    480         strip_spaces(tmp);
    481         if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') {
    482             strcpy(sz, tmp);
    483             strncpy(tmp, sz + 1, strlen(sz) - 2);
    484             tmp[strlen(sz) - 2] = '\0';
    485         }
    486         if (!strcmp(tmp, "concat")) {
    487             out = -1;
    488         } else if (!strcmp(tmp, "striped")) {
    489             out = 0;
    490         } else if (!strcmp(tmp, "raid5")) {
    491             out = 5;
    492         }
    493         log_it(tmp);
    494         if (is_this_raid_personality_registered(out)) {
    495             log_it("Groovy. You've picked a RAID personality which is registered.");
    496         } else {
    497             if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?"))
    498             {
    499                 out = 999;
     1665    mr_asprintf(format_str, "ufs");
     1666#else
     1667    mr_asprintf(format_str, "ext3");
     1668#endif
     1669    newtOpenWindow(20, 5, 48, 10, "Add entry");
     1670    label0 = newtLabel(2, 1, "Device:    ");
     1671    label1 = newtLabel(2, 2, "Mountpoint:");
     1672    label2 = newtLabel(2, 3, "Size (MB): ");
     1673    label3 = newtLabel(2, 4, "Format:    ");
     1674    deviceComp = newtEntry(14, 1, device_str, 30, (void *) &device_here, 0);
     1675    mountpointComp = newtEntry(14, 2, mountpoint_str, 30, (void *) &mountpoint_here, 0);
     1676    formatComp = newtEntry(14, 4, format_str, 15, (void *) &format_here, 0);
     1677    sizeComp = newtEntry(14, 3, size_str, 10, (void *) &size_here, 0);
     1678    bOK = newtButton(5, 6, "  OK  ");
     1679    bCancel = newtButton(17, 6, "Cancel");
     1680    newtPushHelpLine
     1681        ("To add an entry to the mountlist, please fill in these fields and then hit 'OK'");
     1682    myForm = newtForm(NULL, NULL, 0);
     1683    newtFormAddComponents(myForm, deviceComp, mountpointComp, sizeComp,
     1684                          formatComp, label0, label1, label2, label3, bOK,
     1685                          bCancel, NULL);
     1686    for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
     1687        b_res = newtRunForm(myForm);
     1688        mr_free(device_str);
     1689        device_str = mr_strip_spaces(device_here);
     1690
     1691        mr_free(mountpoint_str);
     1692        mountpoint_str = mr_strip_spaces(mountpoint_here);
     1693
     1694        mr_free(format_str);
     1695        format_str = mr_strip_spaces(format_here);
     1696
     1697        mr_free(size_str);
     1698        size_str = mr_strip_spaces(size_here);
     1699
     1700        if (b_res == bOK) {
     1701            if (device_str[strlen(device_str) - 1] == '/') {
     1702                popup_and_OK("You left the device nearly blank!");
     1703                b_res = NULL;
    5001704            }
    501         }
    502     }
    503     mr_free(prompt);
    504 
    505     raidrec->raidlevel = out;
    506 #else
    507     /** buffers ***********************************************************/
    508     char tmp[MAX_STR_LEN];
    509     char *personalities = NULL;
    510     char *prompt = NULL;
    511     char sz[MAX_STR_LEN];
    512     int out = 0;
    513     int res = 0;
    514 
    515 
    516     assert(raidrec != NULL);
    517     paranoid_system("grep Pers /proc/mdstat > /tmp/raid-personalities.txt 2> /dev/null");
    518     mr_asprintf(personalities, "%s", last_line_of_file("/tmp/raid-personalities.txt"));
    519     mr_asprintf(prompt, "Please enter the RAID level you want. %s", personalities);
    520     mr_free(personalities);
    521 
    522     if (raidrec->raid_level == -1) {
    523         strcpy(tmp, "linear");
    524     } else {
    525         sprintf(tmp, "%d", raidrec->raid_level);
    526     }
    527     for (out = 999;
    528          out != -1 && out != 0 && out != 1 && out != 4 && out != 5
    529          && out != 10;) {
    530         res = popup_and_get_string("Specify RAID level", prompt, tmp, 10);
    531         if (!res) {
    532             return;
    533         }
    534         strip_spaces(tmp);
    535         if (tmp[0] == '[' && tmp[strlen(tmp) - 1] == ']') {
    536             strcpy(sz, tmp);
    537             strncpy(tmp, sz + 1, strlen(sz) - 2);
    538             tmp[strlen(sz) - 2] = '\0';
    539         }
    540         if (!strcmp(tmp, "linear")) {
    541             out = -1;
    542         } else if (!strncmp(tmp, "raid", 4)) {
    543             out = atoi(tmp + 4);
    544         } else {
    545             out = atoi(tmp);
    546         }
    547         log_it(tmp);
    548         if (is_this_raid_personality_registered(out)) {
    549             log_it("Groovy. You've picked a RAID personality which is registered.");
    550         } else {
    551             if (ask_me_yes_or_no("You have chosen a RAID personality which is not registered with the kernel. Make another selection?")) {
    552                 out = 999;
     1705            if (size_of_specific_device_in_mountlist(mountlist, device_str) >= 0) {
     1706                popup_and_OK("Can't add this - you've got one already!");
     1707                b_res = NULL;
    5531708            }
    5541709        }
    5551710    }
    556     mr_free(prompt);
    557 
    558     raidrec->raid_level = out;
    559 #endif
     1711    newtFormDestroy(myForm);
     1712    newtPopHelpLine();
     1713    newtPopWindow();
     1714    if (b_res == bCancel) {
     1715        return;
     1716    }
     1717    mr_asprintf(drive_to_add, "%s", device_str);
     1718    for (i = strlen(drive_to_add); isdigit(drive_to_add[i - 1]); i--);
     1719    mr_free(drive_to_add);
     1720
     1721    currline = mountlist->entries;
     1722    strcpy(mountlist->el[currline].device, device_str);
     1723    strcpy(mountlist->el[currline].mountpoint, mountpoint_str);
     1724    mr_free(mountpoint_str);
     1725
     1726    strcpy(mountlist->el[currline].format, format_str);
     1727    mr_free(format_str);
     1728
     1729    mountlist->el[currline].size = atol(size_str) * 1024L;
     1730    mr_free(size_str);
     1731
     1732    mountlist->entries++;
     1733    if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
     1734        initiate_new_raidlist_entry(raidlist, mountlist, currline, device_str);
     1735    }
     1736    mr_free(device_str);
     1737
     1738    redraw_mountlist(mountlist, keylist, listbox);
    5601739}
    5611740
     
    6011780
    6021781
    603 
    604 /**
    605  * Delete entry number @p currline from @p disklist.
    606  * @param disklist The disklist to remove the entry from.
    607  * @param raid_device The RAID device containing the partition we're removing.
    608  * Used only in the popup "are you sure?" box.
    609  * @param currline The line number (starting from 0) of the item to delete.
    610  * @ingroup restoreGuiDisklist
    611  */
    612 void
    613 delete_disklist_entry(struct list_of_disks *disklist, char *raid_device,
    614                       int currline)
    615 {
    616 
    617     /** int ***************************************************************/
    618     int pos = 0;
    619     int res = 0;
    620 
    621     /** buffers ***********************************************************/
    622     char *tmp = NULL;
    623 
    624     assert(disklist != NULL);
    625     assert_string_is_neither_NULL_nor_zerolength(raid_device);
    626 
    627     mr_asprintf(tmp, "Delete %s from RAID device %s - are you sure?", disklist->el[currline].device, raid_device);
    628     res = ask_me_yes_or_no(tmp);
    629     mr_free(tmp);
    630 
    631     if (!res) {
    632         return;
    633     }
    634     for (pos = currline; pos < disklist->entries - 1; pos++) {
    635         strcpy(disklist->el[pos].device, disklist->el[pos + 1].device);
    636     }
    637     disklist->entries--;
    638 }
    639 
    640 
    641 
    642 /**
    643  * Delete entry number @p currline from @p mountlist.
    644  * @param mountlist The mountlist to delete the entry from.
    645  * @param raidlist The raidlist that goes with @p mountlist.
    646  * @param listbox The Newt listbox component in the mountlist editor.
    647  * @param currline The line number (starting from 0) of the item to delete.
    648  * @param keylist The list of keys for @p listbox.
    649  * @ingroup restoreGuiMountlist
    650  */
    651 void
    652 delete_mountlist_entry(struct mountlist_itself *mountlist,
    653                        struct raidlist_itself *raidlist,
    654                        newtComponent listbox, int currline,
    655                        void *keylist[])
    656 {
    657 
    658     /** int ***************************************************************/
    659     int pos = 0;
    660     int res = 0;
    661 
    662     /** buffers ***********************************************************/
    663     char *tmp = NULL;
    664     char *device = NULL;
    665 
    666 
    667     assert(mountlist != NULL);
    668     assert(raidlist != NULL);
    669     assert(listbox != NULL);
    670     assert(keylist != NULL);
    671 
    672     pos = which_raid_device_is_using_this_partition(raidlist, mountlist->el[currline].device);
    673     if (pos >= 0) {
    674         mr_asprintf(tmp, "Cannot delete %s: it is in use by RAID device %s", mountlist->el[currline].device, raidlist->el[pos].OSSWAP(raid_device, volname));
    675         popup_and_OK(tmp);
    676         mr_free(tmp);
    677         return;
    678     }
    679     mr_asprintf(tmp, "Delete %s - are you sure?", mountlist->el[currline].device);
    680     res = ask_me_yes_or_no(tmp);
    681     mr_free(tmp);
    682 
    683     if (!res) {
    684         return;
    685     }
    686     if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
    687         mr_asprintf(device, "%s", mountlist->el[currline].device);
    688         delete_raidlist_entry(mountlist, raidlist, device);
    689         for (currline = 0;
    690              currline < mountlist->entries
    691              && strcmp(mountlist->el[currline].device, device);
    692              currline++);
    693         mr_free(device);
    694 
    695         if (currline == mountlist->entries) {
    696             log_it("Dev is gone. I can't delete it. Ho-hum");
    697             return;
    698         }
    699     }
    700     memcpy((void *) &mountlist->el[currline],
    701            (void *) &mountlist->el[mountlist->entries - 1],
    702            sizeof(struct mountlist_line));
    703     mountlist->entries--;
    704     redraw_mountlist(mountlist, keylist, listbox);
    705 }
    706 
    707 
    7081782/**
    7091783 * Delete @p device from @p raidlist.
     
    7131787 * @ingroup restoreGuiMountlist
    7141788 */
    715 void
    716 delete_raidlist_entry(struct mountlist_itself *mountlist,
     1789void delete_raidlist_entry(struct mountlist_itself *mountlist,
    7171790                      struct raidlist_itself *raidlist, char *device)
    7181791{
     
    7831856
    7841857
    785 #ifndef __FreeBSD__
    786 /**
    787  * Delete entry number @p lino in the additional RAID variables section of @p raidrec.
    788  * @param raidrec The RAID device record containing the RAID variable to delete.
    789  * @param lino The line number (starting from 0) of the variable to delete.
    790  * @ingroup restoreGuiVarslist
    791  */
    792 void delete_varslist_entry(struct raid_device_record *raidrec, int lino)
    793 {
    794 
    795     /** buffers ************************************************************/
     1858
     1859/**
     1860 * Delete entry number @p currline from @p mountlist.
     1861 * @param mountlist The mountlist to delete the entry from.
     1862 * @param raidlist The raidlist that goes with @p mountlist.
     1863 * @param listbox The Newt listbox component in the mountlist editor.
     1864 * @param currline The line number (starting from 0) of the item to delete.
     1865 * @param keylist The list of keys for @p listbox.
     1866 * @ingroup restoreGuiMountlist
     1867 */
     1868void
     1869delete_mountlist_entry(struct mountlist_itself *mountlist,
     1870                       struct raidlist_itself *raidlist,
     1871                       newtComponent listbox, int currline,
     1872                       void *keylist[])
     1873{
     1874
     1875    /** int ***************************************************************/
     1876    int pos = 0;
     1877    int res = 0;
     1878
     1879    /** buffers ***********************************************************/
    7961880    char *tmp = NULL;
    797     int res = 0;
    798 
    799     /** structures *********************************************************/
    800     struct additional_raid_variables *av;
    801 
    802     assert(raidrec != NULL);
    803 
    804     av = &raidrec->additional_vars;
    805     mr_asprintf(tmp, "Delete %s - are you sure?", av->el[lino].label);
     1881    char *device = NULL;
     1882
     1883
     1884    assert(mountlist != NULL);
     1885    assert(raidlist != NULL);
     1886    assert(listbox != NULL);
     1887    assert(keylist != NULL);
     1888
     1889    pos = which_raid_device_is_using_this_partition(raidlist, mountlist->el[currline].device);
     1890    if (pos >= 0) {
     1891        mr_asprintf(tmp, "Cannot delete %s: it is in use by RAID device %s", mountlist->el[currline].device, raidlist->el[pos].OSSWAP(raid_device, volname));
     1892        popup_and_OK(tmp);
     1893        mr_free(tmp);
     1894        return;
     1895    }
     1896    mr_asprintf(tmp, "Delete %s - are you sure?", mountlist->el[currline].device);
    8061897    res = ask_me_yes_or_no(tmp);
    8071898    mr_free(tmp);
    8081899
    809     if (res) {
    810         if (!strcmp(av->el[lino].label, "persistent-superblock")
    811             || !strcmp(av->el[lino].label, "chunk-size")) {
    812             mr_asprintf(tmp, "%s must not be deleted. It would be bad.", av->el[lino].label);
    813             popup_and_OK(tmp);
    814             mr_free(tmp);
     1900    if (!res) {
     1901        return;
     1902    }
     1903    if (strstr(mountlist->el[currline].device, RAID_DEVICE_STUB)) {
     1904        mr_asprintf(device, "%s", mountlist->el[currline].device);
     1905        delete_raidlist_entry(mountlist, raidlist, device);
     1906        for (currline = 0;
     1907             currline < mountlist->entries
     1908             && strcmp(mountlist->el[currline].device, device);
     1909             currline++);
     1910        mr_free(device);
     1911
     1912        if (currline == mountlist->entries) {
     1913            log_it("Dev is gone. I can't delete it. Ho-hum");
     1914            return;
     1915        }
     1916    }
     1917    memcpy((void *) &mountlist->el[currline],
     1918           (void *) &mountlist->el[mountlist->entries - 1],
     1919           sizeof(struct mountlist_line));
     1920    mountlist->entries--;
     1921    redraw_mountlist(mountlist, keylist, listbox);
     1922}
     1923
     1924
     1925/**
     1926 * Strip a path to the bare minimum (^ pointing to the directory above, plus filename).
     1927 * @param tmp The path to strip.
     1928 * @return The stripped path.
     1929 * @author Conor Daly
     1930 * @ingroup restoreUtilityGroup
     1931 */
     1932char *strip_path(char *tmp)
     1933{
     1934
     1935    int i = 0, j = 0, slashcount = 0;
     1936    int slashloc = 0, lastslashloc = 0;
     1937
     1938    while (tmp[i] != '\0') {    /* Count the slashes in tmp
     1939                                   1 slash per dir */
     1940        if (tmp[i] == '/') {
     1941            slashcount++;
     1942            lastslashloc = slashloc;
     1943            slashloc = i;
     1944            if (tmp[i + 1] == '\0') {   /* if this slash is last char, back off */
     1945                slashcount--;
     1946                slashloc = lastslashloc;
     1947            }
     1948        }
     1949        i++;
     1950    }
     1951    if (slashcount > 0)
     1952        slashcount--;           /* Keep one slash 'cos Hugh does... */
     1953
     1954    for (i = 0; i < slashcount; i++) {  /* Replace each dir with a space char */
     1955        tmpnopath[i] = ' ';
     1956    }
     1957
     1958    i = slashloc;
     1959    j = slashcount;
     1960    while (tmp[i] != '\0') {    /* Now add what's left of tmp */
     1961        if ((tmpprevpath[j] == ' ' || tmpprevpath[j] == '^')
     1962            && tmp[i] == '/' && tmpnopath[j - 1] != '^' && j != 0) {    /* Add a pointer upwards if this is not in the same dir as line above */
     1963            tmpnopath[j - 1] = '^';
    8151964        } else {
    816             memcpy((void *) &av->el[lino], (void *) &av->el[av->entries--],
    817                    sizeof(struct raid_var_line));
    818         }
    819     }
    820 }
    821 #endif
     1965            tmpnopath[j++] = tmp[i++];
     1966        }
     1967    }
     1968    tmpnopath[j] = '\0';
     1969
     1970    strcpy(tmpprevpath, tmpnopath); /* Make a copy for next iteration */
     1971
     1972    return (tmpnopath);
     1973}
     1974
    8221975
    8231976
     
    9242077        return (0);
    9252078    }
    926 }
    927 
    928 
    929 /**
    930  * Strip a path to the bare minimum (^ pointing to the directory above, plus filename).
    931  * @param tmp The path to strip.
    932  * @return The stripped path.
    933  * @author Conor Daly
    934  * @ingroup restoreUtilityGroup
    935  */
    936 char *strip_path(char *tmp)
    937 {
    938 
    939     int i = 0, j = 0, slashcount = 0;
    940     int slashloc = 0, lastslashloc = 0;
    941 
    942     while (tmp[i] != '\0') {    /* Count the slashes in tmp
    943                                    1 slash per dir */
    944         if (tmp[i] == '/') {
    945             slashcount++;
    946             lastslashloc = slashloc;
    947             slashloc = i;
    948             if (tmp[i + 1] == '\0') {   /* if this slash is last char, back off */
    949                 slashcount--;
    950                 slashloc = lastslashloc;
    951             }
    952         }
    953         i++;
    954     }
    955     if (slashcount > 0)
    956         slashcount--;           /* Keep one slash 'cos Hugh does... */
    957 
    958     for (i = 0; i < slashcount; i++) {  /* Replace each dir with a space char */
    959         tmpnopath[i] = ' ';
    960     }
    961 
    962     i = slashloc;
    963     j = slashcount;
    964     while (tmp[i] != '\0') {    /* Now add what's left of tmp */
    965         if ((tmpprevpath[j] == ' ' || tmpprevpath[j] == '^')
    966             && tmp[i] == '/' && tmpnopath[j - 1] != '^' && j != 0) {    /* Add a pointer upwards if this is not in the same dir as line above */
    967             tmpnopath[j - 1] = '^';
    968         } else {
    969             tmpnopath[j++] = tmp[i++];
    970         }
    971     }
    972     tmpnopath[j] = '\0';
    973 
    974     strcpy(tmpprevpath, tmpnopath); /* Make a copy for next iteration */
    975 
    976     return (tmpnopath);
    9772079}
    9782080
     
    11132215
    11142216/**
     2217 * Change all RAID devices to use @p new_dev instead of @p old_dev.
     2218 * @param raidlist The raidlist to make the changes in.
     2219 * @param old_dev The old name of the device (what it used to be).
     2220 * @param new_dev The new name of the device (what it is now).
     2221 * @ingroup restoreGuiMountlist
     2222 */
     2223void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself
     2224                                                   *raidlist,
     2225                                                   char *old_dev,
     2226                                                   char *new_dev)
     2227{
     2228    /** int ************************************************************/
     2229    int pos = 0;
     2230    int j = 0;
     2231
     2232    assert(raidlist != NULL);
     2233    assert_string_is_neither_NULL_nor_zerolength(old_dev);
     2234    assert_string_is_neither_NULL_nor_zerolength(new_dev);
     2235
     2236    pos = which_raid_device_is_using_this_partition(raidlist, old_dev);
     2237    if (pos < 0) {
     2238        log_it("No need to rejig %s in raidlist: it's not listed.", old_dev);
     2239    } else {
     2240        if ((j =
     2241             where_in_drivelist_is_drive(&raidlist->
     2242                                         OSSWAP(el[pos].data_disks, disks),
     2243                                         old_dev)) >= 0) {
     2244            strcpy(raidlist->OSSWAP(el[pos].data_disks, disks).el[j].device, new_dev);
     2245        } else
     2246            if ((j =
     2247                 where_in_drivelist_is_drive(&raidlist->
     2248                                             OSSWAP(el[pos].spare_disks,
     2249                                                    spares),
     2250                                             old_dev)) >= 0) {
     2251            strcpy(raidlist->OSSWAP(el[pos].spare_disks, spares).el[j].device, new_dev);
     2252        }
     2253#ifndef __FreeBSD__
     2254        else if ((j =
     2255                  where_in_drivelist_is_drive(&raidlist->el[pos].
     2256                                              parity_disks,
     2257                                              old_dev)) >= 0) {
     2258            strcpy(raidlist->el[pos].parity_disks.el[j].device, new_dev);
     2259        } else
     2260            if ((j =
     2261                 where_in_drivelist_is_drive(&raidlist->el[pos].
     2262                                             failed_disks,
     2263                                             old_dev)) >= 0) {
     2264            strcpy(raidlist->el[pos].failed_disks.el[j].device, new_dev);
     2265        }
     2266#endif
     2267        else {
     2268            log_it("%s is supposed to be listed in this raid dev but it's not...", old_dev);
     2269        }
     2270    }
     2271}
     2272
     2273
     2274/**
    11152275 * Edit an entry in @p mountlist.
    11162276 * @param mountlist The mountlist containing information about the user's partitions.
     
    13802540                   struct vinum_plex *raidrec, int currline,
    13812541                   int currline2);
    1382 
    1383 #endif
    1384 
    1385 
    1386 /**
    1387  * Edit the entry for @p raidrec in @p raidlist.
    1388  * @param mountlist The mountlist to get some information from.
    1389  * @param raidlist The raidlist containing information about RAID devices.
    1390  * @param raidrec The RAID device record for this partition.
    1391  * @param currline The line number (starting from 0) in the mountlist of the RAID device.
    1392  * @ingroup restoreGuiMountlist
    1393  */
    1394 void
    1395 edit_raidlist_entry(struct mountlist_itself *mountlist,
    1396                     struct raidlist_itself *raidlist,
    1397                     struct OSSWAP (raid_device_record,
    1398                                    vinum_volume) * raidrec, int currline)
    1399 {
    1400 
    1401 #ifdef __FreeBSD__
    1402     /** structures ********************************************************/
    1403     struct vinum_volume bkp_raidrec;
    1404 
    1405 
    1406     /** buffers ***********************************************************/
    1407     char title_of_editraidForm_window[MAX_STR_LEN];
    1408 
    1409     /** newt **************************************************************/
    1410     newtComponent editraidForm;
    1411     newtComponent bOK;
    1412     newtComponent bCancel;
    1413     newtComponent bEdit;
    1414     newtComponent bAdd;
    1415     newtComponent bDelete;
    1416     newtComponent b_res;
    1417     newtComponent plexesListbox;
    1418     newtComponent plexesHeader;
    1419 
    1420     void *keylist[10];
    1421     void *curr_choice;
    1422     char *raidlevel = NULL;
    1423     char *chunksize = NULL;
    1424     char *msg = NULL;
    1425 
    1426     int currline2 = 0;
    1427     int res = 0;
    1428 
    1429     log_it("Started edit_raidlist_entry");
    1430     memcpy((void *) &bkp_raidrec, (void *) raidrec,
    1431            sizeof(struct vinum_volume));
    1432     sprintf(title_of_editraidForm_window, "Plexes on %s",
    1433             raidrec->volname);
    1434     newtPushHelpLine("   Please select a plex to edit");
    1435     newtOpenWindow(13, 5, 54, 15, title_of_editraidForm_window);
    1436     for (;;) {
    1437         int i;
    1438         char *headerstr = NULL;
    1439         mr_asprintf(headerstr, "%-14s %-8s  %11s  %8s", "Plex", "Level", "Stripe Size", "Subdisks");
    1440 
    1441         bOK = newtCompactButton(2, 13, "  OK  ");
    1442         bCancel = newtCompactButton(12, 13, "Cancel");
    1443         bAdd = newtCompactButton(22, 13, " Add ");
    1444         bEdit = newtCompactButton(32, 13, " Edit ");
    1445         bDelete = newtCompactButton(42, 13, "Delete");
    1446 
    1447         plexesListbox =
    1448             newtListbox(2, 3, 9, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
    1449         plexesHeader = newtLabel(2, 2, headerstr);
    1450         mr_free(headerstr);
    1451         editraidForm = newtForm(NULL, NULL, 0);
    1452 
    1453         newtListboxClear(plexesListbox);
    1454         for (i = 0; i < 10; ++i) {
    1455             keylist[i] = (void *) i;
    1456             if (i < raidrec->plexes) {
    1457                 char *pname;
    1458                 char *entry;
    1459                 switch (raidrec->plex[i].raidlevel) {
    1460                 case -1:
    1461                     mr_asprintf(raidlevel, "concat");
    1462                     break;
    1463                 case 0:
    1464                     mr_asprintf(raidlevel, "striped");
    1465                     break;
    1466                 case 5:
    1467                     mr_asprintf(raidlevel, "raid5");
    1468                     break;
    1469                 default:
    1470                     mr_asprintf(raidlevel, "raid%i", raidrec->plex[i].raidlevel);
    1471                     break;
    1472                 }
    1473 
    1474                 if (raidrec->plex[i].raidlevel == -1) {
    1475                     mr_asprintf(chunksize, "N/A");
    1476                 } else {
    1477                     mr_asprintf(chunksize, "%dk", raidrec->plex[i].stripesize);
    1478                 }
    1479                 mr_asprintf(pname, "%s.p%i", raidrec->volname, i);
    1480                 mr_asprintf(entry, "%-14s %-8s  %11s  %8d", pname, raidlevel, chunksize, raidrec->plex[i].subdisks);
    1481                 mr_free(pname);
    1482                 mr_free(raidlevel);
    1483                 mr_free(chunksize);
    1484 
    1485                 newtListboxAppendEntry(plexesListbox, entry, keylist[i]);
    1486                 mr_free(entry);
    1487             }
    1488         }
    1489 
    1490         newtFormAddComponents(editraidForm, bOK, bCancel, bAdd, bEdit,
    1491                               bDelete, plexesListbox, plexesHeader, NULL);
    1492 
    1493         b_res = newtRunForm(editraidForm);
    1494         if (b_res == bOK || b_res == bCancel) {
    1495             break;
    1496         }
    1497 
    1498         curr_choice = newtListboxGetCurrent(plexesListbox);
    1499         for (currline2 = 0; currline2 < raidrec->plexes; ++currline2) {
    1500             if (currline2 > 9)
    1501                 break;
    1502             if (keylist[currline2] == curr_choice)
    1503                 break;
    1504         }
    1505 
    1506         if (b_res == bDelete) {
    1507             mr_asprintf(msg, "Are you sure you want to delete %s.p%i?", raidrec->volname, currline2);
    1508             res = ask_me_yes_or_no(msg);
    1509             mr_free(msg);
    1510 
    1511             if (res) {
    1512                 log_it("Deleting RAID plex");
    1513                 memcpy((void *) &raidrec->plex[currline2],
    1514                        (void *) &raidrec->plex[raidrec->plexes - 1],
    1515                        sizeof(struct vinum_plex));
    1516                 raidrec->plexes--;
    1517             }
    1518             continue;
    1519         }
    1520         if (b_res == bAdd) {
    1521             raidrec->plex[raidrec->plexes].raidlevel = 0;
    1522             raidrec->plex[raidrec->plexes].stripesize = 279;
    1523             raidrec->plex[raidrec->plexes].subdisks = 0;
    1524             currline2 = raidrec->plexes++;
    1525         }
    1526         edit_raidlist_plex(mountlist, raidlist, &raidrec->plex[currline2],
    1527                            currline, currline2);
    1528         newtFormDestroy(editraidForm);
    1529     }
    1530     if (b_res == bCancel) {
    1531         memcpy((void *) raidrec, (void *) &bkp_raidrec,
    1532                sizeof(struct vinum_volume));
    1533     }
    1534     newtPopHelpLine();
    1535     newtPopWindow();
    1536     mountlist->el[currline].size =
    1537         calculate_raid_device_size(mountlist, raidlist, raidrec->volname);
    1538 #else
    1539     /** structures ********************************************************/
    1540     struct raid_device_record *bkp_raidrec;
    1541 
    1542 
    1543     /** buffers ***********************************************************/
    1544     char *title_of_editraidForm_window;
    1545     char *sz_raid_level = NULL;
    1546     char *sz_data_disks = NULL;
    1547     char *sz_spare_disks = NULL;
    1548     char *sz_parity_disks = NULL;
    1549     char *sz_failed_disks = NULL;
    1550 
    1551     /** newt **************************************************************/
    1552     newtComponent editraidForm;
    1553     newtComponent bOK;
    1554     newtComponent bCancel;
    1555     newtComponent bAdditional;
    1556     newtComponent bChangeRaid;
    1557     newtComponent bSelectData;
    1558     newtComponent bSelectSpare;
    1559     newtComponent bSelectParity;
    1560     newtComponent bSelectFailed;
    1561     newtComponent b_res;
    1562 
    1563     assert(mountlist != NULL);
    1564     assert(raidlist != NULL);
    1565     assert(raidrec != NULL);
    1566 
    1567     bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));
    1568     log_it("Started edit_raidlist_entry");
    1569 
    1570     memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));
    1571     mr_asprintf(title_of_editraidForm_window, "%s", raidrec->raid_device);
    1572     log_msg(2, "Opening newt window");
    1573     newtOpenWindow(20, 5, 40, 14, title_of_editraidForm_window);
    1574     for (;;) {
    1575         log_msg(2, "Main loop");
    1576         mr_free(title_of_editraidForm_window);
    1577         mr_asprintf(title_of_editraidForm_window, "Edit %s", raidrec->raid_device);
    1578         sz_raid_level = turn_raid_level_number_to_string(raidrec->raid_level);
    1579         sz_data_disks = number_of_disks_as_string(raidrec->data_disks.entries, "data");
    1580         sz_spare_disks = number_of_disks_as_string(raidrec->spare_disks.entries, "spare");
    1581         sz_parity_disks = number_of_disks_as_string(raidrec->parity_disks.entries, "parity");
    1582         sz_failed_disks = number_of_disks_as_string(raidrec->failed_disks.entries, "failed");
    1583         bSelectData = newtButton(1, 1, sz_data_disks);
    1584         bSelectSpare = newtButton(20, 1, sz_spare_disks);
    1585         bSelectParity = newtButton(1, 5, sz_parity_disks);
    1586         bSelectFailed = newtButton(20, 5, sz_failed_disks);
    1587         bChangeRaid = newtButton(1, 9, sz_raid_level);
    1588         bOK = newtButton(16 + (raidrec->raid_level == -1), 9, "  OK  ");
    1589         bCancel = newtButton(28, 9, "Cancel");
    1590         bAdditional =
    1591             newtCompactButton(1, 13,
    1592                               "Additional settings and information");
    1593         newtPushHelpLine
    1594             ("  Edit the RAID device's settings to your heart's content, then hit OK/Cancel.");
    1595         editraidForm = newtForm(NULL, NULL, 0);
    1596         newtFormAddComponents(editraidForm, bSelectData, bSelectParity,
    1597                               bChangeRaid, bSelectSpare, bSelectFailed,
    1598                               bOK, bCancel, bAdditional);
    1599         b_res = newtRunForm(editraidForm);
    1600         if (b_res == bChangeRaid) {
    1601             choose_raid_level(raidrec);
    1602         } else if (b_res == bSelectData) {
    1603             select_raid_disks(mountlist, raidlist, raidrec, "data", &raidrec->data_disks);
    1604         } else if (b_res == bSelectSpare) {
    1605             select_raid_disks(mountlist, raidlist, raidrec, "spare", &raidrec->spare_disks);
    1606         } else if (b_res == bSelectParity) {
    1607             select_raid_disks(mountlist, raidlist, raidrec, "parity", &raidrec->parity_disks);
    1608         } else if (b_res == bSelectFailed) {
    1609             select_raid_disks(mountlist, raidlist, raidrec, "failed", &raidrec->failed_disks);
    1610         } else if (b_res == bAdditional) {
    1611             edit_raidrec_additional_vars(raidrec);
    1612         }
    1613         newtFormDestroy(editraidForm);
    1614         if (b_res == bOK || b_res == bCancel) {
    1615             break;
    1616         }
    1617         mr_free(sz_data_disks);
    1618         mr_free(sz_spare_disks);
    1619         mr_free(sz_parity_disks);
    1620         mr_free(sz_failed_disks);
    1621     }
    1622     if (b_res == bCancel) {
    1623         memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));
    1624     }
    1625     newtPopHelpLine();
    1626     newtPopWindow();
    1627     mountlist->el[currline].size = calculate_raid_device_size(mountlist, raidlist, raidrec->raid_device);
    1628     mr_free(title_of_editraidForm_window);
    1629     mr_free(sz_raid_level);
    1630     paranoid_free(bkp_raidrec);
    1631 #endif
    1632 }
    1633 
    1634 #ifdef __FreeBSD__
    1635 
    1636 /**
    1637  * Edit the plex @p raidrec in @p raidlist.
    1638  * @param mountlist The mountlist to get some of the information from.
    1639  * @param raidlist The raidlist containing information about RAID devices.
    1640  * @param raidrec The plex to edit.
    1641  * @param currline The line number (starting from 0) of the RAID device in @p mountlist.
    1642  * @param currline2 The line number (starting from 0) of the plex within the RAID device.
    1643  * @author Joshua Oreman
    1644  * @ingroup restoreGuiMountlist
    1645  */
    1646 void
    1647 edit_raidlist_plex(struct mountlist_itself *mountlist,
    1648                    struct raidlist_itself *raidlist,
    1649                    struct vinum_plex *raidrec, int currline, int currline2)
    1650 {
    1651 
    1652     /** structures ********************************************************/
    1653     struct vinum_plex bkp_raidrec;
    1654 
    1655 
    1656     /** buffers ***********************************************************/
    1657     char *title_of_editraidForm_window = NULL;
    1658 
    1659     /** newt **************************************************************/
    1660     newtComponent editraidForm;
    1661     newtComponent bOK;
    1662     newtComponent bCancel;
    1663     newtComponent bEdit;
    1664     newtComponent bAdd;
    1665     newtComponent bDelete;
    1666     newtComponent b_res;
    1667     newtComponent unallocListbox, allocListbox;
    1668     newtComponent bLevel, sLevel;
    1669     newtComponent bStripeSize, sStripeSize;
    1670     newtComponent bAlloc, bUnalloc;
    1671 
    1672     void *keylist[ARBITRARY_MAXIMUM];
    1673     void *curr_choice_a, *curr_choice_u;
    1674     int currline_a, currline_u;
    1675 
    1676     char *p = NULL;
    1677     char *tmp = NULL;
    1678     char *entry = NULL;
    1679 
    1680     struct mountlist_itself *unallocparts;
    1681 
    1682     unallocparts = malloc(sizeof(struct mountlist_itself));
    1683 
    1684     log_it("Started edit_raidlist_entry");
    1685     memcpy((void *) &bkp_raidrec, (void *) raidrec,
    1686            sizeof(struct vinum_plex));
    1687     mr_asprintf(title_of_editraidForm_window, "%s.p%i", raidlist->el[currline].volname, currline2);
    1688     newtPushHelpLine
    1689         ("   Please select a subdisk to edit, or edit this plex's parameters");
    1690     newtOpenWindow(13, 3, 54, 18, title_of_editraidForm_window);
    1691     mr_free(title_of_editraidForm_window);
    1692 
    1693     for (;;) {
    1694         int i;
    1695 
    1696         switch (raidrec->raidlevel) {
    1697         case -1:
    1698             mr_asprintf(tmp, "concat");
    1699             break;
    1700         case 0:
    1701             mr_asprintf(tmp, "striped");
    1702             break;
    1703         case 5:
    1704             mr_asprintf(tmp, "raid5");
    1705             break;
    1706         default:
    1707             mr_asprintf(tmp, "unknown (%i)", raidrec->raidlevel);
    1708             break;
    1709         }
    1710         bLevel = newtCompactButton(2, 2, " RAID level ");
    1711         sLevel = newtLabel(19, 2, tmp);
    1712         mr_free(tmp);
    1713 
    1714         if (raidrec->raidlevel >= 0) {
    1715             mr_asprintf(tmp, "%ik", raidrec->stripesize);
    1716             bStripeSize = newtCompactButton(2, 4, " Stripe size ");
    1717         } else {
    1718             mr_asprintf(tmp, "N/A");
    1719             bStripeSize = newtLabel(2, 4, "Stripe size:");
    1720         }
    1721         sStripeSize = newtLabel(19, 4, tmp);
    1722         mr_free(tmp);
    1723 
    1724         bOK = newtCompactButton(2, 16, "  OK  ");
    1725         bCancel = newtCompactButton(12, 16, "Cancel");
    1726         bAdd = newtCompactButton(22, 16, " Add ");
    1727         bEdit = newtCompactButton(32, 16, " Edit ");
    1728         bDelete = newtCompactButton(42, 16, "Delete");
    1729 
    1730 
    1731         unallocListbox =
    1732             newtListbox(2, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
    1733         allocListbox =
    1734             newtListbox(33, 7, 7, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
    1735         bAlloc = newtButton(23, 7, " -> ");
    1736         bUnalloc = newtButton(23, 11, " <- ");
    1737 
    1738         editraidForm = newtForm(NULL, NULL, 0);
    1739 
    1740         newtListboxClear(allocListbox);
    1741         newtListboxClear(unallocListbox);
    1742         bzero(unallocparts, sizeof(struct mountlist_itself));
    1743         make_list_of_unallocated_raid_partitions(unallocparts, mountlist,
    1744                                                  raidlist);
    1745         for (i = 0; i < ARBITRARY_MAXIMUM; ++i) {
    1746             keylist[i] = (void *) i;
    1747             if (i < raidrec->subdisks) {
    1748                 mr_asprintf(entry, "%-17s", find_dev_entry_for_raid_device_name(raidlist, raidrec->sd[i].which_device));
    1749                 newtListboxAppendEntry(allocListbox, entry, keylist[i]);
    1750                 mr_free(entry);
    1751             }
    1752             if (i < unallocparts->entries) {
    1753                 mr_asprintf(entry, "%-17s", unallocparts->el[i].device);
    1754                 newtListboxAppendEntry(unallocListbox, entry, keylist[i]);
    1755                 mr_free(entry);
    1756             }
    1757         }
    1758 
    1759 #define COMP(x)  newtFormAddComponent (editraidForm, x)
    1760 #define UCOMP(x) if (unallocparts->entries > 0) COMP(x)
    1761 #define ACOMP(x) if (raidrec->subdisks > 0) COMP(x)
    1762         editraidForm = newtForm(NULL, NULL, 0);
    1763         UCOMP(unallocListbox);
    1764         UCOMP(bAlloc);
    1765         ACOMP(allocListbox);
    1766         ACOMP(bUnalloc);
    1767         COMP(bOK);
    1768         COMP(bCancel);
    1769         COMP(bLevel);
    1770         COMP(sLevel);
    1771         if (raidrec->raidlevel != -1) {
    1772             COMP(bStripeSize);
    1773             COMP(sStripeSize);
    1774         }
    1775 #undef COMP
    1776 #undef UCOMP
    1777 #undef ACOMP
    1778 
    1779         newtDrawForm(editraidForm);
    1780         newtRefresh();
    1781         b_res = newtRunForm(editraidForm);
    1782         if (b_res == bOK || b_res == bCancel) {
    1783             break;
    1784         }
    1785 
    1786         curr_choice_a = (raidrec->subdisks > 0) ?
    1787             newtListboxGetCurrent(allocListbox) : (void *) 1234;
    1788         curr_choice_u = (unallocparts->entries > 0) ?
    1789             newtListboxGetCurrent(unallocListbox) : (void *) 1234;
    1790         for (currline_a = 0; currline_a < raidrec->subdisks; ++currline_a) {
    1791             if (currline_a > ARBITRARY_MAXIMUM)
    1792                 break;
    1793             if (keylist[currline_a] == curr_choice_a)
    1794                 break;
    1795         }
    1796         for (currline_u = 0; currline_u < unallocparts->entries;
    1797              ++currline_u) {
    1798             if (currline_u > ARBITRARY_MAXIMUM)
    1799                 break;
    1800             if (keylist[currline_u] == curr_choice_u)
    1801                 break;
    1802         }
    1803         if (b_res == bLevel) {
    1804             choose_raid_level(raidrec);
    1805         } else if (b_res == bStripeSize) {
    1806             char tmp1[64];
    1807             sprintf(tmp1, "%i", raidrec->stripesize);
    1808             if (popup_and_get_string
    1809                 ("Stripe size",
    1810                  "Please enter the stripe size in kilobytes.", tmp1, 20)) {
    1811                 raidrec->stripesize = atoi(tmp1);
    1812             }
    1813         } else if ((b_res == bAlloc) || (b_res == unallocListbox)) {
    1814             if (currline_u <= unallocparts->entries)
    1815                 add_raid_subdisk(raidlist, raidrec,
    1816                                  unallocparts->el[currline_u].device);
    1817         } else if ((b_res == bUnalloc) || (b_res == allocListbox)) {
    1818             if (currline_a <= raidrec->subdisks) {
    1819                 memcpy((void *) &raidrec->sd[currline_a],
    1820                        (void *) &raidrec->sd[raidrec->subdisks - 1],
    1821                        sizeof(struct vinum_subdisk));
    1822                 raidrec->subdisks--;
    1823             }
    1824         }
    1825     newtFormDestroy(editraidForm);
    1826     newtRefresh();
    1827 }
    1828 
    1829 if (b_res == bCancel) {
    1830     memcpy((void *) raidrec, (void *) &bkp_raidrec, sizeof(struct vinum_plex));
    1831 }
    1832 newtPopWindow();
    1833 newtPopHelpLine();
    1834 }
    1835 #else
    1836 /**
    1837  * Edit additional RAID variable number @p lino.
    1838  * @param raidrec The RAID device record to edit the variable in.
    1839  * @param lino The line number (starting from 0) of the variable to edit.
    1840  * @ingroup restoreGuiVarslist
    1841  */
    1842 void edit_varslist_entry(struct raid_device_record *raidrec, int lino)
    1843 {
    1844 
    1845     /** buffers ***********************************************************/
    1846     char *header = NULL;
    1847     char *comment = NULL;
    1848     char sz_out[MAX_STR_LEN];
    1849 
    1850     assert(raidrec != 0);
    1851     assert(lino >= 0);
    1852 
    1853     strcpy(sz_out, raidrec->additional_vars.el[lino].value);
    1854     mr_asprintf(header, "Edit %s", raidrec->additional_vars.el[lino].label);
    1855     mr_asprintf(comment, "Please set %s's value (currently '%s')", raidrec->additional_vars.el[lino].label, sz_out);
    1856     if (popup_and_get_string(header, comment, sz_out, MAX_STR_LEN)) {
    1857         strip_spaces(sz_out);
    1858         strcpy(raidrec->additional_vars.el[lino].value, sz_out);
    1859     }
    1860     mr_free(header);
    1861     mr_free(comment);
    1862 }
    18632542
    18642543#endif
     
    20482727}
    20492728
    2050 
    2051 
    2052 
    2053 #ifndef __FreeBSD__
    2054 /**
    2055  * Edit the additional RAID variables in @p raidrec.
    2056  * @param raidrec The RAID device record to edit the RAID variables in.
    2057  * @ingroup restoreGuiVarslist
    2058  */
    2059 void edit_raidrec_additional_vars(struct raid_device_record *raidrec)
    2060 {
    2061 
    2062     /** structure *********************************************************/
    2063     struct raid_device_record bkp_raidrec;
    2064 
    2065     /** newt **************************************************************/
    2066     newtComponent myForm;
    2067     newtComponent bAdd;
    2068     newtComponent bEdit;
    2069     newtComponent bDelete;
    2070     newtComponent bOK;
    2071     newtComponent bCancel;
    2072     newtComponent b_res;
    2073     newtComponent varsListbox;
    2074     newtComponent headerMsg;
    2075 
    2076     /** ?? ***************************************************************/
    2077     void *keylist[ARBITRARY_MAXIMUM], *curr_choice;
    2078 
    2079     /** buffers **********************************************************/
    2080     char title_of_window[MAX_STR_LEN];
    2081 
    2082     /** int **************************************************************/
    2083     int i = 0;
    2084     int currline = 0;
    2085 
    2086 
    2087     assert(raidrec != NULL);
    2088 
    2089     memcpy((void *) &bkp_raidrec, (void *) raidrec,
    2090            sizeof(struct raid_device_record));
    2091     sprintf(title_of_window, "Additional variables");
    2092     newtPushHelpLine
    2093         ("  Edit the additional fields to your heart's content, then click OK or Cancel.");
    2094     headerMsg = newtLabel(1, 1, "Label                            Value");
    2095     varsListbox =
    2096         newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
    2097     i = 1;
    2098     bAdd = newtCompactButton(i, 9, " Add ");
    2099     bEdit = newtCompactButton(i += 8, 9, " Edit ");
    2100     bDelete = newtCompactButton(i += 9, 9, "Delete");
    2101     bOK = newtCompactButton(i += 9, 9, "  OK  ");
    2102     bCancel = newtCompactButton(i += 9, 9, "Cancel");
    2103     newtOpenWindow(17, 7, 46, 10, title_of_window);
    2104     myForm = newtForm(NULL, NULL, 0);
    2105     newtFormAddComponents(myForm, headerMsg, varsListbox, bAdd, bEdit,
    2106                           bDelete, bOK, bCancel, NULL);
    2107     insert_essential_additionalvars(raidrec);
    2108     redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);
    2109     for (b_res = NULL; b_res != bOK && b_res != bCancel;) {
    2110         b_res = newtRunForm(myForm);
    2111         curr_choice = newtListboxGetCurrent(varsListbox);
    2112         for (currline = 0;
    2113              currline < raidrec->additional_vars.entries
    2114              && keylist[currline] != curr_choice; currline++);
    2115         if (currline == raidrec->additional_vars.entries
    2116             && raidrec->additional_vars.entries > 0) {
    2117             log_it("Warning - I don't know what this button does");
    2118         }
    2119         if (b_res == bOK) {     /* do nothing */
    2120         } else if (b_res == bCancel) {  /* do nothing */
    2121         } else if (b_res == bAdd) {
    2122             add_varslist_entry(raidrec);
    2123         } else if (b_res == bDelete) {
    2124             delete_varslist_entry(raidrec, currline);
    2125         } else {
    2126             edit_varslist_entry(raidrec, currline);
    2127         }
    2128         redraw_varslist(&raidrec->additional_vars, keylist, varsListbox);
    2129     }
    2130     remove_essential_additionalvars(raidrec);
    2131     newtFormDestroy(myForm);
    2132     newtPopWindow();
    2133     newtPopHelpLine();
    2134     if (b_res == bCancel) {
    2135         memcpy((void *) raidrec, (void *) &bkp_raidrec,
    2136                sizeof(struct raid_device_record));
    2137     }
    2138     return;
    2139 }
    2140 #endif
    2141 
    2142 
    2143 /**
    2144  * Find the next free location to place a disk in @p disklist.
    2145  * @param disklist The disklist to operate on.
    2146  * @return The next free location (starting from 0).
    2147  * @ingroup restoreGuiDisklist
    2148  */
    2149 int find_next_free_index_in_disklist(struct list_of_disks *disklist)
    2150 {
    2151 
    2152     /** int ***************************************************************/
    2153     int index = -1;
    2154     int pos = 0;
    2155 
    2156   /** bool **************************************************************/
    2157     bool done;
    2158 
    2159     assert(disklist != NULL);
    2160 
    2161     for (done = FALSE; !done;) {
    2162         for (pos = 0;
    2163              pos < disklist->entries && disklist->el[pos].index <= index;
    2164              pos++);
    2165         if (pos >= disklist->entries) {
    2166             done = TRUE;
    2167         } else {
    2168             index = disklist->el[pos].index;
    2169         }
    2170     }
    2171     return (index + 1);
    2172 }
    2173 
    2174 
    2175 
    2176 /**
    2177  * Locate @p device in @p raidlist.
    2178  * @param raidlist The raidlist ot search in.
    2179  * @param device The RAID device to search for.
    2180  * @return The index of the device, or -1 if it could not be found.
    2181  * @ingroup restoreGuiMountlist
    2182  */
    2183 int
    2184 find_raid_device_in_raidlist(struct raidlist_itself *raidlist,
    2185                              char *device)
    2186 {
    2187 
    2188     /** int ***************************************************************/
    2189     int i = 0;
    2190 #ifdef __FreeBSD__
    2191     char *vdev = NULL;
    2192     int res = 0;
    2193 #else
    2194 // Linux
    2195 #endif
    2196 
    2197     assert(raidlist != NULL);
    2198     assert_string_is_neither_NULL_nor_zerolength(device);
    2199 
    2200 #ifdef __FreeBSD__
    2201     for (i = 0; i < raidlist->entries; i++) {
    2202         mr_asprintf(vdev, "/dev/vinum/%s", raidlist->el[i].volname);
    2203         res = strcmp(device, vdev);
    2204         mr_free(vdev);
    2205 
    2206         if (!res)
    2207             break;
    2208     }
    2209 #else
    2210 
    2211     for (i = 0;
    2212          strcmp(raidlist->el[i].raid_device, device)
    2213          && i < raidlist->entries; i++);
    2214 #endif
    2215     if (i == raidlist->entries) {
    2216         return (-1);
    2217     } else {
    2218         return (i);
    2219     }
    2220 }
    2221 
    2222 
    2223 /**
    2224  * Create a new raidtab entry for @p device in @p raidlist.
    2225  * @param raidlist The raidlist to add the device to.
    2226  * @param mountlist The mountlist containing information about the user's partitions.
    2227  * @param currline The selected line in the mountlist.
    2228  * @param device The RAID device (e.g. /dev/md0) to use.
    2229  * @ingroup restoreGuiMountlist
    2230  */
    2231 void
    2232 initiate_new_raidlist_entry(struct raidlist_itself *raidlist,
    2233                             struct mountlist_itself *mountlist,
    2234                             int currline, char *device)
    2235 {
    2236 
    2237     /** structure *********************************************************/
    2238     struct OSSWAP (raid_device_record, vinum_volume) * raidrec;
    2239 
    2240     /** int ***************************************************************/
    2241     int pos_in_raidlist = 0;
    2242 
    2243     assert(raidlist != NULL);
    2244     assert(mountlist != NULL);
    2245     assert_string_is_neither_NULL_nor_zerolength(device);
    2246 
    2247     pos_in_raidlist =
    2248         find_raid_device_in_raidlist(raidlist,
    2249                                      mountlist->el[currline].device);
    2250     if (pos_in_raidlist >= 0) {
    2251         fatal_error("Sorry, that RAID device already exists. Weird.");
    2252     }
    2253     pos_in_raidlist = raidlist->entries++;
    2254     raidrec = &raidlist->el[pos_in_raidlist];
    2255     initialize_raidrec(raidrec);
    2256     strcpy(raidrec->OSSWAP(raid_device, volname), OSSWAP(device, basename(device)));
    2257 #ifndef __FreeBSD__
    2258     choose_raid_level(raidrec);
    2259     select_raid_disks(mountlist, raidlist, raidrec, "data",
    2260                       &raidrec->data_disks);
    2261 #endif
    2262     edit_raidlist_entry(mountlist, raidlist, raidrec, currline);
    2263 }
    2264 
    2265 
    2266 #ifndef __FreeBSD__
    2267 /**
    2268  * Insert the RAID variables not stored in the "additional RAID variables" list there too.
    2269  * @param raidrec The RAID device record to operate on.
    2270  * @ingroup restoreGuiVarslist
    2271  */
    2272 void insert_essential_additionalvars(struct raid_device_record *raidrec)
    2273 {
    2274 
    2275     /** int **************************************************************/
    2276     int items = 0;
    2277 
    2278     assert(raidrec != NULL);
    2279 
    2280     items = raidrec->additional_vars.entries;
    2281     write_variableINT_to_raid_var_line(raidrec, items++,
    2282                                        "persistent-superblock",
    2283                                        raidrec->persistent_superblock);
    2284     write_variableINT_to_raid_var_line(raidrec, items++, "chunk-size",
    2285                                        raidrec->chunk_size);
    2286     raidrec->additional_vars.entries = items;
    2287 }
    2288 
    2289 #endif
    2290 
    22912729/**
    22922730 * Dummy function that proves that we can get to the point where Mondo is run.
     
    23142752    newtPopHelpLine();
    23152753}
    2316 
    2317 
    2318 
    2319 /**
    2320  * Redraw the disklist.
    2321  * @param disklist The disklist to read from.
    2322  * @param keylist The list of keys for @p listbox.
    2323  * @param listbox The Newt listbox component to redraw.
    2324  * @ingroup restoreGuiDisklist
    2325  */
    2326 void
    2327 redraw_disklist(struct list_of_disks *disklist,
    2328                 void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
    2329 {
    2330 
    2331     /** long **************************************************************/
    2332     long i = 0;
    2333     char *tmp = NULL;
    2334 
    2335     assert(disklist != NULL);
    2336     assert(keylist != NULL);
    2337     assert(listbox != NULL);
    2338 
    2339     newtListboxClear(listbox);
    2340 
    2341     for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
    2342         keylist[i] = (void *) i;
    2343     }
    2344     for (i = 0; i < disklist->entries; i++) {
    2345         tmp = disklist_entry_to_string(disklist, i);
    2346         newtListboxAppendEntry(listbox, tmp, keylist[i]);
    2347         mr_free(tmp);
    2348     }
    2349 }
    2350 
    2351 
    2352 /**
    2353  * Redraw the mountlist.
    2354  * @param mountlist The mountlist to read from.
    2355  * @param keylist The list of keys for @p listbox.
    2356  * @param listbox The Newt listbox component to redraw.
    2357  * @ingroup restoreGuiMountlist
    2358  */
    2359 void
    2360 redraw_mountlist(struct mountlist_itself *mountlist,
    2361                  void *keylist[ARBITRARY_MAXIMUM], newtComponent listbox)
    2362 {
    2363 
    2364     /** long **************************************************************/
    2365     long i = 0;
    2366     char * tmp = NULL;
    2367 
    2368     assert(mountlist != NULL);
    2369     assert(keylist != NULL);
    2370     assert(listbox != NULL);
    2371 
    2372     newtListboxClear(listbox);
    2373 //  sort_mountlist_by_device (mountlist);
    2374     for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
    2375         keylist[i] = (void *) i;
    2376     }
    2377     for (i = 0; i < mountlist->entries; i++) {
    2378         tmp = mountlist_entry_to_string(mountlist, i);
    2379         newtListboxAppendEntry(listbox, tmp, keylist[i]);
    2380         mr_free(tmp);
    2381     }
    2382 }
    2383 
    2384 
    2385 
    2386 
    2387 /**
    2388  * Redraw the list of unallocated RAID partitions.
    2389  * @param unallocated_raid_partitions The mountlist containing unallocated RAID partitions.
    2390  * @param keylist The list of keys for @p listbox.
    2391  * @param listbox The Newt listbox component to redraw.
    2392  * @ingroup restoreGuiDisklist
    2393  */
    2394 void redraw_unallocpartnslist(struct mountlist_itself
    2395                               *unallocated_raid_partitions,
    2396                               void *keylist[ARBITRARY_MAXIMUM],
    2397                               newtComponent listbox)
    2398 {
    2399 
    2400     /** long *************************************************************/
    2401     long i = 0;
    2402 
    2403     /** buffers **********************************************************/
    2404     char tmp[MAX_STR_LEN];
    2405 
    2406     assert(unallocated_raid_partitions != NULL);
    2407     assert(keylist != NULL);
    2408     assert(listbox != NULL);
    2409 
    2410     newtListboxClear(listbox);
    2411     for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
    2412         keylist[i] = (void *) i;
    2413     }
    2414     for (i = 0; i < unallocated_raid_partitions->entries; i++) {
    2415         sprintf(tmp, "%-22s %8lld",
    2416                 unallocated_raid_partitions->el[i].device,
    2417                 unallocated_raid_partitions->el[i].size / 1024L);
    2418         newtListboxAppendEntry(listbox, tmp, keylist[i]);
    2419     }
    2420 }
    2421 
    2422 #ifndef __FreeBSD__
    2423 /**
    2424  * Redraw the list of additional RAID variables.
    2425  * @param additional_vars The list of additional RAID varibals.
    2426  * @param keylist The list of keys for @p listbox.
    2427  * @param listbox The Newt listbox component to redraw.
    2428  * @ingroup restoreGuiVarslist
    2429  */
    2430 void
    2431 redraw_varslist(struct additional_raid_variables *additional_vars,
    2432                 void *keylist[], newtComponent listbox)
    2433 {
    2434     /** long ************************************************************/
    2435     long i = 0;
    2436 
    2437     /** buffers *********************************************************/
    2438     char tmp[MAX_STR_LEN];
    2439 
    2440     assert(additional_vars != NULL);
    2441     assert(keylist != NULL);
    2442     assert(listbox != NULL);
    2443 
    2444     newtListboxClear(listbox);
    2445 
    2446     for (i = 0; i < ARBITRARY_MAXIMUM; i++) {
    2447         keylist[i] = (void *) i;
    2448     }
    2449     for (i = 0; i < additional_vars->entries; i++) {
    2450         sprintf(tmp, "%-32s %-8s", additional_vars->el[i].label,
    2451                 additional_vars->el[i].value);
    2452         newtListboxAppendEntry(listbox, tmp, keylist[i]);
    2453     }
    2454 }
    2455 
    2456 
    2457 /**
    2458  * Remove variable @p label from the RAID variables list in @p raidrec.
    2459  * @param raidrec The RAID device record to remove the variable from.
    2460  * @param label The variable name to remove.
    2461  * @return The value of the variable removed.
    2462  * @ingroup restoreUtilityGroup
    2463  */
    2464 int
    2465 read_variableINT_and_remove_from_raidvars(struct
    2466                                           OSSWAP (raid_device_record,
    2467                                                   vinum_volume) * raidrec,
    2468                                           char *label)
    2469 {
    2470     /** int ***************************************************************/
    2471     int i = 0;
    2472     int res = 0;
    2473 
    2474 
    2475     assert(raidrec != NULL);
    2476     assert(label != NULL);
    2477 
    2478     for (i = 0;
    2479          i < raidrec->additional_vars.entries
    2480          && strcmp(raidrec->additional_vars.el[i].label, label); i++);
    2481     if (i == raidrec->additional_vars.entries) {
    2482         res = -1;
    2483     } else {
    2484         res = atoi(raidrec->additional_vars.el[i].value);
    2485         for (i++; i < raidrec->additional_vars.entries; i++) {
    2486             memcpy((void *) &raidrec->additional_vars.el[i - 1],
    2487                    (void *) &raidrec->additional_vars.el[i],
    2488                    sizeof(struct raid_var_line));
    2489         }
    2490         raidrec->additional_vars.entries--;
    2491     }
    2492     return (res);
    2493 }
    2494 #endif
    2495 
    2496 /**
    2497  * Change all RAID devices to use @p new_dev instead of @p old_dev.
    2498  * @param raidlist The raidlist to make the changes in.
    2499  * @param old_dev The old name of the device (what it used to be).
    2500  * @param new_dev The new name of the device (what it is now).
    2501  * @ingroup restoreGuiMountlist
    2502  */
    2503 void rejig_partition_name_in_raidlist_if_necessary(struct raidlist_itself
    2504                                                    *raidlist,
    2505                                                    char *old_dev,
    2506                                                    char *new_dev)
    2507 {
    2508     /** int ************************************************************/
    2509     int pos = 0;
    2510     int j = 0;
    2511 
    2512     assert(raidlist != NULL);
    2513     assert_string_is_neither_NULL_nor_zerolength(old_dev);
    2514     assert_string_is_neither_NULL_nor_zerolength(new_dev);
    2515 
    2516     pos = which_raid_device_is_using_this_partition(raidlist, old_dev);
    2517     if (pos < 0) {
    2518         log_it("No need to rejig %s in raidlist: it's not listed.", old_dev);
    2519     } else {
    2520         if ((j =
    2521              where_in_drivelist_is_drive(&raidlist->
    2522                                          OSSWAP(el[pos].data_disks, disks),
    2523                                          old_dev)) >= 0) {
    2524             strcpy(raidlist->OSSWAP(el[pos].data_disks, disks).el[j].device, new_dev);
    2525         } else
    2526             if ((j =
    2527                  where_in_drivelist_is_drive(&raidlist->
    2528                                              OSSWAP(el[pos].spare_disks,
    2529                                                     spares),
    2530                                              old_dev)) >= 0) {
    2531             strcpy(raidlist->OSSWAP(el[pos].spare_disks, spares).el[j].device, new_dev);
    2532         }
    2533 #ifndef __FreeBSD__
    2534         else if ((j =
    2535                   where_in_drivelist_is_drive(&raidlist->el[pos].
    2536                                               parity_disks,
    2537                                               old_dev)) >= 0) {
    2538             strcpy(raidlist->el[pos].parity_disks.el[j].device, new_dev);
    2539         } else
    2540             if ((j =
    2541                  where_in_drivelist_is_drive(&raidlist->el[pos].
    2542                                              failed_disks,
    2543                                              old_dev)) >= 0) {
    2544             strcpy(raidlist->el[pos].failed_disks.el[j].device, new_dev);
    2545         }
    2546 #endif
    2547         else {
    2548             log_it("%s is supposed to be listed in this raid dev but it's not...", old_dev);
    2549         }
    2550     }
    2551 }
    2552 
    2553 
    2554 #ifndef __FreeBSD__
    2555 /**
    2556  * Remove the essential RAID variables from the "additional variables" section.
    2557  * If they have been changed, set them in their normal locations too.
    2558  * @param raidrec The RAID device record to operate on.
    2559  * @ingroup restoreUtilityVarslist
    2560  */
    2561 void remove_essential_additionalvars(struct raid_device_record *raidrec)
    2562 {
    2563 
    2564     /** int **************************************************************/
    2565     int res = 0;
    2566 
    2567     assert(raidrec != NULL);
    2568 
    2569     res =
    2570         read_variableINT_and_remove_from_raidvars(raidrec,
    2571                                                   "persistent-superblock");
    2572     if (res > 0) {
    2573         raidrec->persistent_superblock = res;
    2574     }
    2575     res = read_variableINT_and_remove_from_raidvars(raidrec, "chunk-size");
    2576     if (res > 0) {
    2577         raidrec->chunk_size = res;
    2578     }
    2579     res = read_variableINT_and_remove_from_raidvars(raidrec, "block-size");
    2580 }
    2581 
    2582 /**
    2583  * Select the RAID disks to use in @p raidrec.
    2584  * @param mountlist_dontedit The mountlist (will not be edited).
    2585  * @param raidlist The raidlist to modify.
    2586  * @param raidrec The RAID device record in @p raidlist to work on.
    2587  * @param description_of_list The type of disks we're selecting (e.g. "data").
    2588  * @param disklist The disklist to put the user-selected disks in.
    2589  * @ingroup restoreGuiMountlist
    2590  */
    2591 void
    2592 select_raid_disks(struct mountlist_itself *mountlist_dontedit,
    2593                   struct raidlist_itself *raidlist,
    2594                   struct raid_device_record *raidrec,
    2595                   char *description_of_list,
    2596                   struct list_of_disks *disklist)
    2597 {
    2598     void *curr_choice;
    2599 
    2600     /** ??? ***************************************************************/
    2601 
    2602     /** structures ********************************************************/
    2603     struct raidlist_itself *bkp_raidlist;
    2604     struct raid_device_record *bkp_raidrec;
    2605     struct list_of_disks *bkp_disklist;
    2606     struct mountlist_itself *unallocated_raid_partitions;
    2607 
    2608     /** newt **************************************************************/
    2609     newtComponent myForm = NULL;
    2610     newtComponent bAdd = NULL;
    2611     newtComponent bDelete = NULL;
    2612     newtComponent bOK = NULL;
    2613     newtComponent bCancel = NULL;
    2614     newtComponent b_res = NULL;
    2615     newtComponent partitionsListbox = NULL;
    2616     newtComponent headerMsg = NULL;
    2617 
    2618     /** buffers **********************************************************/
    2619     void *keylist[ARBITRARY_MAXIMUM];
    2620     char *tmp = NULL;
    2621     char *help_text = NULL;
    2622     char *title_of_window = NULL;
    2623     char sz_res[MAX_STR_LEN];
    2624     char *header_text = NULL;
    2625 
    2626   /** int **************************************************************/
    2627     int i = 0;
    2628     int currline = 0;
    2629 
    2630     assert(mountlist_dontedit != NULL);
    2631     assert(raidlist != NULL);
    2632     assert(raidrec != NULL);
    2633     assert(description_of_list != NULL);
    2634     assert(disklist != NULL);
    2635 
    2636     log_it("malloc'ing");
    2637     bkp_raidrec = mr_malloc(sizeof(struct raid_device_record));
    2638     bkp_disklist = mr_malloc(sizeof(struct list_of_disks));
    2639     bkp_raidlist = mr_malloc(sizeof(struct raidlist_itself));
    2640     unallocated_raid_partitions = mr_malloc(sizeof(struct mountlist_itself));
    2641 
    2642     memcpy((void *) bkp_raidlist, (void *) raidlist, sizeof(struct raidlist_itself));
    2643     memcpy((void *) bkp_raidrec, (void *) raidrec, sizeof(struct raid_device_record));
    2644     memcpy((void *) bkp_disklist, (void *) disklist, sizeof(struct list_of_disks));
    2645 
    2646     log_it("Post-malloc");
    2647     mr_asprintf(help_text, "   Edit this RAID device's list of partitions. Choose OK or Cancel when done.");
    2648     mr_asprintf(header_text, "%-24s    %s", "Device", "Index");
    2649     mr_asprintf(title_of_window, "%s contains...", raidrec->raid_device);
    2650     newtPushHelpLine(help_text);
    2651     for (b_res = (newtComponent) 12345; b_res != bOK && b_res != bCancel;) {
    2652         headerMsg = newtLabel(1, 1, header_text);
    2653         partitionsListbox =
    2654             newtListbox(1, 2, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
    2655         redraw_disklist(disklist, keylist, partitionsListbox);
    2656         i = 1;
    2657         bAdd = newtCompactButton(i, 9, " Add ");
    2658         bDelete = newtCompactButton(i += 8, 9, "Delete");
    2659         bOK = newtCompactButton(i += 9, 9, "  OK  ");
    2660         bCancel = newtCompactButton(i += 9, 9, "Cancel");
    2661         newtOpenWindow(21, 7, 38, 10, title_of_window);
    2662         myForm = newtForm(NULL, NULL, 0);
    2663         if (disklist->entries == 0) {
    2664             newtFormAddComponents(myForm, headerMsg, bAdd, bDelete, bOK,
    2665                                   bCancel, NULL);
    2666         } else {
    2667             newtFormAddComponents(myForm, headerMsg, partitionsListbox,
    2668                                   bAdd, bDelete, bOK, bCancel, NULL);
    2669         }
    2670         b_res = newtRunForm(myForm);
    2671         if (b_res == bOK || b_res == bCancel) { /* do nothing */
    2672 // That's OK. At the end of this subroutine (after this do/while loop),
    2673 // we'll throw away the changes if Cancel was pushed.
    2674         } else {
    2675             curr_choice = newtListboxGetCurrent(partitionsListbox);
    2676             for (i = 0; i < disklist->entries && keylist[i] != curr_choice;
    2677                  i++);
    2678             if (i == disklist->entries && disklist->entries > 0) {
    2679                 log_to_screen("I don't know what that button does!");
    2680             } else {
    2681                 currline = i;
    2682                 if (b_res == bAdd) {
    2683                     log_it("Making list of unallocated RAID slices");
    2684                     make_list_of_unallocated_raid_partitions
    2685                         (unallocated_raid_partitions, mountlist_dontedit,
    2686                          raidlist);
    2687                     if (unallocated_raid_partitions->entries <= 0) {
    2688                         popup_and_OK
    2689                             ("There are no unallocated partitions marked for RAID.");
    2690                     } else {
    2691                         log_it
    2692                             ("Done. The user may add one or more of the above to RAID device");
    2693                         add_disklist_entry(disklist, raidrec->raid_device,
    2694                                            unallocated_raid_partitions);
    2695                         log_it("I have finished adding a disklist entry.");
    2696                         redraw_disklist(disklist, keylist,
    2697                                         partitionsListbox);
    2698                     }
    2699                 } else if (b_res == bDelete) {
    2700                     delete_disklist_entry(disklist, raidrec->raid_device,
    2701                                           currline);
    2702                     redraw_disklist(disklist, keylist, partitionsListbox);
    2703                 } else {
    2704                     mr_asprintf(tmp, "%s's index is %d. What should it be?", raidrec->raid_device, disklist->el[currline].index);
    2705                     sprintf(sz_res, "%d", disklist->el[currline].index);
    2706                     if (popup_and_get_string("Set index", tmp, sz_res, 10)) {
    2707                         disklist->el[currline].index = atoi(sz_res);
    2708                     }
    2709                     mr_free(tmp);
    2710 
    2711                     redraw_disklist(disklist, keylist, partitionsListbox);
    2712                 }
    2713             }
    2714         }
    2715         newtFormDestroy(myForm);
    2716         newtPopWindow();
    2717     }
    2718     newtPopHelpLine();
    2719     mr_free(help_text);
    2720     mr_free(header_text);
    2721     mr_free(title_of_window);
    2722 
    2723     if (b_res == bCancel) {
    2724         memcpy((void *) raidlist, (void *) bkp_raidlist, sizeof(struct raidlist_itself));
    2725         memcpy((void *) raidrec, (void *) bkp_raidrec, sizeof(struct raid_device_record));
    2726         memcpy((void *) disklist, (void *) bkp_disklist, sizeof(struct list_of_disks));
    2727     }
    2728     mr_free(bkp_raidrec);
    2729     mr_free(bkp_disklist);
    2730     mr_free(bkp_raidlist);
    2731     mr_free(unallocated_raid_partitions);
    2732 }
    2733 #endif
    2734 
    2735 
    27362754
    27372755/**
  • branches/3.3/mondo/src/mondorestore/mondo-rstr-tools.c

    r3876 r3879  
    1010#include "mr_file.h"
    1111#include "mr_sys.h"
    12 #include "../common/mondostructures.h"
    13 #include "../common/libmondo.h"
    14 #include "mr-externs.h"
    15 #include "mondo-rstr-tools.h"
     12#include "mondostructures.h"
    1613#include "libmondo-mountlist-EXT.h"
     14#include "libmondo-tools-EXT.h"
     15#include "libmondo-filelist-EXT.h"
     16#include "libmondo-files-EXT.h"
     17#include "libmondo-devices-EXT.h"
     18#include "libmondo-string-EXT.h"
     19#include "libmondo-raid-EXT.h"
     20#include "libmondo-fork-EXT.h"
    1721#include "newt-specific-EXT.h"
     22// no include for now in mondo-rstr-newt.c
     23extern int edit_filelist(struct s_node *);
    1824
    1925/**
     
    7480extern char *g_mountlist_fname; // where mountlist.txt (the mountlist file) is stored
    7581extern char *g_mondo_home;      // homedir of Mondo; usually /usr/local/share/mondo
     82extern int g_currentY;
     83extern bool g_restoring_live_from_cd;
     84extern bool g_text_mode;
     85extern int g_current_media_number;
    7686
    7787extern t_bkptype g_backup_media_type;
     
    169179
    170180
    171 
     181/**
     182 * Extract mondorestore.cfg and the mountlist from the tape inserted
     183 * to the ./tmp/ directory.
     184 * @param dev The tape device to read from.
     185 * @return 0 for success, nonzero for failure.
     186 */
     187int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
     188{
     189    char *command = NULL;
     190    int res = 0;
     191
     192    if (bkpinfo->use_obdr) {
     193        skip_obdr();
     194    } else {
     195        // TODO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
     196        set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
     197    }
     198
     199    mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
     200    log_msg(2, "command = '%s'", command);
     201    res = run_program_and_log_output(command, -1);
     202    mr_free(command);
     203
     204    if (res != 0) {
     205        if (does_file_exist(MONDO_CFG_FILE_STUB)) {
     206            res = 0;
     207        } else {
     208            /* Doing that allow us to remain compatible with pre-2.2.5 versions */
     209            log_msg(2, "pre-2.2.4 compatible mode on");
     210            mr_asprintf(command,    "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
     211            log_msg(2, "command = '%s'", command);
     212            res = run_program_and_log_output(command, -1);
     213            mr_free(command);
     214            if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {
     215                res = 0;
     216            }
     217        }
     218    }
     219    paranoid_free(command);
     220    return (res);
     221}
     222
     223
     224
     225
     226
     227/**
     228 * Get the configuration file from the tape, or CD.
     229 * @param bkpinfo The backup information structure. Fields used:
     230 * - @c bkpinfo->backup_media_type
     231 * - @c bkpinfo->media_device
     232 * - @c bkpinfo->tmpdir
     233 * @return 0 for success, nonzero for failure.
     234 */
     235int get_cfg_file_from_archive()
     236{
     237    int retval = 0;
     238
     239   /** malloc *****/
     240    char *command = NULL;
     241    char *cfg_file = NULL;
     242    char *tmp = NULL;
     243    char *tmp1 = NULL;
     244    char *mountpt = NULL;
     245    char *mountlist_file = NULL;
     246    bool extract_mountlist_stub = FALSE;
     247    bool extract_i_want_my_lvm = FALSE;
     248
     249    bool try_plan_B;
     250
     251    assert(bkpinfo != NULL);
     252    log_msg(2, "gcffa --- starting");
     253    log_to_screen("I'm thinking...");
     254    mr_asprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
     255    if (chdir(bkpinfo->tmpdir)) {
     256        // FIXME
     257    }
     258    mr_asprintf(cfg_file, "%s", MONDO_CFG_FILE_STUB);
     259    unlink(cfg_file);           // cfg_file[] is missing the '/' at the start, FYI, by intent
     260    mr_free(cfg_file);
     261
     262    unlink(FILELIST_FULL_STUB);
     263    unlink(BIGGIELIST_TXT_STUB);
     264    mr_asprintf(command, "mkdir -p %s", mountpt);
     265    run_program_and_log_output(command, FALSE);
     266    mr_free(command);
     267
     268    mr_asprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
     269    mr_asprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
     270    log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
     271    mr_free(mountpt);
     272
     273    if (!does_file_exist(cfg_file)) {
     274        log_msg(2, "gcffa --- we don't have cfg file yet.");
     275        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     276            try_plan_B = TRUE;
     277        } else {
     278            log_msg(2, "gcffa --- calling mount_media now :)");
     279            if (!mount_media(MNT_CDROM)) {
     280                log_msg(2, "gcffa --- managed to mount CD; so, no need for Plan B");
     281                try_plan_B = FALSE;
     282            } else {
     283                try_plan_B = TRUE;
     284            }
     285            if (what_number_cd_is_this() > 1) {
     286                insist_on_this_cd_number((g_current_media_number = 1));
     287            }
     288        }
     289        if (try_plan_B) {
     290            log_msg(2, "gcffa --- OK, switching to Plan B");
     291            if (chdir(bkpinfo->tmpdir)) {
     292                // FIXME
     293            }
     294            run_program_and_log_output("mkdir -p tmp", FALSE);
     295
     296            if (bkpinfo->media_device == NULL) {
     297                mr_asprintf(bkpinfo->media_device, "%s", "/dev/st0");
     298                log_msg(2, "media_device is blank; assuming %s", bkpinfo->media_device);
     299            }
     300            mr_asprintf(tmp, "%s", bkpinfo->media_device);
     301            if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {
     302                mr_free(bkpinfo->media_device);
     303                mr_asprintf(bkpinfo->media_device, "%s", "/dev/st0");
     304                if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {
     305                    mr_free(bkpinfo->media_device);
     306                    mr_asprintf(bkpinfo->media_device, "%s", "/dev/osst0");
     307                    if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {
     308                        mr_free(bkpinfo->media_device);
     309                        mr_asprintf(bkpinfo->media_device, "%s", "/dev/ht0");
     310                        if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {
     311                            log_msg(3, "I tried lots of devices but none worked.");
     312                            mr_free(bkpinfo->media_device);
     313                        }
     314                    }
     315                }
     316            }
     317            if (bkpinfo->media_device == NULL) {
     318                bkpinfo->media_device = tmp;
     319            } else {
     320                mr_free(tmp);
     321            }
     322
     323            if (!does_file_exist("tmp/mondorestore.cfg")) {
     324                log_to_screen("Cannot find config info on media");
     325                return (1);
     326            }
     327        } else {
     328                if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
     329                    extract_mountlist_stub = FALSE;
     330                } else {
     331                    extract_mountlist_stub = TRUE;
     332                }
     333                if (does_file_exist("/"IWANTMYLVM_STUB)) {
     334                    extract_i_want_my_lvm = FALSE;
     335                } else {
     336                    extract_i_want_my_lvm = TRUE;
     337                }
     338
     339                log_msg(2, "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
     340                mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);    // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
     341                run_program_and_log_output(command, TRUE);
     342                mr_free(command);
     343
     344                if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
     345                    /* Doing that allow us to remain compatible with pre-2.2.5 versions */
     346                    log_msg(2, "pre-2.2.4 compatible mode on");
     347                    mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz %s %s %s %s %s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);  // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
     348                    run_program_and_log_output(command, TRUE);
     349                    mr_free(command);
     350                    if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
     351                        fatal_error
     352                            ("Please reinsert the disk/CD and try again.");
     353                    }
     354                }
     355        }
     356    }
     357    if (does_file_exist(MONDO_CFG_FILE_STUB)) {
     358        log_msg(1, "gcffa --- great! We've got the config file");
     359        tmp1 = call_program_and_get_last_line_of_output("pwd");
     360        mr_asprintf(tmp, "%s/%s", tmp1, MONDO_CFG_FILE_STUB);
     361        mr_asprintf(command, "cp -f %s %s", tmp, cfg_file);
     362        log_it("%s",command);
     363        if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) {
     364            log_msg(1,
     365                    "... but an error occurred when I tried to move it to %s",
     366                    cfg_file);
     367        } else {
     368            log_msg(1, "... and I moved it successfully to %s", cfg_file);
     369        }
     370        mr_free(command);
     371
     372        mr_asprintf(command, "cp -f %s/%s %s", tmp1, MOUNTLIST_FNAME_STUB, mountlist_file);
     373        mr_free(tmp1);
     374        log_it("%s",command);
     375        if (extract_mountlist_stub) {
     376            if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) {
     377                log_msg(1, "Failed to get mountlist");
     378            } else {
     379                log_msg(1, "Got mountlist too");
     380                mr_free(command);
     381                mr_asprintf(command, "cp -f %s %s", mountlist_file, g_mountlist_fname);
     382                if (run_program_and_log_output(command, 1)) {
     383                    log_msg(1, "Failed to copy mountlist to /tmp");
     384                } else {
     385                    log_msg(1, "Copied mountlist to /tmp as well OK");
     386                    mr_free(command);
     387                    mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
     388                    run_program_and_log_output(command, 1);
     389                }
     390            }
     391        }
     392        mr_free(command);
     393        mr_free(tmp);
     394    }
     395
     396    run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
     397    if (!does_file_exist(cfg_file)) {
     398        log_it("%s",cfg_file);
     399        log_msg(1, "%s not found", cfg_file);
     400        log_to_screen("Oh dear. Unable to recover configuration file from boot disk");
     401        return (1);
     402    }
     403
     404    log_to_screen("Recovered mondorestore.cfg");
     405    if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
     406        log_to_screen("...but not mountlist.txt - a pity, really...");
     407    } else {
     408            /* Is this code really useful ??? */
     409        if (extract_mountlist_stub) {
     410            mr_asprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
     411            run_program_and_log_output(command, FALSE);
     412            mr_free(command);
     413        }
     414    }
     415
     416    mr_asprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
     417    mr_free(cfg_file);
     418
     419    run_program_and_log_output(command, FALSE);
     420    mr_free(command);
     421
     422    if (extract_mountlist_stub) {
     423        mr_asprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
     424        run_program_and_log_output(command, FALSE);
     425        mr_free(command);
     426    }
     427    mr_free(mountlist_file);
     428
     429    mr_asprintf(command, "cp -f etc/raidtab /etc/");
     430    run_program_and_log_output(command, FALSE);
     431    mr_free(command);
     432
     433    if (extract_i_want_my_lvm) {
     434        mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
     435        run_program_and_log_output(command, FALSE);
     436        mr_free(command);
     437    }
     438    g_backup_media_type = bkpinfo->backup_media_type;
     439    return (retval);
     440}
     441
     442/**************************************************************************
     443 *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
     444 **************************************************************************/
    172445
    173446
     
    642915/** add mallocs **/
    643916char value[MAX_STR_LEN];
     917char *tmp = NULL;
    644918char *tmp1 = NULL;
    645919char *envtmp1 = NULL;
     
    683957                run_program_and_log_output("mount /dev/cdrom "MNT_CDROM, 1);
    684958            }
    685             if (does_file_exist(MNT_CDROM"/archives/filelist.0")) {
     959            if (does_file_exist(ARCHIVES_PATH "/filelist.0")) {
    686960                bkpinfo->backup_media_type = cdr;
    687961                run_program_and_log_output("umount -d "MNT_CDROM, 1);
     
    12841558
    12851559/**
    1286  * Install the user's boot loader in the MBR.
    1287  * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
    1288  * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
    1289  * @return 0 for success, nonzero for failure.
    1290  */
    1291 int run_boot_loader(bool offer_to_hack_scripts)
    1292 {
    1293     int res;
    1294     int retval = 0;
    1295 
    1296   /** malloc *******/
    1297     char *device = NULL;
    1298     char *disk = NULL;
    1299     char *name = NULL;
    1300     char *type = NULL;
    1301     char *cmd = NULL;
    1302 
    1303     malloc_string(device);
    1304     malloc_string(name);
    1305     malloc_string(type);
    1306 
    1307     /* In order to have a working bootloader, we need to have all devices
    1308      * ready in the chroot. If they are not there (udev) then copy them from
    1309      * the current /dev location
    1310      */
    1311     mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
    1312     run_program_and_log_output(cmd, 3);
    1313     mr_free(cmd);
    1314 
    1315     backup_crucial_file(MNT_RESTORING, "/etc/fstab");
    1316     backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
    1317     backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
    1318     backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg");
    1319     backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
    1320     backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
    1321     backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
    1322     backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map");
    1323     backup_crucial_file(MNT_RESTORING, "/etc/mtab");
    1324     read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
    1325     read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
    1326     read_cfg_var(g_mondo_cfg_file, "boot-type", type);
    1327     log_msg(2, "run_boot_loader: device='%s', name='%s', type='%s'", device, name, type);
    1328     sync();
    1329 
    1330     offer_to_make_initrd();
    1331 
    1332     disk = truncate_to_drive_name(device);
    1333     if (strcmp(type,"BIOS") == 0) {
    1334         // Force installation of a MBR bootloader brought by mindi on the disk
    1335         // in case none was available and we then start from a partition
    1336         log_msg(2, "Reinstalling mbr.bin on %s", disk);
    1337         mr_system("dd bs=440 count=1 conv=notrunc if=/tmp/mbr.bin of=%s &> /dev/null",disk);
    1338     } else {
    1339         // Same for GPT
    1340         log_msg(2, "Reinstalling gptmbr.bin on %s", disk);
    1341         mr_system("dd bs=440 count=1 conv=notrunc if=/tmp/gptmbr.bin of=%s &> /dev/null",disk);
    1342     }
    1343 
    1344     // Now reinstall bootloader
    1345     if (!strcmp(name, "LILO")) {
    1346         res = run_lilo(offer_to_hack_scripts);
    1347     } else if (!strcmp(name, "ELILO")) {
    1348         res = run_elilo(offer_to_hack_scripts);
    1349     } else if (!strcmp(name, "GRUB")) {
    1350         res = run_grub(offer_to_hack_scripts, device);
    1351     } else if (!strcmp(name, "RAW")) {
    1352         res = run_raw_mbr(offer_to_hack_scripts, device);
    1353     }
    1354 #ifdef __FreeBSD__
    1355     else if (!strcmp(name, "BOOT0")) {
    1356         mr_asprintf(tmp, "boot0cfg -B %s", device);
    1357         res = run_program_and_log_output(tmp, FALSE);
    1358         paranoid_free(tmp);
    1359     } else {
    1360         mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
    1361         if (!system(tmp)) {
    1362             mr_free(tmp);
    1363             mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
    1364             res = run_program_and_log_output(tmp, 3);
    1365         } else {
    1366             log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
    1367         }
    1368         mr_free(tmp);
    1369     }
    1370 #else
    1371     else {
    1372         log_to_screen
    1373             ("Unable to determine type of boot loader. Defaulting to LILO.");
    1374         res = run_lilo(offer_to_hack_scripts);
    1375     }
    1376 #endif
    1377     retval += res;
    1378     if (res) {
    1379         log_to_screen("Your boot loader returned an error");
    1380     } else {
    1381         log_to_screen("Your boot loader ran OK");
    1382     }
    1383     paranoid_free(device);
    1384     paranoid_free(name);
    1385     return (retval);
    1386 }
    1387 
    1388 /**************************************************************************
    1389  *END_ RUN_BOOT_LOADER                                                    *
    1390  **************************************************************************/
    1391 
    1392 
    1393 
    1394 /**
    13951560 * Attempt to find the user's editor.
    13961561 * @return The editor found ("vi" if none could be found).
     
    14171582    return (output);
    14181583}
     1584
     1585
     1586
     1587
     1588/**
     1589 * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
     1590 * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
     1591 * @return 0 for success, nonzero for failure.
     1592 */
     1593int run_lilo(bool offer_to_run_stablilo)
     1594{
     1595  /** malloc **/
     1596    char *command = NULL;
     1597    char *tmp = NULL;
     1598    char *editor = NULL;
     1599
     1600    int res;
     1601    int done;
     1602    bool run_lilo_M = FALSE;
     1603
     1604    if (!run_program_and_log_output
     1605        ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
     1606        run_lilo_M = TRUE;
     1607    }
     1608
     1609    if (offer_to_run_stablilo
     1610        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
     1611
     1612        /* interactive mode */
     1613    {
     1614        mvaddstr_and_log_it(g_currentY,
     1615                            0,
     1616                            "Modifying fstab and lilo.conf, and running LILO...                             ");
     1617        mr_asprintf(command, "mr-stablilo-me");
     1618        res = run_program_and_log_output(command, 3);
     1619        mr_free(command);
     1620
     1621        if (res) {
     1622            popup_and_OK
     1623                ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
     1624            for (done = FALSE; !done;) {
     1625                editor = find_my_editor();
     1626                if (editor == NULL) {
     1627                    popup_and_OK("No editor found. You won't be able to edit conf files");
     1628                } else {
     1629                    if (!g_text_mode) {
     1630                        newtSuspend();
     1631                    }
     1632                    mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
     1633                    paranoid_system(tmp);
     1634                    mr_free(tmp);
     1635   
     1636                    mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
     1637                    paranoid_system(tmp);
     1638                    mr_free(tmp);
     1639                    mr_free(editor);
     1640   
     1641                    if (!g_text_mode) {
     1642                        newtResume();
     1643                    }
     1644//              newtCls();
     1645                    if (ask_me_yes_or_no("Edit them again?")) {
     1646                        continue;
     1647                    }
     1648                }
     1649                mr_free(editor);
     1650
     1651                res = run_program_and_log_output("chroot " MNT_RESTORING " lilo -L", 3);
     1652                if (res) {
     1653                    res = run_program_and_log_output("chroot " MNT_RESTORING " lilo", 3);
     1654                }
     1655                if (res) {
     1656                    done = ask_me_yes_or_no("LILO failed. Re-edit system files?");
     1657                } else {
     1658                    done = TRUE;
     1659                }
     1660            }
     1661        } else {
     1662            log_to_screen("lilo.conf and fstab were modified OK");
     1663        }
     1664    } else
     1665        /* nuke mode */
     1666    {
     1667        mvaddstr_and_log_it(g_currentY,
     1668                            0,
     1669                            "Running LILO...                                                 ");
     1670        res =
     1671            run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
     1672                                       3);
     1673        if (res) {
     1674            res =
     1675                run_program_and_log_output("chroot " MNT_RESTORING " lilo",
     1676                                           3);
     1677        }
     1678        if (res) {
     1679            mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
     1680            log_to_screen
     1681                ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
     1682        } else {
     1683            mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     1684        }
     1685    }
     1686    if (run_lilo_M) {
     1687        run_program_and_log_output("chroot " MNT_RESTORING
     1688                                   " lilo -M /dev/hda", 3);
     1689        run_program_and_log_output("chroot " MNT_RESTORING
     1690                                   " lilo -M /dev/sda", 3);
     1691    }
     1692    return (res);
     1693}
     1694
     1695/**************************************************************************
     1696 *END_RUN_LILO                                                            *
     1697 **************************************************************************/
     1698
     1699
     1700/**
     1701 * Install a raw MBR onto @p bd.
     1702 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
     1703 * @param bd The device to copy the stored MBR to.
     1704 * @return 0 for success, nonzero for failure.
     1705 */
     1706int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
     1707{
     1708  /** malloc **/
     1709    char *command = NULL;
     1710    char *boot_device = NULL;
     1711    char *tmp = NULL;
     1712    char *editor;
     1713    int res;
     1714    int done;
     1715
     1716    malloc_string(boot_device);
     1717    assert_string_is_neither_NULL_nor_zerolength(bd);
     1718
     1719    strcpy(boot_device, bd);
     1720
     1721    if (offer_to_hack_scripts
     1722        && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
     1723        /* interactive mode */
     1724        mvaddstr_and_log_it(g_currentY, 0, "Modifying fstab and restoring MBR...                           ");
     1725        for (done = FALSE; !done;) {
     1726            popup_and_OK("You will now edit fstab");
     1727            editor = find_my_editor();
     1728            if (editor == NULL) {
     1729                popup_and_OK("No editor found. You won't be able to edit conf files");
     1730            } else {
     1731                if (!g_text_mode) {
     1732                    newtSuspend();
     1733                }
     1734                mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
     1735
     1736                paranoid_system(tmp);
     1737                mr_free(tmp);
     1738                if (!g_text_mode) {
     1739                    newtResume();
     1740                }
     1741            }
     1742            mr_free(editor);
     1743
     1744            popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4);
     1745            mr_asprintf(command, "mr-stabraw-me %s", boot_device);
     1746            res = run_program_and_log_output(command, 3);
     1747            mr_free(command);
     1748
     1749            if (res) {
     1750                done = ask_me_yes_or_no("Modifications failed. Re-try?");
     1751            } else {
     1752                done = TRUE;
     1753            }
     1754        }
     1755    } else {
     1756        /* nuke mode */
     1757        mr_asprintf(command, "mr-raw %s /"MOUNTLIST_FNAME_STUB, boot_device);
     1758        log_msg(2, "run_raw_mbr() --- command='%s'", command);
     1759
     1760        mvaddstr_and_log_it(g_currentY, 0, "Restoring MBR...                                               ");
     1761        res = run_program_and_log_output(command, 3);
     1762        mr_free(command);
     1763    }
     1764    if (res) {
     1765        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
     1766        log_to_screen("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
     1767    } else {
     1768        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     1769    }
     1770    paranoid_free(boot_device);
     1771    return (res);
     1772}
     1773
     1774/**************************************************************************
     1775 *END_RUN_RAW_MBR                                                         *
     1776 **************************************************************************/
    14191777
    14201778
     
    14651823                    popup_and_OK("The mountlist was changed. You will now edit fstab, mtab, device.map and menu.lst/grub.cfg in order to fix grub install");
    14661824                }
    1467                 editor = find_my_editor());
     1825                editor = find_my_editor();
    14681826                if (editor == NULL) {
    14691827                    popup_and_OK("No editor found. You won't be able to edit conf files");
     
    16442002
    16452003
    1646 /**
    1647  * Install LILO on the user's boot drive (determined by /etc/lilo.conf).
    1648  * @param offer_to_run_stablilo If TRUE, then offer to hack the user's fstab for them.
     2004
     2005/**
     2006 * Install the user's boot loader in the MBR.
     2007 * Currently LILO, ELILO, GRUB, RAW (dd of MBR), and the FreeBSD bootloader are supported.
     2008 * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
    16492009 * @return 0 for success, nonzero for failure.
    16502010 */
    1651 int run_lilo(bool offer_to_run_stablilo)
     2011int run_boot_loader(bool offer_to_hack_scripts)
    16522012{
    1653   /** malloc **/
    1654     char *command = NULL;
    1655     char *tmp = NULL;
    1656     char *editor = NULL;
    1657 
    16582013    int res;
    1659     int done;
    1660     bool run_lilo_M = FALSE;
    1661 
    1662     if (!run_program_and_log_output
    1663         ("grep \"boot.*=.*/dev/md\" " MNT_RESTORING "/etc/lilo.conf", 1)) {
    1664         run_lilo_M = TRUE;
    1665     }
    1666 
    1667     if (offer_to_run_stablilo
    1668         && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?"))
    1669 
    1670         /* interactive mode */
    1671     {
    1672         mvaddstr_and_log_it(g_currentY,
    1673                             0,
    1674                             "Modifying fstab and lilo.conf, and running LILO...                             ");
    1675         mr_asprintf(command, "mr-stablilo-me");
    1676         res = run_program_and_log_output(command, 3);
    1677         mr_free(command);
    1678 
    1679         if (res) {
    1680             popup_and_OK
    1681                 ("You will now edit fstab and lilo.conf, to make sure they match your new mountlist.");
    1682             for (done = FALSE; !done;) {
    1683                 editor = find_my_editor();
    1684                 if (editor == NULL) {
    1685                     popup_and_OK("No editor found. You won't be able to edit conf files");
    1686                 } else {
    1687                     if (!g_text_mode) {
    1688                         newtSuspend();
    1689                     }
    1690                     mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
    1691                     paranoid_system(tmp);
    1692                     mr_free(tmp);
    1693    
    1694                     mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/lilo.conf", editor);
    1695                     paranoid_system(tmp);
    1696                     mr_free(tmp);
    1697                     mr_free(editor);
    1698    
    1699                     if (!g_text_mode) {
    1700                         newtResume();
    1701                     }
    1702 //              newtCls();
    1703                     if (ask_me_yes_or_no("Edit them again?")) {
    1704                         continue;
    1705                     }
    1706                 }
    1707                 mr_free(editor);
    1708 
    1709                 res = run_program_and_log_output("chroot " MNT_RESTORING " lilo -L", 3);
    1710                 if (res) {
    1711                     res = run_program_and_log_output("chroot " MNT_RESTORING " lilo", 3);
    1712                 }
    1713                 if (res) {
    1714                     done = ask_me_yes_or_no("LILO failed. Re-edit system files?");
    1715                 } else {
    1716                     done = TRUE;
    1717                 }
    1718             }
     2014    int retval = 0;
     2015
     2016  /** malloc *******/
     2017    char *device = NULL;
     2018    char *disk = NULL;
     2019    char *name = NULL;
     2020    char *type = NULL;
     2021    char *cmd = NULL;
     2022
     2023    malloc_string(device);
     2024    malloc_string(name);
     2025    malloc_string(type);
     2026
     2027    /* In order to have a working bootloader, we need to have all devices
     2028     * ready in the chroot. If they are not there (udev) then copy them from
     2029     * the current /dev location
     2030     */
     2031    mr_asprintf(cmd,"tar cf - /dev | ( cd %s ; tar xf - )",MNT_RESTORING);
     2032    run_program_and_log_output(cmd, 3);
     2033    mr_free(cmd);
     2034
     2035    backup_crucial_file(MNT_RESTORING, "/etc/fstab");
     2036    backup_crucial_file(MNT_RESTORING, "/boot/grub/menu.lst");
     2037    backup_crucial_file(MNT_RESTORING, "/boot/grub/grub.cfg");
     2038    backup_crucial_file(MNT_RESTORING, "/boot/grub2/grub.cfg");
     2039    backup_crucial_file(MNT_RESTORING, "/etc/lilo.conf");
     2040    backup_crucial_file(MNT_RESTORING, "/etc/elilo.conf");
     2041    backup_crucial_file(MNT_RESTORING, "/boot/grub/device.map");
     2042    backup_crucial_file(MNT_RESTORING, "/boot/grub2/device.map");
     2043    backup_crucial_file(MNT_RESTORING, "/etc/mtab");
     2044    read_cfg_var(g_mondo_cfg_file, "bootloader.device", device);
     2045    read_cfg_var(g_mondo_cfg_file, "bootloader.name", name);
     2046    read_cfg_var(g_mondo_cfg_file, "boot-type", type);
     2047    log_msg(2, "run_boot_loader: device='%s', name='%s', type='%s'", device, name, type);
     2048    sync();
     2049
     2050    offer_to_make_initrd();
     2051
     2052    disk = truncate_to_drive_name(device);
     2053    if (strcmp(type,"BIOS") == 0) {
     2054        // Force installation of a MBR bootloader brought by mindi on the disk
     2055        // in case none was available and we then start from a partition
     2056        log_msg(2, "Reinstalling mbr.bin on %s", disk);
     2057        mr_system("dd bs=440 count=1 conv=notrunc if=/tmp/mbr.bin of=%s &> /dev/null",disk);
     2058    } else {
     2059        // Same for GPT
     2060        log_msg(2, "Reinstalling gptmbr.bin on %s", disk);
     2061        mr_system("dd bs=440 count=1 conv=notrunc if=/tmp/gptmbr.bin of=%s &> /dev/null",disk);
     2062    }
     2063
     2064    // Now reinstall bootloader
     2065    if (!strcmp(name, "LILO")) {
     2066        res = run_lilo(offer_to_hack_scripts);
     2067    } else if (!strcmp(name, "ELILO")) {
     2068        res = run_elilo(offer_to_hack_scripts);
     2069    } else if (!strcmp(name, "GRUB")) {
     2070        res = run_grub(offer_to_hack_scripts, device);
     2071    } else if (!strcmp(name, "RAW")) {
     2072        res = run_raw_mbr(offer_to_hack_scripts, device);
     2073    }
     2074#ifdef __FreeBSD__
     2075    else if (!strcmp(name, "BOOT0")) {
     2076        mr_asprintf(tmp, "boot0cfg -B %s", device);
     2077        res = run_program_and_log_output(tmp, FALSE);
     2078        paranoid_free(tmp);
     2079    } else {
     2080        mr_asprintf(tmp, "ls /dev | grep -Eq '^%ss[1-4].*'", device);
     2081        if (!system(tmp)) {
     2082            mr_free(tmp);
     2083            mr_asprintf(tmp, MNT_RESTORING "/sbin/fdisk -B %s", device);
     2084            res = run_program_and_log_output(tmp, 3);
    17192085        } else {
    1720             log_to_screen("lilo.conf and fstab were modified OK");
    1721         }
    1722     } else
    1723         /* nuke mode */
    1724     {
    1725         mvaddstr_and_log_it(g_currentY,
    1726                             0,
    1727                             "Running LILO...                                                 ");
    1728         res =
    1729             run_program_and_log_output("chroot " MNT_RESTORING " lilo -L",
    1730                                        3);
    1731         if (res) {
    1732             res =
    1733                 run_program_and_log_output("chroot " MNT_RESTORING " lilo",
    1734                                            3);
    1735         }
    1736         if (res) {
    1737             mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
    1738             log_to_screen
    1739                 ("Failed to re-jig fstab and/or lilo. Edit/run manually, please.");
    1740         } else {
    1741             mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    1742         }
    1743     }
    1744     if (run_lilo_M) {
    1745         run_program_and_log_output("chroot " MNT_RESTORING
    1746                                    " lilo -M /dev/hda", 3);
    1747         run_program_and_log_output("chroot " MNT_RESTORING
    1748                                    " lilo -M /dev/sda", 3);
    1749     }
    1750     return (res);
     2086            log_msg(1, "I'm not running any boot loader. You have a DD boot drive. It's already loaded up.");
     2087        }
     2088        mr_free(tmp);
     2089    }
     2090#else
     2091    else {
     2092        log_to_screen
     2093            ("Unable to determine type of boot loader. Defaulting to LILO.");
     2094        res = run_lilo(offer_to_hack_scripts);
     2095    }
     2096#endif
     2097    retval += res;
     2098    if (res) {
     2099        log_to_screen("Your boot loader returned an error");
     2100    } else {
     2101        log_to_screen("Your boot loader ran OK");
     2102    }
     2103    paranoid_free(device);
     2104    paranoid_free(name);
     2105    return (retval);
    17512106}
    17522107
    17532108/**************************************************************************
    1754  *END_RUN_LILO                                                            *
    1755  **************************************************************************/
    1756 
    1757 
    1758 /**
    1759  * Install a raw MBR onto @p bd.
    1760  * @param offer_to_hack_scripts If TRUE, then offer to hack the user's fstab for them.
    1761  * @param bd The device to copy the stored MBR to.
    1762  * @return 0 for success, nonzero for failure.
    1763  */
    1764 int run_raw_mbr(bool offer_to_hack_scripts, char *bd)
    1765 {
    1766   /** malloc **/
    1767     char *command = NULL;
    1768     char *boot_device = NULL;
    1769     char *tmp = NULL;
    1770     char *editor;
    1771     int res;
    1772     int done;
    1773 
    1774     malloc_string(boot_device);
    1775     assert_string_is_neither_NULL_nor_zerolength(bd);
    1776 
    1777     strcpy(boot_device, bd);
    1778 
    1779     if (offer_to_hack_scripts
    1780         && ask_me_yes_or_no("Did you change the mountlist or cloned the system ?")) {
    1781         /* interactive mode */
    1782         mvaddstr_and_log_it(g_currentY, 0, "Modifying fstab and restoring MBR...                           ");
    1783         for (done = FALSE; !done;) {
    1784             popup_and_OK("You will now edit fstab");
    1785             editor = find_my_editor());
    1786             if (editor == NULL) {
    1787                 popup_and_OK("No editor found. You won't be able to edit conf files");
    1788             } else {
    1789                 if (!g_text_mode) {
    1790                     newtSuspend();
    1791                 }
    1792                 mr_asprintf(tmp, "%s " MNT_RESTORING "/etc/fstab", editor);
    1793 
    1794                 paranoid_system(tmp);
    1795                 mr_free(tmp);
    1796                 if (!g_text_mode) {
    1797                     newtResume();
    1798                 }
    1799             }
    1800             mr_free(editor);
    1801 
    1802             popup_and_get_string("Boot device", "Please confirm/enter the boot device. If in doubt, try /dev/hda", boot_device, MAX_STR_LEN / 4);
    1803             mr_asprintf(command, "mr-stabraw-me %s", boot_device);
    1804             res = run_program_and_log_output(command, 3);
    1805             mr_free(command);
    1806 
    1807             if (res) {
    1808                 done = ask_me_yes_or_no("Modifications failed. Re-try?");
    1809             } else {
    1810                 done = TRUE;
    1811             }
    1812         }
    1813     } else {
    1814         /* nuke mode */
    1815         mr_asprintf(command, "mr-raw %s /"MOUNTLIST_FNAME_STUB, boot_device);
    1816         log_msg(2, "run_raw_mbr() --- command='%s'", command);
    1817 
    1818         mvaddstr_and_log_it(g_currentY, 0, "Restoring MBR...                                               ");
    1819         res = run_program_and_log_output(command, 3);
    1820         mr_free(command);
    1821     }
    1822     if (res) {
    1823         mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
    1824         log_to_screen("MBR+fstab processed w/error(s). See %s for more info.", MONDO_LOGFILE);
    1825     } else {
    1826         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    1827     }
    1828     paranoid_free(boot_device);
    1829     return (res);
    1830 }
    1831 
    1832 /**************************************************************************
    1833  *END_RUN_RAW_MBR                                                         *
     2109 *END_ RUN_BOOT_LOADER                                                    *
    18342110 **************************************************************************/
    18352111
     
    20682344 *END_UNMOUNT_ALL_DEVICES                                                 *
    20692345 **************************************************************************/
    2070 
    2071 /**
    2072  * Extract mondorestore.cfg and the mountlist from the tape inserted
    2073  * to the ./tmp/ directory.
    2074  * @param dev The tape device to read from.
    2075  * @return 0 for success, nonzero for failure.
    2076  */
    2077 int extract_cfg_file_and_mountlist_from_tape_dev(char *dev)
    2078 {
    2079     char *command = NULL;
    2080     int res = 0;
    2081 
    2082     if (bkpinfo->use_obdr) {
    2083         skip_obdr();
    2084     } else {
    2085         // TODO: below 32KB seems to block at least on RHAS 2.1 and MDK 10.0
    2086         set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
    2087     }
    2088 
    2089     mr_asprintf(command, "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx ./%s ./%s ./%s ./%s ./%s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
    2090     log_msg(2, "command = '%s'", command);
    2091     res = run_program_and_log_output(command, -1);
    2092     mr_free(command);
    2093 
    2094     if (res != 0) {
    2095         if (does_file_exist(MONDO_CFG_FILE_STUB)) {
    2096             res = 0;
    2097         } else {
    2098             /* Doing that allow us to remain compatible with pre-2.2.5 versions */
    2099             log_msg(2, "pre-2.2.4 compatible mode on");
    2100             mr_asprintf(command,    "dd if=%s bs=%ld count=%ld 2> /dev/null | tar -zx %s %s %s %s %s", dev, bkpinfo->internal_tape_block_size, 1024L * 1024 * 32 / bkpinfo->internal_tape_block_size, MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);
    2101             log_msg(2, "command = '%s'", command);
    2102             res = run_program_and_log_output(command, -1);
    2103             mr_free(command);
    2104             if ((res != 0) && (does_file_exist(MONDO_CFG_FILE_STUB))) {
    2105                 res = 0;
    2106             }
    2107         }
    2108     }
    2109     paranoid_free(command);
    2110     return (res);
    2111 }
    2112 
    2113 
    2114 /**
    2115  * Get the configuration file from the tape, or CD.
    2116  * @param bkpinfo The backup information structure. Fields used:
    2117  * - @c bkpinfo->backup_media_type
    2118  * - @c bkpinfo->media_device
    2119  * - @c bkpinfo->tmpdir
    2120  * @return 0 for success, nonzero for failure.
    2121  */
    2122 int get_cfg_file_from_archive()
    2123 {
    2124     int retval = 0;
    2125 
    2126    /** malloc *****/
    2127     char *command = NULL;
    2128     char *cfg_file = NULL;
    2129     char *tmp = NULL;
    2130     char *tmp1 = NULL;
    2131     char *mountpt = NULL;
    2132     char *mountlist_file = NULL;
    2133     bool extract_mountlist_stub = FALSE;
    2134     bool extract_i_want_my_lvm = FALSE;
    2135 
    2136     bool try_plan_B;
    2137 
    2138     assert(bkpinfo != NULL);
    2139     log_msg(2, "gcffa --- starting");
    2140     log_to_screen("I'm thinking...");
    2141     mr_asprintf(mountpt, "%s/mount.bootdisk", bkpinfo->tmpdir);
    2142     if (chdir(bkpinfo->tmpdir)) {
    2143         // FIXME
    2144     }
    2145     mr_asprintf(cfg_file, "%s", MONDO_CFG_FILE_STUB);
    2146     unlink(cfg_file);           // cfg_file[] is missing the '/' at the start, FYI, by intent
    2147     mr_free(cfg_file);
    2148 
    2149     unlink(FILELIST_FULL_STUB);
    2150     unlink(BIGGIELIST_TXT_STUB);
    2151     mr_asprintf(command, "mkdir -p %s", mountpt);
    2152     run_program_and_log_output(command, FALSE);
    2153     mr_free(command);
    2154 
    2155     mr_asprintf(cfg_file, "%s/%s", bkpinfo->tmpdir, MONDO_CFG_FILE_STUB);
    2156     mr_asprintf(mountlist_file, "%s/%s", bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
    2157     log_msg(2, "mountpt = %s; cfg_file=%s", mountpt, cfg_file);
    2158     mr_free(mountpt);
    2159 
    2160     if (!does_file_exist(cfg_file)) {
    2161         log_msg(2, "gcffa --- we don't have cfg file yet.");
    2162         if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    2163             try_plan_B = TRUE;
    2164         } else {
    2165             log_msg(2, "gcffa --- calling mount_media now :)");
    2166             if (!mount_media(MNT_CDROM)) {
    2167                 log_msg(2, "gcffa --- managed to mount CD; so, no need for Plan B");
    2168                 try_plan_B = FALSE;
    2169             } else {
    2170                 try_plan_B = TRUE;
    2171             }
    2172             if (what_number_cd_is_this() > 1) {
    2173                 insist_on_this_cd_number((g_current_media_number = 1));
    2174             }
    2175         }
    2176         if (try_plan_B) {
    2177             log_msg(2, "gcffa --- OK, switching to Plan B");
    2178             if (chdir(bkpinfo->tmpdir)) {
    2179                 // FIXME
    2180             }
    2181             run_program_and_log_output("mkdir -p tmp", FALSE);
    2182 
    2183             if (bkpinfo->media_device == NULL) {
    2184                 mr_asprintf(bkpinfo->media_device, "%s", "/dev/st0");
    2185                 log_msg(2, "media_device is blank; assuming %s", bkpinfo->media_device);
    2186             }
    2187             mr_asprintf(tmp, "%s", bkpinfo->media_device);
    2188             if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {
    2189                 mr_free(bkpinfo->media_device);
    2190                 mr_asprintf(bkpinfo->media_device, "%s", "/dev/st0");
    2191                 if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {
    2192                     mr_free(bkpinfo->media_device);
    2193                     mr_asprintf(bkpinfo->media_device, "%s", "/dev/osst0");
    2194                     if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {
    2195                         mr_free(bkpinfo->media_device);
    2196                         mr_asprintf(bkpinfo->media_device, "%s", "/dev/ht0");
    2197                         if (extract_cfg_file_and_mountlist_from_tape_dev(bkpinfo->media_device)) {
    2198                             log_msg(3, "I tried lots of devices but none worked.");
    2199                             mr_free(bkpinfo->media_device);
    2200                         }
    2201                     }
    2202                 }
    2203             }
    2204             if (bkpinfo->media_device == NULL) {
    2205                 bkpinfo->media_device = tmp;
    2206             } else {
    2207                 mr_free(tmp);
    2208             }
    2209 
    2210             if (!does_file_exist("tmp/mondorestore.cfg")) {
    2211                 log_to_screen("Cannot find config info on media");
    2212                 return (1);
    2213             }
    2214         } else {
    2215                 if (does_file_exist("/"MOUNTLIST_FNAME_STUB)) {
    2216                     extract_mountlist_stub = FALSE;
    2217                 } else {
    2218                     extract_mountlist_stub = TRUE;
    2219                 }
    2220                 if (does_file_exist("/"IWANTMYLVM_STUB)) {
    2221                     extract_i_want_my_lvm = FALSE;
    2222                 } else {
    2223                     extract_i_want_my_lvm = TRUE;
    2224                 }
    2225 
    2226                 log_msg(2, "gcffa --- Plan B, a.k.a. untarring some file from all.tar.gz");
    2227                 mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz ./%s ./%s ./%s ./%s ./%s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);    // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
    2228                 run_program_and_log_output(command, TRUE);
    2229                 mr_free(command);
    2230 
    2231                 if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
    2232                     /* Doing that allow us to remain compatible with pre-2.2.5 versions */
    2233                     log_msg(2, "pre-2.2.4 compatible mode on");
    2234                     mr_asprintf(command, "tar -zxvf " MNT_CDROM "/images/all.tar.gz %s %s %s %s %s", MOUNTLIST_FNAME_STUB, MONDO_CFG_FILE_STUB, BIGGIELIST_TXT_STUB, FILELIST_FULL_STUB, IWANTMYLVM_STUB);  // add -b TAPE_BLOCK_SIZE if you _really_ think it's necessary
    2235                     run_program_and_log_output(command, TRUE);
    2236                     mr_free(command);
    2237                     if (!does_file_exist(MONDO_CFG_FILE_STUB)) {
    2238                         fatal_error
    2239                             ("Please reinsert the disk/CD and try again.");
    2240                     }
    2241                 }
    2242         }
    2243     }
    2244     if (does_file_exist(MONDO_CFG_FILE_STUB)) {
    2245         log_msg(1, "gcffa --- great! We've got the config file");
    2246         tmp1 = call_program_and_get_last_line_of_output("pwd");
    2247         mr_asprintf(tmp, "%s/%s", tmp1, MONDO_CFG_FILE_STUB);
    2248         mr_asprintf(command, "cp -f %s %s", tmp, cfg_file);
    2249         log_it("%s",command);
    2250         if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) {
    2251             log_msg(1,
    2252                     "... but an error occurred when I tried to move it to %s",
    2253                     cfg_file);
    2254         } else {
    2255             log_msg(1, "... and I moved it successfully to %s", cfg_file);
    2256         }
    2257         mr_free(command);
    2258 
    2259         mr_asprintf(command, "cp -f %s/%s %s", tmp1, MOUNTLIST_FNAME_STUB, mountlist_file);
    2260         mr_free(tmp1);
    2261         log_it("%s",command);
    2262         if (extract_mountlist_stub) {
    2263             if (strcmp(tmp, cfg_file) && run_program_and_log_output(command, 1)) {
    2264                 log_msg(1, "Failed to get mountlist");
    2265             } else {
    2266                 log_msg(1, "Got mountlist too");
    2267                 mr_free(command);
    2268                 mr_asprintf(command, "cp -f %s %s", mountlist_file, g_mountlist_fname);
    2269                 if (run_program_and_log_output(command, 1)) {
    2270                     log_msg(1, "Failed to copy mountlist to /tmp");
    2271                 } else {
    2272                     log_msg(1, "Copied mountlist to /tmp as well OK");
    2273                     mr_free(command);
    2274                     mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
    2275                     run_program_and_log_output(command, 1);
    2276                 }
    2277             }
    2278         }
    2279         mr_free(command);
    2280         mr_free(tmp);
    2281     }
    2282 
    2283     run_program_and_log_output("umount -d " MNT_CDROM, FALSE);
    2284     if (!does_file_exist(cfg_file)) {
    2285         log_it("%s",cfg_file);
    2286         log_msg(1, "%s not found", cfg_file);
    2287         log_to_screen("Oh dear. Unable to recover configuration file from boot disk");
    2288         return (1);
    2289     }
    2290 
    2291     log_to_screen("Recovered mondorestore.cfg");
    2292     if (!does_file_exist(MOUNTLIST_FNAME_STUB)) {
    2293         log_to_screen("...but not mountlist.txt - a pity, really...");
    2294     } else {
    2295             /* Is this code really useful ??? */
    2296         if (extract_mountlist_stub) {
    2297             mr_asprintf(command, "cp -f %s %s/%s", MOUNTLIST_FNAME_STUB, bkpinfo->tmpdir, MOUNTLIST_FNAME_STUB);
    2298             run_program_and_log_output(command, FALSE);
    2299             mr_free(command);
    2300         }
    2301     }
    2302 
    2303     mr_asprintf(command, "cp -f %s /%s", cfg_file, MONDO_CFG_FILE_STUB);
    2304     mr_free(cfg_file);
    2305 
    2306     run_program_and_log_output(command, FALSE);
    2307     mr_free(command);
    2308 
    2309     if (extract_mountlist_stub) {
    2310         mr_asprintf(command, "cp -f %s /%s", mountlist_file, MOUNTLIST_FNAME_STUB);
    2311         run_program_and_log_output(command, FALSE);
    2312         mr_free(command);
    2313     }
    2314     mr_free(mountlist_file);
    2315 
    2316     mr_asprintf(command, "cp -f etc/raidtab /etc/");
    2317     run_program_and_log_output(command, FALSE);
    2318     mr_free(command);
    2319 
    2320     if (extract_i_want_my_lvm) {
    2321         mr_asprintf(command, "cp -f %s /tmp/",IWANTMYLVM_STUB);
    2322         run_program_and_log_output(command, FALSE);
    2323         mr_free(command);
    2324     }
    2325     g_backup_media_type = bkpinfo->backup_media_type;
    2326     return (retval);
    2327 }
    2328 
    2329 /**************************************************************************
    2330  *END_GET_CFG_FILE_FROM_ARCHIVE                                           *
    2331  **************************************************************************/
    2332 
    23332346/* @} - end restoreUtilityGroup */
    23342347
  • branches/3.3/mondo/src/mondorestore/mondorestore.c

    r3876 r3879  
    1313#include "mr_mem.h"
    1414#include "mr_file.h"
    15 #include "../common/mondostructures.h"
    16 #include "../common/libmondo.h"
    17 #include "mr-externs.h"
     15#include "mondostructures.h"
    1816#include "mondorestore.h"
    1917#include "mr_msg.h"
     
    2119#include "mondo-rstr-tools-EXT.h"
    2220#include "libmondo-mountlist-EXT.h"
     21#include "libmondo-tools-EXT.h"
     22#include "libmondo-gui-EXT.h"
     23#include "libmondo-devices-EXT.h"
     24#include "libmondo-fork-EXT.h"
     25#include "libmondo-string-EXT.h"
     26#include "libmondo-archive-EXT.h"
     27#include "libmondo-raid-EXT.h"
     28#include "libmondo-filelist-EXT.h"
     29#include "libmondo-files-EXT.h"
     30#include "libmondo-stream-EXT.h"
     31#include "libmondo-cli-EXT.h"
    2332#include "newt-specific-EXT.h"
    2433
    2534extern void wait_until_software_raids_are_prepped(char *, int);
    2635extern void twenty_seconds_til_yikes(void);
     36// in mondo-prep.c
     37extern void resize_mountlist_proportionately_to_suit_new_drives(struct mountlist_itself *);
     38extern int format_everything(struct mountlist_itself *, bool , struct raidlist_itself *);
     39extern int partition_everything(struct mountlist_itself *);
     40extern int fput_string_one_char_at_a_time(FILE *, char *);
     41extern int do_my_funky_lvm_stuff(bool, bool );
     42extern int stop_all_raid_devices(struct mountlist_itself *);
     43
     44// in mondo-rstr-newt.c
     45extern int edit_mountlist(char *, struct mountlist_itself *, struct raidlist_itself *);
     46
     47// from libmondo-devices.c
     48extern bool g_restoring_live_from_cd;
     49extern bool g_restoring_live_from_netfs;
     50
     51extern int g_currentY;
    2752
    2853/* We don't have a cleanup function yet */
     
    5378extern int g_partition_table_locked_up;
    5479extern int g_noof_rows;
    55 
    56 extern int partition_everything(struct mountlist_itself *mountlist);
    57 extern int handle_incoming_parameters(int argc, char *argv[]);
     80extern int g_current_media_number;
    5881
    5982/**
     
    121144char *g_getfattr;
    122145
     146extern long g_current_progress;
     147extern int g_currentY;
     148extern int g_current_media_number;
     149
     150
    123151/* @} - end of "Restore-Time Globals" in globalGroup */
    124152
    125 
    126 
    127 extern int copy_from_src_to_dest(FILE * f_orig, FILE * f_archived,
    128                                  char direction);
    129153
    130154
     
    580604                just_changed_cds = FALSE;
    581605                log_msg(3, "I'll continue to scan this CD for bigfiles to be restored.");
    582             } else if (does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")) {
     606            } else if (does_file_exist(ARCHIVES_PATH "/NOT-THE-LAST")) {
    583607                insist_on_this_cd_number(++g_current_media_number);
    584608                log_to_screen("Restoring from %s #%d", mds, g_current_media_number);
     
    691715    paranoid_free(command);
    692716
    693     mr_asprintf(filelist_name, MNT_CDROM "/archives/filelist.%ld", current_tarball_number);
     717    mr_asprintf(filelist_name, ARCHIVES_PATH "/filelist.%ld", current_tarball_number);
    694718    if (length_of_file(filelist_name) <= 2) {
    695719        log_msg(2, "There are _zero_ files in filelist '%s'", filelist_name);
     
    726750    if (filelist == NULL || matches > 0) {
    727751        if (g_getfattr) {
    728             mr_asprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives", current_tarball_number);
     752            mr_asprintf(xattr_fname, XATTR_LIST_FNAME_RAW_SZ, ARCHIVES_PATH, current_tarball_number);
    729753        }
    730754        if (g_getfacl) {
    731             mr_asprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, MNT_CDROM "/archives", current_tarball_number);
     755            mr_asprintf(acl_fname, ACL_LIST_FNAME_RAW_SZ, ARCHIVES_PATH, current_tarball_number);
    732756        }
    733757        if (strstr(tarball_fname, ".bz2")) {
     
    922946        mr_free(progress_str);
    923947
    924         mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.bz2", current_tarball_number);
     948        mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.bz2", current_tarball_number);
    925949        if (!does_file_exist(tarball_fname)) {
    926950            mr_free(tarball_fname);
    927             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.gz", current_tarball_number);
     951            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.gz", current_tarball_number);
    928952        }
    929953        if (!does_file_exist(tarball_fname)) {
    930954            mr_free(tarball_fname);
    931             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzma", current_tarball_number);
     955            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.lzma", current_tarball_number);
    932956        }
    933957        if (!does_file_exist(tarball_fname)) {
    934958            mr_free(tarball_fname);
    935             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.lzo", current_tarball_number);
     959            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.lzo", current_tarball_number);
    936960        }
    937961        if (!does_file_exist(tarball_fname)) {
    938962            mr_free(tarball_fname);
    939             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.afio.", current_tarball_number);
     963            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.afio.", current_tarball_number);
    940964        }
    941965        if (!does_file_exist(tarball_fname)) {
    942966            mr_free(tarball_fname);
    943             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.bz2", current_tarball_number);
     967            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.star.bz2", current_tarball_number);
    944968        }
    945969        if (!does_file_exist(tarball_fname)) {
    946970            mr_free(tarball_fname);
    947             mr_asprintf(tarball_fname, MNT_CDROM "/archives/%ld.star.", current_tarball_number);
     971            mr_asprintf(tarball_fname, ARCHIVES_PATH "/%ld.star.", current_tarball_number);
    948972        }
    949973        if (!does_file_exist(tarball_fname)) {
     
    954978                return (0);
    955979            }
    956             if (!does_file_exist(MNT_CDROM "/archives/NOT-THE-LAST")
    957                 || system("find " MNT_CDROM
    958                           "/archives/slice* > /dev/null 2> /dev/null") ==
     980            if (!does_file_exist(ARCHIVES_PATH "/NOT-THE-LAST")
     981                || system("find " ARCHIVES_PATH "/slice* > /dev/null 2> /dev/null") ==
    959982                0) {
    960983                break;
  • branches/3.3/mondo/test/Makefile.am

    r3614 r3879  
    1 AM_CPPFLAGS = -DMONDO_CONF_DIR=\"$(sysconfdir)/mondo\" -I${top_builddir}/src/include -I${top_builddir}/src/common
     1AM_CPPFLAGS = -DMONDO_CONF_DIR=\"$(sysconfdir)/mondo\" -I${top_builddir}/src/include -I${top_builddir}/src/common -I${top_builddir}/src/mondoarchive -I${top_builddir}/src/mondorestore
    22AUTOMAKE_OPTIONS = subdir-objects
    33
  • branches/3.3/mondo/test/test-mountlist.c

    r3825 r3879  
    88#include "my-stuff.h"
    99#include "mr_mem.h"
    10 #include "../common/mondostructures.h"
    11 #include "../common/libmondo.h"
    12 #include "../mondorestore/mondorestore.h"
    13 #include "../mondorestore/mr-externs.h"
    14 #include "../mondorestore/libmondo-mountlist-EXT.h"
    15 
     10#include "mondostructures.h"
     11#include "mondorestore.h"
     12#include "libmondo-mountlist-EXT.h"
     13#include "libmondo-raid-EXT.h"
     14#include "libmondo-tools-EXT.h"
     15#include "newt-specific-EXT.h"
     16extern void resize_mountlist_proportionately_to_suit_new_drives(struct mountlist_itself *);
     17extern int edit_mountlist(char *, struct mountlist_itself *, struct raidlist_itself *);
    1618
    1719#define RAIDTAB_TEST "/tmp/raidtab"
  • branches/3.3/mondo/test/test-truncname.c

    r3819 r3879  
    88#include "my-stuff.h"
    99#include "mr_mem.h"
    10 #include "../common/mondostructures.h"
    11 #include "../common/libmondo.h"
    12 #include "../mondoarchive/mondoarchive.h"
     10#include "mondostructures.h"
     11#include "mondoarchive.h"
     12#include "libmondo-tools-EXT.h"
     13#include "newt-specific-EXT.h"
    1314
    1415extern void twenty_seconds_til_yikes(void);
Note: See TracChangeset for help on using the changeset viewer.