Changeset 3879 in MondoRescue for branches/3.3/mondo/src/mondorestore


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

Fix all remaining compiler errors

Location:
branches/3.3/mondo/src/mondorestore
Files:
7 deleted
7 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.