Changeset 3877 in MondoRescue for branches/3.3


Ignore:
Timestamp:
Mar 8, 2024, 3:59:07 AM (4 months ago)
Author:
Bruno Cornec
Message:

More compiler fixes

Location:
branches/3.3/mondo/src/common
Files:
6 edited

Legend:

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

    r3875 r3877  
    318318
    319319
     320
     321
     322/**
     323 * Finalize the backup.
     324 * For streaming backups, this writes the closing block
     325 * to the stream. For CD-based backups, this creates
     326 * the final ISO image.
     327 * @param bkpinfo The backup information structure, used only
     328 * for the @c backup_media_type.
     329 * @ingroup MLarchiveGroup
     330 */
     331int do_that_final_phase()
     332{
     333
     334    /*@ int ************************************** */
     335    int res = 0;
     336    int retval = 0;
     337
     338    /*@ buffers ********************************** */
     339
     340    assert(bkpinfo != NULL);
     341    mvaddstr_and_log_it(g_currentY, 0,
     342                        "Writing any remaining data to media         ");
     343
     344    log_msg(1, "Closing tape/CD/USB ... ");
     345    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     346        /* write tape/cdstream */
     347        closeout_tape();
     348    } else {
     349        /* write final ISO/USB */
     350        res = write_final_iso_if_necessary();
     351        retval += res;
     352        if (res) {
     353            log_msg(1, "write_final_iso_if_necessary returned an error");
     354        }
     355    }
     356    log_msg(2, "Fork is exiting ... ");
     357
     358    mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     359
     360    /* final stuff */
     361    if (retval) {
     362        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     363    } else {
     364        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     365    }
     366
     367    return (retval);
     368}
     369
     370/**
     371 * Wrapper around @c make_slices_and_images().
     372 * @param bkpinfo The backup information structure. Fields used:
     373 * - @c backup_media_type
     374 * - @c scratchdir
     375 * - @c tmpdir
     376 * @return The number of errors encountered (0 for success)
     377 * @ingroup MLarchiveGroup
     378 */
     379int make_those_slices_phase()
     380{
     381
     382    /*@ int ***************************************************** */
     383    int res = 0;
     384    int retval = 0;
     385
     386    /*@ buffers ************************************************** */
     387    char *biggielist = NULL;
     388    char *command = NULL;
     389    char *blah = NULL;
     390    char *xattr_fname = NULL;
     391    char *acl_fname = NULL;
     392
     393    assert(bkpinfo != NULL);
     394    /* slice big files */
     395    mvaddstr_and_log_it(g_currentY, 0, "Archiving large files to media           ");
     396    mr_asprintf(biggielist, "%s/archives/biggielist.txt", bkpinfo->scratchdir);
     397    if (g_getfattr) {
     398        mr_asprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
     399    }
     400    if (g_getfacl) {
     401        mr_asprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
     402    }
     403
     404    mr_asprintf(command, "cp %s/biggielist.txt %s", bkpinfo->tmpdir, biggielist);
     405    paranoid_system(command);
     406    mr_free(command);
     407
     408    mr_asprintf(blah, "biggielist = %s", biggielist);
     409    log_msg(2, blah);
     410    mr_free(blah);
     411
     412    if (!does_file_exist(biggielist)) {
     413        log_msg(1, "BTW, the biggielist does not exist");
     414    }
     415
     416    if (g_getfattr) {
     417        get_fattr_list(biggielist, xattr_fname);
     418        mr_asprintf(command, "cp %s %s/archives/", xattr_fname, bkpinfo->scratchdir);
     419        paranoid_system(command);
     420        mr_free(command);
     421    }
     422    if (g_getfacl) {
     423        get_acl_list(biggielist, acl_fname);
     424        mr_asprintf(command, "cp %s %s/archives/", acl_fname, bkpinfo->scratchdir);
     425        paranoid_system(command);
     426        mr_free(command);
     427    }
     428
     429    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     430        res += write_EXAT_files_to_tape(xattr_fname, acl_fname);
     431        mr_asprintf(blah, "%ld", count_lines_in_file(biggielist));
     432        write_header_block_to_stream((off_t)0, blah, BLK_START_BIGGIEFILES);
     433        mr_free(blah);
     434    }
     435    res = make_slices_and_images(biggielist);
     436    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     437        write_header_block_to_stream((off_t)0, "end-of-biggiefiles", BLK_STOP_BIGGIEFILES);
     438    }
     439    retval += res;
     440    if (res) {
     441        log_msg(1, "make_slices_and_images returned an error");
     442        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     443    } else {
     444        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     445    }
     446    mr_free(biggielist);
     447    mr_free(xattr_fname);
     448    mr_free(acl_fname);
     449    return (retval);
     450}
     451
     452
     453
     454/**
     455 * Wrapper around @c make_afioballs_and_images().
     456 * @param bkpinfo the backup information structure. Only the
     457 * @c backup_media_type field is used within this function.
     458 * @return return code of make_afioballs_and_images
     459 * @see make_afioballs_and_images
     460 * @ingroup MLarchiveGroup
     461 */
     462int make_those_afios_phase()
     463{
     464    /*@ int ******************************************* */
     465    int res = 0;
     466    int retval = 0;
     467
     468    assert(bkpinfo != NULL);
     469
     470    mvaddstr_and_log_it(g_currentY, 0, "Archiving regular files to media          ");
     471
     472    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     473        write_header_block_to_stream((off_t)0, "start-of-afioballs", BLK_START_AFIOBALLS);
     474#if __FreeBSD__ == 5
     475        log_msg(1, "Using single-threaded make_afioballs_and_images() to suit b0rken FreeBSD 5.0");
     476        res = make_afioballs_and_images_OLD();
     477#else
     478        res = make_afioballs_and_images_OLD();
     479#endif
     480        write_header_block_to_stream((off_t)0, "stop-afioballs", BLK_STOP_AFIOBALLS);
     481    } else {
     482        res = make_afioballs_and_images();
     483    }
     484
     485    retval += res;
     486    if (res) {
     487        mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
     488        log_msg(1, "make_afioballs_and_images returned an error");
     489    } else {
     490        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     491    }
     492    return (retval);
     493}
    320494
    321495
     
    8901064
    8911065
     1066/**
     1067 * Set the <tt>N</tt>th bit of @c array to @c true_or_false.
     1068 * @param array The bit array (as a @c char pointer).
     1069 * @param N The bit number to set or reset.
     1070 * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N.
     1071 * @see get_bit_N_of_array
     1072 */
     1073void set_bit_N_of_array(char *array, int N, bool true_or_false)
     1074{
     1075    int bit_number;
     1076    int mask, orig_val, to_add;
     1077    int element_number;
     1078
     1079    assert(array != NULL);
     1080
     1081    element_number = N / 8;
     1082    bit_number = N % 8;
     1083    to_add = (1 << bit_number);
     1084    mask = 255 - to_add;
     1085    orig_val = array[element_number] & mask;
     1086    //  log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val);
     1087    if (true_or_false) {
     1088        array[element_number] = orig_val | to_add;
     1089    }
     1090}
     1091
     1092
    8921093
    8931094/**
     
    10511252
    10521253
    1053 
    1054 
    1055 
    1056 /**
    1057  * Finalize the backup.
    1058  * For streaming backups, this writes the closing block
    1059  * to the stream. For CD-based backups, this creates
    1060  * the final ISO image.
    1061  * @param bkpinfo The backup information structure, used only
    1062  * for the @c backup_media_type.
    1063  * @ingroup MLarchiveGroup
    1064  */
    1065 int do_that_final_phase()
     1254/**
     1255 * Write the final ISO image.
     1256 * @param bkpinfo The backup information structure. Used only
     1257 * in the call to @c write_iso_and_go_on().
     1258 * @return The number of errors encountered (0 for success)
     1259 * @see write_iso_and_go_on
     1260 * @see make_iso_fs
     1261 * @bug The final ISO is written even if there are no files on it. In practice,
     1262 * however, this occurs rarely.
     1263 */
     1264int write_final_iso_if_necessary()
    10661265{
    1067 
    1068     /*@ int ************************************** */
    1069     int res = 0;
    1070     int retval = 0;
    1071 
    1072     /*@ buffers ********************************** */
     1266    /*@ int ***************************************************** */
     1267    int res;
     1268
     1269    /*@ buffers ************************************************** */
     1270    char *tmp = NULL;
    10731271
    10741272    assert(bkpinfo != NULL);
    1075     mvaddstr_and_log_it(g_currentY, 0,
    1076                         "Writing any remaining data to media         ");
    1077 
    1078     log_msg(1, "Closing tape/CD/USB ... ");
    1079     if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    1080         /* write tape/cdstream */
    1081         closeout_tape();
    1082     } else {
    1083         /* write final ISO/USB */
    1084         res = write_final_iso_if_necessary();
    1085         retval += res;
    1086         if (res) {
    1087             log_msg(1, "write_final_iso_if_necessary returned an error");
    1088         }
    1089     }
    1090     log_msg(2, "Fork is exiting ... ");
    1091 
    1092     mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    1093 
    1094     /* final stuff */
    1095     if (retval) {
    1096         mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
    1097     } else {
    1098         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    1099     }
    1100 
    1101     return (retval);
     1273    // I should really check if there are any slices or tarballs to be copied to CD-R(W)'s; the odds are approx. 1 in a million that there are no files here, so I'll just go ahead & make one more CD anyway
     1274
     1275    tmp = mr_center_string("Writing the final ISO", 80);
     1276    log_msg(2, tmp);
     1277    if (!g_text_mode) {
     1278        newtPushHelpLine(tmp);
     1279    }
     1280    mr_free(tmp);
     1281    res = write_iso_and_go_on(TRUE);
     1282    if (!g_text_mode) {
     1283        newtPopHelpLine();
     1284    }
     1285    log_msg(2, "Returning from writing final ISO (res=%d)", res);
     1286    return (res);
     1287}
     1288
     1289
     1290
     1291
     1292/**
     1293 * Remove the archives in @c d.
     1294 * This could possibly include any of:
     1295 * - all afioballs (compressed and not)
     1296 * - all filelists
     1297 * - all slices
     1298 * - all checksums
     1299 * - a zero filler file
     1300 *
     1301 * @param d The directory to wipe the archives from.
     1302 * @ingroup utilityGroup
     1303 */
     1304void wipe_archives(char *d)
     1305{
     1306    /*@ buffers ********************************************* */
     1307    char *tmp = NULL;
     1308    char *dir = NULL;
     1309
     1310    assert_string_is_neither_NULL_nor_zerolength(d);
     1311
     1312    mr_asprintf(dir, "%s/archives", d);
     1313    mr_asprintf(tmp, "rm -f %s/*.afio.* %s/*.star.*", dir, dir);
     1314    run_program_and_log_output(tmp, FALSE);
     1315    mr_free(tmp);
     1316    mr_asprintf(tmp, "rm -f %s/*list.[0-9]* %s/slice*", dir, dir);
     1317    run_program_and_log_output(tmp, FALSE);
     1318    mr_free(tmp);
     1319    mr_asprintf(tmp, "rm -f %s/cklist* %s/zero", dir, dir);
     1320    run_program_and_log_output(tmp, FALSE);
     1321    mr_free(tmp);
     1322    log_msg(1, "Wiped %s's archives", dir);
     1323    mr_asprintf(tmp, "ls -l %s", dir);
     1324    mr_free(dir);
     1325    run_program_and_log_output(tmp, FALSE);
     1326    mr_free(tmp);
    11021327}
    11031328
     
    12121437
    12131438
    1214 
    1215 
    1216 
    1217 
     1439/**
     1440 * @addtogroup LLarchiveGroup
     1441 * @{
     1442 */
     1443/**
     1444 * Function pointer to an appropriate @c move_files_to_stream routine.
     1445 * You can set this to your own function (for example, one to
     1446 * transfer files over the network) or leave it as is.
     1447 */
     1448int (*move_files_to_stream) (char *, ...) =
     1449    _move_files_to_stream;
     1450
     1451
     1452/**
     1453 * Function pointer to an appropriate @c move_files_to_cd routine.
     1454 * You can set this to your own function (for example, one to
     1455 * transfer files over the network) or leave it as is.
     1456 */
     1457int (*move_files_to_cd) (char *, ...) =
     1458    _move_files_to_cd;
    12181459
    12191460
     
    15351776
    15361777/**
     1778 * Asks the user to put a CD-R(W) in the drive.
     1779 * @param ask_for_one_if_more_than_this (unused)
     1780 * @param pmountable If non-NULL, pointed-to value is set to TRUE if the CD is mountable, FALSE otherwise.
     1781 */
     1782void pause_and_ask_for_cdr(int ask_for_one_if_more_than_this, bool * pmountable) {
     1783
     1784    /*@ buffers ********************************************* */
     1785    char *tmp = NULL;
     1786    char *cdrom_dev = NULL;
     1787    char *cd_dev = NULL;
     1788    char *our_serial_str = NULL;
     1789    bool ok_go_ahead_burn_it;
     1790    int cd_number = -1;
     1791    int attempt_to_mount_returned_this = 999;
     1792    char *mtpt = NULL;
     1793    char *szcdno = NULL;
     1794    char *szserfname = NULL;
     1795    char *szunmount = NULL;
     1796    char *mds = NULL;
     1797
     1798    malloc_string(cd_dev);
     1799
     1800    mds = media_descriptor_string(g_backup_media_type);
     1801    log_to_screen("I am about to burn %s #%d", mds, g_current_media_number);
     1802    mr_free(mds);
     1803    if (g_current_media_number < ask_for_one_if_more_than_this) {
     1804        return;
     1805    }
     1806    log_to_screen("Scanning CD-ROM drive...");
     1807    mr_asprintf(mtpt, "%s/cd.mtpt", bkpinfo->tmpdir);
     1808    make_hole_for_dir(mtpt);
     1809
     1810  gotos_make_me_puke:
     1811    ok_go_ahead_burn_it = TRUE;
     1812    mr_free(cdrom_dev);
     1813    if ((cdrom_dev = find_optical_device()) != NULL) {
     1814        /* When enabled, it made CD eject-and-retract when wrong CD inserted.. Weird
     1815        log_msg(2, "paafcd: Retracting CD-ROM drive if possible" );
     1816        retract_CD_tray_and_defeat_autorun();
     1817        */
     1818        mr_asprintf(tmp, "umount %s", cdrom_dev);
     1819        run_program_and_log_output(tmp, 1);
     1820        mr_asprintf(szcdno, "%s/archives/THIS-CD-NUMBER", mtpt);
     1821        mr_asprintf(szserfname, "%s/archives/SERIAL-STRING", mtpt);
     1822        mr_asprintf(szunmount, "umount %s", mtpt);
     1823        cd_number = -1;
     1824        mr_asprintf(tmp, "mount %s %s", cdrom_dev, mtpt);
     1825        mr_asprintf(our_serial_str, "%s", "");
     1826        attempt_to_mount_returned_this = run_program_and_log_output(tmp, 1);
     1827        mr_free(tmp);
     1828
     1829        if (attempt_to_mount_returned_this) {
     1830            log_msg(4, "Failed to mount %s at %s", cdrom_dev, mtpt);
     1831            log_to_screen("If there's a CD/DVD in the drive, it's blank.");
     1832        } else if (!does_file_exist(szcdno) || !does_file_exist(szserfname)) {
     1833            mds = media_descriptor_string(g_backup_media_type);
     1834            log_to_screen("%s has data on it but it's probably not a Mondo CD.", mds);
     1835            mr_free(mds);
     1836        } else {
     1837            mds = media_descriptor_string(g_backup_media_type);
     1838            log_to_screen("%s found in drive. It's a Mondo disk.", mds);
     1839            mr_free(mds);
     1840
     1841            cd_number = atoi(last_line_of_file(szcdno));
     1842            mr_asprintf(tmp, "cat %s 2> /dev/null", szserfname);
     1843            mr_free(our_serial_str);
     1844            our_serial_str = call_program_and_get_last_line_of_output(tmp);
     1845            mr_free(tmp);
     1846            // FIXME - should be able to use last_line_of_file(), surely?
     1847        }
     1848        mr_free(szcdno);
     1849        mr_free(szserfname);
     1850
     1851        run_program_and_log_output(szunmount, 1);
     1852        mr_free(szunmount);
     1853
     1854        log_msg(2, "paafcd: cd_number = %d", cd_number);
     1855        log_msg(2, "our serial str = %s; bkpinfo->serial_string = %s", our_serial_str, bkpinfo->serial_string);
     1856        if (cd_number > 0 && !strcmp(our_serial_str, bkpinfo->serial_string)) {
     1857            mds = media_descriptor_string(g_backup_media_type);
     1858            log_msg(2, "This %s is part of this backup set!", mds);
     1859            ok_go_ahead_burn_it = FALSE;
     1860            if (cd_number == g_current_media_number - 1) {
     1861                log_to_screen("I think you've left the previous %s in the drive.", mds);
     1862            } else {
     1863                log_to_screen("Please remove this %s. It is part of the backup set you're making now.", mds);
     1864            }
     1865            mr_free(mds);
     1866
     1867        } else {
     1868            log_to_screen("...but not part of _our_ backup set.");
     1869        }
     1870        mr_free(our_serial_str);
     1871    } else {
     1872        mds = media_descriptor_string(g_backup_media_type);
     1873        log_msg(2,
     1874                "paafcd: Can't find CD-ROM drive. Perhaps it has a blank %s in it?", mds);
     1875        if (interrogate_disk_currently_in_cddrive(cd_dev, FALSE)) {
     1876            ok_go_ahead_burn_it = FALSE;
     1877            log_to_screen("There isn't a writable %s in the drive.", mds);
     1878        }
     1879        mr_free(mds);
     1880    }
     1881
     1882    if (!ok_go_ahead_burn_it) {
     1883        if (!bkpinfo->please_dont_eject) {
     1884            eject_device(cdrom_dev);
     1885        }
     1886        mds = media_descriptor_string(g_backup_media_type);
     1887        mr_asprintf(tmp, "I am about to burn %s #%d of the backup set. Please insert %s and press Enter.", mds, g_current_media_number, mds);
     1888        mr_free(mds);
     1889
     1890        popup_and_OK(tmp);
     1891        mr_free(tmp);
     1892        goto gotos_make_me_puke;
     1893    } else {
     1894        log_msg(2, "paafcd: OK, going ahead and burning it.");
     1895    }
     1896
     1897    mds = media_descriptor_string(g_backup_media_type);
     1898    log_msg(2, "paafcd: OK, I assume I have a blank/reusable %s in the drive...", mds);
     1899
     1900    log_to_screen("Proceeding w/ %s in drive.", mds);
     1901    mr_free(mds);
     1902
     1903    mr_free(cdrom_dev);
     1904    paranoid_free(cd_dev);
     1905    mr_free(mtpt);
     1906    if (pmountable) {
     1907        if (attempt_to_mount_returned_this) {
     1908            *pmountable = FALSE;
     1909        } else {
     1910            *pmountable = TRUE;
     1911        }
     1912    }
     1913
     1914}
     1915
     1916
     1917/**
    15371918 * Create an ISO image in @c destfile, from files in @c bkpinfo->scratchdir.
    15381919 *
     
    18472228
    18482229/**
     2230 * Chop up @c filename.
     2231 * @param bkpinfo The backup information structure. Fields used:
     2232 * - @c backup_media_type
     2233 * - @c compression_level
     2234 * - @c optimal_set_size
     2235 * - @c tmpdir
     2236 * - @c use_lzo
     2237 * - @c zip_exe
     2238 * - @c zip_suffix
     2239 *
     2240 * @param biggie_filename The file to chop up.
     2241 * @param ntfsprog_fifo The FIFO to ntfsclone if this is an imagedev, NULL otherwise.
     2242 * @param biggie_file_number The sequence number of this biggie file (starting from 0).
     2243 * @param noof_biggie_files The number of biggie files there are total.
     2244 * @return The number of errors encountered (0 for success)
     2245 * @see make_slices_and_images
     2246 * @ingroup LLarchiveGroup
     2247 */
     2248int slice_up_file_etc(char *biggie_filename, char *ntfsprog_fifo, long biggie_file_number, long noof_biggie_files, bool use_ntfsprog) {
     2249
     2250    /*@ buffers ************************************************** */
     2251    char *tmp = NULL;
     2252    char *checksum_line = NULL;
     2253    char *command = NULL;
     2254    char *tempblock = NULL;
     2255    char *curr_slice_fname_uncompressed = NULL;
     2256    char *curr_slice_fname_compressed = NULL;
     2257    char *file_to_archive = NULL;
     2258    char *file_to_openin = NULL;
     2259    /*@ pointers ************************************************** */
     2260    char *pB = NULL;
     2261    FILE *fin = NULL;
     2262    FILE *fout = NULL;
     2263
     2264    /*@ bool ****************************************************** */
     2265    bool finished = FALSE;
     2266
     2267    /*@ long ****************************************************** */
     2268    size_t blksize = (size_t)0;
     2269    long slice_num = 0L;
     2270    long i = 0L;
     2271    bool should_I_compress_slices = TRUE;
     2272    char *suffix = NULL;                // for compressed slices
     2273
     2274    /*@ long long ************************************************** */
     2275    off_t totalread = (off_t)0;
     2276    off_t totallength = (off_t)0;
     2277
     2278    /*@ int ******************************************************** */
     2279    int retval = 0;
     2280    int res = 0;
     2281
     2282    /*@ structures ************************************************** */
     2283    struct s_filename_and_lstat_info biggiestruct;
     2284
     2285    assert(bkpinfo != NULL);
     2286    assert_string_is_neither_NULL_nor_zerolength(biggie_filename);
     2287
     2288    biggiestruct.for_backward_compatibility = '\n';
     2289    biggiestruct.use_ntfsprog = use_ntfsprog;
     2290    if (is_this_file_compressed(biggie_filename) || bkpinfo->compression_level == 0) {
     2291        mr_asprintf(suffix, "%s", "");
     2292        should_I_compress_slices = FALSE;
     2293    } else {
     2294        mr_asprintf(suffix, "%s", bkpinfo->zip_suffix);
     2295        should_I_compress_slices = TRUE;
     2296    }
     2297
     2298    if (bkpinfo->optimal_set_size < 999L) {
     2299        fatal_error("bkpinfo->optimal_set_size is insanely small");
     2300    }
     2301
     2302    if (ntfsprog_fifo) {
     2303        file_to_openin = ntfsprog_fifo;
     2304        mr_asprintf(checksum_line, "IGNORE");
     2305        log_msg(2, "Not calculating checksum for %s: it would take too long", biggie_filename);
     2306        if ((tmp = find_home_of_exe("ntfsresize")) == NULL) {
     2307            fatal_error("ntfsresize not found");
     2308        }
     2309        mr_asprintf(command, "%s --force --info %s|grep '^You might resize at '|cut -d' ' -f5", tmp, biggie_filename);
     2310        mr_free(tmp);
     2311        log_it("command = %s", command);
     2312        tmp = call_program_and_get_last_line_of_output(command);
     2313        mr_free(command);
     2314        log_it("res of it = %s", tmp);
     2315        totallength = (off_t)atoll(tmp);
     2316        mr_free(tmp);
     2317    } else {
     2318        file_to_openin = biggie_filename;
     2319        if (strchr(biggie_filename,'\'') != NULL) {
     2320            mr_asprintf(command, "md5sum \"%s\"", biggie_filename);
     2321        } else {
     2322            mr_asprintf(command, "md5sum '%s'", biggie_filename);
     2323        }
     2324        if (!(fin = popen(command, "r"))) {
     2325            log_OS_error("Unable to popen-in command");
     2326            mr_free(suffix);
     2327            return (1);
     2328        }
     2329        mr_free(command);
     2330        mr_getline(checksum_line, fin);
     2331        pclose(fin);
     2332        totallength = length_of_file(biggie_filename);
     2333    }
     2334    lstat(biggie_filename, &biggiestruct.properties);
     2335    strcpy(biggiestruct.filename, biggie_filename);
     2336    pB = strchr(checksum_line, ' ');
     2337    if (!pB) {
     2338        pB = strchr(checksum_line, '\t');
     2339    }
     2340    if (pB) {
     2341        *pB = '\0';
     2342    }
     2343    strcpy(biggiestruct.checksum, checksum_line);
     2344    mr_free(checksum_line);
     2345
     2346    mr_asprintf(tmp, "%s", slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""));
     2347    fout = fopen(tmp, "w");
     2348    if (fout == NULL) {
     2349        log_msg(1, "Unable to open and write to %s", tmp);
     2350        mr_free(tmp);
     2351        mr_free(suffix);
     2352        return (1);
     2353    }
     2354    res = fwrite((void *) &biggiestruct, 1, sizeof(biggiestruct), fout);
     2355    paranoid_fclose(fout);
     2356    mr_free(tmp);
     2357
     2358    log_msg(1, "Opening in %s; slicing it and writing to CD/tape", file_to_openin);
     2359    if (!(fin = fopen(file_to_openin, "r"))) {
     2360        log_OS_error("Unable to openin biggie_filename");
     2361        log_to_screen("Cannot archive bigfile '%s': not found", biggie_filename);
     2362
     2363        mr_free(suffix);
     2364        return (1);
     2365    }
     2366    if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     2367        res = move_files_to_stream(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);
     2368    } else {
     2369        res = move_files_to_cd(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);
     2370    }
     2371    i = bkpinfo->optimal_set_size / 256L;
     2372    if (!(tempblock = (char *) malloc(256 * 1024))) {
     2373        fatal_error("malloc error 256*1024");
     2374    }
     2375    for (slice_num = 1; !finished; slice_num++) {
     2376        mr_asprintf(curr_slice_fname_uncompressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, ""));
     2377        mr_asprintf(curr_slice_fname_compressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, suffix));
     2378
     2379        tmp = percent_media_full_comment();
     2380        update_progress_form(tmp);
     2381        mr_free(tmp);
     2382
     2383        if (!(fout = fopen(curr_slice_fname_uncompressed, "w"))) {
     2384            log_OS_error(curr_slice_fname_uncompressed);
     2385            mr_free(suffix);
     2386            return (1);
     2387        }
     2388        if ((i == bkpinfo->optimal_set_size / 256L) && (totalread < (off_t)1.1 * totallength)) {
     2389            for (i = 0L; i < (bkpinfo->optimal_set_size / 256L); i++) {
     2390                blksize = fread(tempblock, 1, 256 * 1024, fin);
     2391                if (blksize > (size_t)0) {
     2392                    totalread = totalread + (off_t)blksize;
     2393                    res = fwrite(tempblock, 1, blksize, fout);
     2394                } else {
     2395                    break;
     2396                }
     2397            }
     2398        } else {
     2399            i = 0L;
     2400        }
     2401        paranoid_fclose(fout);
     2402        if (i > 0L)             // length_of_file (curr_slice_fname_uncompressed)
     2403        {
     2404            if (!does_file_exist(curr_slice_fname_uncompressed)) {
     2405                log_msg(2, "Warning - '%s' doesn't exist. How can I compress slice?", curr_slice_fname_uncompressed);
     2406            }
     2407            if (should_I_compress_slices && bkpinfo->compression_level > 0) {
     2408                mr_asprintf(command, "%s -%d %s", bkpinfo->zip_exe, bkpinfo->compression_level, curr_slice_fname_uncompressed);
     2409                log_msg(2, command);
     2410                if ((res = system(command))) {
     2411                    log_OS_error(command);
     2412                }
     2413                //          did_I_compress_slice = TRUE;
     2414            } else {
     2415                mr_asprintf(command, "mv %s %s 2>> %s", curr_slice_fname_uncompressed, curr_slice_fname_compressed, MONDO_LOGFILE);
     2416                res = 0;        // don't do it :)
     2417                //          did_I_compress_slice = FALSE;
     2418            }
     2419            mr_free(command);
     2420
     2421            retval += res;
     2422            if (res) {
     2423                log_msg(2, "Failed to compress the slice");
     2424            }
     2425            if (bkpinfo->use_lzo && strcmp(curr_slice_fname_compressed, curr_slice_fname_uncompressed)) {
     2426                unlink(curr_slice_fname_uncompressed);
     2427            }
     2428            if (res) {
     2429                mr_asprintf(tmp, "Problem with slice # %ld", slice_num);
     2430            } else {
     2431                mr_asprintf(tmp, "%s - Bigfile #%ld, slice #%ld compressed OK          ", biggie_filename, biggie_file_number + 1, slice_num);
     2432            }
     2433            if (!g_text_mode) {
     2434                newtDrawRootText(0, g_noof_rows - 2, tmp);
     2435                newtRefresh();
     2436            } else {
     2437                log_msg(2, tmp);
     2438            }
     2439            mr_free(tmp);
     2440
     2441            mr_asprintf(file_to_archive, "%s", curr_slice_fname_compressed);
     2442            g_current_progress++;
     2443        } else {                /* if i==0 then ... */
     2444            finished = TRUE;
     2445            mr_asprintf(file_to_archive, "%s", curr_slice_fname_uncompressed);
     2446            if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     2447                break;
     2448            }
     2449        }
     2450        mr_free(curr_slice_fname_uncompressed);
     2451        mr_free(curr_slice_fname_compressed);
     2452
     2453        if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
     2454            register_in_tape_catalog(biggieslice, biggie_file_number, slice_num, file_to_archive);
     2455            maintain_collection_of_recent_archives(bkpinfo->tmpdir, file_to_archive);
     2456            res = move_files_to_stream(file_to_archive, NULL);
     2457        } else {
     2458            res = move_files_to_cd(file_to_archive, NULL);
     2459        }
     2460        mr_free(file_to_archive);
     2461
     2462        retval += res;
     2463        if (res) {
     2464            log_to_screen("Failed to add slice %ld of bigfile %ld to scratchdir", slice_num, biggie_file_number + 1);
     2465            fatal_error("Hard disk full. You should have bought a bigger one.");
     2466        }
     2467    }
     2468    mr_free(tempblock);
     2469    mr_free(suffix);
     2470    paranoid_fclose(fin);
     2471    mr_asprintf(tmp, "Sliced bigfile #%ld", biggie_file_number + 1);
     2472    if (retval) {
     2473        mr_strcat(tmp, "...FAILED");
     2474    } else {
     2475        mr_strcat(tmp, "...OK!");
     2476    }
     2477    log_msg(1, tmp);
     2478    mr_free(tmp);
     2479
     2480    return (retval);
     2481}
     2482
     2483
     2484/**
    18492485 * Back up big files by chopping them up.
    18502486 * This function backs up all "big" files (where "big" depends
     
    21362772/* @} - end of LLarchiveGroup */
    21372773
    2138 
    2139 /**
    2140  * Wrapper around @c make_afioballs_and_images().
    2141  * @param bkpinfo the backup information structure. Only the
    2142  * @c backup_media_type field is used within this function.
    2143  * @return return code of make_afioballs_and_images
    2144  * @see make_afioballs_and_images
    2145  * @ingroup MLarchiveGroup
    2146  */
    2147 int make_those_afios_phase()
    2148 {
    2149     /*@ int ******************************************* */
    2150     int res = 0;
    2151     int retval = 0;
    2152 
    2153     assert(bkpinfo != NULL);
    2154 
    2155     mvaddstr_and_log_it(g_currentY, 0, "Archiving regular files to media          ");
    2156 
    2157     if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    2158         write_header_block_to_stream((off_t)0, "start-of-afioballs", BLK_START_AFIOBALLS);
    2159 #if __FreeBSD__ == 5
    2160         log_msg(1, "Using single-threaded make_afioballs_and_images() to suit b0rken FreeBSD 5.0");
    2161         res = make_afioballs_and_images_OLD();
    2162 #else
    2163         res = make_afioballs_and_images_OLD();
    2164 #endif
    2165         write_header_block_to_stream((off_t)0, "stop-afioballs", BLK_STOP_AFIOBALLS);
    2166     } else {
    2167         res = make_afioballs_and_images();
    2168     }
    2169 
    2170     retval += res;
    2171     if (res) {
    2172         mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
    2173         log_msg(1, "make_afioballs_and_images returned an error");
    2174     } else {
    2175         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    2176     }
    2177     return (retval);
    2178 }
    2179 
    2180 /**
    2181  * Wrapper around @c make_slices_and_images().
     2774/**
     2775 * Write an ISO image to <tt>[bkpinfo->isodir]/bkpinfo->prefix-[g_current_media_number].iso</tt>.
    21822776 * @param bkpinfo The backup information structure. Fields used:
    21832777 * - @c backup_media_type
     2778 * - @c prefix
     2779 * - @c isodir
     2780 * - @c manual_cd_tray
     2781 * - @c media_size
     2782 * - @c netfs_remote_dir
    21842783 * - @c scratchdir
    2185  * - @c tmpdir
     2784 * - @c verify_data
     2785 *
     2786 * @param last_cd If TRUE, this is the last CD to write; if FALSE, it's not.
    21862787 * @return The number of errors encountered (0 for success)
    2187  * @ingroup MLarchiveGroup
    2188  */
    2189 int make_those_slices_phase()
     2788 * @see make_iso_fs
     2789 */
     2790int write_iso_and_go_on(bool last_cd)
    21902791{
    2191 
    2192     /*@ int ***************************************************** */
     2792    /*@ pointers **************************************************** */
     2793    FILE *fout;
     2794
     2795    /*@ buffers ***************************************************** */
     2796    char *tmp = NULL;
     2797    char *tmp1 = NULL;
     2798    char *cdno_fname = NULL;
     2799    char *lastcd_fname = NULL;
     2800    char *isofile = NULL;
     2801    char *mds = NULL;
     2802
     2803    /*@ bool ******************************************************** */
     2804    bool that_one_was_ok;
     2805    bool orig_vfy_flag_val;
     2806
     2807    /*@ int *********************************************************** */
    21932808    int res = 0;
    2194     int retval = 0;
    2195 
    2196     /*@ buffers ************************************************** */
    2197     char *biggielist = NULL;
    2198     char *command = NULL;
    2199     char *blah = NULL;
    2200     char *xattr_fname = NULL;
    2201     char *acl_fname = NULL;
    22022809
    22032810    assert(bkpinfo != NULL);
    2204     /* slice big files */
    2205     mvaddstr_and_log_it(g_currentY, 0, "Archiving large files to media           ");
    2206     mr_asprintf(biggielist, "%s/archives/biggielist.txt", bkpinfo->scratchdir);
    2207     if (g_getfattr) {
    2208         mr_asprintf(xattr_fname, XATTR_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
    2209     }
    2210     if (g_getfacl) {
    2211         mr_asprintf(acl_fname, ACL_BIGGLST_FNAME_RAW_SZ, bkpinfo->tmpdir);
    2212     }
    2213 
    2214     mr_asprintf(command, "cp %s/biggielist.txt %s", bkpinfo->tmpdir, biggielist);
    2215     paranoid_system(command);
    2216     mr_free(command);
    2217 
    2218     mr_asprintf(blah, "biggielist = %s", biggielist);
    2219     log_msg(2, blah);
    2220     mr_free(blah);
    2221 
    2222     if (!does_file_exist(biggielist)) {
    2223         log_msg(1, "BTW, the biggielist does not exist");
    2224     }
    2225 
    2226     if (g_getfattr) {
    2227         get_fattr_list(biggielist, xattr_fname);
    2228         mr_asprintf(command, "cp %s %s/archives/", xattr_fname, bkpinfo->scratchdir);
    2229         paranoid_system(command);
    2230         mr_free(command);
    2231     }
    2232     if (g_getfacl) {
    2233         get_acl_list(biggielist, acl_fname);
    2234         mr_asprintf(command, "cp %s %s/archives/", acl_fname, bkpinfo->scratchdir);
    2235         paranoid_system(command);
    2236         mr_free(command);
    2237     }
    2238 
    2239     if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    2240         res += write_EXAT_files_to_tape(xattr_fname, acl_fname);
    2241         mr_asprintf(blah, "%ld", count_lines_in_file(biggielist));
    2242         write_header_block_to_stream((off_t)0, blah, BLK_START_BIGGIEFILES);
    2243         mr_free(blah);
    2244     }
    2245     res = make_slices_and_images(biggielist);
    2246     if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    2247         write_header_block_to_stream((off_t)0, "end-of-biggiefiles", BLK_STOP_BIGGIEFILES);
    2248     }
    2249     retval += res;
    2250     if (res) {
    2251         log_msg(1, "make_slices_and_images returned an error");
    2252         mvaddstr_and_log_it(g_currentY++, 74, "Errors.");
    2253     } else {
    2254         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    2255     }
    2256     mr_free(biggielist);
    2257     mr_free(xattr_fname);
    2258     mr_free(acl_fname);
    2259     return (retval);
     2811    orig_vfy_flag_val = bkpinfo->verify_data;
     2812    if (bkpinfo->media_size <= 0) {
     2813        fatal_error("write_iso_and_go_on() - unknown media size");
     2814    }
     2815
     2816    mds = media_descriptor_string(bkpinfo->backup_media_type);
     2817    log_msg(1, "OK, time to make %s #%d", mds, g_current_media_number);
     2818    mr_free(mds);
     2819
     2820    /* label the ISO with its number */
     2821
     2822    mr_asprintf(cdno_fname, "%s/archives/THIS-CD-NUMBER", bkpinfo->scratchdir);
     2823    fout = fopen(cdno_fname, "w");
     2824    mr_free(cdno_fname);
     2825
     2826    fprintf(fout, "%d", g_current_media_number);
     2827    paranoid_fclose(fout);
     2828
     2829    mr_asprintf(tmp1, "cp -f %s/autorun %s/", g_mondo_home, bkpinfo->scratchdir);
     2830    if (run_program_and_log_output(tmp1, FALSE)) {
     2831        log_msg(2, "Warning - unable to copy autorun to scratchdir");
     2832    }
     2833    mr_free(tmp1);
     2834
     2835    /* last CD or not? Label accordingly */
     2836    mr_asprintf(lastcd_fname, "%s/archives/NOT-THE-LAST", bkpinfo->scratchdir);
     2837    if (last_cd) {
     2838        unlink(lastcd_fname);
     2839        log_msg(2,
     2840                "OK, you're telling me this is the last CD. Fair enough.");
     2841    } else {
     2842        fout = fopen(lastcd_fname, "w");
     2843        fprintf(fout,
     2844                "You're listening to 90.3 WPLN, Nashville Public Radio.\n");
     2845        paranoid_fclose(fout);
     2846    }
     2847    mr_free(lastcd_fname);
     2848
     2849    if (space_occupied_by_cd(bkpinfo->scratchdir) / 1024 > bkpinfo->media_size) {
     2850        log_to_screen("Warning! CD is too big. It occupies %ld KB, which is more than the %ld MB allowed.",(long) space_occupied_by_cd(bkpinfo->scratchdir),(long) bkpinfo->media_size);
     2851    }
     2852
     2853    if (bkpinfo->netfs_remote_dir != NULL) {
     2854        // NETFS
     2855        mr_asprintf(isofile, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);
     2856    } else {
     2857        // ISO
     2858        mr_asprintf(isofile, "%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number);
     2859    }
     2860    for (that_one_was_ok = FALSE; !that_one_was_ok;) {
     2861        if (bkpinfo->backup_media_type != usb) {
     2862            res = make_iso_fs(isofile);
     2863        } else {
     2864            res = make_usb_fs();
     2865        }
     2866        if (g_current_media_number == 1 && !res
     2867            && (bkpinfo->backup_media_type == cdr)) {
     2868            if ((tmp = find_optical_device())   == NULL) {  // make sure find_optical_device() finds, records CD-R's loc
     2869                log_msg(3, "*Sigh* Mike, I hate your computer.");
     2870                // if it can't be found then force pausing
     2871                bkpinfo->manual_cd_tray = TRUE;
     2872            } else {
     2873                log_msg(3, "Great. Found Mike's CD-ROM drive.");
     2874            }
     2875            mr_free(tmp);
     2876        }
     2877        if (bkpinfo->verify_data && !res) {
     2878            mds = media_descriptor_string(g_backup_media_type);
     2879            log_to_screen("Please reboot from the 1st %s in Compare Mode, as a precaution.", mds);
     2880            mr_free(mds);
     2881            if (chdir("/")) {
     2882                // FIXME
     2883            }
     2884            log_it("Before calling verification of image()");
     2885            if (bkpinfo->backup_media_type == usb) {
     2886                res += verify_usb_image();
     2887            } else {
     2888                res += verify_cd_image();
     2889            }
     2890            log_it("After calling verification of image()");
     2891        }
     2892        if (!res) {
     2893            that_one_was_ok = TRUE;
     2894        } else {
     2895            mds = media_descriptor_string(bkpinfo->backup_media_type);
     2896            mr_asprintf(tmp1, "Failed to create %s #%d. Retry?", mds, g_current_media_number);
     2897            mr_free(mds);
     2898            res = ask_me_yes_or_no(tmp1);
     2899            mr_free(tmp1);
     2900
     2901            if (!res) {
     2902                if (ask_me_yes_or_no("Abort the backup?")) {
     2903                    fatal_error("FAILED TO BACKUP");
     2904                } else {
     2905                    break;
     2906                }
     2907            } else {
     2908                log_msg(2, "Retrying, at user's request...");
     2909                res = 0;
     2910            }
     2911        }
     2912    }
     2913    mr_free(isofile);
     2914
     2915    g_current_media_number++;
     2916    wipe_archives(bkpinfo->scratchdir);
     2917    mr_asprintf(tmp1, "rm -Rf %s/images/*gz %s/images/*data*img", bkpinfo->scratchdir, bkpinfo->scratchdir);
     2918    if (system(tmp1)) {
     2919        log_msg(2, "Error occurred when I tried to delete the redundant IMGs and GZs");
     2920    }
     2921    mr_free(tmp1);
     2922
     2923    if (last_cd) {
     2924        log_msg(2, "This was your last media.");
     2925    } else {
     2926        log_msg(2, "Continuing to backup your data...");
     2927    }
     2928
     2929    bkpinfo->verify_data = orig_vfy_flag_val;
     2930    return (0);
    22602931}
    22612932
    2262 
    2263 /**
    2264  * @addtogroup LLarchiveGroup
    2265  * @{
    2266  */
    2267 /**
    2268  * Function pointer to an appropriate @c move_files_to_cd routine.
    2269  * You can set this to your own function (for example, one to
    2270  * transfer files over the network) or leave it as is.
    2271  */
    2272 int (*move_files_to_cd) (char *, ...) =
    2273     _move_files_to_cd;
     2933/* @} - end of LLarchiveGroup */
    22742934
    22752935/**
     
    23653025/* @} - end of LLarchiveGroup */
    23663026
    2367 
    2368 /**
    2369  * @addtogroup LLarchiveGroup
    2370  * @{
    2371  */
    2372 /**
    2373  * Function pointer to an appropriate @c move_files_to_stream routine.
    2374  * You can set this to your own function (for example, one to
    2375  * transfer files over the network) or leave it as is.
    2376  */
    2377 int (*move_files_to_stream) (char *, ...) =
    2378     _move_files_to_stream;
    2379 
    23803027/**
    23813028 * Copy some files to tape.
     
    24973144}
    24983145
    2499 
    2500 /**
    2501  * Asks the user to put a CD-R(W) in the drive.
    2502  * @param ask_for_one_if_more_than_this (unused)
    2503  * @param pmountable If non-NULL, pointed-to value is set to TRUE if the CD is mountable, FALSE otherwise.
    2504  */
    2505 void
    2506 pause_and_ask_for_cdr(int ask_for_one_if_more_than_this, bool * pmountable)
    2507 {
    2508 
    2509     /*@ buffers ********************************************* */
    2510     char *tmp = NULL;
    2511     char *cdrom_dev = NULL;
    2512     char *cd_dev = NULL;
    2513     char *our_serial_str = NULL;
    2514     bool ok_go_ahead_burn_it;
    2515     int cd_number = -1;
    2516     int attempt_to_mount_returned_this = 999;
    2517     char *mtpt = NULL;
    2518     char *szcdno = NULL;
    2519     char *szserfname = NULL;
    2520     char *szunmount = NULL;
    2521     char *mds = NULL;
    2522 
    2523     malloc_string(cd_dev);
    2524 
    2525     mds = media_descriptor_string(g_backup_media_type);
    2526     log_to_screen("I am about to burn %s #%d", mds, g_current_media_number);
    2527     mr_free(mds);
    2528     if (g_current_media_number < ask_for_one_if_more_than_this) {
    2529         return;
    2530     }
    2531     log_to_screen("Scanning CD-ROM drive...");
    2532     mr_asprintf(mtpt, "%s/cd.mtpt", bkpinfo->tmpdir);
    2533     make_hole_for_dir(mtpt);
    2534 
    2535   gotos_make_me_puke:
    2536     ok_go_ahead_burn_it = TRUE;
    2537     mr_free(cdrom_dev);
    2538     if ((cdrom_dev = find_optical_device()) != NULL) {
    2539         /* When enabled, it made CD eject-and-retract when wrong CD inserted.. Weird
    2540         log_msg(2, "paafcd: Retracting CD-ROM drive if possible" );
    2541         retract_CD_tray_and_defeat_autorun();
    2542         */
    2543         mr_asprintf(tmp, "umount %s", cdrom_dev);
    2544         run_program_and_log_output(tmp, 1);
    2545         mr_asprintf(szcdno, "%s/archives/THIS-CD-NUMBER", mtpt);
    2546         mr_asprintf(szserfname, "%s/archives/SERIAL-STRING", mtpt);
    2547         mr_asprintf(szunmount, "umount %s", mtpt);
    2548         cd_number = -1;
    2549         mr_asprintf(tmp, "mount %s %s", cdrom_dev, mtpt);
    2550         mr_asprintf(our_serial_str, "%s", "");
    2551         attempt_to_mount_returned_this = run_program_and_log_output(tmp, 1);
    2552         mr_free(tmp);
    2553 
    2554         if (attempt_to_mount_returned_this) {
    2555             log_msg(4, "Failed to mount %s at %s", cdrom_dev, mtpt);
    2556             log_to_screen("If there's a CD/DVD in the drive, it's blank.");
    2557         } else if (!does_file_exist(szcdno) || !does_file_exist(szserfname)) {
    2558             mds = media_descriptor_string(g_backup_media_type);
    2559             log_to_screen("%s has data on it but it's probably not a Mondo CD.", mds);
    2560             mr_free(mds);
    2561         } else {
    2562             mds = media_descriptor_string(g_backup_media_type);
    2563             log_to_screen("%s found in drive. It's a Mondo disk.", mds);
    2564             mr_free(mds);
    2565 
    2566             cd_number = atoi(last_line_of_file(szcdno));
    2567             mr_asprintf(tmp, "cat %s 2> /dev/null", szserfname);
    2568             mr_free(our_serial_str);
    2569             our_serial_str = call_program_and_get_last_line_of_output(tmp);
    2570             mr_free(tmp);
    2571             // FIXME - should be able to use last_line_of_file(), surely?
    2572         }
    2573         mr_free(szcdno);
    2574         mr_free(szserfname);
    2575 
    2576         run_program_and_log_output(szunmount, 1);
    2577         mr_free(szunmount);
    2578 
    2579         log_msg(2, "paafcd: cd_number = %d", cd_number);
    2580         log_msg(2, "our serial str = %s; bkpinfo->serial_string = %s", our_serial_str, bkpinfo->serial_string);
    2581         if (cd_number > 0 && !strcmp(our_serial_str, bkpinfo->serial_string)) {
    2582             mds = media_descriptor_string(g_backup_media_type);
    2583             log_msg(2, "This %s is part of this backup set!", mds);
    2584             ok_go_ahead_burn_it = FALSE;
    2585             if (cd_number == g_current_media_number - 1) {
    2586                 log_to_screen("I think you've left the previous %s in the drive.", mds);
    2587             } else {
    2588                 log_to_screen("Please remove this %s. It is part of the backup set you're making now.", mds);
    2589             }
    2590             mr_free(mds);
    2591 
    2592         } else {
    2593             log_to_screen("...but not part of _our_ backup set.");
    2594         }
    2595         mr_free(our_serial_str);
    2596     } else {
    2597         mds = media_descriptor_string(g_backup_media_type);
    2598         log_msg(2,
    2599                 "paafcd: Can't find CD-ROM drive. Perhaps it has a blank %s in it?", mds);
    2600         if (interrogate_disk_currently_in_cddrive(cd_dev, FALSE)) {
    2601             ok_go_ahead_burn_it = FALSE;
    2602             log_to_screen("There isn't a writable %s in the drive.", mds);
    2603         }
    2604         mr_free(mds);
    2605     }
    2606 
    2607     if (!ok_go_ahead_burn_it) {
    2608         if (!bkpinfo->please_dont_eject) {
    2609             eject_device(cdrom_dev);
    2610         }
    2611         mds = media_descriptor_string(g_backup_media_type);
    2612         mr_asprintf(tmp, "I am about to burn %s #%d of the backup set. Please insert %s and press Enter.", mds, g_current_media_number, mds);
    2613         mr_free(mds);
    2614 
    2615         popup_and_OK(tmp);
    2616         mr_free(tmp);
    2617         goto gotos_make_me_puke;
    2618     } else {
    2619         log_msg(2, "paafcd: OK, going ahead and burning it.");
    2620     }
    2621 
    2622     mds = media_descriptor_string(g_backup_media_type);
    2623     log_msg(2, "paafcd: OK, I assume I have a blank/reusable %s in the drive...", mds);
    2624 
    2625     log_to_screen("Proceeding w/ %s in drive.", mds);
    2626     mr_free(mds);
    2627 
    2628     mr_free(cdrom_dev);
    2629     paranoid_free(cd_dev);
    2630     mr_free(mtpt);
    2631     if (pmountable) {
    2632         if (attempt_to_mount_returned_this) {
    2633             *pmountable = FALSE;
    2634         } else {
    2635             *pmountable = TRUE;
    2636         }
    2637     }
    2638 
    2639 }
    2640 
    2641 
    2642 /**
    2643  * Set the <tt>N</tt>th bit of @c array to @c true_or_false.
    2644  * @param array The bit array (as a @c char pointer).
    2645  * @param N The bit number to set or reset.
    2646  * @param true_or_false If TRUE then set bit @c N, if FALSE then reset bit @c N.
    2647  * @see get_bit_N_of_array
    2648  */
    2649 void set_bit_N_of_array(char *array, int N, bool true_or_false)
    2650 {
    2651     int bit_number;
    2652     int mask, orig_val, to_add;
    2653     int element_number;
    2654 
    2655     assert(array != NULL);
    2656 
    2657     element_number = N / 8;
    2658     bit_number = N % 8;
    2659     to_add = (1 << bit_number);
    2660     mask = 255 - to_add;
    2661     orig_val = array[element_number] & mask;
    2662     //  log_it("array[%d]=%02x; %02x&%02x = %02x", element_number, array[element_number], mask, orig_val);
    2663     if (true_or_false) {
    2664         array[element_number] = orig_val | to_add;
    2665     }
    2666 }
    2667 
    26683146/* @} - end of utilityGroup */
    2669 
    2670 
    2671 /**
    2672  * Chop up @c filename.
    2673  * @param bkpinfo The backup information structure. Fields used:
    2674  * - @c backup_media_type
    2675  * - @c compression_level
    2676  * - @c optimal_set_size
    2677  * - @c tmpdir
    2678  * - @c use_lzo
    2679  * - @c zip_exe
    2680  * - @c zip_suffix
    2681  *
    2682  * @param biggie_filename The file to chop up.
    2683  * @param ntfsprog_fifo The FIFO to ntfsclone if this is an imagedev, NULL otherwise.
    2684  * @param biggie_file_number The sequence number of this biggie file (starting from 0).
    2685  * @param noof_biggie_files The number of biggie files there are total.
    2686  * @return The number of errors encountered (0 for success)
    2687  * @see make_slices_and_images
    2688  * @ingroup LLarchiveGroup
    2689  */
    2690 int slice_up_file_etc(char *biggie_filename, char *ntfsprog_fifo, long biggie_file_number, long noof_biggie_files, bool use_ntfsprog) {
    2691 
    2692     /*@ buffers ************************************************** */
    2693     char *tmp = NULL;
    2694     char *checksum_line = NULL;
    2695     char *command = NULL;
    2696     char *tempblock = NULL;
    2697     char *curr_slice_fname_uncompressed = NULL;
    2698     char *curr_slice_fname_compressed = NULL;
    2699     char *file_to_archive = NULL;
    2700     char *file_to_openin = NULL;
    2701     /*@ pointers ************************************************** */
    2702     char *pB = NULL;
    2703     FILE *fin = NULL;
    2704     FILE *fout = NULL;
    2705 
    2706     /*@ bool ****************************************************** */
    2707     bool finished = FALSE;
    2708 
    2709     /*@ long ****************************************************** */
    2710     size_t blksize = (size_t)0;
    2711     long slice_num = 0L;
    2712     long i = 0L;
    2713     bool should_I_compress_slices = TRUE;
    2714     char *suffix = NULL;                // for compressed slices
    2715 
    2716     /*@ long long ************************************************** */
    2717     off_t totalread = (off_t)0;
    2718     off_t totallength = (off_t)0;
    2719 
    2720     /*@ int ******************************************************** */
    2721     int retval = 0;
    2722     int res = 0;
    2723 
    2724     /*@ structures ************************************************** */
    2725     struct s_filename_and_lstat_info biggiestruct;
    2726 
    2727     assert(bkpinfo != NULL);
    2728     assert_string_is_neither_NULL_nor_zerolength(biggie_filename);
    2729 
    2730     biggiestruct.for_backward_compatibility = '\n';
    2731     biggiestruct.use_ntfsprog = use_ntfsprog;
    2732     if (is_this_file_compressed(biggie_filename) || bkpinfo->compression_level == 0) {
    2733         mr_asprintf(suffix, "%s", "");
    2734         should_I_compress_slices = FALSE;
    2735     } else {
    2736         mr_asprintf(suffix, "%s", bkpinfo->zip_suffix);
    2737         should_I_compress_slices = TRUE;
    2738     }
    2739 
    2740     if (bkpinfo->optimal_set_size < 999L) {
    2741         fatal_error("bkpinfo->optimal_set_size is insanely small");
    2742     }
    2743 
    2744     if (ntfsprog_fifo) {
    2745         file_to_openin = ntfsprog_fifo;
    2746         mr_asprintf(checksum_line, "IGNORE");
    2747         log_msg(2, "Not calculating checksum for %s: it would take too long", biggie_filename);
    2748         if ((tmp = find_home_of_exe("ntfsresize")) == NULL) {
    2749             fatal_error("ntfsresize not found");
    2750         }
    2751         mr_asprintf(command, "%s --force --info %s|grep '^You might resize at '|cut -d' ' -f5", tmp, biggie_filename);
    2752         mr_free(tmp);
    2753         log_it("command = %s", command);
    2754         tmp = call_program_and_get_last_line_of_output(command);
    2755         mr_free(command);
    2756         log_it("res of it = %s", tmp);
    2757         totallength = (off_t)atoll(tmp);
    2758         mr_free(tmp);
    2759     } else {
    2760         file_to_openin = biggie_filename;
    2761         if (strchr(biggie_filename,'\'') != NULL) {
    2762             mr_asprintf(command, "md5sum \"%s\"", biggie_filename);
    2763         } else {
    2764             mr_asprintf(command, "md5sum '%s'", biggie_filename);
    2765         }
    2766         if (!(fin = popen(command, "r"))) {
    2767             log_OS_error("Unable to popen-in command");
    2768             mr_free(suffix);
    2769             return (1);
    2770         }
    2771         mr_free(command);
    2772         mr_getline(checksum_line, fin);
    2773         pclose(fin);
    2774         totallength = length_of_file(biggie_filename);
    2775     }
    2776     lstat(biggie_filename, &biggiestruct.properties);
    2777     strcpy(biggiestruct.filename, biggie_filename);
    2778     pB = strchr(checksum_line, ' ');
    2779     if (!pB) {
    2780         pB = strchr(checksum_line, '\t');
    2781     }
    2782     if (pB) {
    2783         *pB = '\0';
    2784     }
    2785     strcpy(biggiestruct.checksum, checksum_line);
    2786     mr_free(checksum_line);
    2787 
    2788     mr_asprintf(tmp, "%s", slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""));
    2789     fout = fopen(tmp, "w");
    2790     if (fout == NULL) {
    2791         log_msg(1, "Unable to open and write to %s", tmp);
    2792         mr_free(tmp);
    2793         mr_free(suffix);
    2794         return (1);
    2795     }
    2796     res = fwrite((void *) &biggiestruct, 1, sizeof(biggiestruct), fout);
    2797     paranoid_fclose(fout);
    2798     mr_free(tmp);
    2799 
    2800     log_msg(1, "Opening in %s; slicing it and writing to CD/tape", file_to_openin);
    2801     if (!(fin = fopen(file_to_openin, "r"))) {
    2802         log_OS_error("Unable to openin biggie_filename");
    2803         log_to_screen("Cannot archive bigfile '%s': not found", biggie_filename);
    2804 
    2805         mr_free(suffix);
    2806         return (1);
    2807     }
    2808     if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    2809         res = move_files_to_stream(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);
    2810     } else {
    2811         res = move_files_to_cd(slice_fname(biggie_file_number, 0, bkpinfo->tmpdir, ""), NULL);
    2812     }
    2813     i = bkpinfo->optimal_set_size / 256L;
    2814     if (!(tempblock = (char *) malloc(256 * 1024))) {
    2815         fatal_error("malloc error 256*1024");
    2816     }
    2817     for (slice_num = 1; !finished; slice_num++) {
    2818         mr_asprintf(curr_slice_fname_uncompressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, ""));
    2819         mr_asprintf(curr_slice_fname_compressed, "%s", slice_fname(biggie_file_number, slice_num, bkpinfo->tmpdir, suffix));
    2820 
    2821         tmp = percent_media_full_comment();
    2822         update_progress_form(tmp);
    2823         mr_free(tmp);
    2824 
    2825         if (!(fout = fopen(curr_slice_fname_uncompressed, "w"))) {
    2826             log_OS_error(curr_slice_fname_uncompressed);
    2827             mr_free(suffix);
    2828             return (1);
    2829         }
    2830         if ((i == bkpinfo->optimal_set_size / 256L) && (totalread < (off_t)1.1 * totallength)) {
    2831             for (i = 0L; i < (bkpinfo->optimal_set_size / 256L); i++) {
    2832                 blksize = fread(tempblock, 1, 256 * 1024, fin);
    2833                 if (blksize > (size_t)0) {
    2834                     totalread = totalread + (off_t)blksize;
    2835                     res = fwrite(tempblock, 1, blksize, fout);
    2836                 } else {
    2837                     break;
    2838                 }
    2839             }
    2840         } else {
    2841             i = 0L;
    2842         }
    2843         paranoid_fclose(fout);
    2844         if (i > 0L)             // length_of_file (curr_slice_fname_uncompressed)
    2845         {
    2846             if (!does_file_exist(curr_slice_fname_uncompressed)) {
    2847                 log_msg(2, "Warning - '%s' doesn't exist. How can I compress slice?", curr_slice_fname_uncompressed);
    2848             }
    2849             if (should_I_compress_slices && bkpinfo->compression_level > 0) {
    2850                 mr_asprintf(command, "%s -%d %s", bkpinfo->zip_exe, bkpinfo->compression_level, curr_slice_fname_uncompressed);
    2851                 log_msg(2, command);
    2852                 if ((res = system(command))) {
    2853                     log_OS_error(command);
    2854                 }
    2855                 //          did_I_compress_slice = TRUE;
    2856             } else {
    2857                 mr_asprintf(command, "mv %s %s 2>> %s", curr_slice_fname_uncompressed, curr_slice_fname_compressed, MONDO_LOGFILE);
    2858                 res = 0;        // don't do it :)
    2859                 //          did_I_compress_slice = FALSE;
    2860             }
    2861             mr_free(command);
    2862 
    2863             retval += res;
    2864             if (res) {
    2865                 log_msg(2, "Failed to compress the slice");
    2866             }
    2867             if (bkpinfo->use_lzo && strcmp(curr_slice_fname_compressed, curr_slice_fname_uncompressed)) {
    2868                 unlink(curr_slice_fname_uncompressed);
    2869             }
    2870             if (res) {
    2871                 mr_asprintf(tmp, "Problem with slice # %ld", slice_num);
    2872             } else {
    2873                 mr_asprintf(tmp, "%s - Bigfile #%ld, slice #%ld compressed OK          ", biggie_filename, biggie_file_number + 1, slice_num);
    2874             }
    2875             if (!g_text_mode) {
    2876                 newtDrawRootText(0, g_noof_rows - 2, tmp);
    2877                 newtRefresh();
    2878             } else {
    2879                 log_msg(2, tmp);
    2880             }
    2881             mr_free(tmp);
    2882 
    2883             mr_asprintf(file_to_archive, "%s", curr_slice_fname_compressed);
    2884             g_current_progress++;
    2885         } else {                /* if i==0 then ... */
    2886             finished = TRUE;
    2887             mr_asprintf(file_to_archive, "%s", curr_slice_fname_uncompressed);
    2888             if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    2889                 break;
    2890             }
    2891         }
    2892         mr_free(curr_slice_fname_uncompressed);
    2893         mr_free(curr_slice_fname_compressed);
    2894 
    2895         if (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type)) {
    2896             register_in_tape_catalog(biggieslice, biggie_file_number, slice_num, file_to_archive);
    2897             maintain_collection_of_recent_archives(bkpinfo->tmpdir, file_to_archive);
    2898             res = move_files_to_stream(file_to_archive, NULL);
    2899         } else {
    2900             res = move_files_to_cd(file_to_archive, NULL);
    2901         }
    2902         mr_free(file_to_archive);
    2903 
    2904         retval += res;
    2905         if (res) {
    2906             log_to_screen("Failed to add slice %ld of bigfile %ld to scratchdir", slice_num, biggie_file_number + 1);
    2907             fatal_error("Hard disk full. You should have bought a bigger one.");
    2908         }
    2909     }
    2910     mr_free(tempblock);
    2911     mr_free(suffix);
    2912     paranoid_fclose(fin);
    2913     mr_asprintf(tmp, "Sliced bigfile #%ld", biggie_file_number + 1);
    2914     if (retval) {
    2915         mr_strcat(tmp, "...FAILED");
    2916     } else {
    2917         mr_strcat(tmp, "...OK!");
    2918     }
    2919     log_msg(1, tmp);
    2920     mr_free(tmp);
    2921 
    2922     return (retval);
    2923 }
    2924 
    2925 
    2926 /**
    2927  * Remove the archives in @c d.
    2928  * This could possibly include any of:
    2929  * - all afioballs (compressed and not)
    2930  * - all filelists
    2931  * - all slices
    2932  * - all checksums
    2933  * - a zero filler file
    2934  *
    2935  * @param d The directory to wipe the archives from.
    2936  * @ingroup utilityGroup
    2937  */
    2938 void wipe_archives(char *d)
    2939 {
    2940     /*@ buffers ********************************************* */
    2941     char *tmp = NULL;
    2942     char *dir = NULL;
    2943 
    2944     assert_string_is_neither_NULL_nor_zerolength(d);
    2945 
    2946     mr_asprintf(dir, "%s/archives", d);
    2947     mr_asprintf(tmp, "rm -f %s/*.afio.* %s/*.star.*", dir, dir);
    2948     run_program_and_log_output(tmp, FALSE);
    2949     mr_free(tmp);
    2950     mr_asprintf(tmp, "rm -f %s/*list.[0-9]* %s/slice*", dir, dir);
    2951     run_program_and_log_output(tmp, FALSE);
    2952     mr_free(tmp);
    2953     mr_asprintf(tmp, "rm -f %s/cklist* %s/zero", dir, dir);
    2954     run_program_and_log_output(tmp, FALSE);
    2955     mr_free(tmp);
    2956     log_msg(1, "Wiped %s's archives", dir);
    2957     mr_asprintf(tmp, "ls -l %s", dir);
    2958     mr_free(dir);
    2959     run_program_and_log_output(tmp, FALSE);
    2960     mr_free(tmp);
    2961 }
    29623147
    29633148
     
    29663151 * @{
    29673152 */
    2968 /**
    2969  * Write the final ISO image.
    2970  * @param bkpinfo The backup information structure. Used only
    2971  * in the call to @c write_iso_and_go_on().
    2972  * @return The number of errors encountered (0 for success)
    2973  * @see write_iso_and_go_on
    2974  * @see make_iso_fs
    2975  * @bug The final ISO is written even if there are no files on it. In practice,
    2976  * however, this occurs rarely.
    2977  */
    2978 int write_final_iso_if_necessary()
    2979 {
    2980     /*@ int ***************************************************** */
    2981     int res;
    2982 
    2983     /*@ buffers ************************************************** */
    2984     char *tmp = NULL;
    2985 
    2986     assert(bkpinfo != NULL);
    2987     // I should really check if there are any slices or tarballs to be copied to CD-R(W)'s; the odds are approx. 1 in a million that there are no files here, so I'll just go ahead & make one more CD anyway
    2988 
    2989     tmp = mr_center_string("Writing the final ISO", 80);
    2990     log_msg(2, tmp);
    2991     if (!g_text_mode) {
    2992         newtPushHelpLine(tmp);
    2993     }
    2994     mr_free(tmp);
    2995     res = write_iso_and_go_on(TRUE);
    2996     if (!g_text_mode) {
    2997         newtPopHelpLine();
    2998     }
    2999     log_msg(2, "Returning from writing final ISO (res=%d)", res);
    3000     return (res);
    3001 }
    3002 
    3003 
    3004 /**
    3005  * Write an ISO image to <tt>[bkpinfo->isodir]/bkpinfo->prefix-[g_current_media_number].iso</tt>.
    3006  * @param bkpinfo The backup information structure. Fields used:
    3007  * - @c backup_media_type
    3008  * - @c prefix
    3009  * - @c isodir
    3010  * - @c manual_cd_tray
    3011  * - @c media_size
    3012  * - @c netfs_remote_dir
    3013  * - @c scratchdir
    3014  * - @c verify_data
    3015  *
    3016  * @param last_cd If TRUE, this is the last CD to write; if FALSE, it's not.
    3017  * @return The number of errors encountered (0 for success)
    3018  * @see make_iso_fs
    3019  */
    3020 int write_iso_and_go_on(bool last_cd)
    3021 {
    3022     /*@ pointers **************************************************** */
    3023     FILE *fout;
    3024 
    3025     /*@ buffers ***************************************************** */
    3026     char *tmp = NULL;
    3027     char *tmp1 = NULL;
    3028     char *cdno_fname = NULL;
    3029     char *lastcd_fname = NULL;
    3030     char *isofile = NULL;
    3031     char *mds = NULL;
    3032 
    3033     /*@ bool ******************************************************** */
    3034     bool that_one_was_ok;
    3035     bool orig_vfy_flag_val;
    3036 
    3037     /*@ int *********************************************************** */
    3038     int res = 0;
    3039 
    3040     assert(bkpinfo != NULL);
    3041     orig_vfy_flag_val = bkpinfo->verify_data;
    3042     if (bkpinfo->media_size <= 0) {
    3043         fatal_error("write_iso_and_go_on() - unknown media size");
    3044     }
    3045 
    3046     mds = media_descriptor_string(bkpinfo->backup_media_type);
    3047     log_msg(1, "OK, time to make %s #%d", mds, g_current_media_number);
    3048     mr_free(mds);
    3049 
    3050     /* label the ISO with its number */
    3051 
    3052     mr_asprintf(cdno_fname, "%s/archives/THIS-CD-NUMBER", bkpinfo->scratchdir);
    3053     fout = fopen(cdno_fname, "w");
    3054     mr_free(cdno_fname);
    3055 
    3056     fprintf(fout, "%d", g_current_media_number);
    3057     paranoid_fclose(fout);
    3058 
    3059     mr_asprintf(tmp1, "cp -f %s/autorun %s/", g_mondo_home, bkpinfo->scratchdir);
    3060     if (run_program_and_log_output(tmp1, FALSE)) {
    3061         log_msg(2, "Warning - unable to copy autorun to scratchdir");
    3062     }
    3063     mr_free(tmp1);
    3064 
    3065     /* last CD or not? Label accordingly */
    3066     mr_asprintf(lastcd_fname, "%s/archives/NOT-THE-LAST", bkpinfo->scratchdir);
    3067     if (last_cd) {
    3068         unlink(lastcd_fname);
    3069         log_msg(2,
    3070                 "OK, you're telling me this is the last CD. Fair enough.");
    3071     } else {
    3072         fout = fopen(lastcd_fname, "w");
    3073         fprintf(fout,
    3074                 "You're listening to 90.3 WPLN, Nashville Public Radio.\n");
    3075         paranoid_fclose(fout);
    3076     }
    3077     mr_free(lastcd_fname);
    3078 
    3079     if (space_occupied_by_cd(bkpinfo->scratchdir) / 1024 > bkpinfo->media_size) {
    3080         log_to_screen("Warning! CD is too big. It occupies %ld KB, which is more than the %ld MB allowed.",(long) space_occupied_by_cd(bkpinfo->scratchdir),(long) bkpinfo->media_size);
    3081     }
    3082 
    3083     if (bkpinfo->netfs_remote_dir != NULL) {
    3084         // NETFS
    3085         mr_asprintf(isofile, "%s/%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->netfs_remote_dir, bkpinfo->prefix, g_current_media_number);
    3086     } else {
    3087         // ISO
    3088         mr_asprintf(isofile, "%s/%s-%d.iso", bkpinfo->isodir, bkpinfo->prefix, g_current_media_number);
    3089     }
    3090     for (that_one_was_ok = FALSE; !that_one_was_ok;) {
    3091         if (bkpinfo->backup_media_type != usb) {
    3092             res = make_iso_fs(isofile);
    3093         } else {
    3094             res = make_usb_fs();
    3095         }
    3096         if (g_current_media_number == 1 && !res
    3097             && (bkpinfo->backup_media_type == cdr)) {
    3098             if ((tmp = find_optical_device())   == NULL) {  // make sure find_optical_device() finds, records CD-R's loc
    3099                 log_msg(3, "*Sigh* Mike, I hate your computer.");
    3100                 // if it can't be found then force pausing
    3101                 bkpinfo->manual_cd_tray = TRUE;
    3102             } else {
    3103                 log_msg(3, "Great. Found Mike's CD-ROM drive.");
    3104             }
    3105             mr_free(tmp);
    3106         }
    3107         if (bkpinfo->verify_data && !res) {
    3108             mds = media_descriptor_string(g_backup_media_type);
    3109             log_to_screen("Please reboot from the 1st %s in Compare Mode, as a precaution.", mds);
    3110             mr_free(mds);
    3111             if (chdir("/")) {
    3112                 // FIXME
    3113             }
    3114             log_it("Before calling verification of image()");
    3115             if (bkpinfo->backup_media_type == usb) {
    3116                 res += verify_usb_image();
    3117             } else {
    3118                 res += verify_cd_image();
    3119             }
    3120             log_it("After calling verification of image()");
    3121         }
    3122         if (!res) {
    3123             that_one_was_ok = TRUE;
    3124         } else {
    3125             mds = media_descriptor_string(bkpinfo->backup_media_type);
    3126             mr_asprintf(tmp1, "Failed to create %s #%d. Retry?", mds, g_current_media_number);
    3127             mr_free(mds);
    3128             res = ask_me_yes_or_no(tmp1);
    3129             mr_free(tmp1);
    3130 
    3131             if (!res) {
    3132                 if (ask_me_yes_or_no("Abort the backup?")) {
    3133                     fatal_error("FAILED TO BACKUP");
    3134                 } else {
    3135                     break;
    3136                 }
    3137             } else {
    3138                 log_msg(2, "Retrying, at user's request...");
    3139                 res = 0;
    3140             }
    3141         }
    3142     }
    3143     mr_free(isofile);
    3144 
    3145     g_current_media_number++;
    3146     wipe_archives(bkpinfo->scratchdir);
    3147     mr_asprintf(tmp1, "rm -Rf %s/images/*gz %s/images/*data*img", bkpinfo->scratchdir, bkpinfo->scratchdir);
    3148     if (system(tmp1)) {
    3149         log_msg(2, "Error occurred when I tried to delete the redundant IMGs and GZs");
    3150     }
    3151     mr_free(tmp1);
    3152 
    3153     if (last_cd) {
    3154         log_msg(2, "This was your last media.");
    3155     } else {
    3156         log_msg(2, "Continuing to backup your data...");
    3157     }
    3158 
    3159     bkpinfo->verify_data = orig_vfy_flag_val;
    3160     return (0);
    3161 }
    3162 
    3163 /* @} - end of LLarchiveGroup */
    3164 
    3165 
    31663153
    31673154
  • branches/3.3/mondo/src/common/libmondo-devices-EXT.h

    r3876 r3877  
    2424extern char *make_vn(char *file);
    2525extern int kick_vn(char *vn);
    26 extern char which_boot_loader(char *which_device);
     26extern char which_boot_loader(const char *which_device);
    2727
    2828extern int interactively_obtain_media_parameters_from_user(bool);
  • branches/3.3/mondo/src/common/libmondo-devices.c

    r3875 r3877  
    11641164        log_msg(3, "Mounting next media %d",cd_number_i_want);
    11651165        g_current_media_number = cd_number_i_want;
    1166         mount_media();
     1166        mount_media(MNT_CDROM);
    11671167
    11681168        mds = media_descriptor_string(bkpinfo->backup_media_type);
     
    18251825
    18261826/**
    1827  * Ask user for details of backup/restore information.
    1828  * Called when @c mondoarchive doesn't get any parameters.
    1829  * @param bkpinfo The backup information structure to fill out with the user's data.
    1830  * @param archiving_to_media TRUE if archiving, FALSE if restoring.
    1831  * @return 0, always.
    1832  * @bug No point of `int' return value.
    1833  * @ingroup archiveGroup
    1834  */
    1835 int interactively_obtain_media_parameters_from_user(bool archiving_to_media)
    1836 // archiving_to_media is TRUE if I'm being called by mondoarchive
    1837 // archiving_to_media is FALSE if I'm being called by mondorestore
    1838 {
    1839     char *tmp = NULL;
    1840     char *sz = NULL;
    1841     char *tmpro = NULL;
    1842     char *tmp1 = NULL;
    1843     char *tmp2 = NULL;
    1844     char *mds = NULL;
    1845     char *oldtmp = NULL;
    1846     char *q = NULL;
    1847     char p[16*MAX_STR_LEN];
    1848     char *sz_size = NULL;
    1849     char *command = NULL;
    1850     char *compression_type = NULL;
    1851     char *comment = NULL;
    1852     int i;
    1853     FILE *fin;
    1854 
    1855     malloc_string(tmp1);
    1856     assert(bkpinfo != NULL);
    1857     bkpinfo->nonbootable_backup = FALSE;
    1858 
    1859     // Tape, CD, NETFS, ...?
    1860     srandom(getpid());
    1861     bkpinfo->backup_media_type =
    1862         (g_restoring_live_from_cd) ? cdr :
    1863         which_backup_media_type(bkpinfo->restore_data);
    1864     if (bkpinfo->backup_media_type == none) {
    1865         log_to_screen("User has chosen not to backup the machine");
    1866         finish(1);
    1867     }
    1868     log_msg(3, "media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
    1869 
    1870     /* Why asking to remove the media with tape ?
    1871     if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
    1872         popup_and_OK("Please remove media from drive(s)");
    1873     }
    1874     */
    1875     if (archiving_to_media) {
    1876         // TODO: Should be common ?
    1877         setup_tmpdir(NULL);
    1878         /*
    1879          * Set the scratchdir to reside on the partition with the most free space.
    1880          * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
    1881          */
    1882 #ifdef __FreeBSD__
    1883         tmp = call_program_and_get_last_line_of_output("df -m -P -t nonfs,msdosfs,ntfs,ntfs-3g,vmhgfs,smbfs,smb,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done");
    1884 #else
    1885         tmp = call_program_and_get_last_line_of_output("df -m -P -x nfs -x nfs4 -x fuse.sshfs -x fuse -x vfat -x ntfs -x ntfs-3g -x vmhgfs -x smbfs -x smb -x cifs -x afs -x gfs -x ocfs -x ocfs2 -x mvfs -x nsspool -x nssvol -x iso9660 | grep -vE \"none|Filesystem|/dev/shm\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done");
    1886 #endif
    1887 
    1888         if (tmp[0] != '/') {
    1889             mr_asprintf(sz, "%s", tmp);
    1890             mr_free(tmp);
    1891             mr_asprintf(tmp, "/%s", sz);
    1892             mr_free(sz);
    1893         }
    1894         setup_scratchdir(tmp);
    1895         mr_free(tmp);
    1896 
    1897         if ((compression_type = which_compression_type()) == NULL) {
    1898             log_to_screen("User has chosen not to backup the machine");
    1899             finish(1);
    1900         }
    1901 
    1902         bkpinfo->compression_level = (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
    1903         if ((bkpinfo->compression_level = which_compression_level()) == -1) {
    1904             log_to_screen("User has chosen not to backup the machine");
    1905             finish(1);
    1906         }
    1907         bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
    1908         bkpinfo->use_lzo = (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
    1909     }
    1910     mvaddstr_and_log_it(2, 0, " ");
    1911 
    1912     // Find device's /dev (or SCSI) entry
    1913     switch (bkpinfo->backup_media_type) {
    1914     case cdr:
    1915     case dvd:
    1916     case usb:
    1917         /* Never try to eject a USB device */
    1918         if (bkpinfo->backup_media_type == usb) {
    1919             bkpinfo->please_dont_eject = TRUE;
    1920         }
    1921         mds = media_descriptor_string(bkpinfo->backup_media_type);
    1922         if (bkpinfo->backup_media_type != usb) {
    1923             if (ask_me_yes_or_no("Is your computer a laptop type (manual insert of MondoRescue media)?")) {
    1924                 bkpinfo->manual_cd_tray = TRUE;
    1925             }
    1926         }
    1927 
    1928         if (bkpinfo->media_device == NULL) {
    1929             bkpinfo->media_device = find_device(bkpinfo->backup_media_type);
    1930             if (bkpinfo->media_device != NULL) {
    1931                 log_msg(1, "MondoRescue device found automatically for your %s is %s", mds, bkpinfo->media_device);
    1932             } else {
    1933                 log_msg(1, "No MondoRescue device found yet for your %s", mds);
    1934             }
    1935         }
    1936 
    1937         if (archiving_to_media) {
    1938             if (bkpinfo->backup_media_type == dvd) {
    1939                 strcpy(tmp1, "1");
    1940                 mr_asprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE);  // 4.7 salesman's GB = 4.482 real GB = 4482 MB
    1941                 log_msg(1, "Setting to DVD defaults");
    1942             } else {
    1943                 strcpy(tmp1, "4");
    1944                 mr_asprintf(sz_size, "%d", 650);
    1945                 log_msg(1, "Setting to CD defaults");
    1946             }
    1947 
    1948             mr_asprintf(comment, "What speed is your %s writer?", mds);
    1949             if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
    1950                 if (!popup_and_get_string("Speed", comment, tmp1, 4)) {
    1951                     log_to_screen("User has chosen not to backup the machine");
    1952                     mr_free(comment);
    1953                     finish(1);
    1954                 }
    1955             }
    1956             mr_free(comment);
    1957             bkpinfo->cdrw_speed = atoi(tmp1);   // if DVD then this shouldn't ever be used anyway :)
    1958 
    1959             strcpy(tmp1, sz_size);
    1960             mr_asprintf(comment, "How much data (in Megabytes) will each %s store?", mds);
    1961             if (!popup_and_get_string("Size", comment, tmp1, 5)) {
    1962                 log_to_screen("User has chosen not to backup the machine");
    1963                 finish(1);
    1964             }
    1965             mr_asprintf(sz_size, "%s", tmp1);
    1966             bkpinfo->media_size = atoi(sz_size);
    1967 
    1968             if (bkpinfo->media_size <= 0) {
    1969                 log_to_screen("User has chosen not to backup the machine");
    1970                 finish(1);
    1971             }
    1972         }
    1973         /* No break because we continue even for usb */
    1974     case cdstream:
    1975 
    1976         // If media_device not found ask
    1977         if (bkpinfo->media_device == NULL) {
    1978             mr_asprintf(comment, "Please specify your Mondorescue %s media /dev entry", mds);
    1979             tmp2 = mr_popup_and_get_string("/dev entry?", comment, bkpinfo->media_device);
    1980             if (!tmp2) {
    1981                 log_to_screen("User has chosen not to backup the machine");
    1982                 finish(1);
    1983             } else {
    1984                 mr_free(bkpinfo->media_device);
    1985                 bkpinfo->media_device = tmp2;
    1986             }
    1987         }
    1988         log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
    1989         mr_asprintf(tmp, "MondoRescue thinks your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device);
    1990         if (!ask_me_yes_or_no(tmp)) {
    1991             mr_free(bkpinfo->media_device);
    1992         }
    1993         mr_free(tmp);
    1994 
    1995         if (bkpinfo->media_device == NULL) {
    1996             mr_asprintf(tmp, "Please then specify your Mondorescue %s media /dev entry", mds);
    1997             tmp2 = mr_popup_and_get_string("/dev entry?", tmp, bkpinfo->media_device);
    1998             mr_free(tmp);
    1999             if (tmp2 == NULL) {
    2000                 log_to_screen("User has chosen not to backup the machine");
    2001                 finish(1);
    2002             } else {
    2003                 mr_free(bkpinfo->media_device);
    2004                 bkpinfo->media_device = tmp2;
    2005             }
    2006         }
    2007         mr_free(mds);
    2008 
    2009         if (bkpinfo->backup_media_type == cdstream) {
    2010             bkpinfo->media_size = 650;
    2011         }
    2012         break;
    2013     case udev:
    2014         if (!ask_me_yes_or_no
    2015             ("This option is for advanced users only. Are you sure?")) {
    2016             log_to_screen("User has chosen not to backup the machine");
    2017             finish(1);
    2018         }
    2019     case tape:
    2020 
    2021         bkpinfo->media_device = find_tape_device();
    2022         if (bkpinfo->media_device != NULL) {
    2023             if ((fin = fopen(bkpinfo->media_device, "r"))) {
    2024                 paranoid_fclose(fin);
    2025             } else {
    2026                 if (does_file_exist("/tmp/mondorestore.cfg")) {
    2027                     read_cfg_var("/tmp/mondorestore.cfg", "media-dev", bkpinfo->media_device);
    2028                 }
    2029             }
    2030         }
    2031         if (bkpinfo->media_device != NULL) {
    2032             mr_asprintf(tmp, "Mondorescue thinks your tape streamer at %s; is that correct?", bkpinfo->media_device);
    2033             if (!ask_me_yes_or_no(tmp)) {
    2034                 mr_free(bkpinfo->media_device);
    2035             }
    2036             mr_free(tmp);
    2037         }
    2038         if (bkpinfo->media_device == NULL) {
    2039             tmp2 = mr_popup_and_get_string("Device name?", "What is the /dev entry of your tape streamer?", "");
    2040             if (tmp2 == NULL) {
    2041                 log_to_screen("User has chosen not to backup the machine");
    2042                 finish(1);
    2043             } else {
    2044                 bkpinfo->media_device = tmp2;
    2045             }
    2046         }
    2047         mr_asprintf(tmp, "ls -l %s", bkpinfo->media_device);
    2048         if (run_program_and_log_output(tmp, FALSE)) {
    2049             log_to_screen("User has not specified a valid /dev entry");
    2050             finish(1);
    2051         }
    2052         mr_free(tmp);
    2053 
    2054         mr_asprintf(sz_size,"%ld",bkpinfo->internal_tape_block_size);
    2055         tmp = mr_popup_and_get_string("Tape block size?", "What is the block size of your tape streamer?", sz_size);
    2056         if (tmp == NULL) {
    2057             log_to_screen("User has chosen not to backup the machine");
    2058             finish(1);
    2059         }
    2060         bkpinfo->internal_tape_block_size = atol(tmp);
    2061         mr_free(sz_size);
    2062         mr_free(tmp);
    2063 
    2064         // log the block-size
    2065         log_msg(0,"Tape block size= %ld", bkpinfo->internal_tape_block_size);
    2066 
    2067         if (bkpinfo->internal_tape_block_size <= 0) {
    2068             log_to_screen("User has chosen not to backup the machine");
    2069             finish(1);
    2070         }
    2071 
    2072         bkpinfo->media_size = 0;
    2073         log_msg(4, "media_size = %ld", bkpinfo->media_size);
    2074 
    2075         if (archiving_to_media) {
    2076             bkpinfo->use_obdr = ask_me_yes_or_no("Do you want to activate OBDR support for your tapes ?");
    2077             if (bkpinfo->use_obdr) {
    2078                 log_msg(4, "obdr mode = TRUE");
    2079             } else {
    2080                 log_msg(4, "obdr mode = FALSE");
    2081             }
    2082         }
    2083         break;
    2084 
    2085     case netfs:
    2086         /* Never try to eject a NETFS device */
    2087         bkpinfo->please_dont_eject = TRUE;
    2088         /*  Force NFS to be the protocol by default */
    2089         if (bkpinfo->netfs_proto == NULL) {
    2090             mr_asprintf(bkpinfo->netfs_proto, "nfs");
    2091         }
    2092 
    2093         /* Initiate bkpinfo netfs_mount path from running environment if not already done */
    2094         if (bkpinfo->netfs_mount == NULL) {
    2095             bkpinfo->netfs_mount = call_program_and_get_last_line_of_output("mount | grep \":\" | cut -d' ' -f1 | head -n1");
    2096         }
    2097 #ifdef __FreeBSD__
    2098         if (TRUE)
    2099 #else
    2100         if (!bkpinfo->disaster_recovery)
    2101 #endif
    2102         {
    2103             if (!popup_and_get_string("Network shared dir.", "Please enter path and directory where archives are stored remotely. (Mondo has taken a guess at the correct value. If it is incorrect, delete it and type the correct one.)", p,(MAX_STR_LEN / 4)-1)) {
    2104                 log_to_screen("User has chosen not to backup the machine");
    2105                 finish(1);
    2106             }
    2107             mr_free(bkpinfo->netfs_mount);
    2108             // check whether already mounted - we better remove
    2109             // surrounding spaces and trailing '/' for this
    2110             bkpinfo->netfs_mount = mr_strip_spaces(p);
    2111             if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/')
    2112                 bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0';
    2113             q = strchr(bkpinfo->netfs_mount, '@');
    2114             if (q != NULL) {
    2115                 /* User found. Store the 2 values */
    2116                 q++;
    2117                 /* new netfs mount */
    2118                 strcpy(tmp1,q);
    2119             } else {
    2120                 strcpy(tmp1,bkpinfo->netfs_mount);
    2121             }
    2122             mr_asprintf(command, "mount | grep \"%s \" | cut -d' ' -f3", tmp1);
    2123             mr_free(bkpinfo->isodir);
    2124             bkpinfo->isodir = call_program_and_get_last_line_of_output(command);
    2125             mr_free(command);
    2126 
    2127             if (!bkpinfo->restore_data) {
    2128                 mr_asprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE);  // 4.7 salesman's GB = 4.482 real GB = 4482 MB
    2129                 mr_asprintf(comment, "How much data (in Megabytes) will each media store?");
    2130                 strcpy(tmp1, sz_size);
    2131                 mr_free(sz_size);
    2132                 if (!popup_and_get_string("Size", comment, tmp1, 5)) {
    2133                     log_to_screen("User has chosen not to backup the machine");
    2134                     finish(1);
    2135                 }
    2136                 mr_free(comment);
    2137                 mr_asprintf(sz_size, "%s", tmp1);
    2138             } else {
    2139                 mr_asprintf(sz_size, "0");
    2140             }
    2141             bkpinfo->media_size = atoi(sz_size);
    2142             mr_free(sz_size);
    2143 
    2144             if (bkpinfo->media_size < 0) {
    2145                 log_to_screen("User has chosen not to backup the machine");
    2146                 finish(1);
    2147             }
    2148         }
    2149         /*  TODO: Useless I think */
    2150         if (bkpinfo->disaster_recovery) {
    2151             mr_asprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
    2152             paranoid_system(command);
    2153             mr_free(command);
    2154 
    2155         }
    2156         strcpy(tmp1, bkpinfo->netfs_proto);
    2157         if (!popup_and_get_string("Network protocol", "Which protocol should I use (nfs/sshfs/smbfs) ?",tmp1, MAX_STR_LEN-1)) {
    2158             log_to_screen("User has chosen not to backup the machine");
    2159             finish(1);
    2160         }
    2161         mr_free(bkpinfo->netfs_proto);
    2162         mr_asprintf(bkpinfo->netfs_proto, "%s", tmp1);
    2163 
    2164         strcpy(tmp1, bkpinfo->netfs_mount);
    2165         if (!popup_and_get_string("Network share", "Which remote share should I mount?", tmp1, MAX_STR_LEN-1)) {
    2166             log_to_screen("User has chosen not to backup the machine");
    2167             finish(1);
    2168         }
    2169         mr_free(bkpinfo->netfs_mount);
    2170         mr_asprintf(bkpinfo->netfs_mount, "%s", tmp1);
    2171 
    2172         if (bkpinfo->netfs_user) {
    2173             strcpy(tmp1, bkpinfo->netfs_user);
    2174         } else {
    2175             strcpy(tmp1, "");
    2176         }
    2177         if (!popup_and_get_string("Network user", "Which user should I use if any ?",tmp1, MAX_STR_LEN-1)) {
    2178             log_to_screen("User has chosen not to backup the machine");
    2179             finish(1);
    2180         }
    2181         mr_free(bkpinfo->netfs_user);
    2182         if (strcmp(tmp1, "") != 0) {
    2183             mr_asprintf(bkpinfo->netfs_user, "%s", tmp1);
    2184         }
    2185 
    2186         /* Initiate bkpinfo isodir path from running environment if mount already done */
    2187         log_msg(3, "Testing mount for %s", bkpinfo->netfs_mount);
    2188         if (is_this_device_mounted(bkpinfo->netfs_mount)) {
    2189             mr_free(bkpinfo->isodir);
    2190             bkpinfo->isodir = call_program_and_get_last_line_of_output("mount | grep \":\" | cut -d' ' -f3 | head -n1");
    2191         } else {
    2192             // Why netfsdir ?
    2193             mr_asprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir);
    2194             mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
    2195             run_program_and_log_output(command, 5);
    2196             mr_free(command);
    2197 
    2198             if (bkpinfo->restore_data) {
    2199                 /*  mount the FS read-only in restore mode to avoid any erase of whatever */
    2200                 mr_asprintf(tmpro, "-o ro");
    2201             } else {
    2202                 mr_asprintf(tmpro, "");
    2203             }
    2204 
    2205             /*  Build the mount string */
    2206             if (strstr(bkpinfo->netfs_proto, "smbfs")) {
    2207                 mr_asprintf(tmp, "mount -t cifs %s %s %s",bkpinfo->netfs_mount, bkpinfo->isodir,tmpro);
    2208                 if (bkpinfo->netfs_user) {
    2209                     mr_strcat(tmp, " -o user=%s", bkpinfo->netfs_user);
    2210                 }
    2211             else {
    2212                 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
    2213                     mr_asprintf(tmp, "sshfs %s ",tmpro);
    2214                 } else {
    2215                     mr_asprintf(tmp, "mount -t %s -o nolock %s ", bkpinfo->netfs_proto,tmpro);
    2216                 }
    2217                 if (bkpinfo->netfs_user) {
    2218                     mr_strcat(tmp, "%s@", bkpinfo->netfs_user);
    2219                 }
    2220                 mr_strcat(tmp, "%s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
    2221             }
    2222             run_program_and_log_output(tmp, 3);
    2223             mr_free(tmp);
    2224 
    2225             malloc_string(g_selfmounted_isodir);
    2226             strcpy(g_selfmounted_isodir, bkpinfo->isodir);
    2227             }
    2228         }
    2229        
    2230         log_msg(3, "Testing mount for %s", bkpinfo->netfs_mount);
    2231         if (!is_this_device_mounted(bkpinfo->netfs_mount)) {
    2232             popup_and_OK("Please mount that partition before you try to backup to or restore from it.");
    2233             finish(1);
    2234         }
    2235         if (bkpinfo->netfs_remote_dir == NULL) {
    2236             fatal_error("bkpinfo->netfs_remote_dir should not be NULL");
    2237         }
    2238         strcpy(tmp1, bkpinfo->netfs_remote_dir);
    2239         if (!popup_and_get_string ("Directory", "Which directory within that mountpoint?", tmp1, MAX_STR_LEN-1)) {
    2240             log_to_screen("User has chosen not to backup the machine");
    2241             finish(1);
    2242         }
    2243         mr_free(bkpinfo->netfs_remote_dir);
    2244         // check whether writable - we better remove surrounding spaces for this
    2245         bkpinfo->netfs_remote_dir = mr_strip_spaces(tmp1);
    2246 
    2247         tmp = mr_popup_and_get_string("Prefix.", "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files", bkpinfo->prefix);
    2248         if (tmp == NULL) {
    2249             log_to_screen("User has chosen not to backup the machine");
    2250             finish(1);
    2251         }
    2252         mr_free(bkpinfo->prefix);
    2253         bkpinfo->prefix = tmp;
    2254         log_msg(3, "prefix set to %s", bkpinfo->prefix);
    2255         log_msg(3, "Just set netfs_remote_dir to %s", bkpinfo->netfs_remote_dir);
    2256         log_msg(3, "isodir is still %s", bkpinfo->isodir);
    2257         break;
    2258 
    2259     case iso:
    2260         if (!bkpinfo->disaster_recovery) {
    2261             tmp = mr_popup_and_get_string("Storage dir.", "Please enter the full path name to the directory for your ISO images.  Example: /mnt/raid0_0", bkpinfo->isodir);
    2262             if (tmp == NULL) {
    2263                 log_to_screen("User has chosen not to backup the machine");
    2264                 finish(1);
    2265             } else {
    2266                 mr_free(bkpinfo->isodir);
    2267                 bkpinfo->isodir = tmp;
    2268             }
    2269             if (archiving_to_media) {
    2270                 sprintf(tmp1, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
    2271                 if (!popup_and_get_string("ISO size.", "Please enter how big you want each ISO image to be (in megabytes). This should be less than or equal to the size of the CD-R[W]'s (700) or DVD's (4480) you plan to backup to.", tmp1, 16)) {
    2272                     log_to_screen("User has chosen not to backup the machine");
    2273                     finish(1);
    2274                 }
    2275                 bkpinfo->media_size = atoi(tmp1);
    2276             } else {
    2277                 bkpinfo->media_size = 650;
    2278             }
    2279         }
    2280         tmp = mr_popup_and_get_string("Prefix.", "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files", bkpinfo->prefix);
    2281         if (tmp == NULL) {
    2282             log_to_screen("User has chosen not to backup the machine");
    2283             finish(1);
    2284         }
    2285         mr_free(bkpinfo->prefix);
    2286         bkpinfo->prefix = tmp;
    2287         log_msg(3, "prefix set to %s", bkpinfo->prefix);
    2288         break;
    2289     default:
    2290         fatal_error("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
    2291     }
    2292 
    2293     if (archiving_to_media) {
    2294         /*  Needs to be done before calling which_boot_loader */
    2295         bkpinfo->boot_type = mr_boot_type();
    2296         mr_free(bkpinfo->boot_device);
    2297 #ifdef __FreeBSD__
    2298         bkpinfo->boot_device = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'");
    2299 #else
    2300         bkpinfo->boot_device = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'");
    2301 #endif
    2302         i = which_boot_loader(bkpinfo->boot_device);
    2303         if (i == 'U')           // unknown
    2304         {
    2305 
    2306 #ifdef __FreeBSD__
    2307             if (!popup_and_get_string("Boot device", "What is your boot device? (e.g. /dev/ad0)", bkpinfo->boot_device,(MAX_STR_LEN / 4)-1)) {
    2308                 log_to_screen("User has chosen not to backup the machine");
    2309                 finish(1);
    2310             }
    2311             i = which_boot_loader(bkpinfo->boot_device);
    2312 #else
    2313             strcpy(tmp1, bkpinfo->boot_device);
    2314             if (!popup_and_get_string("Boot device", "What is your boot device? (e.g. /dev/hda)", tmp1,(MAX_STR_LEN / 4)-1)) {
    2315                 log_to_screen("User has chosen not to backup the machine");
    2316                 finish(1);
    2317             }
    2318             mr_free(bkpinfo->boot_device);
    2319             mr_asprintf(bkpinfo->boot_device, "%s", tmp1);
    2320 
    2321             if (does_string_exist_in_boot_block(bkpinfo->boot_device, "ELILO")) {
    2322                 i = 'E';
    2323             } else
    2324                 if (does_string_exist_in_boot_block(bkpinfo->boot_device, "LILO")) {
    2325                 i = 'L';
    2326             } else
    2327                 if (does_string_exist_in_boot_block(bkpinfo->boot_device, "GRUB")) {
    2328                 i = 'G';
    2329             } else {
    2330                 i = 'U';
    2331             }
    2332 #endif
    2333             if (i == 'U') {
    2334                 if (ask_me_yes_or_no("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")) {
    2335                     i = 'R';    // raw
    2336                 } else {
    2337                     log_to_screen("I cannot find your boot loader. Please run mondoarchive with parameters.");
    2338                     finish(1);
    2339                 }
    2340             }
    2341         }
    2342         bkpinfo->boot_loader = i;
    2343         /* TODO: Check consistency of boot type and boot loader */
    2344 
    2345         if (bkpinfo->include_paths) {
    2346             strcpy(tmp1, bkpinfo->include_paths);
    2347             mr_free(bkpinfo->include_paths);
    2348         } else {
    2349             strcpy(tmp1, "/");
    2350         }
    2351         if (!popup_and_get_string("Backup paths", "Please enter paths (separated by '|') which you want me to backup. The default is '/' (i.e. everything).", tmp1, MAX_STR_LEN-1)) {
    2352             log_to_screen("User has chosen not to backup the machine");
    2353             finish(1);
    2354         }
    2355         mr_asprintf(bkpinfo->include_paths, "%s", tmp1);
    2356 
    2357         tmp = list_of_NETFS_mounts_only();
    2358         if (strlen(tmp) > 2) {
    2359             mr_strcat(bkpinfo->exclude_paths, "|%s",tmp);
    2360         }
    2361         mr_free(tmp);
    2362 // NTFS
    2363         tmp = call_program_and_get_last_line_of_output("mr-parted2fdisk -l 2>/dev/null | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'");
    2364         strncpy(tmp1, tmp,(MAX_STR_LEN / 4)-1);
    2365         mr_free(tmp);
    2366         if (strlen(tmp1) > 2) {
    2367             if (!popup_and_get_string("NTFS partitions", "Please enter/confirm the NTFS partitions you wish to backup as well.", tmp1,(MAX_STR_LEN / 4)-1)) {
    2368                 log_to_screen("User has chosen not to backup the machine");
    2369                 finish(1);
    2370             }
    2371             mr_asprintf(bkpinfo->image_devs, "%s", tmp1);
    2372         }
    2373 
    2374         if (bkpinfo->exclude_paths != NULL ) {
    2375             mr_asprintf(p, "%s", bkpinfo->exclude_paths);
    2376         } else {
    2377             mr_asprintf(p, "%s", "");
    2378         }
    2379         tmp = mr_popup_and_get_string("Exclude paths", "Please enter paths which you do NOT want to backup. Separate them with '|'. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.", p);
    2380         mr_free(p);
    2381         if (tmp == NULL) {
    2382             log_to_screen("User has chosen not to backup the machine");
    2383             finish(1);
    2384         }
    2385         mr_free(bkpinfo->exclude_paths);
    2386         bkpinfo->exclude_paths = tmp;
    2387 
    2388         mr_asprintf(oldtmp, "%s", bkpinfo->tmpdir);
    2389         if (bkpinfo->tmpdir != NULL ) {
    2390             mr_asprintf(p, "%s", bkpinfo->tmpdir);
    2391         } else {
    2392             mr_asprintf(p, "%s", "");
    2393         }
    2394         tmp = mr_popup_and_get_string("Temporary directory", "Please enter your temporary directory.", p);
    2395         mr_free(p);
    2396         if (tmp == NULL) {
    2397             mr_free(oldtmp);
    2398             log_to_screen("User has chosen not to backup the machine");
    2399             finish(1);
    2400         }
    2401         /*  if modified to another path */
    2402         if (strcmp(tmp,oldtmp) != 0) {
    2403             setup_tmpdir(tmp);
    2404         }
    2405         mr_free(oldtmp);
    2406 
    2407         mr_asprintf(oldtmp, "%s", bkpinfo->scratchdir);
    2408         if (bkpinfo->scratchdir != NULL ) {
    2409             mr_asprintf(p, "%s", bkpinfo->scratchdir);
    2410         } else {
    2411             mr_asprintf(p, "%s", "");
    2412         }
    2413         tmp = mr_popup_and_get_string("Scratch directory", "Please enter your scratch directory.", p);
    2414         mr_free(p);
    2415         if (tmp == NULL) {
    2416             mr_free(oldtmp);
    2417             log_to_screen("User has chosen not to backup the machine");
    2418             finish(1);
    2419         }
    2420         /*  if modified to another path */
    2421         if (strcmp(tmp,oldtmp) != 0) {
    2422             setup_scratchdir(tmp);
    2423         }
    2424         mr_free(oldtmp);
    2425 
    2426         if (ask_me_yes_or_no("Do you want to backup extended attributes?")) {
    2427             mr_free(g_getfattr);
    2428             g_getfattr = find_home_of_exe("getfattr");
    2429             mr_free(g_getfacl);
    2430             g_getfacl = find_home_of_exe("getfacl");
    2431             log_it("Backup of extended attributes");
    2432         }
    2433 // Interactive mode:
    2434 #ifdef __IA64__
    2435         bkpinfo->make_cd_use_lilo = TRUE;
    2436 #else
    2437         bkpinfo->make_cd_use_lilo = FALSE;
    2438 #endif
    2439         bkpinfo->backup_data = TRUE;
    2440         if (strcmp(compression_type,"lzo") == 0) {
    2441             mr_asprintf(bkpinfo->zip_exe, "%s", "lzop");
    2442             mr_asprintf(bkpinfo->zip_suffix, "%s", "lzo");
    2443         } else if (strcmp(compression_type,"gzip") == 0) {
    2444             mr_asprintf(bkpinfo->zip_exe, "%s", "gzip");
    2445             mr_asprintf(bkpinfo->zip_suffix, "%s", "gz");
    2446         } else if (strcmp(compression_type,"lzma") == 0) {
    2447             mr_asprintf(bkpinfo->zip_exe, "%s", "xz");
    2448             mr_asprintf(bkpinfo->zip_suffix, "%s", "xz");
    2449         } else if (strcmp(compression_type,"bzip2") == 0) {
    2450             mr_asprintf(bkpinfo->zip_exe, "%s", "bzip2");
    2451             mr_asprintf(bkpinfo->zip_suffix, "%s", "bz2");
    2452         } else {
    2453             mr_free(bkpinfo->zip_exe);
    2454             mr_free(bkpinfo->zip_suffix);
    2455         }
    2456         mr_free(compression_type);
    2457 
    2458 #if __FreeBSD__ == 5
    2459         mr_asprintf(bkpinfo->kernel_path, "%s", "/boot/kernel/kernel");
    2460 #elif __FreeBSD__ == 4
    2461         mr_asprintf(bkpinfo->kernel_path, "%s", "/kernel");
    2462 #elif linux
    2463         if (figure_out_kernel_path_interactively_if_necessary(bkpinfo->kernel_path)) {
    2464             fatal_error("Kernel not found. Please specify manually with the '-k' switch.");
    2465         }
    2466 #else
    2467 #error "I don't know about this system!"
    2468 #endif
    2469 
    2470 
    2471         bkpinfo->verify_data =
    2472             ask_me_yes_or_no
    2473             ("Will you want to verify your backups after Mondo has created them?");
    2474 
    2475         if (!ask_me_yes_or_no
    2476             ("Are you sure you want to proceed? Hit 'no' to abort.")) {
    2477             log_to_screen("User has chosen not to backup the machine");
    2478             finish(1);
    2479         }
    2480     } else {
    2481         bkpinfo->restore_data = TRUE;   // probably...
    2482     }
    2483 
    2484     if (bkpinfo->backup_media_type == iso
    2485         || bkpinfo->backup_media_type == netfs) {
    2486         g_ISO_restore_mode = TRUE;
    2487     }
    2488 #ifdef __FreeSD__
    2489 // skip
    2490 #else
    2491     if (bkpinfo->backup_media_type == netfs) {
    2492         log_msg(3, "I think the Remote mount is mounted at %s", bkpinfo->isodir);
    2493     }
    2494     log_it("isodir = %s", bkpinfo->isodir);
    2495     if (bkpinfo->netfs_mount) {
    2496         log_it("netfs_mount = '%s'", bkpinfo->netfs_mount);
    2497     }
    2498     if (bkpinfo->netfs_user) {
    2499         log_it("netfs_user = '%s'", bkpinfo->netfs_user);
    2500     }
    2501     if (bkpinfo->netfs_proto) {
    2502         log_it("netfs_proto = '%s'", bkpinfo->netfs_proto);
    2503     }
    2504 #endif
    2505 
    2506     log_it("media device = %s", bkpinfo->media_device);
    2507     log_it("media size = %ld", bkpinfo->media_size);
    2508     log_it("media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
    2509     if (bkpinfo->prefix != NULL) {
    2510         log_it("prefix = %s", bkpinfo->prefix);
    2511     }
    2512     log_it("compression = %ld", bkpinfo->compression_level);
    2513     log_it("exclude_path = %s", bkpinfo->exclude_paths);
    2514     if (bkpinfo->include_paths) {
    2515         log_it("include_path = %s", bkpinfo->include_paths);
    2516     }
    2517 
    2518     /* Handle devices passed in bkpinfo and print result */
    2519     /*  the mr_make_devlist_from_pathlist function appends */
    2520     /*  to the *_paths variables so copy before */
    2521     mr_make_devlist_from_pathlist(bkpinfo->exclude_paths, 'E');
    2522     mr_make_devlist_from_pathlist(bkpinfo->include_paths, 'I');
    2523 
    2524     log_it("scratchdir = '%s'", bkpinfo->scratchdir);
    2525     log_it("tmpdir = '%s'", bkpinfo->tmpdir);
    2526     if (bkpinfo->image_devs) {
    2527         log_it("image_devs = '%s'", bkpinfo->image_devs);
    2528     }
    2529     log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device, bkpinfo->boot_loader);
    2530     if (bkpinfo->media_size < 0) {
    2531         if (archiving_to_media) {
    2532             fatal_error("Media size is less than zero.");
    2533         } else {
    2534             log_msg(2, "Warning - media size is less than zero.");
    2535             bkpinfo->media_size = 0;
    2536         }
    2537     }
    2538     paranoid_free(sz_size);
    2539     paranoid_free(tmp1);
    2540     return (0);
    2541 }
    2542 
    2543 
    2544 /**
    2545  * Get a |-separated list of NETFS mounts.
    2546  * @return The list created.
    2547  * @note The return value points to allocated string that needs to be freed by
    2548  * caller
    2549  * @bug Even though we only want the mounts, the devices are still checked.
    2550  */
    2551 char *list_of_NETFS_mounts_only(void)
    2552 {
    2553     char *exclude_these_directories = NULL;
    2554 
    2555     exclude_these_directories = call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,vmhgfs,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol,fuse.boostfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' '|' | awk '{print $0;}'");
    2556     log_msg(9,"list_of_NETFS_mounts_only returns %s",exclude_these_directories);
    2557     return(exclude_these_directories);
    2558 }
    2559 
    2560 /* @} - end of utilityGroup */
    2561 
    2562 
    2563 
    2564 
    2565 
    2566 /**
    2567  * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
    2568  * [random] is a random number between 1 and 32767.
    2569  * @param store_name_here Where to store the new filename.
    2570  * @param stub A random number will be appended to this to make the FIFO's name.
    2571  * @ingroup deviceGroup
    2572  */
    2573 void make_fifo(char *store_name_here, char *stub)
    2574 {
    2575     char *tmp = NULL;
    2576 
    2577     assert_string_is_neither_NULL_nor_zerolength(stub);
    2578 
    2579     sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
    2580             (int) (random() % 32768));
    2581     make_hole_for_file(store_name_here);
    2582     mkfifo(store_name_here, S_IRWXU | S_IRWXG);
    2583     mr_asprintf(tmp, "chmod 770 %s", store_name_here);
    2584     paranoid_system(tmp);
    2585     mr_free(tmp);
    2586 }
    2587 
    2588 
    2589 
    2590 /**
    2591  * @addtogroup deviceGroup
    2592  * @{
    2593  */
    2594 /**
    2595  * If we can read @p dev, set @p output to it.
    2596  * If @p dev cannot be read, set @p output to "".
    2597  * @param dev The device to check for.
    2598  * @param output Set to @p dev if @p dev exists, "" otherwise.
    2599  * @return TRUE if @p dev exists, FALSE if it doesn't.
    2600  */
    2601 bool set_dev_to_this_if_rx_OK(char *output, char *dev)
    2602 {
    2603     char *command = NULL;
    2604     bool ret=FALSE;
    2605 
    2606     if (!dev || dev[0] == '\0') {
    2607         output[0] = '\0';
    2608         return(ret);
    2609     }
    2610 //  assert_string_is_neither_NULL_nor_zerolength(dev);
    2611     if (!bkpinfo->please_dont_eject) {
    2612         log_msg(10, "Injecting %s", dev);
    2613         inject_device(dev);
    2614     }
    2615     if (!does_file_exist(dev)) {
    2616         log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
    2617         return(ret);
    2618     }
    2619     mr_asprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null", 512L, dev);
    2620     if (!run_program_and_log_output(command, FALSE) && !run_program_and_log_output(command, FALSE)) {
    2621         strcpy(output, dev);
    2622         log_msg(4, "Found it - %s", dev);
    2623         ret = TRUE;
    2624     } else {
    2625         output[0] = '\0';
    2626         log_msg(4, "It's not %s", dev);
    2627     }
    2628     mr_free(command);
    2629     return(ret);
    2630 }
    2631 
    2632 
    2633 
    2634 
    2635 
    2636 /**
    2637  * Find out what number CD is in the drive.
    2638  * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
    2639  * @return The current CD number, or -1 if it could not be found.
    2640  * @note If the CD is not mounted, it will be mounted
    2641  * (and remain mounted after this function returns).
    2642  */
    2643 int what_number_cd_is_this(void) {
    2644 
    2645     int cd_number = -1;
    2646     char *mountdev = NULL;
    2647     char *tmp = NULL;
    2648 
    2649     assert(bkpinfo != NULL);
    2650 //  log_it("Asking what_number_cd_is_this");
    2651     if ((g_ISO_restore_mode) || (g_restoring_live_from_cd)) {
    2652         tmp = call_program_and_get_last_line_of_output("mount | grep iso9660 | awk '{print $3;}'");
    2653         mr_asprintf(mountdev, "%s%s", tmp, "/archives/THIS-CD-NUMBER");
    2654         mr_free(tmp);
    2655         cd_number = atoi(last_line_of_file(mountdev));
    2656         mr_free(mountdev);
    2657         return (cd_number);
    2658     }
    2659 
    2660     if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {
    2661         log_it("ERROR: bkpinfo->media_device shoulnd't be unaccessible here\n");
    2662         /* trying again ! */
    2663         bkpinfo->media_device = find_optical_device();
    2664     }
    2665     if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {
    2666         fatal_error("ERROR: bkpinfo->media_device shoulnd't really be unaccessible here\n");
    2667     }
    2668     if (!is_this_device_mounted(bkpinfo->media_device, MNT_CDROM)) {
    2669         mount_media(MNT_CDROM);
    2670     }
    2671 
    2672     cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
    2673     return(cd_number);
    2674 }
    2675 
    2676 
    2677 /**
    2678  * Find out what device is mounted as root (/).
    2679  * @return Root device.
    2680  * @note The returned string points to storage that needs to be freed by
    2681  * caller
    2682  * @bug A bit of a misnomer; it's actually finding out the root device.
    2683  * The mountpoint (where it's mounted) will obviously be '/'.
    2684  */
    2685 char *where_is_root_mounted() {
    2686 
    2687 /*@ buffers **************** */
    2688 char *tmp = NULL;
    2689 
    2690 #ifdef __FreeBSD__
    2691     tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");
    2692 #else
    2693     tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//");
    2694     if (strstr(tmp, "/dev/cciss/")) {
    2695         mr_free(tmp);
    2696         tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1");
    2697     }
    2698     if (strstr(tmp, "/dev/md")) {
    2699         mr_free(tmp);
    2700         tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");
    2701     }
    2702 #endif
    2703 
    2704 return (tmp);
    2705 }
    2706 
    2707 
    2708 /**
    27091827 * Find out which boot loader is in use.
    27101828 * @param which_device Device to look for the boot loader on.
     
    27131831 */
    27141832#ifdef __FreeBSD__
    2715 char which_boot_loader(char *which_device)
     1833char which_boot_loader(const char *which_device)
    27161834{
    27171835    int count_lilos = 0;
     
    27571875#else
    27581876
    2759 char which_boot_loader(char *which_device)
     1877char which_boot_loader(const char *which_device)
    27601878{
    27611879    /*@ buffer ***************************************************** */
     
    28791997}
    28801998#endif
     1999
     2000
     2001/**
     2002 * Ask user for details of backup/restore information.
     2003 * Called when @c mondoarchive doesn't get any parameters.
     2004 * @param bkpinfo The backup information structure to fill out with the user's data.
     2005 * @param archiving_to_media TRUE if archiving, FALSE if restoring.
     2006 * @return 0, always.
     2007 * @bug No point of `int' return value.
     2008 * @ingroup archiveGroup
     2009 */
     2010int interactively_obtain_media_parameters_from_user(bool archiving_to_media)
     2011// archiving_to_media is TRUE if I'm being called by mondoarchive
     2012// archiving_to_media is FALSE if I'm being called by mondorestore
     2013{
     2014    char *tmp = NULL;
     2015    char *sz = NULL;
     2016    char *tmpro = NULL;
     2017    char *tmp1 = NULL;
     2018    char *tmp2 = NULL;
     2019    char *mds = NULL;
     2020    char *oldtmp = NULL;
     2021    char *q = NULL;
     2022    char p[16*MAX_STR_LEN];
     2023    char *sz_size = NULL;
     2024    char *command = NULL;
     2025    char *compression_type = NULL;
     2026    char *comment = NULL;
     2027    char i = '\0';
     2028    FILE *fin;
     2029
     2030    malloc_string(tmp1);
     2031    assert(bkpinfo != NULL);
     2032    bkpinfo->nonbootable_backup = FALSE;
     2033
     2034    // Tape, CD, NETFS, ...?
     2035    srandom(getpid());
     2036    bkpinfo->backup_media_type =
     2037        (g_restoring_live_from_cd) ? cdr :
     2038        which_backup_media_type(bkpinfo->restore_data);
     2039    if (bkpinfo->backup_media_type == none) {
     2040        log_to_screen("User has chosen not to backup the machine");
     2041        finish(1);
     2042    }
     2043    log_msg(3, "media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
     2044
     2045    /* Why asking to remove the media with tape ?
     2046    if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) {
     2047        popup_and_OK("Please remove media from drive(s)");
     2048    }
     2049    */
     2050    if (archiving_to_media) {
     2051        // TODO: Should be common ?
     2052        setup_tmpdir(NULL);
     2053        /*
     2054         * Set the scratchdir to reside on the partition with the most free space.
     2055         * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
     2056         */
     2057#ifdef __FreeBSD__
     2058        tmp = call_program_and_get_last_line_of_output("df -m -P -t nonfs,msdosfs,ntfs,ntfs-3g,vmhgfs,smbfs,smb,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done");
     2059#else
     2060        tmp = call_program_and_get_last_line_of_output("df -m -P -x nfs -x nfs4 -x fuse.sshfs -x fuse -x vfat -x ntfs -x ntfs-3g -x vmhgfs -x smbfs -x smb -x cifs -x afs -x gfs -x ocfs -x ocfs2 -x mvfs -x nsspool -x nssvol -x iso9660 | grep -vE \"none|Filesystem|/dev/shm\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -nr | awk '{print $NF;}' | while read x ; do test -w $x && echo $x && break ; done");
     2061#endif
     2062
     2063        if (tmp[0] != '/') {
     2064            mr_asprintf(sz, "%s", tmp);
     2065            mr_free(tmp);
     2066            mr_asprintf(tmp, "/%s", sz);
     2067            mr_free(sz);
     2068        }
     2069        setup_scratchdir(tmp);
     2070        mr_free(tmp);
     2071
     2072        if ((compression_type = which_compression_type()) == NULL) {
     2073            log_to_screen("User has chosen not to backup the machine");
     2074            finish(1);
     2075        }
     2076
     2077        bkpinfo->compression_level = (bkpinfo->backup_media_type == cdstream) ? 1 : 5;
     2078        if ((bkpinfo->compression_level = which_compression_level()) == -1) {
     2079            log_to_screen("User has chosen not to backup the machine");
     2080            finish(1);
     2081        }
     2082        bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4;
     2083        bkpinfo->use_lzo = (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE;
     2084    }
     2085    mvaddstr_and_log_it(2, 0, " ");
     2086
     2087    // Find device's /dev (or SCSI) entry
     2088    switch (bkpinfo->backup_media_type) {
     2089    case cdr:
     2090    case dvd:
     2091    case usb:
     2092        /* Never try to eject a USB device */
     2093        if (bkpinfo->backup_media_type == usb) {
     2094            bkpinfo->please_dont_eject = TRUE;
     2095        }
     2096        mds = media_descriptor_string(bkpinfo->backup_media_type);
     2097        if (bkpinfo->backup_media_type != usb) {
     2098            if (ask_me_yes_or_no("Is your computer a laptop type (manual insert of MondoRescue media)?")) {
     2099                bkpinfo->manual_cd_tray = TRUE;
     2100            }
     2101        }
     2102
     2103        if (bkpinfo->media_device == NULL) {
     2104            bkpinfo->media_device = find_device(bkpinfo->backup_media_type);
     2105            if (bkpinfo->media_device != NULL) {
     2106                log_msg(1, "MondoRescue device found automatically for your %s is %s", mds, bkpinfo->media_device);
     2107            } else {
     2108                log_msg(1, "No MondoRescue device found yet for your %s", mds);
     2109            }
     2110        }
     2111
     2112        if (archiving_to_media) {
     2113            if (bkpinfo->backup_media_type == dvd) {
     2114                strcpy(tmp1, "1");
     2115                mr_asprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE);  // 4.7 salesman's GB = 4.482 real GB = 4482 MB
     2116                log_msg(1, "Setting to DVD defaults");
     2117            } else {
     2118                strcpy(tmp1, "4");
     2119                mr_asprintf(sz_size, "%d", 650);
     2120                log_msg(1, "Setting to CD defaults");
     2121            }
     2122
     2123            mr_asprintf(comment, "What speed is your %s writer?", mds);
     2124            if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) {
     2125                if (!popup_and_get_string("Speed", comment, tmp1, 4)) {
     2126                    log_to_screen("User has chosen not to backup the machine");
     2127                    mr_free(comment);
     2128                    finish(1);
     2129                }
     2130            }
     2131            mr_free(comment);
     2132            bkpinfo->cdrw_speed = atoi(tmp1);   // if DVD then this shouldn't ever be used anyway :)
     2133
     2134            strcpy(tmp1, sz_size);
     2135            mr_asprintf(comment, "How much data (in Megabytes) will each %s store?", mds);
     2136            if (!popup_and_get_string("Size", comment, tmp1, 5)) {
     2137                log_to_screen("User has chosen not to backup the machine");
     2138                finish(1);
     2139            }
     2140            mr_asprintf(sz_size, "%s", tmp1);
     2141            bkpinfo->media_size = atoi(sz_size);
     2142
     2143            if (bkpinfo->media_size <= 0) {
     2144                log_to_screen("User has chosen not to backup the machine");
     2145                finish(1);
     2146            }
     2147        }
     2148        /* No break because we continue even for usb */
     2149    case cdstream:
     2150
     2151        // If media_device not found ask
     2152        if (bkpinfo->media_device == NULL) {
     2153            mr_asprintf(comment, "Please specify your Mondorescue %s media /dev entry", mds);
     2154            tmp2 = mr_popup_and_get_string("/dev entry?", comment, bkpinfo->media_device);
     2155            if (!tmp2) {
     2156                log_to_screen("User has chosen not to backup the machine");
     2157                finish(1);
     2158            } else {
     2159                mr_free(bkpinfo->media_device);
     2160                bkpinfo->media_device = tmp2;
     2161            }
     2162        }
     2163        log_msg(2, "%s device found at %s", mds, bkpinfo->media_device);
     2164        mr_asprintf(tmp, "MondoRescue thinks your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device);
     2165        if (!ask_me_yes_or_no(tmp)) {
     2166            mr_free(bkpinfo->media_device);
     2167        }
     2168        mr_free(tmp);
     2169
     2170        if (bkpinfo->media_device == NULL) {
     2171            mr_asprintf(tmp, "Please then specify your Mondorescue %s media /dev entry", mds);
     2172            tmp2 = mr_popup_and_get_string("/dev entry?", tmp, bkpinfo->media_device);
     2173            mr_free(tmp);
     2174            if (tmp2 == NULL) {
     2175                log_to_screen("User has chosen not to backup the machine");
     2176                finish(1);
     2177            } else {
     2178                mr_free(bkpinfo->media_device);
     2179                bkpinfo->media_device = tmp2;
     2180            }
     2181        }
     2182        mr_free(mds);
     2183
     2184        if (bkpinfo->backup_media_type == cdstream) {
     2185            bkpinfo->media_size = 650;
     2186        }
     2187        break;
     2188    case udev:
     2189        if (!ask_me_yes_or_no
     2190            ("This option is for advanced users only. Are you sure?")) {
     2191            log_to_screen("User has chosen not to backup the machine");
     2192            finish(1);
     2193        }
     2194    case tape:
     2195
     2196        bkpinfo->media_device = find_tape_device();
     2197        if (bkpinfo->media_device != NULL) {
     2198            if ((fin = fopen(bkpinfo->media_device, "r"))) {
     2199                paranoid_fclose(fin);
     2200            } else {
     2201                if (does_file_exist("/tmp/mondorestore.cfg")) {
     2202                    read_cfg_var("/tmp/mondorestore.cfg", "media-dev", bkpinfo->media_device);
     2203                }
     2204            }
     2205        }
     2206        if (bkpinfo->media_device != NULL) {
     2207            mr_asprintf(tmp, "Mondorescue thinks your tape streamer at %s; is that correct?", bkpinfo->media_device);
     2208            if (!ask_me_yes_or_no(tmp)) {
     2209                mr_free(bkpinfo->media_device);
     2210            }
     2211            mr_free(tmp);
     2212        }
     2213        if (bkpinfo->media_device == NULL) {
     2214            tmp2 = mr_popup_and_get_string("Device name?", "What is the /dev entry of your tape streamer?", "");
     2215            if (tmp2 == NULL) {
     2216                log_to_screen("User has chosen not to backup the machine");
     2217                finish(1);
     2218            } else {
     2219                bkpinfo->media_device = tmp2;
     2220            }
     2221        }
     2222        mr_asprintf(tmp, "ls -l %s", bkpinfo->media_device);
     2223        if (run_program_and_log_output(tmp, FALSE)) {
     2224            log_to_screen("User has not specified a valid /dev entry");
     2225            finish(1);
     2226        }
     2227        mr_free(tmp);
     2228
     2229        mr_asprintf(sz_size,"%ld",bkpinfo->internal_tape_block_size);
     2230        tmp = mr_popup_and_get_string("Tape block size?", "What is the block size of your tape streamer?", sz_size);
     2231        if (tmp == NULL) {
     2232            log_to_screen("User has chosen not to backup the machine");
     2233            finish(1);
     2234        }
     2235        bkpinfo->internal_tape_block_size = atol(tmp);
     2236        mr_free(sz_size);
     2237        mr_free(tmp);
     2238
     2239        // log the block-size
     2240        log_msg(0,"Tape block size= %ld", bkpinfo->internal_tape_block_size);
     2241
     2242        if (bkpinfo->internal_tape_block_size <= 0) {
     2243            log_to_screen("User has chosen not to backup the machine");
     2244            finish(1);
     2245        }
     2246
     2247        bkpinfo->media_size = 0;
     2248        log_msg(4, "media_size = %ld", bkpinfo->media_size);
     2249
     2250        if (archiving_to_media) {
     2251            bkpinfo->use_obdr = ask_me_yes_or_no("Do you want to activate OBDR support for your tapes ?");
     2252            if (bkpinfo->use_obdr) {
     2253                log_msg(4, "obdr mode = TRUE");
     2254            } else {
     2255                log_msg(4, "obdr mode = FALSE");
     2256            }
     2257        }
     2258        break;
     2259
     2260    case netfs:
     2261        /* Never try to eject a NETFS device */
     2262        bkpinfo->please_dont_eject = TRUE;
     2263        /*  Force NFS to be the protocol by default */
     2264        if (bkpinfo->netfs_proto == NULL) {
     2265            mr_asprintf(bkpinfo->netfs_proto, "nfs");
     2266        }
     2267
     2268        /* Initiate bkpinfo netfs_mount path from running environment if not already done */
     2269        if (bkpinfo->netfs_mount == NULL) {
     2270            bkpinfo->netfs_mount = call_program_and_get_last_line_of_output("mount | grep \":\" | cut -d' ' -f1 | head -n1");
     2271        }
     2272#ifdef __FreeBSD__
     2273        if (TRUE)
     2274#else
     2275        if (!bkpinfo->disaster_recovery)
     2276#endif
     2277        {
     2278            if (!popup_and_get_string("Network shared dir.", "Please enter path and directory where archives are stored remotely. (Mondo has taken a guess at the correct value. If it is incorrect, delete it and type the correct one.)", p,(MAX_STR_LEN / 4)-1)) {
     2279                log_to_screen("User has chosen not to backup the machine");
     2280                finish(1);
     2281            }
     2282            mr_free(bkpinfo->netfs_mount);
     2283            // check whether already mounted - we better remove
     2284            // surrounding spaces and trailing '/' for this
     2285            bkpinfo->netfs_mount = mr_strip_spaces(p);
     2286            if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/')
     2287                bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0';
     2288            q = strchr(bkpinfo->netfs_mount, '@');
     2289            if (q != NULL) {
     2290                /* User found. Store the 2 values */
     2291                q++;
     2292                /* new netfs mount */
     2293                strcpy(tmp1,q);
     2294            } else {
     2295                strcpy(tmp1,bkpinfo->netfs_mount);
     2296            }
     2297            mr_asprintf(command, "mount | grep \"%s \" | cut -d' ' -f3", tmp1);
     2298            mr_free(bkpinfo->isodir);
     2299            bkpinfo->isodir = call_program_and_get_last_line_of_output(command);
     2300            mr_free(command);
     2301
     2302            if (!bkpinfo->restore_data) {
     2303                mr_asprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE);  // 4.7 salesman's GB = 4.482 real GB = 4482 MB
     2304                mr_asprintf(comment, "How much data (in Megabytes) will each media store?");
     2305                strcpy(tmp1, sz_size);
     2306                mr_free(sz_size);
     2307                if (!popup_and_get_string("Size", comment, tmp1, 5)) {
     2308                    log_to_screen("User has chosen not to backup the machine");
     2309                    finish(1);
     2310                }
     2311                mr_free(comment);
     2312                mr_asprintf(sz_size, "%s", tmp1);
     2313            } else {
     2314                mr_asprintf(sz_size, "0");
     2315            }
     2316            bkpinfo->media_size = atoi(sz_size);
     2317            mr_free(sz_size);
     2318
     2319            if (bkpinfo->media_size < 0) {
     2320                log_to_screen("User has chosen not to backup the machine");
     2321                finish(1);
     2322            }
     2323        }
     2324        /*  TODO: Useless I think */
     2325        if (bkpinfo->disaster_recovery) {
     2326            mr_asprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir);
     2327            paranoid_system(command);
     2328            mr_free(command);
     2329
     2330        }
     2331        strcpy(tmp1, bkpinfo->netfs_proto);
     2332        if (!popup_and_get_string("Network protocol", "Which protocol should I use (nfs/sshfs/smbfs) ?",tmp1, MAX_STR_LEN-1)) {
     2333            log_to_screen("User has chosen not to backup the machine");
     2334            finish(1);
     2335        }
     2336        mr_free(bkpinfo->netfs_proto);
     2337        mr_asprintf(bkpinfo->netfs_proto, "%s", tmp1);
     2338
     2339        strcpy(tmp1, bkpinfo->netfs_mount);
     2340        if (!popup_and_get_string("Network share", "Which remote share should I mount?", tmp1, MAX_STR_LEN-1)) {
     2341            log_to_screen("User has chosen not to backup the machine");
     2342            finish(1);
     2343        }
     2344        mr_free(bkpinfo->netfs_mount);
     2345        mr_asprintf(bkpinfo->netfs_mount, "%s", tmp1);
     2346
     2347        if (bkpinfo->netfs_user) {
     2348            strcpy(tmp1, bkpinfo->netfs_user);
     2349        } else {
     2350            strcpy(tmp1, "");
     2351        }
     2352        if (!popup_and_get_string("Network user", "Which user should I use if any ?",tmp1, MAX_STR_LEN-1)) {
     2353            log_to_screen("User has chosen not to backup the machine");
     2354            finish(1);
     2355        }
     2356        mr_free(bkpinfo->netfs_user);
     2357        if (strcmp(tmp1, "") != 0) {
     2358            mr_asprintf(bkpinfo->netfs_user, "%s", tmp1);
     2359        }
     2360
     2361        /* Initiate bkpinfo isodir path from running environment if mount already done */
     2362        log_msg(3, "Testing mount for %s", bkpinfo->netfs_mount);
     2363        if (is_this_device_mounted(bkpinfo->netfs_mount)) {
     2364            mr_free(bkpinfo->isodir);
     2365            bkpinfo->isodir = call_program_and_get_last_line_of_output("mount | grep \":\" | cut -d' ' -f3 | head -n1");
     2366        } else {
     2367            // Why netfsdir ?
     2368            mr_asprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir);
     2369            mr_asprintf(command, "mkdir -p %s", bkpinfo->isodir);
     2370            run_program_and_log_output(command, 5);
     2371            mr_free(command);
     2372
     2373            if (bkpinfo->restore_data) {
     2374                /*  mount the FS read-only in restore mode to avoid any erase of whatever */
     2375                mr_asprintf(tmpro, "-o ro");
     2376            } else {
     2377                mr_asprintf(tmpro, "");
     2378            }
     2379
     2380            /*  Build the mount string */
     2381            if (strstr(bkpinfo->netfs_proto, "smbfs")) {
     2382                mr_asprintf(tmp, "mount -t cifs %s %s %s",bkpinfo->netfs_mount, bkpinfo->isodir,tmpro);
     2383                if (bkpinfo->netfs_user) {
     2384                    mr_strcat(tmp, " -o user=%s", bkpinfo->netfs_user);
     2385                }
     2386            else {
     2387                if (strstr(bkpinfo->netfs_proto, "sshfs")) {
     2388                    mr_asprintf(tmp, "sshfs %s ",tmpro);
     2389                } else {
     2390                    mr_asprintf(tmp, "mount -t %s -o nolock %s ", bkpinfo->netfs_proto,tmpro);
     2391                }
     2392                if (bkpinfo->netfs_user) {
     2393                    mr_strcat(tmp, "%s@", bkpinfo->netfs_user);
     2394                }
     2395                mr_strcat(tmp, "%s %s", bkpinfo->netfs_mount, bkpinfo->isodir);
     2396            }
     2397            run_program_and_log_output(tmp, 3);
     2398            mr_free(tmp);
     2399
     2400            malloc_string(g_selfmounted_isodir);
     2401            strcpy(g_selfmounted_isodir, bkpinfo->isodir);
     2402            }
     2403        }
     2404       
     2405        log_msg(3, "Testing mount for %s", bkpinfo->netfs_mount);
     2406        if (!is_this_device_mounted(bkpinfo->netfs_mount)) {
     2407            popup_and_OK("Please mount that partition before you try to backup to or restore from it.");
     2408            finish(1);
     2409        }
     2410        if (bkpinfo->netfs_remote_dir == NULL) {
     2411            fatal_error("bkpinfo->netfs_remote_dir should not be NULL");
     2412        }
     2413        strcpy(tmp1, bkpinfo->netfs_remote_dir);
     2414        if (!popup_and_get_string ("Directory", "Which directory within that mountpoint?", tmp1, MAX_STR_LEN-1)) {
     2415            log_to_screen("User has chosen not to backup the machine");
     2416            finish(1);
     2417        }
     2418        mr_free(bkpinfo->netfs_remote_dir);
     2419        // check whether writable - we better remove surrounding spaces for this
     2420        bkpinfo->netfs_remote_dir = mr_strip_spaces(tmp1);
     2421
     2422        tmp = mr_popup_and_get_string("Prefix.", "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files", bkpinfo->prefix);
     2423        if (tmp == NULL) {
     2424            log_to_screen("User has chosen not to backup the machine");
     2425            finish(1);
     2426        }
     2427        mr_free(bkpinfo->prefix);
     2428        bkpinfo->prefix = tmp;
     2429        log_msg(3, "prefix set to %s", bkpinfo->prefix);
     2430        log_msg(3, "Just set netfs_remote_dir to %s", bkpinfo->netfs_remote_dir);
     2431        log_msg(3, "isodir is still %s", bkpinfo->isodir);
     2432        break;
     2433
     2434    case iso:
     2435        if (!bkpinfo->disaster_recovery) {
     2436            tmp = mr_popup_and_get_string("Storage dir.", "Please enter the full path name to the directory for your ISO images.  Example: /mnt/raid0_0", bkpinfo->isodir);
     2437            if (tmp == NULL) {
     2438                log_to_screen("User has chosen not to backup the machine");
     2439                finish(1);
     2440            } else {
     2441                mr_free(bkpinfo->isodir);
     2442                bkpinfo->isodir = tmp;
     2443            }
     2444            if (archiving_to_media) {
     2445                sprintf(tmp1, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB
     2446                if (!popup_and_get_string("ISO size.", "Please enter how big you want each ISO image to be (in megabytes). This should be less than or equal to the size of the CD-R[W]'s (700) or DVD's (4480) you plan to backup to.", tmp1, 16)) {
     2447                    log_to_screen("User has chosen not to backup the machine");
     2448                    finish(1);
     2449                }
     2450                bkpinfo->media_size = atoi(tmp1);
     2451            } else {
     2452                bkpinfo->media_size = 650;
     2453            }
     2454        }
     2455        tmp = mr_popup_and_get_string("Prefix.", "Please enter the prefix that will be prepended to your ISO filename.  Example: machine1 to obtain machine1-[1-9]*.iso files", bkpinfo->prefix);
     2456        if (tmp == NULL) {
     2457            log_to_screen("User has chosen not to backup the machine");
     2458            finish(1);
     2459        }
     2460        mr_free(bkpinfo->prefix);
     2461        bkpinfo->prefix = tmp;
     2462        log_msg(3, "prefix set to %s", bkpinfo->prefix);
     2463        break;
     2464    default:
     2465        fatal_error("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!");
     2466    }
     2467
     2468    if (archiving_to_media) {
     2469        /*  Needs to be done before calling which_boot_loader */
     2470        bkpinfo->boot_type = mr_boot_type();
     2471        mr_free(bkpinfo->boot_device);
     2472#ifdef __FreeBSD__
     2473        bkpinfo->boot_device = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'");
     2474#else
     2475        bkpinfo->boot_device = call_program_and_get_last_line_of_output("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'");
     2476#endif
     2477        i = which_boot_loader(bkpinfo->boot_device);
     2478        if (i == 'U')           // unknown
     2479        {
     2480
     2481#ifdef __FreeBSD__
     2482            if (!popup_and_get_string("Boot device", "What is your boot device? (e.g. /dev/ad0)", bkpinfo->boot_device,(MAX_STR_LEN / 4)-1)) {
     2483                log_to_screen("User has chosen not to backup the machine");
     2484                finish(1);
     2485            }
     2486            i = which_boot_loader(bkpinfo->boot_device);
     2487#else
     2488            strcpy(tmp1, bkpinfo->boot_device);
     2489            if (!popup_and_get_string("Boot device", "What is your boot device? (e.g. /dev/hda)", tmp1,(MAX_STR_LEN / 4)-1)) {
     2490                log_to_screen("User has chosen not to backup the machine");
     2491                finish(1);
     2492            }
     2493            mr_free(bkpinfo->boot_device);
     2494            mr_asprintf(bkpinfo->boot_device, "%s", tmp1);
     2495
     2496            if (does_string_exist_in_boot_block(bkpinfo->boot_device, "ELILO")) {
     2497                i = 'E';
     2498            } else
     2499                if (does_string_exist_in_boot_block(bkpinfo->boot_device, "LILO")) {
     2500                i = 'L';
     2501            } else
     2502                if (does_string_exist_in_boot_block(bkpinfo->boot_device, "GRUB")) {
     2503                i = 'G';
     2504            } else {
     2505                i = 'U';
     2506            }
     2507#endif
     2508            if (i == 'U') {
     2509                if (ask_me_yes_or_no("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")) {
     2510                    i = 'R';    // raw
     2511                } else {
     2512                    log_to_screen("I cannot find your boot loader. Please run mondoarchive with parameters.");
     2513                    finish(1);
     2514                }
     2515            }
     2516        }
     2517        bkpinfo->boot_loader = i;
     2518        /* TODO: Check consistency of boot type and boot loader */
     2519
     2520        if (bkpinfo->include_paths) {
     2521            strcpy(tmp1, bkpinfo->include_paths);
     2522            mr_free(bkpinfo->include_paths);
     2523        } else {
     2524            strcpy(tmp1, "/");
     2525        }
     2526        if (!popup_and_get_string("Backup paths", "Please enter paths (separated by '|') which you want me to backup. The default is '/' (i.e. everything).", tmp1, MAX_STR_LEN-1)) {
     2527            log_to_screen("User has chosen not to backup the machine");
     2528            finish(1);
     2529        }
     2530        mr_asprintf(bkpinfo->include_paths, "%s", tmp1);
     2531
     2532        tmp = list_of_NETFS_mounts_only();
     2533        if (strlen(tmp) > 2) {
     2534            mr_strcat(bkpinfo->exclude_paths, "|%s",tmp);
     2535        }
     2536        mr_free(tmp);
     2537// NTFS
     2538        tmp = call_program_and_get_last_line_of_output("mr-parted2fdisk -l 2>/dev/null | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'");
     2539        strncpy(tmp1, tmp,(MAX_STR_LEN / 4)-1);
     2540        mr_free(tmp);
     2541        if (strlen(tmp1) > 2) {
     2542            if (!popup_and_get_string("NTFS partitions", "Please enter/confirm the NTFS partitions you wish to backup as well.", tmp1,(MAX_STR_LEN / 4)-1)) {
     2543                log_to_screen("User has chosen not to backup the machine");
     2544                finish(1);
     2545            }
     2546            mr_asprintf(bkpinfo->image_devs, "%s", tmp1);
     2547        }
     2548
     2549        if (bkpinfo->exclude_paths != NULL ) {
     2550            mr_asprintf(p, "%s", bkpinfo->exclude_paths);
     2551        } else {
     2552            mr_asprintf(p, "%s", "");
     2553        }
     2554        tmp = mr_popup_and_get_string("Exclude paths", "Please enter paths which you do NOT want to backup. Separate them with '|'. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.", p);
     2555        mr_free(p);
     2556        if (tmp == NULL) {
     2557            log_to_screen("User has chosen not to backup the machine");
     2558            finish(1);
     2559        }
     2560        mr_free(bkpinfo->exclude_paths);
     2561        bkpinfo->exclude_paths = tmp;
     2562
     2563        mr_asprintf(oldtmp, "%s", bkpinfo->tmpdir);
     2564        if (bkpinfo->tmpdir != NULL ) {
     2565            mr_asprintf(p, "%s", bkpinfo->tmpdir);
     2566        } else {
     2567            mr_asprintf(p, "%s", "");
     2568        }
     2569        tmp = mr_popup_and_get_string("Temporary directory", "Please enter your temporary directory.", p);
     2570        mr_free(p);
     2571        if (tmp == NULL) {
     2572            mr_free(oldtmp);
     2573            log_to_screen("User has chosen not to backup the machine");
     2574            finish(1);
     2575        }
     2576        /*  if modified to another path */
     2577        if (strcmp(tmp,oldtmp) != 0) {
     2578            setup_tmpdir(tmp);
     2579        }
     2580        mr_free(oldtmp);
     2581
     2582        mr_asprintf(oldtmp, "%s", bkpinfo->scratchdir);
     2583        if (bkpinfo->scratchdir != NULL ) {
     2584            mr_asprintf(p, "%s", bkpinfo->scratchdir);
     2585        } else {
     2586            mr_asprintf(p, "%s", "");
     2587        }
     2588        tmp = mr_popup_and_get_string("Scratch directory", "Please enter your scratch directory.", p);
     2589        mr_free(p);
     2590        if (tmp == NULL) {
     2591            mr_free(oldtmp);
     2592            log_to_screen("User has chosen not to backup the machine");
     2593            finish(1);
     2594        }
     2595        /*  if modified to another path */
     2596        if (strcmp(tmp,oldtmp) != 0) {
     2597            setup_scratchdir(tmp);
     2598        }
     2599        mr_free(oldtmp);
     2600
     2601        if (ask_me_yes_or_no("Do you want to backup extended attributes?")) {
     2602            mr_free(g_getfattr);
     2603            g_getfattr = find_home_of_exe("getfattr");
     2604            mr_free(g_getfacl);
     2605            g_getfacl = find_home_of_exe("getfacl");
     2606            log_it("Backup of extended attributes");
     2607        }
     2608// Interactive mode:
     2609#ifdef __IA64__
     2610        bkpinfo->make_cd_use_lilo = TRUE;
     2611#else
     2612        bkpinfo->make_cd_use_lilo = FALSE;
     2613#endif
     2614        bkpinfo->backup_data = TRUE;
     2615        if (strcmp(compression_type,"lzo") == 0) {
     2616            mr_asprintf(bkpinfo->zip_exe, "%s", "lzop");
     2617            mr_asprintf(bkpinfo->zip_suffix, "%s", "lzo");
     2618        } else if (strcmp(compression_type,"gzip") == 0) {
     2619            mr_asprintf(bkpinfo->zip_exe, "%s", "gzip");
     2620            mr_asprintf(bkpinfo->zip_suffix, "%s", "gz");
     2621        } else if (strcmp(compression_type,"lzma") == 0) {
     2622            mr_asprintf(bkpinfo->zip_exe, "%s", "xz");
     2623            mr_asprintf(bkpinfo->zip_suffix, "%s", "xz");
     2624        } else if (strcmp(compression_type,"bzip2") == 0) {
     2625            mr_asprintf(bkpinfo->zip_exe, "%s", "bzip2");
     2626            mr_asprintf(bkpinfo->zip_suffix, "%s", "bz2");
     2627        } else {
     2628            mr_free(bkpinfo->zip_exe);
     2629            mr_free(bkpinfo->zip_suffix);
     2630        }
     2631        mr_free(compression_type);
     2632
     2633#if __FreeBSD__ == 5
     2634        mr_asprintf(bkpinfo->kernel_path, "%s", "/boot/kernel/kernel");
     2635#elif __FreeBSD__ == 4
     2636        mr_asprintf(bkpinfo->kernel_path, "%s", "/kernel");
     2637#elif linux
     2638        if (figure_out_kernel_path_interactively_if_necessary(bkpinfo->kernel_path)) {
     2639            fatal_error("Kernel not found. Please specify manually with the '-k' switch.");
     2640        }
     2641#else
     2642#error "I don't know about this system!"
     2643#endif
     2644
     2645
     2646        bkpinfo->verify_data =
     2647            ask_me_yes_or_no
     2648            ("Will you want to verify your backups after Mondo has created them?");
     2649
     2650        if (!ask_me_yes_or_no
     2651            ("Are you sure you want to proceed? Hit 'no' to abort.")) {
     2652            log_to_screen("User has chosen not to backup the machine");
     2653            finish(1);
     2654        }
     2655    } else {
     2656        bkpinfo->restore_data = TRUE;   // probably...
     2657    }
     2658
     2659    if (bkpinfo->backup_media_type == iso
     2660        || bkpinfo->backup_media_type == netfs) {
     2661        g_ISO_restore_mode = TRUE;
     2662    }
     2663#ifdef __FreeSD__
     2664// skip
     2665#else
     2666    if (bkpinfo->backup_media_type == netfs) {
     2667        log_msg(3, "I think the Remote mount is mounted at %s", bkpinfo->isodir);
     2668    }
     2669    log_it("isodir = %s", bkpinfo->isodir);
     2670    if (bkpinfo->netfs_mount) {
     2671        log_it("netfs_mount = '%s'", bkpinfo->netfs_mount);
     2672    }
     2673    if (bkpinfo->netfs_user) {
     2674        log_it("netfs_user = '%s'", bkpinfo->netfs_user);
     2675    }
     2676    if (bkpinfo->netfs_proto) {
     2677        log_it("netfs_proto = '%s'", bkpinfo->netfs_proto);
     2678    }
     2679#endif
     2680
     2681    log_it("media device = %s", bkpinfo->media_device);
     2682    log_it("media size = %ld", bkpinfo->media_size);
     2683    log_it("media type = %s", bkptype_to_string(bkpinfo->backup_media_type));
     2684    if (bkpinfo->prefix != NULL) {
     2685        log_it("prefix = %s", bkpinfo->prefix);
     2686    }
     2687    log_it("compression = %ld", bkpinfo->compression_level);
     2688    log_it("exclude_path = %s", bkpinfo->exclude_paths);
     2689    if (bkpinfo->include_paths) {
     2690        log_it("include_path = %s", bkpinfo->include_paths);
     2691    }
     2692
     2693    /* Handle devices passed in bkpinfo and print result */
     2694    /*  the mr_make_devlist_from_pathlist function appends */
     2695    /*  to the *_paths variables so copy before */
     2696    mr_make_devlist_from_pathlist(bkpinfo->exclude_paths, 'E');
     2697    mr_make_devlist_from_pathlist(bkpinfo->include_paths, 'I');
     2698
     2699    log_it("scratchdir = '%s'", bkpinfo->scratchdir);
     2700    log_it("tmpdir = '%s'", bkpinfo->tmpdir);
     2701    if (bkpinfo->image_devs) {
     2702        log_it("image_devs = '%s'", bkpinfo->image_devs);
     2703    }
     2704    log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device, bkpinfo->boot_loader);
     2705    if (bkpinfo->media_size < 0) {
     2706        if (archiving_to_media) {
     2707            fatal_error("Media size is less than zero.");
     2708        } else {
     2709            log_msg(2, "Warning - media size is less than zero.");
     2710            bkpinfo->media_size = 0;
     2711        }
     2712    }
     2713    paranoid_free(sz_size);
     2714    paranoid_free(tmp1);
     2715    return (0);
     2716}
     2717
     2718
     2719/**
     2720 * Get a |-separated list of NETFS mounts.
     2721 * @return The list created.
     2722 * @note The return value points to allocated string that needs to be freed by
     2723 * caller
     2724 * @bug Even though we only want the mounts, the devices are still checked.
     2725 */
     2726char *list_of_NETFS_mounts_only(void)
     2727{
     2728    char *exclude_these_directories = NULL;
     2729
     2730    exclude_these_directories = call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,vmhgfs,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol,fuse.boostfs | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' '|' | awk '{print $0;}'");
     2731    log_msg(9,"list_of_NETFS_mounts_only returns %s",exclude_these_directories);
     2732    return(exclude_these_directories);
     2733}
     2734
     2735/* @} - end of utilityGroup */
     2736
     2737
     2738
     2739
     2740
     2741/**
     2742 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
     2743 * [random] is a random number between 1 and 32767.
     2744 * @param store_name_here Where to store the new filename.
     2745 * @param stub A random number will be appended to this to make the FIFO's name.
     2746 * @ingroup deviceGroup
     2747 */
     2748void make_fifo(char *store_name_here, char *stub)
     2749{
     2750    char *tmp = NULL;
     2751
     2752    assert_string_is_neither_NULL_nor_zerolength(stub);
     2753
     2754    sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
     2755            (int) (random() % 32768));
     2756    make_hole_for_file(store_name_here);
     2757    mkfifo(store_name_here, S_IRWXU | S_IRWXG);
     2758    mr_asprintf(tmp, "chmod 770 %s", store_name_here);
     2759    paranoid_system(tmp);
     2760    mr_free(tmp);
     2761}
     2762
     2763
     2764
     2765/**
     2766 * @addtogroup deviceGroup
     2767 * @{
     2768 */
     2769/**
     2770 * If we can read @p dev, set @p output to it.
     2771 * If @p dev cannot be read, set @p output to "".
     2772 * @param dev The device to check for.
     2773 * @param output Set to @p dev if @p dev exists, "" otherwise.
     2774 * @return TRUE if @p dev exists, FALSE if it doesn't.
     2775 */
     2776bool set_dev_to_this_if_rx_OK(char *output, char *dev)
     2777{
     2778    char *command = NULL;
     2779    bool ret=FALSE;
     2780
     2781    if (!dev || dev[0] == '\0') {
     2782        output[0] = '\0';
     2783        return(ret);
     2784    }
     2785//  assert_string_is_neither_NULL_nor_zerolength(dev);
     2786    if (!bkpinfo->please_dont_eject) {
     2787        log_msg(10, "Injecting %s", dev);
     2788        inject_device(dev);
     2789    }
     2790    if (!does_file_exist(dev)) {
     2791        log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
     2792        return(ret);
     2793    }
     2794    mr_asprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null", 512L, dev);
     2795    if (!run_program_and_log_output(command, FALSE) && !run_program_and_log_output(command, FALSE)) {
     2796        strcpy(output, dev);
     2797        log_msg(4, "Found it - %s", dev);
     2798        ret = TRUE;
     2799    } else {
     2800        output[0] = '\0';
     2801        log_msg(4, "It's not %s", dev);
     2802    }
     2803    mr_free(command);
     2804    return(ret);
     2805}
     2806
     2807
     2808
     2809
     2810
     2811/**
     2812 * Find out what number CD is in the drive.
     2813 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
     2814 * @return The current CD number, or -1 if it could not be found.
     2815 * @note If the CD is not mounted, it will be mounted
     2816 * (and remain mounted after this function returns).
     2817 */
     2818int what_number_cd_is_this(void) {
     2819
     2820    int cd_number = -1;
     2821    char *mountdev = NULL;
     2822    char *tmp = NULL;
     2823
     2824    assert(bkpinfo != NULL);
     2825//  log_it("Asking what_number_cd_is_this");
     2826    if ((g_ISO_restore_mode) || (g_restoring_live_from_cd)) {
     2827        tmp = call_program_and_get_last_line_of_output("mount | grep iso9660 | awk '{print $3;}'");
     2828        mr_asprintf(mountdev, "%s%s", tmp, "/archives/THIS-CD-NUMBER");
     2829        mr_free(tmp);
     2830        cd_number = atoi(last_line_of_file(mountdev));
     2831        mr_free(mountdev);
     2832        return (cd_number);
     2833    }
     2834
     2835    if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {
     2836        log_it("ERROR: bkpinfo->media_device shoulnd't be unaccessible here\n");
     2837        /* trying again ! */
     2838        bkpinfo->media_device = find_optical_device();
     2839    }
     2840    if ((bkpinfo->media_device == NULL) || !does_file_exist(bkpinfo->media_device)) {
     2841        fatal_error("ERROR: bkpinfo->media_device shoulnd't really be unaccessible here\n");
     2842    }
     2843    if (!is_this_device_mounted(bkpinfo->media_device, MNT_CDROM)) {
     2844        mount_media(MNT_CDROM);
     2845    }
     2846
     2847    cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER"));
     2848    return(cd_number);
     2849}
     2850
     2851
     2852/**
     2853 * Find out what device is mounted as root (/).
     2854 * @return Root device.
     2855 * @note The returned string points to storage that needs to be freed by
     2856 * caller
     2857 * @bug A bit of a misnomer; it's actually finding out the root device.
     2858 * The mountpoint (where it's mounted) will obviously be '/'.
     2859 */
     2860char *where_is_root_mounted(void) {
     2861
     2862/*@ buffers **************** */
     2863char *tmp = NULL;
     2864
     2865#ifdef __FreeBSD__
     2866    tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");
     2867#else
     2868    tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//");
     2869    if (strstr(tmp, "/dev/cciss/")) {
     2870        mr_free(tmp);
     2871        tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1");
     2872    }
     2873    if (strstr(tmp, "/dev/md")) {
     2874        mr_free(tmp);
     2875        tmp = call_program_and_get_last_line_of_output("mount | grep \" on / \" | cut -d' ' -f1");
     2876    }
     2877#endif
     2878
     2879return (tmp);
     2880}
    28812881
    28822882
  • branches/3.3/mondo/src/common/libmondo-stream.c

    r3872 r3877  
    200200    return (retval);
    201201}
     202
     203
     204
     205/**
     206 * Start to write to the next tape. Assume the user has already inserted it.
     207 * @param bkpinfo The backup information structure. @c bkpinfo->media_device is the only field used.
     208 * @return 0 for success, nonzero for failure.
     209 */
     210int start_to_write_to_next_tape()
     211{
     212    int res = 0;
     213    char *command = NULL;
     214
     215    if (bkpinfo->media_device == NULL) {
     216        log_it("Unable to open out from NULL device");
     217        return (1);
     218    }
     219
     220    paranoid_pclose(g_tape_stream);
     221    sync();
     222    sync();
     223    sync();
     224    log_it("New tape requested.");
     225    insist_on_this_tape_number(g_current_media_number + 1); // will increment g_current_media, too
     226    if (bkpinfo->backup_media_type == cdstream) {
     227        mr_asprintf(command, "cdrecord -eject dev=%s speed=%d fs=24m -waiti - >> %s 2>> %s", bkpinfo->media_device, bkpinfo->cdrw_speed, MONDO_LOGFILE, MONDO_LOGFILE);
     228        log_it("Opening OUT to next CD with the command");
     229        log_it(command);
     230        log_it("Let's see what happens, shall we?");
     231        g_tape_stream = popen(command, "w");
     232        mr_free(command);
     233
     234        if (!g_tape_stream) {
     235            log_to_screen("Failed to openout to cdstream (fifo)");
     236            return (1);
     237        }
     238    } else {
     239        log_it("Opening OUT to next tape");
     240        if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'w', bkpinfo->internal_tape_block_size))) {
     241            log_OS_error(g_tape_fifo);
     242            log_to_screen("Cannot openin stream device");
     243            return (1);
     244        }
     245    }
     246    g_tape_posK = 0;
     247    g_sigpipe = FALSE;
     248    res += write_header_block_to_stream((off_t)0, "start-of-tape", BLK_START_OF_TAPE);  /* just in case */
     249    res += write_header_block_to_stream((off_t)0, "start-of-backup", BLK_START_OF_BACKUP);  /* just in case */
     250    return (res);
     251}
     252
     253
     254
     255/**
     256 * Decide whether we should start a new tape. This is TRUE if we've run out of tape
     257 * (got SIGPIPE) or look like we will.
     258 * @param mediasize The size of the tape in megabytes.
     259 * @param length_of_incoming_file The length of the file we're about to write, in bytes.
     260 * @bug This seems like it'll only work for media_size != autodetect, but Mondo only allows
     261 * autodetecting the size. Huh?
     262 */
     263
     264/* TODO: Should be reviewed for mediasize being a off_t ??? */
     265bool
     266should_we_write_to_next_tape(long mediasize,
     267                             off_t length_of_incoming_file)
     268{
     269    /*@ bool's ***************************************************** */
     270    bool we_need_a_new_tape = FALSE;
     271
     272    /*@ end vars *************************************************** */
     273
     274    if (mediasize == 0) {
     275        return (FALSE);
     276    }
     277    if (mediasize > 0 && (g_tape_posK >> 10 >= mediasize)) {
     278        log_it("mediasize = %ld", mediasize);
     279        we_need_a_new_tape = TRUE;
     280        log_to_screen("Should have started a new tape/CD already");
     281    }
     282    if ((g_tape_posK + length_of_incoming_file / 1024) >> 10 >=
     283        mediasize - (SLICE_SIZE * 4 / 1024)) {
     284        log_it("g_tape_posK = %ld\nmediasize = %ld\n", g_tape_posK,
     285               mediasize);
     286        we_need_a_new_tape = TRUE;
     287    }
     288    return (we_need_a_new_tape);
     289}
     290
     291
    202292
    203293
     
    354444
    355445
     446/**
     447 * Copy a file from the opened stream (CD or tape) to @p outfile.
     448 * @param outfile The file to write to.
     449 * @param size The size of the file in the input stream.
     450 * @return 0 for success, nonzero for failure.
     451 */
     452int
     453read_file_from_stream_to_file(char *outfile, long long size)
     454{
     455
     456    /*@ int ******************************************************** */
     457    int res;
     458
     459    /*@ end vars *************************************************** */
     460
     461    res = read_file_from_stream_FULL(outfile, NULL, size);
     462
     463    return (res);
     464}
     465
     466
     467
     468
    356469int read_EXAT_files_from_tape(long long *ptmp_size, char *tmp_fname,
    357470                              int *pctrl_chr, char *xattr_fname,
     
    419532    return (res);
    420533}
     534
     535
     536/**
     537 * Copy @p infile to the opened stream (CD or tape).
     538 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used.
     539 * @param infile The file to write to the stream.
     540 * @return 0 for success, nonzero for failure.
     541 */
     542int write_file_to_stream_from_file(char *infile)
     543{
     544    /*@ buffers **************************************************** */
     545    char datablock[TAPE_BLOCK_SIZE];
     546    char *checksum = NULL;
     547    char *infile_basename;
     548
     549    /*@ int ******************************************************** */
     550    int retval = 0;
     551    int noof_blocks;
     552
     553    /*  unsigned int ch; */
     554    unsigned int crc16;
     555    unsigned int crctt;
     556
     557    /*@ pointers *************************************************** */
     558    FILE *fin;
     559    char *p;
     560
     561    /*@ long ******************************************************* */
     562    long bytes_to_read = 0;
     563    long i;
     564
     565    off_t filesize;
     566
     567#ifdef EXTRA_TAPE_CHECKSUMS
     568    int ch;
     569#endif
     570
     571    /*@ initialize ************************************************ */
     572    crc16 = 0;
     573    crctt = 0;
     574
     575
     576
     577    /*@ end vars *************************************************** */
     578
     579    infile_basename = strrchr(infile, '/');
     580    if (infile_basename) {
     581        infile_basename++;
     582    } else {
     583        infile_basename = infile;
     584    }
     585    filesize = length_of_file(infile);
     586    if (should_we_write_to_next_tape(bkpinfo->media_size, filesize)) {
     587        start_to_write_to_next_tape();
     588        write_backcatalog_to_tape();
     589    }
     590    p = strrchr(infile, '/');
     591    if (!p) {
     592        p = infile;
     593    } else {
     594        p++;
     595    }
     596    log_it("Writing file '%s' to tape (%ld KB)", p, (long) filesize >> 10);
     597    write_header_block_to_stream(filesize, infile_basename, BLK_START_FILE);
     598//go_here_to_restart_saving_of_file:
     599    if (!(fin = fopen(infile, "r"))) {
     600        log_OS_error(infile);
     601        return (1);
     602    }
     603    for (noof_blocks = 0; filesize > 0;
     604         noof_blocks++, filesize -= bytes_to_read) {
     605        if (filesize < TAPE_BLOCK_SIZE) {
     606            bytes_to_read = (long) filesize;
     607            for (i = 0; i < TAPE_BLOCK_SIZE; i++) {
     608                datablock[i] = '\0';
     609            }
     610        } else {
     611            bytes_to_read = TAPE_BLOCK_SIZE;
     612        }
     613        if (fread(datablock, 1, (size_t) bytes_to_read, fin)) {
     614            // FIXME
     615        }
     616        g_tape_posK +=
     617            fwrite(datablock, 1, /*bytes_to_read */
     618                   (size_t) TAPE_BLOCK_SIZE,
     619                   g_tape_stream) / 1024;
     620        if (g_sigpipe) {
     621            log_it("Sigpipe occurred recently. I'll start a new tape.");
     622            fclose(fin);
     623            g_sigpipe = FALSE;
     624            start_to_write_to_next_tape();
     625            write_backcatalog_to_tape();    // kinda-sorta recursive :)
     626            return (0);
     627        }
     628#ifdef EXTRA_TAPE_CHECKSUMS
     629        for (i = 0; i < bytes_to_read; i++) {
     630            ch = datablock[i];
     631            crc16 = updcrcr(crc16, (unsigned) ch);
     632            crctt = updcrc(crctt, (unsigned) ch);
     633        }
     634#endif
     635    }
     636    paranoid_fclose(fin);
     637    mr_asprintf(checksum, "%04x%04x", crc16, crctt);
     638    /* TODO: what does it do ??? */
     639    write_header_block_to_stream((off_t)g_current_media_number, checksum, BLK_STOP_FILE);
     640    mr_free(checksum);
     641
     642//  log_it("File '%s' written to tape.", infile);
     643    return (retval);
     644}
     645
     646
     647
     648
     649
     650
    421651
    422652
     
    566796}
    567797
    568 
    569 
    570 
    571 /**
    572  * Open the CD stream for input.
    573  * @param bkpinfo The backup information structure. Passed to openin_tape().
    574  * @return 0 for success, nonzero for failure.
    575  * @note Equivalent to openin_tape() for now, but don't count on this behavior.
    576  */
    577 int openin_cdstream()
    578 {
    579     return (openin_tape());
    580 }
    581 
    582 /**
    583  * FIFO used to read/write to the tape device.
    584  * @bug This seems obsolete now that we call an external @c buffer program. Please look onto this.
    585  */
    586 char g_tape_fifo[MAX_STR_LEN];
    587 
    588 
    589 
    590 int set_tape_block_size_with_mt(long internal_tape_block_size)
    591 {
    592     char *tmp = NULL;
    593     int res;
    594 
    595     if (bkpinfo->media_device == NULL) {
    596         return(1);
    597     }
    598 
    599     if (strncmp(bkpinfo->media_device, "/dev/", 5)) {
    600         log_msg(1, "Not using 'mt setblk'. This isn't an actual /dev entry.");
    601         return (0);
    602     }
    603     mr_asprintf(tmp, "mt -f %s setblk %ld", bkpinfo->media_device, internal_tape_block_size);
    604     res = run_program_and_log_output(tmp, 3);
    605     mr_free(tmp);
    606     return (res);
    607 }
    608 
    609 /**
    610  * Return the non-rewinding device when passed the normal one
    611  * @param tapedev The tape device to open for writing.
    612  * @note the caller needs to free the string returned
    613  */
    614 char *get_non_rewind_dev(char *tapedev)
    615 {
    616 
    617     char *ntapedev = NULL;
    618     char *p = NULL;
    619     char *q = NULL;
    620     char *r = NULL;
    621 
    622     ntapedev = (char *)mr_malloc(strlen(tapedev)+2*sizeof(char));
    623     p = strrchr(tapedev,'/');
    624     if (p == NULL) {
    625         log_it("Didn't find a '/' in %s",tapedev);
    626         return(NULL);
    627     }
    628 
    629     /* Copy tapedev content up to the last / */
    630     q = tapedev;
    631     r = ntapedev;
    632     while (q != p) {
    633         *r = *q;
    634         r++;
    635         q++;
    636     }
    637     /* Copy the '/' */
    638     *r = *q;
    639     r++;
    640     q++;
    641     /* Adds a 'n' - non-rewinding */
    642     *r = 'n';
    643     r++;
    644     /* Copy the rest of tapedev */
    645     while (*q != '\0') {
    646         *r = *q;
    647         r++;
    648         q++;
    649     }
    650     *r = '\0';
    651     if (mt_says_tape_exists(ntapedev)) {
    652         log_it("Non-rewinding tape device is %s",ntapedev);
    653     } else {
    654         log_it("Unable to find non-rewinding tape device.");
    655         ntapedev = NULL;
    656     }
    657     return(ntapedev);
    658 }
    659 
    660 
    661 
    662 /**
    663  * Handle OBDR if we were asked to do so
    664  * @param tapedev The tape device to open for reading.
    665  */
    666 int skip_obdr(void)
    667 {
    668     char *command = NULL;
    669     int res = 0;
    670 
    671     if (bkpinfo->media_device == NULL) {
    672         return(1);
    673     }
    674 
    675     log_it("Skipping OBDR headers");
    676     mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device);
    677     res = run_program_and_log_output(command, 1);
    678     paranoid_free(command);
    679 
    680     mr_asprintf(command, "mt -f %s fsf 2",bkpinfo->media_device);
    681     res = run_program_and_log_output(command, 1);
    682     paranoid_free(command);
    683 
    684     set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
    685     return(res);
    686 }
    687 
    688 /**
    689  * Handle OBDR if we were asked to do so
    690  * @param tapedev The tape device to open for writing.
    691  * @return 0 for success, nonzero for failure.
    692  * @note This should be called ONLY from backup processes. It will OVERWRITE ANY
    693  * EXISTING DATA on the tape!
    694  */
    695 int create_obdr(void)
    696 {
    697 
    698     char *command = NULL;
    699     int res = 0;
    700 
    701     if (bkpinfo->media_device == NULL) {
    702         return(1);
    703     }
    704 
    705     log_it("Creating OBDR headers");
    706     /* OBDR: First block 10 kB of zero bs = 512 */
    707     mr_asprintf(command, "mt -f %s compression off",bkpinfo->media_device);
    708     res = run_program_and_log_output(command, 1);
    709     paranoid_free(command);
    710 
    711     mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device);
    712     res += run_program_and_log_output(command, 1);
    713     paranoid_free(command);
    714 
    715     set_tape_block_size_with_mt(512);
    716 
    717     mr_asprintf(command, "dd if=/dev/zero of=%s bs=512 count=20",bkpinfo->media_device);
    718     res += run_program_and_log_output(command, 1);
    719     paranoid_free(command);
    720 
    721     /* OBDR: then ISO boot image bs = 2048 */
    722     set_tape_block_size_with_mt(2048);
    723 
    724     mr_asprintf(command, "dd if=%s of=%s bs=2048",MINDI_CACHE"/mindi.iso",bkpinfo->media_device);
    725     res += run_program_and_log_output(command, 1);
    726     paranoid_free(command);
    727 
    728     set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
    729 
    730     /* restore compression mode on */
    731     mr_asprintf(command, "mt -f %s compression on",bkpinfo->media_device);
    732     res = run_program_and_log_output(command, 1);
    733     paranoid_free(command);
    734 
    735     return(res);
    736 }
    737798
    738799
     
    871932
    872933
     934
     935/**
     936 * Open the CD stream for input.
     937 * @param bkpinfo The backup information structure. Passed to openin_tape().
     938 * @return 0 for success, nonzero for failure.
     939 * @note Equivalent to openin_tape() for now, but don't count on this behavior.
     940 */
     941int openin_cdstream()
     942{
     943    return (openin_tape());
     944}
     945
     946/**
     947 * FIFO used to read/write to the tape device.
     948 * @bug This seems obsolete now that we call an external @c buffer program. Please look onto this.
     949 */
     950char g_tape_fifo[MAX_STR_LEN];
     951
     952
     953
     954int set_tape_block_size_with_mt(long internal_tape_block_size)
     955{
     956    char *tmp = NULL;
     957    int res;
     958
     959    if (bkpinfo->media_device == NULL) {
     960        return(1);
     961    }
     962
     963    if (strncmp(bkpinfo->media_device, "/dev/", 5)) {
     964        log_msg(1, "Not using 'mt setblk'. This isn't an actual /dev entry.");
     965        return (0);
     966    }
     967    mr_asprintf(tmp, "mt -f %s setblk %ld", bkpinfo->media_device, internal_tape_block_size);
     968    res = run_program_and_log_output(tmp, 3);
     969    mr_free(tmp);
     970    return (res);
     971}
     972
     973/**
     974 * Return the non-rewinding device when passed the normal one
     975 * @param tapedev The tape device to open for writing.
     976 * @note the caller needs to free the string returned
     977 */
     978char *get_non_rewind_dev(char *tapedev)
     979{
     980
     981    char *ntapedev = NULL;
     982    char *p = NULL;
     983    char *q = NULL;
     984    char *r = NULL;
     985
     986    ntapedev = (char *)mr_malloc(strlen(tapedev)+2*sizeof(char));
     987    p = strrchr(tapedev,'/');
     988    if (p == NULL) {
     989        log_it("Didn't find a '/' in %s",tapedev);
     990        return(NULL);
     991    }
     992
     993    /* Copy tapedev content up to the last / */
     994    q = tapedev;
     995    r = ntapedev;
     996    while (q != p) {
     997        *r = *q;
     998        r++;
     999        q++;
     1000    }
     1001    /* Copy the '/' */
     1002    *r = *q;
     1003    r++;
     1004    q++;
     1005    /* Adds a 'n' - non-rewinding */
     1006    *r = 'n';
     1007    r++;
     1008    /* Copy the rest of tapedev */
     1009    while (*q != '\0') {
     1010        *r = *q;
     1011        r++;
     1012        q++;
     1013    }
     1014    *r = '\0';
     1015    if (mt_says_tape_exists(ntapedev)) {
     1016        log_it("Non-rewinding tape device is %s",ntapedev);
     1017    } else {
     1018        log_it("Unable to find non-rewinding tape device.");
     1019        ntapedev = NULL;
     1020    }
     1021    return(ntapedev);
     1022}
     1023
     1024
     1025
     1026/**
     1027 * Handle OBDR if we were asked to do so
     1028 * @param tapedev The tape device to open for reading.
     1029 */
     1030int skip_obdr(void)
     1031{
     1032    char *command = NULL;
     1033    int res = 0;
     1034
     1035    if (bkpinfo->media_device == NULL) {
     1036        return(1);
     1037    }
     1038
     1039    log_it("Skipping OBDR headers");
     1040    mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device);
     1041    res = run_program_and_log_output(command, 1);
     1042    paranoid_free(command);
     1043
     1044    mr_asprintf(command, "mt -f %s fsf 2",bkpinfo->media_device);
     1045    res = run_program_and_log_output(command, 1);
     1046    paranoid_free(command);
     1047
     1048    set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
     1049    return(res);
     1050}
     1051
     1052/**
     1053 * Handle OBDR if we were asked to do so
     1054 * @param tapedev The tape device to open for writing.
     1055 * @return 0 for success, nonzero for failure.
     1056 * @note This should be called ONLY from backup processes. It will OVERWRITE ANY
     1057 * EXISTING DATA on the tape!
     1058 */
     1059int create_obdr(void)
     1060{
     1061
     1062    char *command = NULL;
     1063    int res = 0;
     1064
     1065    if (bkpinfo->media_device == NULL) {
     1066        return(1);
     1067    }
     1068
     1069    log_it("Creating OBDR headers");
     1070    /* OBDR: First block 10 kB of zero bs = 512 */
     1071    mr_asprintf(command, "mt -f %s compression off",bkpinfo->media_device);
     1072    res = run_program_and_log_output(command, 1);
     1073    paranoid_free(command);
     1074
     1075    mr_asprintf(command, "mt -f %s rewind",bkpinfo->media_device);
     1076    res += run_program_and_log_output(command, 1);
     1077    paranoid_free(command);
     1078
     1079    set_tape_block_size_with_mt(512);
     1080
     1081    mr_asprintf(command, "dd if=/dev/zero of=%s bs=512 count=20",bkpinfo->media_device);
     1082    res += run_program_and_log_output(command, 1);
     1083    paranoid_free(command);
     1084
     1085    /* OBDR: then ISO boot image bs = 2048 */
     1086    set_tape_block_size_with_mt(2048);
     1087
     1088    mr_asprintf(command, "dd if=%s of=%s bs=2048",MINDI_CACHE"/mindi.iso",bkpinfo->media_device);
     1089    res += run_program_and_log_output(command, 1);
     1090    paranoid_free(command);
     1091
     1092    set_tape_block_size_with_mt(bkpinfo->internal_tape_block_size);
     1093
     1094    /* restore compression mode on */
     1095    mr_asprintf(command, "mt -f %s compression on",bkpinfo->media_device);
     1096    res = run_program_and_log_output(command, 1);
     1097    paranoid_free(command);
     1098
     1099    return(res);
     1100}
     1101
     1102
    8731103/**
    8741104 * Start writing to a CD stream.
     
    9481178}
    9491179return (0);
    950 }
    951 
    952 
    953 
    954 
    955 /**
    956  * Copy a file from the opened stream (CD or tape) to @p outfile.
    957  * @param outfile The file to write to.
    958  * @param size The size of the file in the input stream.
    959  * @return 0 for success, nonzero for failure.
    960  */
    961 int
    962 read_file_from_stream_to_file(char *outfile, long long size)
    963 {
    964 
    965     /*@ int ******************************************************** */
    966     int res;
    967 
    968     /*@ end vars *************************************************** */
    969 
    970     res = read_file_from_stream_FULL(outfile, NULL, size);
    971 
    972     return (res);
    973 }
    974 
    975 
    976 
    977 /**
    978  * Copy a file from the currently opened stream (CD or tape) to the stream indicated
    979  * by @p fout.
    980  * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used.
    981  * @param fout The stream to write the file to.
    982  * @param size The size of the file in bytes.
    983  * @return 0 for success, nonzero for failure.
    984  */
    985 int
    986 read_file_from_stream_to_stream(FILE * fout, long long size)
    987 {
    988 
    989     /*@ int ******************************************************** */
    990     int res;
    991 
    992     /*@ end vars *************************************************** */
    993 
    994     res = read_file_from_stream_FULL(NULL, fout, size);
    995 /*  fflush(g_tape_stream);
    996   fflush(fout);*/
    997     return (res);
    9981180}
    9991181
     
    11471329
    11481330/**
    1149  * Read a header block from the currently opened stream (CD or tape).
    1150  * This block indicates the length of the following file (if it's file-related)
    1151  * the filename (if it's file-related), and the block type.
    1152  * @param plen Where to put the length of the file. Valid only for file-related header blocks.
    1153  * @param filename Where to put the name of the file. Valid only for file-related header blocks.
    1154  * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...)
    1155  * @return 0 for success, nonzero for failure.
    1156  * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker().
     1331 * Copy a file from the currently opened stream (CD or tape) to the stream indicated
     1332 * by @p fout.
     1333 * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used.
     1334 * @param fout The stream to write the file to.
     1335 * @param size The size of the file in bytes.
     1336 * @return 0 for success, nonzero for failure.
    11571337 */
    11581338int
    1159 read_header_block_from_stream(long long *plen, char *filename,
    1160                               int *pcontrol_char)
    1161 {
    1162 
    1163     /*@ buffers ***************************************************** */
    1164     char *tempblock;
    1165     char *tmp = NULL;
    1166 
    1167     /*@ int ********************************************************* */
    1168     int i, retval;
     1339read_file_from_stream_to_stream(FILE * fout, long long size)
     1340{
     1341
     1342    /*@ int ******************************************************** */
     1343    int res;
    11691344
    11701345    /*@ end vars *************************************************** */
    11711346
    1172     tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE);
    1173 
    1174     for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) {
    1175         tempblock[i] = 0;
    1176     }
    1177     while (!(*pcontrol_char = tempblock[7000])) {
    1178         g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024;
    1179     }
    1180     memcpy((char *) plen, tempblock + 7001, sizeof(long long));
    1181     if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) {
    1182         log_it("Bad header block at %ld K", (long) g_tape_posK);
    1183     }
    1184     strcpy(filename, tempblock + 1000);
    1185     if (*pcontrol_char == BLK_ABORTED_BACKUP) {
    1186         log_to_screen("I can't verify an aborted backup.");
    1187         retval = 1;
    1188     } else {
    1189         retval = 0;
    1190     }
    1191     for (i = 1000; i < 1020; i++) {
    1192         if (tempblock[i] < 32 || tempblock[i] > 126) {
    1193             tempblock[i] = ' ';
    1194         }
    1195     }
    1196     tempblock[i] = '\0';
    1197     tmp = marker_to_string(*pcontrol_char);
    1198     log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10);
    1199     mr_free(tmp);
    1200     paranoid_free(tempblock);
    1201     return (retval);
    1202 }
    1203 
    1204 
    1205 
    1206 /**
    1207  * Add specified file/slice to the internal catalog of all archives written.
    1208  * This lets us restart on a new CD/tape/whatever if it runs out of room. We just
    1209  * write the last [buffer size] MB from the catalog to the new tape, so we know
    1210  * we have @e all archives on some CD/tape/whatever.
    1211  * @param type The type of file we're cataloging (afioball, slice, something else)
    1212  * @param number The fileset number or biggiefile number.
    1213  * @param aux The slice number if it's a biggiefile, or any other additional info.
    1214  * @param fn The original full pathname of the file we're recording.
    1215  * @return The index of the record we just added.
    1216  */
    1217 int register_in_tape_catalog(t_archtype type, int number, long aux,
    1218                              char *fn)
    1219 {
    1220     int last;
    1221     char fname[MAX_TAPECAT_FNAME_LEN+1];
    1222     char *p;
    1223 
    1224     p = strrchr(fn, '/');
    1225     if (p) {
    1226         p++;
    1227     } else {
    1228         p = fn;
    1229     }
    1230     strncpy(fname, p, MAX_TAPECAT_FNAME_LEN);
    1231     fname[MAX_TAPECAT_FNAME_LEN] = '\0';
    1232     last = g_tapecatalog->entries;
    1233     if (last >= MAX_TAPECATALOG_ENTRIES) {
    1234         log_it
    1235             ("Warning - can't log #%d in tape catalog - too many entries already",
    1236              number);
    1237         return (-1);
    1238     }
    1239     g_tapecatalog->el[last].type = type;
    1240     g_tapecatalog->el[last].number = number;
    1241     g_tapecatalog->el[last].aux = aux;
    1242     g_tapecatalog->el[last].tape_posK = g_tape_posK;
    1243     strcpy(g_tapecatalog->el[last].fname, fname);
    1244     g_tapecatalog->entries++;
    1245     return (last);              // returns the index of the record we've jsut added
    1246 }
    1247 
    1248 
    1249 
    1250 
    1251 /**
    1252  * Decide whether we should start a new tape. This is TRUE if we've run out of tape
    1253  * (got SIGPIPE) or look like we will.
    1254  * @param mediasize The size of the tape in megabytes.
    1255  * @param length_of_incoming_file The length of the file we're about to write, in bytes.
    1256  * @bug This seems like it'll only work for media_size != autodetect, but Mondo only allows
    1257  * autodetecting the size. Huh?
    1258  */
    1259 
    1260 /* TODO: Should be reviewed for mediasize being a off_t ??? */
    1261 bool
    1262 should_we_write_to_next_tape(long mediasize,
    1263                              off_t length_of_incoming_file)
    1264 {
    1265     /*@ bool's ***************************************************** */
    1266     bool we_need_a_new_tape = FALSE;
    1267 
    1268     /*@ end vars *************************************************** */
    1269 
    1270     if (mediasize == 0) {
    1271         return (FALSE);
    1272     }
    1273     if (mediasize > 0 && (g_tape_posK >> 10 >= mediasize)) {
    1274         log_it("mediasize = %ld", mediasize);
    1275         we_need_a_new_tape = TRUE;
    1276         log_to_screen("Should have started a new tape/CD already");
    1277     }
    1278     if ((g_tape_posK + length_of_incoming_file / 1024) >> 10 >=
    1279         mediasize - (SLICE_SIZE * 4 / 1024)) {
    1280         log_it("g_tape_posK = %ld\nmediasize = %ld\n", g_tape_posK,
    1281                mediasize);
    1282         we_need_a_new_tape = TRUE;
    1283     }
    1284     return (we_need_a_new_tape);
     1347    res = read_file_from_stream_FULL(NULL, fout, size);
     1348/*  fflush(g_tape_stream);
     1349  fflush(fout);*/
     1350    return (res);
    12851351}
    12861352
     
    14481514
    14491515/**
    1450  * Start to write to the next tape. Assume the user has already inserted it.
    1451  * @param bkpinfo The backup information structure. @c bkpinfo->media_device is the only field used.
    1452  * @return 0 for success, nonzero for failure.
    1453  */
    1454 int start_to_write_to_next_tape()
    1455 {
    1456     int res = 0;
    1457     char *command = NULL;
    1458 
    1459     if (bkpinfo->media_device == NULL) {
    1460         log_it("Unable to open out from NULL device");
    1461         return (1);
    1462     }
    1463 
    1464     paranoid_pclose(g_tape_stream);
    1465     sync();
    1466     sync();
    1467     sync();
    1468     log_it("New tape requested.");
    1469     insist_on_this_tape_number(g_current_media_number + 1); // will increment g_current_media, too
    1470     if (bkpinfo->backup_media_type == cdstream) {
    1471         mr_asprintf(command, "cdrecord -eject dev=%s speed=%d fs=24m -waiti - >> %s 2>> %s", bkpinfo->media_device, bkpinfo->cdrw_speed, MONDO_LOGFILE, MONDO_LOGFILE);
    1472         log_it("Opening OUT to next CD with the command");
    1473         log_it(command);
    1474         log_it("Let's see what happens, shall we?");
    1475         g_tape_stream = popen(command, "w");
    1476         mr_free(command);
    1477 
    1478         if (!g_tape_stream) {
    1479             log_to_screen("Failed to openout to cdstream (fifo)");
    1480             return (1);
    1481         }
    1482     } else {
    1483         log_it("Opening OUT to next tape");
    1484         if (!(g_tape_stream = open_device_via_buffer(bkpinfo->media_device, 'w', bkpinfo->internal_tape_block_size))) {
    1485             log_OS_error(g_tape_fifo);
    1486             log_to_screen("Cannot openin stream device");
    1487             return (1);
    1488         }
    1489     }
    1490     g_tape_posK = 0;
    1491     g_sigpipe = FALSE;
    1492     res += write_header_block_to_stream((off_t)0, "start-of-tape", BLK_START_OF_TAPE);  /* just in case */
    1493     res += write_header_block_to_stream((off_t)0, "start-of-backup", BLK_START_OF_BACKUP);  /* just in case */
    1494     return (res);
     1516 * Read a header block from the currently opened stream (CD or tape).
     1517 * This block indicates the length of the following file (if it's file-related)
     1518 * the filename (if it's file-related), and the block type.
     1519 * @param plen Where to put the length of the file. Valid only for file-related header blocks.
     1520 * @param filename Where to put the name of the file. Valid only for file-related header blocks.
     1521 * @param pcontrol_char Where to put the type of block (e.g. start-file, end-file, start-tape, ...)
     1522 * @return 0 for success, nonzero for failure.
     1523 * @note If you read a marker (@p pcontrol_char) you're not expecting, you can call wrong_marker().
     1524 */
     1525int
     1526read_header_block_from_stream(long long *plen, char *filename,
     1527                              int *pcontrol_char)
     1528{
     1529
     1530    /*@ buffers ***************************************************** */
     1531    char *tempblock;
     1532    char *tmp = NULL;
     1533
     1534    /*@ int ********************************************************* */
     1535    int i, retval;
     1536
     1537    /*@ end vars *************************************************** */
     1538
     1539    tempblock = (char *) malloc((size_t) TAPE_BLOCK_SIZE);
     1540
     1541    for (i = 0; i < (int) TAPE_BLOCK_SIZE; i++) {
     1542        tempblock[i] = 0;
     1543    }
     1544    while (!(*pcontrol_char = tempblock[7000])) {
     1545        g_tape_posK += fread(tempblock, 1, (size_t) TAPE_BLOCK_SIZE, g_tape_stream) / 1024;
     1546    }
     1547    memcpy((char *) plen, tempblock + 7001, sizeof(long long));
     1548    if (strcmp(tempblock + 6000 + *pcontrol_char, STR_HEADER)) {
     1549        log_it("Bad header block at %ld K", (long) g_tape_posK);
     1550    }
     1551    strcpy(filename, tempblock + 1000);
     1552    if (*pcontrol_char == BLK_ABORTED_BACKUP) {
     1553        log_to_screen("I can't verify an aborted backup.");
     1554        retval = 1;
     1555    } else {
     1556        retval = 0;
     1557    }
     1558    for (i = 1000; i < 1020; i++) {
     1559        if (tempblock[i] < 32 || tempblock[i] > 126) {
     1560            tempblock[i] = ' ';
     1561        }
     1562    }
     1563    tempblock[i] = '\0';
     1564    tmp = marker_to_string(*pcontrol_char);
     1565    log_msg(6, "%s (fname=%s, size=%ld K)", tmp, tempblock + 1000, (long) (*plen) >> 10);
     1566    mr_free(tmp);
     1567    paranoid_free(tempblock);
     1568    return (retval);
     1569}
     1570
     1571
     1572
     1573/**
     1574 * Add specified file/slice to the internal catalog of all archives written.
     1575 * This lets us restart on a new CD/tape/whatever if it runs out of room. We just
     1576 * write the last [buffer size] MB from the catalog to the new tape, so we know
     1577 * we have @e all archives on some CD/tape/whatever.
     1578 * @param type The type of file we're cataloging (afioball, slice, something else)
     1579 * @param number The fileset number or biggiefile number.
     1580 * @param aux The slice number if it's a biggiefile, or any other additional info.
     1581 * @param fn The original full pathname of the file we're recording.
     1582 * @return The index of the record we just added.
     1583 */
     1584int register_in_tape_catalog(t_archtype type, int number, long aux,
     1585                             char *fn)
     1586{
     1587    int last;
     1588    char fname[MAX_TAPECAT_FNAME_LEN+1];
     1589    char *p;
     1590
     1591    p = strrchr(fn, '/');
     1592    if (p) {
     1593        p++;
     1594    } else {
     1595        p = fn;
     1596    }
     1597    strncpy(fname, p, MAX_TAPECAT_FNAME_LEN);
     1598    fname[MAX_TAPECAT_FNAME_LEN] = '\0';
     1599    last = g_tapecatalog->entries;
     1600    if (last >= MAX_TAPECATALOG_ENTRIES) {
     1601        log_it
     1602            ("Warning - can't log #%d in tape catalog - too many entries already",
     1603             number);
     1604        return (-1);
     1605    }
     1606    g_tapecatalog->el[last].type = type;
     1607    g_tapecatalog->el[last].number = number;
     1608    g_tapecatalog->el[last].aux = aux;
     1609    g_tapecatalog->el[last].tape_posK = g_tape_posK;
     1610    strcpy(g_tapecatalog->el[last].fname, fname);
     1611    g_tapecatalog->entries++;
     1612    return (last);              // returns the index of the record we've jsut added
    14951613}
    14961614
     
    16001718
    16011719
    1602 /**
    1603  * Copy @p infile to the opened stream (CD or tape).
    1604  * @param bkpinfo The backup information structure. @c bkpinfo->media_size is the only field used.
    1605  * @param infile The file to write to the stream.
    1606  * @return 0 for success, nonzero for failure.
    1607  */
    1608 int write_file_to_stream_from_file(char *infile)
    1609 {
    1610     /*@ buffers **************************************************** */
    1611     char datablock[TAPE_BLOCK_SIZE];
    1612     char *checksum = NULL;
    1613     char *infile_basename;
    1614 
    1615     /*@ int ******************************************************** */
    1616     int retval = 0;
    1617     int noof_blocks;
    1618 
    1619     /*  unsigned int ch; */
    1620     unsigned int crc16;
    1621     unsigned int crctt;
    1622 
    1623     /*@ pointers *************************************************** */
    1624     FILE *fin;
    1625     char *p;
    1626 
    1627     /*@ long ******************************************************* */
    1628     long bytes_to_read = 0;
    1629     long i;
    1630 
    1631     off_t filesize;
    1632 
    1633 #ifdef EXTRA_TAPE_CHECKSUMS
    1634     int ch;
    1635 #endif
    1636 
    1637     /*@ initialize ************************************************ */
    1638     crc16 = 0;
    1639     crctt = 0;
    1640 
    1641 
    1642 
    1643     /*@ end vars *************************************************** */
    1644 
    1645     infile_basename = strrchr(infile, '/');
    1646     if (infile_basename) {
    1647         infile_basename++;
    1648     } else {
    1649         infile_basename = infile;
    1650     }
    1651     filesize = length_of_file(infile);
    1652     if (should_we_write_to_next_tape(bkpinfo->media_size, filesize)) {
    1653         start_to_write_to_next_tape();
    1654         write_backcatalog_to_tape();
    1655     }
    1656     p = strrchr(infile, '/');
    1657     if (!p) {
    1658         p = infile;
    1659     } else {
    1660         p++;
    1661     }
    1662     log_it("Writing file '%s' to tape (%ld KB)", p, (long) filesize >> 10);
    1663     write_header_block_to_stream(filesize, infile_basename, BLK_START_FILE);
    1664 //go_here_to_restart_saving_of_file:
    1665     if (!(fin = fopen(infile, "r"))) {
    1666         log_OS_error(infile);
    1667         return (1);
    1668     }
    1669     for (noof_blocks = 0; filesize > 0;
    1670          noof_blocks++, filesize -= bytes_to_read) {
    1671         if (filesize < TAPE_BLOCK_SIZE) {
    1672             bytes_to_read = (long) filesize;
    1673             for (i = 0; i < TAPE_BLOCK_SIZE; i++) {
    1674                 datablock[i] = '\0';
    1675             }
    1676         } else {
    1677             bytes_to_read = TAPE_BLOCK_SIZE;
    1678         }
    1679         if (fread(datablock, 1, (size_t) bytes_to_read, fin)) {
    1680             // FIXME
    1681         }
    1682         g_tape_posK +=
    1683             fwrite(datablock, 1, /*bytes_to_read */
    1684                    (size_t) TAPE_BLOCK_SIZE,
    1685                    g_tape_stream) / 1024;
    1686         if (g_sigpipe) {
    1687             log_it("Sigpipe occurred recently. I'll start a new tape.");
    1688             fclose(fin);
    1689             g_sigpipe = FALSE;
    1690             start_to_write_to_next_tape();
    1691             write_backcatalog_to_tape();    // kinda-sorta recursive :)
    1692             return (0);
    1693         }
    1694 #ifdef EXTRA_TAPE_CHECKSUMS
    1695         for (i = 0; i < bytes_to_read; i++) {
    1696             ch = datablock[i];
    1697             crc16 = updcrcr(crc16, (unsigned) ch);
    1698             crctt = updcrc(crctt, (unsigned) ch);
    1699         }
    1700 #endif
    1701     }
    1702     paranoid_fclose(fin);
    1703     mr_asprintf(checksum, "%04x%04x", crc16, crctt);
    1704     /* TODO: what does it do ??? */
    1705     write_header_block_to_stream((off_t)g_current_media_number, checksum, BLK_STOP_FILE);
    1706     mr_free(checksum);
    1707 
    1708 //  log_it("File '%s' written to tape.", infile);
    1709     return (retval);
    1710 }
    1711 
    1712 
    1713 
    1714 
    1715 
    1716 
    1717 
    1718 
    17191720
    17201721
  • branches/3.3/mondo/src/common/libmondo-tools.c

    r3874 r3877  
    650650
    651651/**
     652 * Check the user's system for sanity. Checks performed:
     653 * - make sure user has enough RAM (32mb required, 64mb recommended)
     654 * - make sure user has enough free space in @c /
     655 * - check kernel for ramdisk support
     656 * - make sure afio, cdrecord, mkisofs, bzip2, awk, md5sum, strings, mindi, and buffer exist
     657 * - make sure CD-ROM is unmounted
     658 * - make sure user's mountlist is OK by running <tt>mindi --makemountlist</tt>
     659 *
     660 * @return number of problems with the user's setup (0 for success)
     661 */
     662int some_basic_system_sanity_checks()
     663{
     664
     665    /*@ buffers ************ */
     666    char *tmp = NULL;
     667
     668    /*@ int's *************** */
     669    int retval = 0;
     670
     671    mvaddstr_and_log_it(g_currentY, 0, "Checking sanity of your Linux distribution");
     672#ifndef __FreeBSD__
     673    if (system("which mkfs.vfat 2> /dev/null 1> /dev/null")
     674        && !system("which mkfs.msdos 2> /dev/null 1> /dev/null")) {
     675        log_it("OK, you've got mkfs.msdos but not mkfs.vfat; time for the fairy to wave her magic wand...");
     676        run_program_and_log_output("ln -sf `which mkfs.msdos` /sbin/mkfs.vfat", FALSE);
     677    }
     678    tmp = call_program_and_get_last_line_of_output("free | grep Mem | head -n1 | tr -s ' ' '\t' | cut -f2");
     679    if (atol(tmp) < 35000) {
     680        retval++;
     681        log_to_screen("You must have at least 32MB of RAM to use Mondo.");
     682    }
     683    if (atol(tmp) < 66000) {
     684        log_to_screen("WARNING! You have very little RAM. Please upgrade to 64MB or more.");
     685    }
     686    mr_free(tmp);
     687#endif
     688
     689    if (system("which " MKE2FS_OR_NEWFS " > /dev/null 2> /dev/null")) {
     690        retval++;
     691        log_to_screen("Unable to find " MKE2FS_OR_NEWFS " in system path.");
     692        fatal_error("Please use \"su -\", not \"su\" to become root. OK?\n...and please don't e-mail the mailing list about this. Just read the message. :)");
     693    }
     694#ifndef __FreeBSD__
     695    if (run_program_and_log_output("grep ramdisk /proc/devices", FALSE)) {
     696        /* Some SuSE have ramdisk as modules, so insert it first, then test again */
     697        run_program_and_log_output("modprobe brd 2> /dev/null > /dev/null",FALSE);
     698        if (run_program_and_log_output("grep ramdisk /proc/devices", FALSE)) {
     699            if (!ask_me_yes_or_no("Your kernel has no ramdisk support. That's mind-numbingly stupid but I'll allow it if you're planning to use another kernel. Are you?")) {
     700                //          retval++;
     701                log_to_screen("It looks as if your kernel lacks ramdisk and initrd support.");
     702                log_to_screen("I'll allow you to proceed but FYI, if I'm right, your kernel is broken.");
     703            }
     704        }
     705    }
     706#endif
     707    retval += whine_if_not_found(MKE2FS_OR_NEWFS);
     708    if (system("which xorriso > /dev/null 2> /dev/null")) {
     709        if (system("which genisoimage > /dev/null 2> /dev/null")) {
     710            retval += whine_if_not_found("mkisofs");
     711        }
     712    }
     713    if (system("which wodim > /dev/null 2> /dev/null")) {
     714        retval += whine_if_not_found("cdrecord");
     715    }
     716    retval += whine_if_not_found("bzip2");
     717    retval += whine_if_not_found("gzip");
     718    retval += whine_if_not_found("cmp");
     719    retval += whine_if_not_found("awk");
     720    retval += whine_if_not_found("md5sum");
     721    retval += whine_if_not_found("strings");
     722    retval += whine_if_not_found("mindi");
     723    retval += whine_if_not_found("buffer");
     724
     725    // abort if Windows partition but no ms-sys and parted
     726    if (!run_program_and_log_output("mount | grep -Ew 'vfat|fat|dos' | grep -vE \"/dev/fd|nexdisk\"", 0)) {
     727        if (!run_program_and_log_output("mount | grep -Ew 'vfat|fat|dos' | grep -Ew efi", 0)) {
     728            log_to_screen("I think you have a EFI/UEFI partition.");
     729        } else {
     730            log_to_screen("I think you have a Windows 9x partition.");
     731        }
     732        retval += whine_if_not_found("parted");
     733    }
     734
     735    run_program_and_log_output("umount `mount | grep cdr | cut -d' ' -f3 | tr '\n' ' '`", 5);
     736    tmp = call_program_and_get_last_line_of_output("mount | grep -E 'cdr(om|w)'");
     737    if (strcmp("", tmp)) {
     738        if (strstr(tmp, "autofs")) {
     739            log_to_screen("Your CD-ROM is mounted via autofs. I therefore cannot tell");
     740            log_to_screen("if a CD actually is inserted. If a CD is inserted, please");
     741            log_to_screen("eject it. Thank you.");
     742            log_it("Ignoring autofs CD-ROM 'mount' since we hope nothing's in it.");
     743        } else
     744            if (run_program_and_log_output("uname -a | grep Knoppix", 5)) {
     745            retval++;
     746            mr_free(tmp);
     747            fatal_error("Your CD-ROM drive is mounted. Please unmount it.");
     748        }
     749    }
     750    mr_free(tmp);
     751
     752    run_program_and_log_output("cat /etc/fstab", 5);
     753#ifdef __FreeBSD__
     754    run_program_and_log_output("vinum printconfig", 5);
     755#else
     756    run_program_and_log_output("cat /etc/raidtab", 5);
     757#endif
     758
     759    if (run_program_and_log_output("mindi -V", 1)) {
     760        log_to_screen("Could not ascertain mindi's version number.");
     761        log_to_screen("You have not installed Mondo and/or Mindi properly.");
     762        log_to_screen("Please uninstall and reinstall them both.");
     763        fatal_error("Please reinstall Mondo and Mindi.");
     764    }
     765    mr_asprintf(tmp, "mindi --makemountlist %s/mountlist.txt.test", bkpinfo->tmpdir);
     766    if (run_program_and_log_output(tmp, 5)) {
     767        log_to_screen("%s failed for some reason.", tmp);
     768        mr_free(tmp);
     769        log_to_screen("Please run that command by hand and examine "MINDI_LOGFILE);
     770        log_to_screen("for more information. Perhaps your /etc/fstab file is insane.");
     771        log_to_screen("Perhaps Mindi's MakeMountlist() subroutine has a bug. We'll see.");
     772        retval++;
     773    }
     774    mr_free(tmp);
     775
     776    if (!run_program_and_log_output("mr-parted2fdisk -l 2>/dev/null | grep -i raid", 1) && !does_file_exist("/etc/raidtab")) {
     777        log_to_screen("You have RAID partitions but no /etc/raidtab - creating one from /proc/mdstat");
     778        create_raidtab_from_mdstat(MDSTAT_FILE,"/etc/raidtab");
     779    }
     780
     781    if (retval) {
     782        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
     783    } else {
     784        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
     785    }
     786    return (retval);
     787}
     788
     789
     790
     791/**
    652792 * Do some miscellaneous setup tasks to be performed before filling @c bkpinfo.
    653793 * Seeds the random-number generator, loads important modules, checks the sanity
     
    8971037}
    8981038
    899 
    900 
    901 /**
    902  * Check the user's system for sanity. Checks performed:
    903  * - make sure user has enough RAM (32mb required, 64mb recommended)
    904  * - make sure user has enough free space in @c /
    905  * - check kernel for ramdisk support
    906  * - make sure afio, cdrecord, mkisofs, bzip2, awk, md5sum, strings, mindi, and buffer exist
    907  * - make sure CD-ROM is unmounted
    908  * - make sure user's mountlist is OK by running <tt>mindi --makemountlist</tt>
    909  *
    910  * @return number of problems with the user's setup (0 for success)
    911  */
    912 int some_basic_system_sanity_checks()
    913 {
    914 
    915     /*@ buffers ************ */
    916     char *tmp = NULL;
    917 
    918     /*@ int's *************** */
    919     int retval = 0;
    920 
    921     mvaddstr_and_log_it(g_currentY, 0, "Checking sanity of your Linux distribution");
    922 #ifndef __FreeBSD__
    923     if (system("which mkfs.vfat 2> /dev/null 1> /dev/null")
    924         && !system("which mkfs.msdos 2> /dev/null 1> /dev/null")) {
    925         log_it("OK, you've got mkfs.msdos but not mkfs.vfat; time for the fairy to wave her magic wand...");
    926         run_program_and_log_output("ln -sf `which mkfs.msdos` /sbin/mkfs.vfat", FALSE);
    927     }
    928     tmp = call_program_and_get_last_line_of_output("free | grep Mem | head -n1 | tr -s ' ' '\t' | cut -f2");
    929     if (atol(tmp) < 35000) {
    930         retval++;
    931         log_to_screen("You must have at least 32MB of RAM to use Mondo.");
    932     }
    933     if (atol(tmp) < 66000) {
    934         log_to_screen("WARNING! You have very little RAM. Please upgrade to 64MB or more.");
    935     }
    936     mr_free(tmp);
    937 #endif
    938 
    939     if (system("which " MKE2FS_OR_NEWFS " > /dev/null 2> /dev/null")) {
    940         retval++;
    941         log_to_screen("Unable to find " MKE2FS_OR_NEWFS " in system path.");
    942         fatal_error("Please use \"su -\", not \"su\" to become root. OK?\n...and please don't e-mail the mailing list about this. Just read the message. :)");
    943     }
    944 #ifndef __FreeBSD__
    945     if (run_program_and_log_output("grep ramdisk /proc/devices", FALSE)) {
    946         /* Some SuSE have ramdisk as modules, so insert it first, then test again */
    947         run_program_and_log_output("modprobe brd 2> /dev/null > /dev/null",FALSE);
    948         if (run_program_and_log_output("grep ramdisk /proc/devices", FALSE)) {
    949             if (!ask_me_yes_or_no("Your kernel has no ramdisk support. That's mind-numbingly stupid but I'll allow it if you're planning to use another kernel. Are you?")) {
    950                 //          retval++;
    951                 log_to_screen("It looks as if your kernel lacks ramdisk and initrd support.");
    952                 log_to_screen("I'll allow you to proceed but FYI, if I'm right, your kernel is broken.");
    953             }
    954         }
    955     }
    956 #endif
    957     retval += whine_if_not_found(MKE2FS_OR_NEWFS);
    958     if (system("which xorriso > /dev/null 2> /dev/null")) {
    959         if (system("which genisoimage > /dev/null 2> /dev/null")) {
    960             retval += whine_if_not_found("mkisofs");
    961         }
    962     }
    963     if (system("which wodim > /dev/null 2> /dev/null")) {
    964         retval += whine_if_not_found("cdrecord");
    965     }
    966     retval += whine_if_not_found("bzip2");
    967     retval += whine_if_not_found("gzip");
    968     retval += whine_if_not_found("cmp");
    969     retval += whine_if_not_found("awk");
    970     retval += whine_if_not_found("md5sum");
    971     retval += whine_if_not_found("strings");
    972     retval += whine_if_not_found("mindi");
    973     retval += whine_if_not_found("buffer");
    974 
    975     // abort if Windows partition but no ms-sys and parted
    976     if (!run_program_and_log_output("mount | grep -Ew 'vfat|fat|dos' | grep -vE \"/dev/fd|nexdisk\"", 0)) {
    977         if (!run_program_and_log_output("mount | grep -Ew 'vfat|fat|dos' | grep -Ew efi", 0)) {
    978             log_to_screen("I think you have a EFI/UEFI partition.");
    979         } else {
    980             log_to_screen("I think you have a Windows 9x partition.");
    981         }
    982         retval += whine_if_not_found("parted");
    983     }
    984 
    985     run_program_and_log_output("umount `mount | grep cdr | cut -d' ' -f3 | tr '\n' ' '`", 5);
    986     tmp = call_program_and_get_last_line_of_output("mount | grep -E 'cdr(om|w)'");
    987     if (strcmp("", tmp)) {
    988         if (strstr(tmp, "autofs")) {
    989             log_to_screen("Your CD-ROM is mounted via autofs. I therefore cannot tell");
    990             log_to_screen("if a CD actually is inserted. If a CD is inserted, please");
    991             log_to_screen("eject it. Thank you.");
    992             log_it("Ignoring autofs CD-ROM 'mount' since we hope nothing's in it.");
    993         } else
    994             if (run_program_and_log_output("uname -a | grep Knoppix", 5)) {
    995             retval++;
    996             mr_free(tmp);
    997             fatal_error("Your CD-ROM drive is mounted. Please unmount it.");
    998         }
    999     }
    1000     mr_free(tmp);
    1001 
    1002     run_program_and_log_output("cat /etc/fstab", 5);
    1003 #ifdef __FreeBSD__
    1004     run_program_and_log_output("vinum printconfig", 5);
    1005 #else
    1006     run_program_and_log_output("cat /etc/raidtab", 5);
    1007 #endif
    1008 
    1009     if (run_program_and_log_output("mindi -V", 1)) {
    1010         log_to_screen("Could not ascertain mindi's version number.");
    1011         log_to_screen("You have not installed Mondo and/or Mindi properly.");
    1012         log_to_screen("Please uninstall and reinstall them both.");
    1013         fatal_error("Please reinstall Mondo and Mindi.");
    1014     }
    1015     mr_asprintf(tmp, "mindi --makemountlist %s/mountlist.txt.test", bkpinfo->tmpdir);
    1016     if (run_program_and_log_output(tmp, 5)) {
    1017         log_to_screen("%s failed for some reason.", tmp);
    1018         mr_free(tmp);
    1019         log_to_screen("Please run that command by hand and examine "MINDI_LOGFILE);
    1020         log_to_screen("for more information. Perhaps your /etc/fstab file is insane.");
    1021         log_to_screen("Perhaps Mindi's MakeMountlist() subroutine has a bug. We'll see.");
    1022         retval++;
    1023     }
    1024     mr_free(tmp);
    1025 
    1026     if (!run_program_and_log_output("mr-parted2fdisk -l 2>/dev/null | grep -i raid", 1) && !does_file_exist("/etc/raidtab")) {
    1027         log_to_screen("You have RAID partitions but no /etc/raidtab - creating one from /proc/mdstat");
    1028         create_raidtab_from_mdstat(MDSTAT_FILE,"/etc/raidtab");
    1029     }
    1030 
    1031     if (retval) {
    1032         mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
    1033     } else {
    1034         mvaddstr_and_log_it(g_currentY++, 74, "Done.");
    1035     }
    1036     return (retval);
    1037 }
    1038 
    10391039/**
    10401040 * Retrieve the line containing @p label from the config file.
  • branches/3.3/mondo/src/common/libmondo-verify.c

    r3871 r3877  
    1919#include "libmondo-devices-EXT.h"
    2020#include "libmondo-tools-EXT.h"
     21#include "libmondo-filelist-EXT.h"
    2122
    2223
     
    3334extern char *g_getfattr;
    3435extern char *MONDO_LOGFILE;
     36extern int g_current_media_number;
     37extern long g_current_progress;
    3538
    3639/* Reference to global bkpinfo */
     
    316319        } else if (does_file_exist(slice_fname(bigfile_num, slice_num, mountpoint, "")) &&
    317320                   (length_of_file(slice_fname(bigfile_num, slice_num, mountpoint, "")) == 0)) {
    318             log_msg(2, "ISO=%d  bigfile=%ld ---END---",
    319                     g_current_media_number, bigfile_num);
     321            log_msg(2, "ISO=%d  bigfile=%ld ---END---", g_current_media_number, bigfile_num);
    320322            bigfile_num++;
    321323            paranoid_fclose(forig);
Note: See TracChangeset for help on using the changeset viewer.