Ignore:
Timestamp:
Sep 30, 2009, 4:44:40 AM (15 years ago)
Author:
Bruno Cornec
Message:
  • priority given to env var for tmpdir
  • fuse FS excluded from tmpdir computation
  • Improves udev timeout handling
  • fuse device is needed at restore time for sshfs
  • Avoids comment analysis in the new code handling deplist.d
  • Avoids error message if some ssh conf files do not exist
  • Improvements on sshfs/ssh management in restore mode
  • Include now all minimal requirements for sshfs
  • Fix udev support in init for Mandriva 2009.1 (udevadm settle is blocking)
  • Improve deplist.d/* files
  • adds libnss for ssh support in boot disk
  • Solve a memory management issue in DSF module (strtok => mr_strtok)
  • DSF now also supports partitions in addition to full disks
  • Adds debug in open_and_list_dir
  • Improve user management for NetFS cases
  • ssh in the restore env needs some dlopened libs (libnss_compat|files)
  • Warning emited in case of duplicate mountpoints or devices in fstab found
  • Use only the AWK veriable everywhere and not the awk command
  • Simplify GetInitrdFilesystemToUse which doesn't need to detect everything, but just know if it's initramfs (new mode) or a compressed FS ext2/3 (older mode) as initrd is anyway re-made by mindi. Should fix #353

(Backport from 2.2.9)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.10/mondo/src/common/libmondo-devices.c

    r2428 r2444  
    14041404
    14051405/**
    1406  * @addtogroup utilityGroup
    1407  * @{
    1408  */
    1409 /**
    1410  * Get a space-separated list of NETFS devices and mounts.
    1411  * @return The list created.
    1412  * @note The return value points to static data that will be overwritten with each call.
    1413  */
    1414 char *list_of_NETFS_devices_and_mounts(void)
    1415 {
    1416     char *exclude_these_devices = NULL;
    1417     char *exclude_these_directories = NULL;
    1418     static char result_sz[1024];
    1419 
    1420     mr_asprintf(exclude_these_directories,"%s",list_of_NETFS_mounts_only());
    1421     exclude_these_devices = call_program_and_get_last_line_of_output("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|sshfs|nfs|nfs4|smbfs|cifs|afs|gfs|ocfs|ocfs2|mvfs|nsspool|nsvol) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'");
    1422     snprintf(result_sz, 1023, "%s %s", exclude_these_directories, exclude_these_devices);
    1423     mr_free(exclude_these_devices);
    1424     mr_free(exclude_these_directories);
    1425     return (result_sz);
    1426 }
    1427 
    1428 
    1429 
    1430 
    1431 /**
    1432  * Get a space-separated list of NETFS mounts.
    1433  * @return The list created.
    1434  * @note The return value points to static data that will be overwritten with each call.
    1435  * @bug Even though we only want the mounts, the devices are still checked.
    1436  */
    1437 char *list_of_NETFS_mounts_only(void)
    1438 {
    1439     char *exclude_these_directories = NULL;
    1440     static char result_sz[512];
    1441 
    1442     exclude_these_directories = call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'");
    1443     snprintf(result_sz, 511, "%s", exclude_these_directories);
    1444     mr_free(exclude_these_directories);
    1445     return (result_sz);
    1446 }
    1447 
    1448 /* @} - end of utilityGroup */
    1449 
    1450 
    1451 
    1452 
    1453 
    1454 /**
    1455  * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
    1456  * [random] is a random number between 1 and 32767.
    1457  * @param store_name_here Where to store the new filename.
    1458  * @param stub A random number will be appended to this to make the FIFO's name.
    1459  * @ingroup deviceGroup
    1460  */
    1461 void make_fifo(char *store_name_here, char *stub)
    1462 {
    1463     char *tmp = NULL;
    1464 
    1465     assert_string_is_neither_NULL_nor_zerolength(stub);
    1466 
    1467     sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
    1468             (int) (random() % 32768));
    1469     make_hole_for_file(store_name_here);
    1470     mkfifo(store_name_here, S_IRWXU | S_IRWXG);
    1471     mr_asprintf(tmp, "chmod 770 %s", store_name_here);
    1472     paranoid_system(tmp);
    1473     mr_free(tmp);
    1474 }
    1475 
    1476 
    1477 
    1478 
    1479 
    1480 
    1481 /**
    1482  * Set the tmpdir and scratchdir to reside on the partition with the most free space.
    1483  * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
    1484  * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
    1485  * @ingroup utilityGroup
    1486  */
    1487 void sensibly_set_scratchdir()
    1488 {
    1489     char *tmp = NULL;
    1490     char *command = NULL;
    1491     char *sz = NULL;
    1492 
    1493 #ifdef __FreeBSD__
    1494     tmp = call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -t nonfs,msdosfs,ntfs,ntfs-3g,smbfs,smb,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -n | tail -n1 | awk '{print $NF;}'");
    1495 #else
    1496     tmp = call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -x nfs -x nfs4 -x fuse.sshfs -x vfat -x ntfs -x ntfs-3g -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 -n | tail -n1 | awk '{print $NF;}'");
    1497 #endif
    1498 
    1499     if (tmp[0] != '/') {
    1500         mr_asprintf(sz, "%s", tmp);
    1501         mr_free(tmp);
    1502         mr_asprintf(tmp, "/%s", sz);
    1503         mr_free(sz);
    1504     }
    1505     if (!tmp[0]) {
    1506         fatal_error("I couldn't figure out the scratchdir!");
    1507     }
    1508 
    1509     /* Cleaning a potential previous scratchdir */
    1510     if (bkpinfo->scratchdir) {
    1511         mr_asprintf(command, "rm -Rf %s", bkpinfo->scratchdir);
    1512         paranoid_system(command);
    1513         mr_free(command);
    1514     }
    1515     mr_free(bkpinfo->scratchdir);
    1516 
    1517     mr_asprintf(bkpinfo->scratchdir , "%s/mondo.scratch.%d", tmp, (int) (random() % 32768));
    1518     log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
    1519 
    1520     /* Cleaning potential previous scratchdir */
    1521     mr_asprintf(command, "rm -Rf %s/mondo.scratch.*", tmp);
    1522     mr_free(tmp);
    1523 
    1524     paranoid_system(command);
    1525     mr_free(command);
    1526 }
    1527 
    1528 
    1529 
    1530 
    1531 
    1532 
    1533 /**
    1534  * @addtogroup deviceGroup
    1535  * @{
    1536  */
    1537 /**
    1538  * If we can read @p dev, set @return output to it.
    1539  * If @p dev cannot be read, set @p output to NULL.
    1540  * @param dev The device to check for.
    1541  * @return output Set to @p dev if @p dev exists, NULL otherwise.
    1542  */
    1543 char *set_dev_to_this_if_rx_OK(char *dev)
    1544 {
    1545     char *command = NULL;
    1546     char *output = NULL;
    1547 
    1548     if (!dev || dev[0] == '\0') {
    1549         return(NULL);
    1550     }
    1551     log_msg(10, "Injecting %s", dev);
    1552     inject_device(dev);
    1553     if (!does_file_exist(dev)) {
    1554         log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
    1555         return(NULL);
    1556     }
    1557     mr_asprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null", 512L, dev);
    1558     if (!run_program_and_log_output(command, FALSE)
    1559         && !run_program_and_log_output(command, FALSE)) {
    1560         mr_asprintf(output, "%s", dev);
    1561         log_msg(4, "Found it - %s", dev);
     1406 * Creates a singly linked list of all of the non-NETFS mounted file systems.
     1407 * @param DSFptr A pointer  to the structure MOUNTED_FS_STRUCT used to hold
     1408 * the list of mounted file systems.
     1409 * @return None.
     1410 */
     1411static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
     1412{
     1413    assert (DSFptr);
     1414    if (DSF_Head == NULL) {
     1415        DSF_Head = DSFptr;
    15621416    } else {
    1563         log_msg(4, "It's not %s", dev);
    1564     }
    1565     mr_free(command);
    1566     return(output);
    1567 }
    1568 
    1569 
    1570 
    1571 
    1572 
    1573 /**
    1574  * Find out what number CD is in the drive.
    1575  * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
    1576  * @return The current CD number, or -1 if it could not be found.
    1577  * @note If the CD is not mounted, it will be mounted
    1578  * (and remain mounted after this function returns).
    1579  */
    1580 int what_number_cd_is_this()
    1581 {
    1582     int cd_number = -1;
    1583     char *mountdev = NULL;
    1584     char *tmp = NULL;
    1585 
    1586     assert(bkpinfo != NULL);
    1587     //  log_it("Asking what_number_cd_is_this");
    1588     if (g_ISO_restore_mode) {
    1589         mr_asprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
    1590         mountdev = call_program_and_get_last_line_of_output(tmp);
    1591         mr_strcat(mountdev, "/archives/THIS-CD-NUMBER");
    1592         mr_free(tmp);
    1593 
    1594         tmp = last_line_of_file(mountdev);
    1595         cd_number = atoi(tmp);
    1596         mr_free(tmp);
    1597         mr_free(mountdev);
    1598         return (cd_number);
    1599     }
    1600 
    1601     if (bkpinfo->media_device) {
    1602         mr_asprintf(mountdev, "%s", bkpinfo->media_device);
    1603     }
    1604     if (!mountdev) {
    1605         log_it("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
    1606         mr_free(bkpinfo->media_device);
    1607         bkpinfo->media_device = find_cdrom_device(FALSE);
    1608         mr_asprintf(mountdev, "%s", bkpinfo->media_device);
    1609     }
    1610     if (!is_this_device_mounted(MNT_CDROM)) {
    1611         if (bkpinfo->backup_media_type == usb) {
    1612             mount_USB_here(mountdev, MNT_CDROM);
    1613         } else {
    1614             mount_CDROM_here(mountdev, MNT_CDROM);
    1615         }
    1616     }
    1617     mr_free(mountdev);
    1618 
    1619     tmp = last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER");
    1620     cd_number = atoi(tmp);
    1621     mr_free(tmp);
    1622     return (cd_number);
    1623 }
    1624 
    1625 
    1626 
    1627 
    1628 
    1629 
    1630 
    1631 /**
    1632  * Find out what device is mounted as root (/).
    1633  * @return Root device.
    1634  * @note The returned string points to static storage and will be overwritten with every call.
    1635  * @bug A bit of a misnomer; it's actually finding out the root device.
    1636  * The mountpoint (where it's mounted) will obviously be '/'.
    1637  */
    1638 char *where_is_root_mounted() {
    1639     /*@ buffers **************** */
    1640     char *output = NULL;
    1641 
    1642 
    1643 #ifdef __FreeBSD__
    1644     output = call_program_and_get_last_line_of_output("mount | grep ' on / ' | cut -d' ' -f1");
    1645 #else
    1646     output = call_program_and_get_last_line_of_output("mount | grep ' on / ' | cut -d' ' -f1 | sed 's/[0-9]//' | sed 's/[0-9]//'");
    1647     if (strstr(output, "/dev/cciss/")) {
    1648         mr_free(output);
    1649         output = call_program_and_get_last_line_of_output("mount | grep ' on / ' | cut -d' ' -f1 | cut -dp -f1");
    1650     }
    1651     if (strstr(output, "/dev/md")) {
    1652         mr_free(output);
    1653         output = call_program_and_get_last_line_of_output("mount | grep ' on / ' | cut -d' ' -f1");
    1654     }
    1655 #endif
    1656 
    1657     return (output);
    1658 }
    1659 
    1660 
    1661 /**
    1662  * Find out which boot loader is in use.
    1663  * @param which_device Device to look for the boot loader on.
    1664  * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
    1665  * @note Under Linux, all drives are examined, not just @p which_device.
    1666  */
    1667 #ifdef __FreeBSD__
    1668 char which_boot_loader(char *which_device) {
    1669     int count_lilos = 0;
    1670     int count_grubs = 0;
    1671     int count_boot0s = 0;
    1672     int count_dangerouslydedicated = 0;
    1673 
    1674     log_it("looking at drive %s's MBR", which_device);
    1675     if (does_string_exist_in_boot_block(which_device, "GRUB")) {
    1676         count_grubs++;
    1677     }
    1678     if (does_string_exist_in_boot_block(which_device, "LILO")) {
    1679         count_lilos++;
    1680     }
    1681     if (does_string_exist_in_boot_block(which_device, "Drive")) {
    1682         count_boot0s++;
    1683     }
    1684     if (does_string_exist_in_first_N_blocks(which_device, "FreeBSD/i386", 17)) {
    1685         count_dangerouslydedicated++;
    1686     }
    1687     log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
    1688            count_grubs, count_lilos, count_elilos, count_boot0s,
    1689            count_dangerouslydedicated);
    1690 
    1691     if (count_grubs && !count_lilos) {
    1692         return ('G');
    1693     } else if (count_lilos && !count_grubs) {
    1694         return ('L');
    1695     } else if (count_grubs == 1 && count_lilos == 1) {
    1696         log_it("I'll bet you used to use LILO but switched to GRUB...");
    1697         return ('G');
    1698     } else if (count_boot0s == 1) {
    1699         return ('B');
    1700     } else if (count_dangerouslydedicated) {
    1701         return ('D');
    1702     } else {
    1703         log_it("Unknown boot loader");
    1704         return ('U');
    1705     }
    1706 }
    1707 
    1708 #else
    1709 
    1710 char which_boot_loader(char *which_device) {
    1711     /*@ buffer ***************************************************** */
    1712     char *list_drives_cmd = NULL;
    1713     char *tmp = NULL;
    1714     char *current_drive = NULL;
    1715 
    1716     /*@ pointers *************************************************** */
    1717     FILE *pdrives = NULL;
    1718 
    1719     /*@ int ******************************************************** */
    1720     int count_lilos = 0;
    1721     int count_grubs = 0;
    1722 
    1723     /*@ end vars *************************************************** */
    1724 
    1725 
    1726 #ifdef __IA64__
    1727     /* No choice for it */
    1728     return ('E');
    1729 #endif
    1730 
    1731     tmp = where_is_root_mounted();
    1732     mr_asprintf(list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s", tmp);
    1733     mr_free(tmp);
    1734     log_it("list_drives_cmd = %s", list_drives_cmd);
    1735 
    1736     pdrives = popen(list_drives_cmd, "r");
    1737     mr_free(list_drives_cmd);
    1738 
    1739     if (!pdrives) {
    1740         log_OS_error("Unable to open list of drives");
    1741         return ('\0');
    1742     }
    1743 
    1744     for (mr_getline(current_drive, pdrives); !feof(pdrives); mr_getline(current_drive, pdrives)) {
    1745         mr_strip_spaces(current_drive);
    1746         log_it("looking at drive %s's MBR", current_drive);
    1747         if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
    1748             count_grubs++;
    1749             /* BERLIOS : removed as I don't think it's mandatory here
    1750             mr_free(which_device);
    1751             mr_asprintf(which_device, "%s", current_drive);
    1752             */
    1753             mr_free(current_drive);
     1417        DSF_Tail->next = DSFptr;
     1418    }
     1419    DSFptr->next = NULL;
     1420    DSF_Tail = DSFptr;
     1421}
     1422
     1423/**
     1424 * Find the structure, in the singly linked list of all of the non-NETFS
     1425 * mounted file systems, that contains the specified device.
     1426 * @param device The device to find
     1427 * @return NULL if it didn't find the device, a pointer to the
     1428 * structure if it did.
     1429 */
     1430static MOUNTED_FS_STRUCT *find_device_in_list (char *device)
     1431{
     1432    MOUNTED_FS_STRUCT *DSFptr = NULL;
     1433
     1434    DSFptr = DSF_Head;
     1435    while (DSFptr != NULL) {
     1436        if (!strcmp(DSFptr->device, device)) {
    17541437            break;
    17551438        }
    1756         if (does_string_exist_in_boot_block(current_drive, "LILO")) {
    1757             count_lilos++;
    1758             /* BERLIOS : removed as I don't think it's mandatory here
    1759             mr_free(which_device);
    1760             mr_asprintf(which_device, "%s", current_drive);
    1761             */
    1762             mr_free(current_drive);
     1439        DSFptr = DSFptr->next;
     1440    }
     1441    return (DSFptr);
     1442}
     1443
     1444/**
     1445 * Find the structure, in the singly linked list of all of the non-NETFS
     1446 * mounted file systems, that contains the specified mount point.
     1447 * @param mount_point The mount point to find
     1448 * @return NULL is it didn't find the mount point, a pointer to the
     1449 * structure if it did.
     1450 */
     1451static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
     1452{
     1453    MOUNTED_FS_STRUCT *DSFptr = NULL;
     1454
     1455    DSFptr = DSF_Head;
     1456    while (DSFptr != NULL) {
     1457        if (!strcmp(DSFptr->mount_point, mount_point)) {
    17631458            break;
    17641459        }
    1765         mr_free(current_drive);
    1766     }
    1767     mr_free(current_drive);
    1768 
    1769     if (pclose(pdrives)) {
    1770         log_OS_error("Cannot pclose pdrives");
    1771     }
    1772     log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
    1773     if (count_grubs && !count_lilos) {
    1774         return ('G');
    1775     } else if (count_lilos && !count_grubs) {
    1776         return ('L');
    1777     } else if (count_grubs == 1 && count_lilos == 1) {
    1778         log_it("I'll bet you used to use LILO but switched to GRUB...");
    1779         return ('G');
    1780     } else {
    1781         // We need to look on each partition then
    1782         mr_asprintf(list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
    1783         log_it("list_drives_cmd = %s", list_drives_cmd);
    1784 
    1785         if (!(pdrives = popen(list_drives_cmd, "r"))) {
    1786             log_OS_error("Unable to open list of drives");
    1787             mr_free(list_drives_cmd);
    1788             return ('\0');
    1789         }
    1790         mr_free(list_drives_cmd);
    1791 
    1792         for (mr_getline(current_drive, pdrives); !feof(pdrives); mr_getline(current_drive, pdrives)) {
    1793             mr_strip_spaces(current_drive);
    1794             log_it("looking at partition %s's BR", current_drive);
    1795             if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
    1796                 count_grubs++;
    1797                 /* BERLIOS : removed as I don't think it's mandatory here
    1798                 mr_free(which_device);
    1799                 mr_asprintf(which_device, "%s", current_drive);
    1800                 */
    1801                 mr_free(current_drive);
    1802                 break;
    1803             }
    1804             if (does_string_exist_in_boot_block(current_drive, "LILO")) {
    1805                 count_lilos++;
    1806                 /* BERLIOS : removed as I don't think it's mandatory here
    1807                 mr_free(which_device);
    1808                 mr_asprintf(which_device, "%s", current_drive);
    1809                 */
    1810                 mr_free(current_drive);
    1811                 break;
    1812             }
    1813             mr_free(current_drive);
    1814         }
    1815         mr_free(current_drive);
    1816 
    1817         if (pclose(pdrives)) {
    1818             log_OS_error("Cannot pclose pdrives");
    1819         }
    1820         log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
    1821         if (count_grubs && !count_lilos) {
    1822             return ('G');
    1823         } else if (count_lilos && !count_grubs) {
    1824             return ('L');
    1825         } else if (count_grubs == 1 && count_lilos == 1) {
    1826             log_it("I'll bet you used to use LILO but switched to GRUB...");
    1827             return ('G');
    1828         } else {
    1829             log_it("Unknown boot loader");
    1830             return ('U');
    1831         }
    1832     }
    1833 }
    1834 #endif
    1835 
    1836 
    1837 
    1838 
    1839 /**
    1840  * Write zeroes over the first 16K of @p device.
    1841  * @param device The device to zero.
    1842  * @return 0 for success, 1 for failure.
    1843  */
    1844 int zero_out_a_device(char *device)
    1845 {
    1846     FILE *fout;
    1847     int i;
    1848 
    1849     assert_string_is_neither_NULL_nor_zerolength(device);
    1850 
    1851     log_it("Zeroing drive %s", device);
    1852     if (!(fout = fopen(device, "w"))) {
    1853         log_OS_error("Unable to open/write to device");
    1854         return (1);
    1855     }
    1856     for (i = 0; i < 16384; i++) {
    1857         fputc('\0', fout);
    1858     }
    1859     paranoid_fclose(fout);
    1860     log_it("Device successfully zeroed.");
    1861     return (0);
    1862 }
    1863 
    1864 /**
    1865  * Return the device pointed to by @p incoming.
    1866  * @param incoming The device to resolve symlinks for.
    1867  * @return The path to the real device file.
    1868  * @note The returned string points to static storage that will be overwritten with each call.
    1869  * @bug Won't work with file v4.0; needs to be written in C.
    1870  */
    1871 char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
    1872 {
    1873     char *output;
    1874     char *command = NULL;
    1875     char *curr_fname;
    1876     char *scratch = NULL;
    1877     char *tmp = NULL;
    1878     char *p;
    1879 
    1880     struct stat statbuf;
    1881     malloc_string(curr_fname);
    1882     if (!does_file_exist(incoming)) {
    1883         log_it("resolve_softlinks_to_get_to_actual_device_file --- device not found");
    1884         mr_asprintf(output, "%s", incoming);
    1885     } else {
    1886         strcpy(curr_fname, incoming);
    1887         lstat(curr_fname, &statbuf);
    1888         while (S_ISLNK(statbuf.st_mode)) {
    1889             log_msg(1, "curr_fname = %s", curr_fname);
    1890             mr_asprintf(command, "file %s", curr_fname);
    1891             tmp = call_program_and_get_last_line_of_output(command);
    1892             mr_free(command);
    1893             for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' '; p--);
    1894             p++;
    1895             mr_asprintf(scratch, "%s", p);
    1896             for (p = scratch; *p != '\0' && *p != '\''; p++);
    1897             *p = '\0';
    1898             log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
    1899             mr_free(tmp);
    1900 
    1901             if (scratch[0] == '/') {
    1902                 strcpy(curr_fname, scratch);    // copy whole thing because it's an absolute softlink
    1903             } else {            // copy over the basename cos it's a relative softlink
    1904                 p = curr_fname + strlen(curr_fname);
    1905                 while (p != curr_fname && *p != '/') {
    1906                     p--;
    1907                 }
    1908                 if (*p == '/') {
    1909                     p++;
    1910                 }
    1911                 strcpy(p, scratch);
    1912             }
    1913             mr_free(scratch);
    1914             lstat(curr_fname, &statbuf);
    1915         }
    1916         mr_asprintf(output, "%s", curr_fname);
    1917         log_it("resolved %s to %s", incoming, output);
    1918     }
    1919     paranoid_free(curr_fname);
    1920     return (output);
    1921 }
    1922 
    1923 /* @} - end of deviceGroup */
    1924 
    1925 /**
    1926  * Return the type of partition format (GPT or MBR)
    1927  */
    1928 char *which_partition_format(const char *drive)
    1929 {
    1930     char *output;
    1931     char *tmp = NULL;
    1932     char *command = NULL;
    1933     char *fdisk = NULL;
    1934 #ifdef __IA64__
    1935     struct stat buf;
    1936 #endif
    1937     mr_asprintf(fdisk, "/sbin/parted2fdisk");
    1938     mr_asprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
    1939     mr_free(fdisk);
    1940 
    1941     tmp = call_program_and_get_last_line_of_output(command);
    1942     mr_free(command);
    1943 
    1944     if (strstr(tmp, "GPT") == NULL) {
    1945         mr_asprintf(output, "MBR");
    1946     } else {
    1947         mr_asprintf(output, "GPT");
    1948     }
    1949     mr_free(tmp);
    1950 
    1951     log_msg(0, "Found %s partition table format type", output);
    1952     return (output);
     1460        DSFptr = DSFptr->next;
     1461    }
     1462    return (DSFptr);
    19531463}
    19541464
     
    19711481}
    19721482
    1973 /**
    1974  * Creates a singly linked list of all of the non-NETFS mounted file systems.
    1975  * @param DSFptr A pointer  to the structure MOUNTED_FS_STRUCT used to hold
    1976  * the list of mounted file systems.
    1977  * @return None.
    1978  */
    1979 static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)
    1980 {
    1981     assert (DSFptr);
    1982     if (DSF_Head == NULL) {
    1983         DSF_Head = DSFptr;
    1984     } else {
    1985         DSF_Tail->next = DSFptr;
    1986     }
    1987     DSFptr->next = NULL;
    1988     DSF_Tail = DSFptr;
    1989 }
    1990 
    1991 /**
    1992  * Find the structure, in the singly linked list of all of the non-NETFS
    1993  * mounted file systems, that contains the specified device.
    1994  * @param device The device to find
    1995  * @return NULL if it didn't find the device, a pointer to the
    1996  * structure if it did.
    1997  */
    1998 static MOUNTED_FS_STRUCT *find_device_in_list (char *device)
    1999 {
    2000     MOUNTED_FS_STRUCT *DSFptr = NULL;
    2001 
    2002     DSFptr = DSF_Head;
    2003     while (DSFptr != NULL) {
    2004         if (!strcmp(DSFptr->device, device)) {
    2005             break;
    2006         }
    2007         DSFptr = DSFptr->next;
    2008     }
    2009     return (DSFptr);
    2010 }
    2011 
    2012 /**
    2013  * Find the structure, in the singly linked list of all of the non-NETFS
    2014  * mounted file systems, that contains the specified mount point.
    2015  * @param mount_point The mount point to find
    2016  * @return NULL is it didn't find the mount point, a pointer to the
    2017  * structure if it did.
    2018  */
    2019 static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)
    2020 {
    2021     MOUNTED_FS_STRUCT *DSFptr = NULL;
    2022 
    2023     DSFptr = DSF_Head;
    2024     while (DSFptr != NULL) {
    2025         if (!strcmp(DSFptr->mount_point, mount_point)) {
    2026             break;
    2027         }
    2028         DSFptr = DSFptr->next;
    2029     }
    2030     return (DSFptr);
    2031 }
    20321483
    20331484/**
     
    20411492    int i = 0;
    20421493    int mount_cnt = 0;
     1494    int lastpos = 0;
    20431495    char *mounted_file_system = NULL;
    20441496    char *command = NULL;
     
    20711523
    20721524        log_msg (5, "mounted_file_system: %s", mounted_file_system);
    2073         if ((token = strtok(mounted_file_system, token_chars)) == NULL) {
     1525        if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
    20741526            log_msg (4, "Could not get the list of mounted file systems");
    20751527            mr_free(mounted_file_system);
     
    20881540            strcpy(DSFptr->device, token);
    20891541            mr_free(token);
    2090             if ((token = strtok(NULL, token_chars)) == NULL) {
     1542            if ((token = mr_strtok(mounted_file_system, token_chars, &lastpos)) == NULL) {
    20911543                log_msg (5, "Ran out of entries on the mounted file systems list");
    20921544                mr_free(mounted_file_system);
     
    20971549            strcpy(DSFptr->mount_point, token);
    20981550            mr_free(token);
    2099             token = strtok(NULL, token_chars);
     1551            token = mr_strtok(mounted_file_system, token_chars, &lastpos);
    21001552        }
    21011553        mr_free(mounted_file_system);
     
    21251577    char *command = NULL;
    21261578    char *partition_list = NULL;
    2127     char partitions[64][MAX_STR_LEN];
     1579    char *partitions[64];
    21281580    char *mount_list = NULL;
    21291581    char *token = NULL;
     1582    char *ndsf = NULL;
    21301583    char token_chars[] =" \t\r\f\a\0";
    21311584    MOUNTED_FS_STRUCT *DSFptr = NULL;
     
    21451598    /* Verify that the dsf exists */
    21461599    mr_asprintf(command, "ls -al %s 2>/dev/null | wc -l", dsf);
    2147     log_msg(5, "Executing: %s", command);
     1600    log_msg(5, "  Executing: %s", command);
    21481601    tmp = call_program_and_get_last_line_of_output(command);
    21491602    mr_free(command);
     
    21741627    partition_list = call_program_and_get_last_line_of_output(command);
    21751628    mr_free(command);
     1629
    21761630    log_msg(4, "Partition list for %s: %s", dsf, partition_list);
    21771631    if (!strlen(partition_list)) {
    21781632        /* There were no partitions on the disk */
    2179         log_msg(4, "Cannot find any partitions on device special file %s", dsf);
    2180         return (-2);
    2181     }
    2182 
    2183     /* Fill the partition list */
    2184     i = 0;
    2185     lastpos = 0;
    2186     while ((token = mr_strtok(partition_list, token_chars, &lastpos)) != NULL) {
    2187         log_msg (5, "Found partition: %s", token);
    2188         strcpy(partitions[i++], token);
    2189         mr_free(token);
    2190     }
    2191     paranoid_free(partition_list);
     1633        log_msg(4, "No partitions on device special file %s", dsf);
     1634        log_msg(4, "I guess it's a partiion itself");
     1635        mr_asprintf(partitions[0], "%s", dsf);
     1636        ndsf = truncate_to_drive_name(dsf);
     1637    } else {
     1638        /* Fill the partition list */
     1639        i = 0;
     1640        lastpos = 0;
     1641        while ((token = mr_strtok(partition_list, token_chars, &lastpos)) != NULL) {
     1642            log_msg (5, "Found partition: %s", token);
     1643            partitions[i++] = token;
     1644        }
     1645        mr_asprintf(ndsf, "%s", dsf);
     1646    }
     1647    mr_free(partition_list);
    21921648 
     1649    /*  For the rest ndsf is the new dsf to deal with */
    21931650    /********
    21941651     * At this point, we have a list of all of the partitions on the dsf. Now try to
     
    22231680        log_msg(4, "Processing partition: %s", partitions[i]);
    22241681        /* See if it's swap. If it is, ignore it. */
    2225         mr_asprintf(command, "parted2fdisk -l %s 2>/dev/null | awk '{if(($1==\"%s\")&&(toupper($0) ~ \"SWAP\")){print $1;exit}}'", dsf, partitions[i]);
     1682        mr_asprintf(command, "parted2fdisk -l %s 2>/dev/null | awk '{if(($1==\"%s\")&&(toupper($0) ~ \"SWAP\")){print $1;exit}}'", ndsf, partitions[i]);
    22261683        log_msg(4, "  Running: %s", command);
    22271684        tmp = call_program_and_get_last_line_of_output(command);
     
    22361693            continue;
    22371694        }
     1695
    22381696        /* It's not swap. See if we can find the mount point from the mount command. */
    22391697        mr_asprintf(command, "mount 2>/dev/null | awk '{if((NF>0)&&($1==\"%s\")){print $3}}'", partitions[i]);
     
    22411699        mr_free(command);
    22421700
    2243         c = strlen(tmp);
    2244         mr_free(tmp);
    2245         if (c) {
     1701        if (strlen(tmp)) {
    22461702            log_msg(4, "  %s is mounted: %s", partitions[i], tmp);
    22471703            if ((DSFptr = find_mount_point_in_list(tmp)) == NULL) {
    22481704                log_msg (4, "Can't find mount point %s in mounted file systems list", tmp);
     1705                mr_free(tmp);
    22491706                return (1);
    22501707            }
    22511708            DSFptr->check = 1;
     1709            mr_free(tmp);
    22521710            continue;
    22531711        }
     1712        mr_free(tmp);
    22541713
    22551714        /* It's not swap and it's not mounted. See if it's LVM */
     
    22571716
    22581717        /* Get the partition ID; 8e for LVM */
    2259         mr_asprintf(command, "parted2fdisk -l %s |awk '{if($1 ~ \"^%s\"){print $5}}'", dsf, partitions[i]);
     1718        mr_asprintf(command, "parted2fdisk -l %s |awk '{if($1 ~ \"^%s\"){print $5}}'", ndsf, partitions[i]);
    22601719        log_msg(4, "  Running: %s", command);
    22611720        tmp = call_program_and_get_last_line_of_output(command);
    22621721        mr_free(command);
    22631722
    2264         c = strlen(tmp);
    2265         mr_free(tmp);
    2266         if (c) {
     1723        if (strlen(tmp)) {
    22671724            log_msg(4, "  Partition ID: %s", tmp);
    22681725            if (!strcasecmp(tmp, "8e")) {
     
    22891746                        if ((DSFptr = find_mount_point_in_list(token)) == NULL) {
    22901747                            log_msg (4, "Can't find mount point %s in mounted file systems list", token);
     1748                            mr_free(tmp);
     1749                            mr_free(VG);
    22911750                            mr_free(token);
    2292                             mr_free(VG);
    22931751                            return (1);
    22941752                        }
     
    23011759                     *******/
    23021760                    mr_free(mount_list);
     1761
    23031762                    mr_asprintf(command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
    23041763                    log_msg (5, "Running: %s", command);
     
    23111770                        mr_asprintf(command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, VG);
    23121771                        log_msg (5, "Running: %s", command);
     1772                        mr_free(tmp);
    23131773
    23141774                        tmp = call_program_and_get_last_line_of_output(command);
    2315                         paranoid_free(command);
     1775                        mr_free(command);
     1776
    23161777                        log_msg(4, "Number of Software raid device: %s", tmp);
    23171778                        c = atoi(tmp);
     
    23221783                            if ((DSFptr = find_device_in_list(token)) == NULL) {
    23231784                                log_msg (4, "Can't find device %s in mounted file systems list", token);
     1785                                mr_free(VG);
    23241786                                mr_free(token);
    23251787                                return (1);
     
    23331795                } else {
    23341796                    log_msg (4, "Error finding Volume Group for partition %s", partitions[i]);
     1797                    mr_free(tmp);
    23351798                    return (1);
    23361799                }
     1800                mr_free(tmp);
     1801                mr_free(VG);
    23371802                continue;
    23381803            }
     
    23401805            log_msg (4, "Error finding partition type for the partition %s", partitions[i]);
    23411806        }
    2342         paranoid_free(tmp);
     1807        mr_free(tmp);
     1808
    23431809        /********
    23441810         * It's not swap, mounted, or LVM. See if it's used in a software raid device.
     
    23501816        mr_free(command);
    23511817
    2352         c = strlen(tmp);
    2353         mr_free(tmp);
    2354         if (!c) {
     1818        if (!strlen(tmp)) {
    23551819            log_msg(4, "  Partition %s is not used in a non-LVM software raid device", partitions[i]);
     1820            mr_free(tmp);
    23561821            continue;
    23571822        }
    23581823        log_msg (5, "  UUID: %s", tmp);
     1824
    23591825        /* Get the Software raid device list */
    23601826        mr_asprintf(command, "%s", "cat /proc/mdstat|grep -iv Personal|awk '{if($0~\"^.*[ ]+:\"){printf(\"/dev/%s \", $1)}}END{print \"\"}'");
     
    23621828        mount_list = call_program_and_get_last_line_of_output(command);
    23631829        mr_free(command);
    2364 
     1830:w!
    23651831        log_msg(4, "  Software raid device list: %s", mount_list);
    23661832        /* Loop through the software raid device list to see if we can find the partition */
     
    23691835            mr_asprintf(command, "mdadm --detail %s 2>/dev/null | grep -c %s", token, tmp);
    23701836            log_msg(4, "  Running: %s", command);
     1837            mr_free(tmp);
     1838
    23711839            tmp = call_program_and_get_last_line_of_output(command);
    23721840            mr_free(command);
     1841
    23731842            c = atoi(tmp);
    23741843            mr_free(tmp);
     
    23871856            mr_free(token);
    23881857        }
    2389     }
    2390     mr_free(partition_list);
    2391     mr_free(mount_list);
     1858        mr_free(tmp);
     1859        mr_free(mount_list);
     1860        mr_free(partitions[i]);
     1861    }
    23921862
    23931863    /* Determine how much memory to allocate for included_dsf_list and excluded_dsf_list */
     
    24081878    while (DSFptr != NULL) {
    24091879        if (DSFptr->check) {
    2410             log_msg (5, "%s is mounted on %s and is on disk %s\n", DSFptr->device, DSFptr->mount_point, dsf);
     1880            log_msg (5, "%s is mounted on %s and is on disk %s\n", DSFptr->device, DSFptr->mount_point, ndsf);
    24111881            strcat(*included_dsf_list, DSFptr->mount_point);
    24121882            strcat(*included_dsf_list, " ");
    24131883        } else {
    2414             log_msg (4, "%s is mounted on %s and is NOT on disk %s\n", DSFptr->device, DSFptr->mount_point, dsf);
     1884            log_msg (4, "%s is mounted on %s and is NOT on disk %s\n", DSFptr->device, DSFptr->mount_point, ndsf);
    24151885            strcat(*excluded_dsf_list, DSFptr->mount_point);
    24161886            strcat(*excluded_dsf_list, " ");
     
    24181888        DSFptr = DSFptr->next;
    24191889    }
     1890    mr_free(ndsf);
     1891
    24201892    log_msg (5, "included_dsf_list: %s", *included_dsf_list);
    24211893    log_msg (5, "excluded_dsf_list: %s", *excluded_dsf_list);
     
    24961968
    24971969
     1970/**
     1971 * @addtogroup utilityGroup
     1972 * @{
     1973 */
     1974/**
     1975 * Get a space-separated list of NETFS devices and mounts.
     1976 * @return The list created.
     1977 * @note The return value points to static data that will be overwritten with each call.
     1978 */
     1979char *list_of_NETFS_devices_and_mounts(void)
     1980{
     1981    char *exclude_these_devices = NULL;
     1982    char *exclude_these_directories = NULL;
     1983    static char result_sz[1024];
     1984
     1985    mr_asprintf(exclude_these_directories,"%s",list_of_NETFS_mounts_only());
     1986    exclude_these_devices = call_program_and_get_last_line_of_output("tr -s '\t' ' ' < /etc/fstab | grep -E '( (coda|ncpfs|sshfs|nfs|nfs4|smbfs|cifs|afs|gfs|ocfs|ocfs2|mvfs|nsspool|nsvol) )' | cut -d' ' -f1 | tr -s '\n' ' ' | awk '{print $0;}'");
     1987    snprintf(result_sz, 1023, "%s %s", exclude_these_directories, exclude_these_devices);
     1988    mr_free(exclude_these_devices);
     1989    mr_free(exclude_these_directories);
     1990    return (result_sz);
     1991}
     1992
     1993
     1994
     1995
     1996/**
     1997 * Get a space-separated list of NETFS mounts.
     1998 * @return The list created.
     1999 * @note The return value points to static data that will be overwritten with each call.
     2000 * @bug Even though we only want the mounts, the devices are still checked.
     2001 */
     2002char *list_of_NETFS_mounts_only(void)
     2003{
     2004    char *exclude_these_directories = NULL;
     2005    static char result_sz[512];
     2006
     2007    exclude_these_directories = call_program_and_get_last_line_of_output("mount -t coda,ncpfs,fuse.sshfs,nfs,nfs4,smbfs,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | tr -s '\t' ' ' | cut -d' ' -f3 | tr -s '\n' ' ' | awk '{print $0;}'");
     2008    snprintf(result_sz, 511, "%s", exclude_these_directories);
     2009    mr_free(exclude_these_directories);
     2010    return (result_sz);
     2011}
     2012
     2013/* @} - end of utilityGroup */
     2014
     2015
     2016
     2017
     2018
     2019/**
     2020 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where
     2021 * [random] is a random number between 1 and 32767.
     2022 * @param store_name_here Where to store the new filename.
     2023 * @param stub A random number will be appended to this to make the FIFO's name.
     2024 * @ingroup deviceGroup
     2025 */
     2026void make_fifo(char *store_name_here, char *stub)
     2027{
     2028    char *tmp = NULL;
     2029
     2030    assert_string_is_neither_NULL_nor_zerolength(stub);
     2031
     2032    sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768),
     2033            (int) (random() % 32768));
     2034    make_hole_for_file(store_name_here);
     2035    mkfifo(store_name_here, S_IRWXU | S_IRWXG);
     2036    mr_asprintf(tmp, "chmod 770 %s", store_name_here);
     2037    paranoid_system(tmp);
     2038    mr_free(tmp);
     2039}
     2040
     2041
     2042
     2043
     2044
     2045
     2046/**
     2047 * Set the tmpdir and scratchdir to reside on the partition with the most free space.
     2048 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems.
     2049 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set.
     2050 * @ingroup utilityGroup
     2051 */
     2052void sensibly_set_scratchdir()
     2053{
     2054    char *tmp = NULL;
     2055    char *command = NULL;
     2056    char *sz = NULL;
     2057
     2058#ifdef __FreeBSD__
     2059    tmp = call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -t nonfs,msdosfs,ntfs,ntfs-3g,smbfs,smb,cifs,afs,gfs,ocfs,ocfs2,mvfs,nsspool,nssvol | grep -vE \"none|Filesystem\" | awk '{printf \"%s %s\\n\", $4, $6;}' | sort -n | tail -n1 | awk '{print $NF;}'");
     2060#else
     2061    tmp = call_program_and_get_last_line_of_output("LANGUAGE=C df -m -P -x nfs -x nfs4 -x fuse.sshfs -x fuse -x vfat -x ntfs -x ntfs-3g -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 -n | tail -n1 | awk '{print $NF;}'");
     2062#endif
     2063
     2064    if (tmp[0] != '/') {
     2065        mr_asprintf(sz, "%s", tmp);
     2066        mr_free(tmp);
     2067        mr_asprintf(tmp, "/%s", sz);
     2068        mr_free(sz);
     2069    }
     2070    if (!tmp[0]) {
     2071        fatal_error("I couldn't figure out the scratchdir!");
     2072    }
     2073
     2074    /* Cleaning a potential previous scratchdir */
     2075    if (bkpinfo->scratchdir) {
     2076        mr_asprintf(command, "rm -Rf %s", bkpinfo->scratchdir);
     2077        paranoid_system(command);
     2078        mr_free(command);
     2079    }
     2080    mr_free(bkpinfo->scratchdir);
     2081
     2082    mr_asprintf(bkpinfo->scratchdir , "%s/mondo.scratch.%d", tmp, (int) (random() % 32768));
     2083    log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir);
     2084
     2085    /* Cleaning potential previous scratchdir */
     2086    mr_asprintf(command, "rm -Rf %s/mondo.scratch.*", tmp);
     2087    mr_free(tmp);
     2088
     2089    paranoid_system(command);
     2090    mr_free(command);
     2091}
     2092
     2093
     2094
     2095
     2096
     2097
     2098/**
     2099 * @addtogroup deviceGroup
     2100 * @{
     2101 */
     2102/**
     2103 * If we can read @p dev, set @return output to it.
     2104 * If @p dev cannot be read, set @p output to NULL.
     2105 * @param dev The device to check for.
     2106 * @return output Set to @p dev if @p dev exists, NULL otherwise.
     2107 */
     2108char *set_dev_to_this_if_rx_OK(char *dev)
     2109{
     2110    char *command = NULL;
     2111    char *output = NULL;
     2112
     2113    if (!dev || dev[0] == '\0') {
     2114        return(NULL);
     2115    }
     2116    log_msg(10, "Injecting %s", dev);
     2117    inject_device(dev);
     2118    if (!does_file_exist(dev)) {
     2119        log_msg(10, "%s doesn't exist. Returning FALSE.", dev);
     2120        return(NULL);
     2121    }
     2122    mr_asprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null", 512L, dev);
     2123    if (!run_program_and_log_output(command, FALSE)
     2124        && !run_program_and_log_output(command, FALSE)) {
     2125        mr_asprintf(output, "%s", dev);
     2126        log_msg(4, "Found it - %s", dev);
     2127    } else {
     2128        log_msg(4, "It's not %s", dev);
     2129    }
     2130    mr_free(command);
     2131    return(output);
     2132}
     2133
     2134
     2135
     2136
     2137
     2138/**
     2139 * Find out what number CD is in the drive.
     2140 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used.
     2141 * @return The current CD number, or -1 if it could not be found.
     2142 * @note If the CD is not mounted, it will be mounted
     2143 * (and remain mounted after this function returns).
     2144 */
     2145int what_number_cd_is_this()
     2146{
     2147    int cd_number = -1;
     2148    char *mountdev = NULL;
     2149    char *tmp = NULL;
     2150
     2151    assert(bkpinfo != NULL);
     2152    //  log_it("Asking what_number_cd_is_this");
     2153    if (g_ISO_restore_mode) {
     2154        mr_asprintf(tmp, "mount | grep iso9660 | awk '{print $3;}'");
     2155        mountdev = call_program_and_get_last_line_of_output(tmp);
     2156        mr_strcat(mountdev, "/archives/THIS-CD-NUMBER");
     2157        mr_free(tmp);
     2158
     2159        tmp = last_line_of_file(mountdev);
     2160        cd_number = atoi(tmp);
     2161        mr_free(tmp);
     2162        mr_free(mountdev);
     2163        return (cd_number);
     2164    }
     2165
     2166    if (bkpinfo->media_device) {
     2167        mr_asprintf(mountdev, "%s", bkpinfo->media_device);
     2168    }
     2169    if (!mountdev) {
     2170        log_it("(what_number_cd_is_this) Warning - media_device unknown. Finding out...");
     2171        mr_free(bkpinfo->media_device);
     2172        bkpinfo->media_device = find_cdrom_device(FALSE);
     2173        mr_asprintf(mountdev, "%s", bkpinfo->media_device);
     2174    }
     2175    if (!is_this_device_mounted(MNT_CDROM)) {
     2176        if (bkpinfo->backup_media_type == usb) {
     2177            mount_USB_here(mountdev, MNT_CDROM);
     2178        } else {
     2179            mount_CDROM_here(mountdev, MNT_CDROM);
     2180        }
     2181    }
     2182    mr_free(mountdev);
     2183
     2184    tmp = last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER");
     2185    cd_number = atoi(tmp);
     2186    mr_free(tmp);
     2187    return (cd_number);
     2188}
     2189
     2190
     2191
     2192
     2193
     2194
     2195
     2196/**
     2197 * Find out what device is mounted as root (/).
     2198 * @return Root device.
     2199 * @note The returned string points to static storage and will be overwritten with every call.
     2200 * @bug A bit of a misnomer; it's actually finding out the root device.
     2201 * The mountpoint (where it's mounted) will obviously be '/'.
     2202 */
     2203char *where_is_root_mounted() {
     2204    /*@ buffers **************** */
     2205    char *output = NULL;
     2206
     2207
     2208#ifdef __FreeBSD__
     2209    output = call_program_and_get_last_line_of_output("mount | grep ' on / ' | cut -d' ' -f1");
     2210#else
     2211    output = call_program_and_get_last_line_of_output("mount | grep ' on / ' | cut -d' ' -f1 | sed 's/[0-9]//' | sed 's/[0-9]//'");
     2212    if (strstr(output, "/dev/cciss/")) {
     2213        mr_free(output);
     2214        output = call_program_and_get_last_line_of_output("mount | grep ' on / ' | cut -d' ' -f1 | cut -dp -f1");
     2215    }
     2216    if (strstr(output, "/dev/md")) {
     2217        mr_free(output);
     2218        output = call_program_and_get_last_line_of_output("mount | grep ' on / ' | cut -d' ' -f1");
     2219    }
     2220#endif
     2221
     2222    return (output);
     2223}
     2224
     2225
     2226/**
     2227 * Find out which boot loader is in use.
     2228 * @param which_device Device to look for the boot loader on.
     2229 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown.
     2230 * @note Under Linux, all drives are examined, not just @p which_device.
     2231 */
     2232#ifdef __FreeBSD__
     2233char which_boot_loader(char *which_device) {
     2234    int count_lilos = 0;
     2235    int count_grubs = 0;
     2236    int count_boot0s = 0;
     2237    int count_dangerouslydedicated = 0;
     2238
     2239    log_it("looking at drive %s's MBR", which_device);
     2240    if (does_string_exist_in_boot_block(which_device, "GRUB")) {
     2241        count_grubs++;
     2242    }
     2243    if (does_string_exist_in_boot_block(which_device, "LILO")) {
     2244        count_lilos++;
     2245    }
     2246    if (does_string_exist_in_boot_block(which_device, "Drive")) {
     2247        count_boot0s++;
     2248    }
     2249    if (does_string_exist_in_first_N_blocks(which_device, "FreeBSD/i386", 17)) {
     2250        count_dangerouslydedicated++;
     2251    }
     2252    log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n",
     2253           count_grubs, count_lilos, count_elilos, count_boot0s,
     2254           count_dangerouslydedicated);
     2255
     2256    if (count_grubs && !count_lilos) {
     2257        return ('G');
     2258    } else if (count_lilos && !count_grubs) {
     2259        return ('L');
     2260    } else if (count_grubs == 1 && count_lilos == 1) {
     2261        log_it("I'll bet you used to use LILO but switched to GRUB...");
     2262        return ('G');
     2263    } else if (count_boot0s == 1) {
     2264        return ('B');
     2265    } else if (count_dangerouslydedicated) {
     2266        return ('D');
     2267    } else {
     2268        log_it("Unknown boot loader");
     2269        return ('U');
     2270    }
     2271}
     2272
     2273#else
     2274
     2275char which_boot_loader(char *which_device) {
     2276    /*@ buffer ***************************************************** */
     2277    char *list_drives_cmd = NULL;
     2278    char *tmp = NULL;
     2279    char *current_drive = NULL;
     2280
     2281    /*@ pointers *************************************************** */
     2282    FILE *pdrives = NULL;
     2283
     2284    /*@ int ******************************************************** */
     2285    int count_lilos = 0;
     2286    int count_grubs = 0;
     2287
     2288    /*@ end vars *************************************************** */
     2289
     2290
     2291#ifdef __IA64__
     2292    /* No choice for it */
     2293    return ('E');
     2294#endif
     2295
     2296    tmp = where_is_root_mounted();
     2297    mr_asprintf(list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s", tmp);
     2298    mr_free(tmp);
     2299    log_it("list_drives_cmd = %s", list_drives_cmd);
     2300
     2301    pdrives = popen(list_drives_cmd, "r");
     2302    mr_free(list_drives_cmd);
     2303
     2304    if (!pdrives) {
     2305        log_OS_error("Unable to open list of drives");
     2306        return ('\0');
     2307    }
     2308
     2309    for (mr_getline(current_drive, pdrives); !feof(pdrives); mr_getline(current_drive, pdrives)) {
     2310        mr_strip_spaces(current_drive);
     2311        log_it("looking at drive %s's MBR", current_drive);
     2312        if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
     2313            count_grubs++;
     2314            /* BERLIOS : removed as I don't think it's mandatory here
     2315            mr_free(which_device);
     2316            mr_asprintf(which_device, "%s", current_drive);
     2317            */
     2318            mr_free(current_drive);
     2319            break;
     2320        }
     2321        if (does_string_exist_in_boot_block(current_drive, "LILO")) {
     2322            count_lilos++;
     2323            /* BERLIOS : removed as I don't think it's mandatory here
     2324            mr_free(which_device);
     2325            mr_asprintf(which_device, "%s", current_drive);
     2326            */
     2327            mr_free(current_drive);
     2328            break;
     2329        }
     2330        mr_free(current_drive);
     2331    }
     2332    mr_free(current_drive);
     2333
     2334    if (pclose(pdrives)) {
     2335        log_OS_error("Cannot pclose pdrives");
     2336    }
     2337    log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
     2338    if (count_grubs && !count_lilos) {
     2339        return ('G');
     2340    } else if (count_lilos && !count_grubs) {
     2341        return ('L');
     2342    } else if (count_grubs == 1 && count_lilos == 1) {
     2343        log_it("I'll bet you used to use LILO but switched to GRUB...");
     2344        return ('G');
     2345    } else {
     2346        // We need to look on each partition then
     2347        mr_asprintf(list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/");
     2348        log_it("list_drives_cmd = %s", list_drives_cmd);
     2349
     2350        if (!(pdrives = popen(list_drives_cmd, "r"))) {
     2351            log_OS_error("Unable to open list of drives");
     2352            mr_free(list_drives_cmd);
     2353            return ('\0');
     2354        }
     2355        mr_free(list_drives_cmd);
     2356
     2357        for (mr_getline(current_drive, pdrives); !feof(pdrives); mr_getline(current_drive, pdrives)) {
     2358            mr_strip_spaces(current_drive);
     2359            log_it("looking at partition %s's BR", current_drive);
     2360            if (does_string_exist_in_boot_block(current_drive, "GRUB")) {
     2361                count_grubs++;
     2362                /* BERLIOS : removed as I don't think it's mandatory here
     2363                mr_free(which_device);
     2364                mr_asprintf(which_device, "%s", current_drive);
     2365                */
     2366                mr_free(current_drive);
     2367                break;
     2368            }
     2369            if (does_string_exist_in_boot_block(current_drive, "LILO")) {
     2370                count_lilos++;
     2371                /* BERLIOS : removed as I don't think it's mandatory here
     2372                mr_free(which_device);
     2373                mr_asprintf(which_device, "%s", current_drive);
     2374                */
     2375                mr_free(current_drive);
     2376                break;
     2377            }
     2378            mr_free(current_drive);
     2379        }
     2380        mr_free(current_drive);
     2381
     2382        if (pclose(pdrives)) {
     2383            log_OS_error("Cannot pclose pdrives");
     2384        }
     2385        log_it("%d grubs and %d lilos\n", count_grubs, count_lilos);
     2386        if (count_grubs && !count_lilos) {
     2387            return ('G');
     2388        } else if (count_lilos && !count_grubs) {
     2389            return ('L');
     2390        } else if (count_grubs == 1 && count_lilos == 1) {
     2391            log_it("I'll bet you used to use LILO but switched to GRUB...");
     2392            return ('G');
     2393        } else {
     2394            log_it("Unknown boot loader");
     2395            return ('U');
     2396        }
     2397    }
     2398}
     2399#endif
     2400
     2401
     2402
     2403
     2404/**
     2405 * Write zeroes over the first 16K of @p device.
     2406 * @param device The device to zero.
     2407 * @return 0 for success, 1 for failure.
     2408 */
     2409int zero_out_a_device(char *device)
     2410{
     2411    FILE *fout;
     2412    int i;
     2413
     2414    assert_string_is_neither_NULL_nor_zerolength(device);
     2415
     2416    log_it("Zeroing drive %s", device);
     2417    if (!(fout = fopen(device, "w"))) {
     2418        log_OS_error("Unable to open/write to device");
     2419        return (1);
     2420    }
     2421    for (i = 0; i < 16384; i++) {
     2422        fputc('\0', fout);
     2423    }
     2424    paranoid_fclose(fout);
     2425    log_it("Device successfully zeroed.");
     2426    return (0);
     2427}
     2428
     2429/**
     2430 * Return the device pointed to by @p incoming.
     2431 * @param incoming The device to resolve symlinks for.
     2432 * @return The path to the real device file.
     2433 * @note The returned string points to static storage that will be overwritten with each call.
     2434 * @bug Won't work with file v4.0; needs to be written in C.
     2435 */
     2436char *resolve_softlinks_to_get_to_actual_device_file(char *incoming)
     2437{
     2438    char *output;
     2439    char *command = NULL;
     2440    char *curr_fname;
     2441    char *scratch = NULL;
     2442    char *tmp = NULL;
     2443    char *p;
     2444
     2445    struct stat statbuf;
     2446    malloc_string(curr_fname);
     2447    if (!does_file_exist(incoming)) {
     2448        log_it("resolve_softlinks_to_get_to_actual_device_file --- device not found");
     2449        mr_asprintf(output, "%s", incoming);
     2450    } else {
     2451        strcpy(curr_fname, incoming);
     2452        lstat(curr_fname, &statbuf);
     2453        while (S_ISLNK(statbuf.st_mode)) {
     2454            log_msg(1, "curr_fname = %s", curr_fname);
     2455            mr_asprintf(command, "file %s", curr_fname);
     2456            tmp = call_program_and_get_last_line_of_output(command);
     2457            mr_free(command);
     2458            for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' '; p--);
     2459            p++;
     2460            mr_asprintf(scratch, "%s", p);
     2461            for (p = scratch; *p != '\0' && *p != '\''; p++);
     2462            *p = '\0';
     2463            log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch);
     2464            mr_free(tmp);
     2465
     2466            if (scratch[0] == '/') {
     2467                strcpy(curr_fname, scratch);    // copy whole thing because it's an absolute softlink
     2468            } else {            // copy over the basename cos it's a relative softlink
     2469                p = curr_fname + strlen(curr_fname);
     2470                while (p != curr_fname && *p != '/') {
     2471                    p--;
     2472                }
     2473                if (*p == '/') {
     2474                    p++;
     2475                }
     2476                strcpy(p, scratch);
     2477            }
     2478            mr_free(scratch);
     2479            lstat(curr_fname, &statbuf);
     2480        }
     2481        mr_asprintf(output, "%s", curr_fname);
     2482        log_it("resolved %s to %s", incoming, output);
     2483    }
     2484    paranoid_free(curr_fname);
     2485    return (output);
     2486}
     2487
     2488/* @} - end of deviceGroup */
     2489
     2490/**
     2491 * Return the type of partition format (GPT or MBR)
     2492 */
     2493char *which_partition_format(const char *drive)
     2494{
     2495    char *output;
     2496    char *tmp = NULL;
     2497    char *command = NULL;
     2498    char *fdisk = NULL;
     2499#ifdef __IA64__
     2500    struct stat buf;
     2501#endif
     2502    mr_asprintf(fdisk, "/sbin/parted2fdisk");
     2503    mr_asprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive);
     2504    mr_free(fdisk);
     2505
     2506    tmp = call_program_and_get_last_line_of_output(command);
     2507    mr_free(command);
     2508
     2509    if (strstr(tmp, "GPT") == NULL) {
     2510        mr_asprintf(output, "MBR");
     2511    } else {
     2512        mr_asprintf(output, "GPT");
     2513    }
     2514    mr_free(tmp);
     2515
     2516    log_msg(0, "Found %s partition table format type", output);
     2517    return (output);
     2518}
    24982519
    24992520/**
Note: See TracChangeset for help on using the changeset viewer.