Changeset 2434 in MondoRescue
- Timestamp:
- Sep 28, 2009, 4:33:14 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mondo/src/common/libmondo-devices.c
r2424 r2434 10 10 #include "my-stuff.h" 11 11 #include "mr_mem.h" 12 #include "mr_str.h" 12 13 #include "mondostructures.h" 13 14 #include "libmondo-files-EXT.h" … … 1460 1461 1461 1462 1462 1463 1464 1465 /** 1466 * Ask user for details of backup/restore information. 1467 * Called when @c mondoarchive doesn't get any parameters. 1468 * @param bkpinfo The backup information structure to fill out with the user's data. 1469 * @param archiving_to_media TRUE if archiving, FALSE if restoring. 1470 * @return 0, always. 1471 * @bug No point of `int' return value. 1472 * @ingroup archiveGroup 1473 */ 1474 int interactively_obtain_media_parameters_from_user(bool archiving_to_media) 1475 // archiving_to_media is TRUE if I'm being called by mondoarchive 1476 // archiving_to_media is FALSE if I'm being called by mondorestore 1477 { 1478 char *tmp = NULL; 1479 char *tmp1 = NULL; 1480 char *mds = NULL; 1481 char *sz_size; 1482 char *command; 1483 char *comment; 1484 char *prompt; 1485 int i; 1486 FILE *fin; 1487 1488 malloc_string(sz_size); 1489 malloc_string(command); 1490 malloc_string(comment); 1491 malloc_string(prompt); 1492 malloc_string(tmp1); 1493 assert(bkpinfo != NULL); 1494 sz_size[0] = '\0'; 1495 bkpinfo->nonbootable_backup = FALSE; 1496 1497 // Tape, CD, NETFS, ...? 1498 srandom(getpid()); 1499 bkpinfo->backup_media_type = 1500 (g_restoring_live_from_cd) ? cdr : 1501 which_backup_media_type(bkpinfo->restore_data); 1502 if (bkpinfo->backup_media_type == none) { 1503 log_to_screen("User has chosen not to backup the PC"); 1504 finish(1); 1505 } 1506 /* Why asking to remove the media with tape ? 1507 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) { 1508 popup_and_OK("Please remove media from drive(s)"); 1509 } 1510 */ 1511 log_msg(3, "media type = %s", 1512 bkptype_to_string(bkpinfo->backup_media_type)); 1513 if (archiving_to_media) { 1514 sensibly_set_tmpdir_and_scratchdir(); 1515 } 1516 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4; 1517 bkpinfo->compression_level = 1518 (bkpinfo->backup_media_type == cdstream) ? 1 : 5; 1519 bkpinfo->use_lzo = 1520 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE; 1521 mvaddstr_and_log_it(2, 0, " "); 1522 1523 // Find device's /dev (or SCSI) entry 1524 switch (bkpinfo->backup_media_type) { 1525 case cdr: 1526 case cdrw: 1527 case dvd: 1528 case usb: 1529 /* Never try to eject a USB device */ 1530 if (bkpinfo->backup_media_type == usb) { 1531 bkpinfo->please_dont_eject = TRUE; 1532 } 1533 if (archiving_to_media) { 1534 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) { 1535 if (ask_me_yes_or_no 1536 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?")) 1537 { 1538 bkpinfo->manual_cd_tray = TRUE; 1539 } 1540 } 1541 if ((bkpinfo->compression_level = 1542 which_compression_level()) == -1) { 1543 log_to_screen("User has chosen not to backup the PC"); 1544 finish(1); 1545 } 1546 mds = media_descriptor_string(bkpinfo->backup_media_type); 1547 sprintf(comment, "What speed is your %s (re)writer?", mds); 1548 if (bkpinfo->backup_media_type == dvd) { 1549 find_dvd_device(bkpinfo->media_device, FALSE); 1550 strcpy(tmp1, "1"); 1551 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB 1552 log_msg(1, "Setting to DVD defaults"); 1553 } else { 1554 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM); 1555 strcpy(tmp1, "4"); 1556 strcpy(sz_size, "650"); 1557 log_msg(1, "Setting to CD defaults"); 1558 } 1559 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) { 1560 if (!popup_and_get_string("Speed", comment, tmp1, 4)) { 1561 log_to_screen("User has chosen not to backup the PC"); 1562 finish(1); 1563 } 1564 } 1565 bkpinfo->cdrw_speed = atoi(tmp1); // if DVD then this shouldn't ever be used anyway :) 1566 1567 sprintf(comment, 1568 "How much data (in Megabytes) will each %s store?", mds); 1569 mr_free(mds); 1570 if (!popup_and_get_string("Size", comment, sz_size, 5)) { 1571 log_to_screen("User has chosen not to backup the PC"); 1572 finish(1); 1573 } 1574 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 1575 bkpinfo->media_size[i] = atoi(sz_size); 1576 } 1577 if (bkpinfo->media_size[0] <= 0) { 1578 log_to_screen("User has chosen not to backup the PC"); 1579 finish(1); 1580 } 1581 } 1582 /* No break because we continue even for usb */ 1583 case cdstream: 1584 mds = media_descriptor_string(bkpinfo->backup_media_type); 1585 1586 if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) { 1587 strcpy(bkpinfo->media_device, "/dev/cdrom"); 1588 log_msg(2, "CD-ROM device assumed to be at %s", 1589 bkpinfo->media_device); 1590 } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb)) 1591 || bkpinfo->backup_media_type == dvd) { 1592 if (!bkpinfo->media_device[0]) { 1593 strcpy(bkpinfo->media_device, "/dev/cdrom"); 1594 } // just for the heck of it :) 1595 log_msg(1, "bkpinfo->media_device = %s", 1596 bkpinfo->media_device); 1597 if (bkpinfo->backup_media_type == dvd 1598 || find_cdrom_device(bkpinfo->media_device, FALSE)) { 1599 log_msg(1, "bkpinfo->media_device = %s", 1600 bkpinfo->media_device); 1601 sprintf(comment, 1602 "Please specify your %s drive's /dev entry", mds); 1603 if (!popup_and_get_string 1604 ("Device?", comment, bkpinfo->media_device, 1605 MAX_STR_LEN / 4)) { 1606 log_to_screen("User has chosen not to backup the PC"); 1607 finish(1); 1608 } 1609 } 1610 log_msg(2, "%s device found at %s", mds, bkpinfo->media_device); 1611 } else { 1612 if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) { 1613 bkpinfo->media_device[0] = '\0'; 1614 } 1615 if (bkpinfo->media_device[0]) { 1616 if (bkpinfo->backup_media_type == usb) { 1617 mr_asprintf(&tmp, "I think your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device); 1618 } else { 1619 mr_asprintf(&tmp, "I think I've found your %s burner at SCSI node %s. Is this correct? (Say no if you have an IDE burner and you are running a 2.6 kernel. You will then be prompted for further details.)", mds, bkpinfo->media_device); 1620 } 1621 if (!ask_me_yes_or_no(tmp)) { 1622 bkpinfo->media_device[0] = '\0'; 1623 } 1624 mr_free(tmp); 1625 } 1626 if (!bkpinfo->media_device[0]) { 1627 if (bkpinfo->backup_media_type == usb) { 1628 i = popup_and_get_string("/dev entry?", 1629 "What is the /dev entry of your USB Disk/Key, please?", 1630 bkpinfo->media_device, 1631 MAX_STR_LEN / 4); 1632 } else { 1633 if (g_kernel_version < 2.6) { 1634 i = popup_and_get_string("Device node?", 1635 "What is the SCSI node of your CD (re)writer, please?", 1636 bkpinfo->media_device, 1637 MAX_STR_LEN / 4); 1638 } else { 1639 i = popup_and_get_string("/dev entry?", 1640 "What is the /dev entry of your CD (re)writer, please?", 1641 bkpinfo->media_device, 1642 MAX_STR_LEN / 4); 1643 } 1644 } 1645 if (!i) { 1646 log_to_screen("User has chosen not to backup the PC"); 1647 finish(1); 1648 } 1649 } 1650 } 1651 mr_free(mds); 1652 1653 if (bkpinfo->backup_media_type == cdstream) { 1654 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 1655 bkpinfo->media_size[i] = 650; 1656 } 1657 } 1658 break; 1659 case udev: 1660 if (!ask_me_yes_or_no 1661 ("This option is for advanced users only. Are you sure?")) { 1662 log_to_screen("User has chosen not to backup the PC"); 1663 finish(1); 1664 } 1665 case tape: 1666 1667 if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) { 1668 log_msg(3, "Ok, using vanilla scsi tape."); 1669 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE); 1670 if ((fin = fopen(bkpinfo->media_device, "r"))) { 1671 paranoid_fclose(fin); 1672 } else { 1673 strcpy(bkpinfo->media_device, "/dev/osst0"); 1674 } 1675 } 1676 if (bkpinfo->media_device[0]) { 1677 if ((fin = fopen(bkpinfo->media_device, "r"))) { 1678 paranoid_fclose(fin); 1679 } else { 1680 if (does_file_exist("/tmp/mondo-restore.cfg")) { 1681 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev", 1682 bkpinfo->media_device); 1683 } 1684 } 1685 } 1686 if (bkpinfo->media_device[0]) { 1687 mr_asprintf(&tmp, "I think I've found your tape streamer at %s; am I right on the money?", bkpinfo->media_device); 1688 if (!ask_me_yes_or_no(tmp)) { 1689 bkpinfo->media_device[0] = '\0'; 1690 } 1691 mr_free(tmp); 1692 } 1693 if (!bkpinfo->media_device[0]) { 1694 if (!popup_and_get_string 1695 ("Device name?", 1696 "What is the /dev entry of your tape streamer?", 1697 bkpinfo->media_device, MAX_STR_LEN / 4)) { 1698 log_to_screen("User has chosen not to backup the PC"); 1699 finish(1); 1700 } 1701 } 1702 mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device); 1703 if (run_program_and_log_output(tmp, FALSE)) { 1704 log_to_screen("User has not specified a valid /dev entry"); 1705 finish(1); 1706 } 1707 mr_free(tmp); 1708 log_msg(4, "sz_size = %s", sz_size); 1709 sz_size[0] = '\0'; 1710 1711 bkpinfo->use_obdr = ask_me_yes_or_no 1712 ("Do you want to activate OBDR support for your tapes ?"); 1713 if (sz_size[0] == '\0') { 1714 bkpinfo->media_size[0] = 0; 1715 } else { 1716 bkpinfo->media_size[0] = 1717 friendly_sizestr_to_sizelong(sz_size) / 2 - 50; 1718 } 1719 log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]); 1720 if (bkpinfo->media_size[0] <= 0) { 1721 bkpinfo->media_size[0] = 0; 1722 } 1723 for (i = 1; i <= MAX_NOOF_MEDIA; i++) { 1724 bkpinfo->media_size[i] = bkpinfo->media_size[0]; 1725 } 1726 if (archiving_to_media) { 1727 if ((bkpinfo->compression_level = 1728 which_compression_level()) == -1) { 1729 log_to_screen("User has chosen not to backup the PC"); 1730 finish(1); 1731 } 1732 } 1733 break; 1734 1735 1736 1737 case netfs: 1738 /* Never try to eject a NETFS device */ 1739 bkpinfo->please_dont_eject = TRUE; 1740 1741 /* Initiate bkpinfo netfs_mount path from running environment if not already done */ 1742 if (!bkpinfo->netfs_mount[0]) { 1743 strcpy(bkpinfo->netfs_mount, 1744 call_program_and_get_last_line_of_output 1745 ("mount | grep \":\" | cut -d' ' -f1 | head -n1")); 1746 } 1747 #ifdef __FreeBSD__ 1748 if (TRUE) 1749 #else 1750 if (!bkpinfo->disaster_recovery) 1751 #endif 1752 { 1753 if (!popup_and_get_string 1754 ("Network shared dir.", 1755 "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.)", 1756 bkpinfo->netfs_mount, MAX_STR_LEN / 4)) { 1757 log_to_screen("User has chosen not to backup the PC"); 1758 finish(1); 1759 } 1760 if (!bkpinfo->restore_data) { 1761 if ((bkpinfo->compression_level = 1762 which_compression_level()) == -1) { 1763 log_to_screen("User has chosen not to backup the PC"); 1764 finish(1); 1765 } 1766 } 1767 // check whether already mounted - we better remove 1768 // surrounding spaces and trailing '/' for this 1769 strip_spaces(bkpinfo->netfs_mount); 1770 if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/') 1771 bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0'; 1772 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3", 1773 bkpinfo->netfs_mount); 1774 strcpy(bkpinfo->isodir, 1775 call_program_and_get_last_line_of_output(command)); 1776 1777 if (!bkpinfo->restore_data) { 1778 sprintf(comment, 1779 "How much data (in Megabytes) will each media store?"); 1780 if (!popup_and_get_string("Size", comment, sz_size, 5)) { 1781 log_to_screen("User has chosen not to backup the PC"); 1782 finish(1); 1783 } 1784 } else { 1785 strcpy(sz_size, "0"); 1786 } 1787 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 1788 bkpinfo->media_size[i] = atoi(sz_size); 1789 } 1790 if (bkpinfo->media_size[0] < 0) { 1791 log_to_screen("User has chosen not to backup the PC"); 1792 finish(1); 1793 } 1794 } 1795 if (bkpinfo->disaster_recovery) { 1796 sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir); 1797 (void)system(command); 1798 strcpy(tmp1, bkpinfo->netfs_proto); 1799 if (!popup_and_get_string 1800 ("Network protocol", "Which protocol should I use?", 1801 tmp1, MAX_STR_LEN)) { 1802 log_to_screen("User has chosen not to backup the PC"); 1803 finish(1); 1804 } 1805 mr_free(bkpinfo->netfs_proto); 1806 mr_asprintf(&(bkpinfo->netfs_proto), "%s", tmp1); 1807 if (!popup_and_get_string 1808 ("Network share", "Which remote share should I mount?", 1809 bkpinfo->netfs_mount, MAX_STR_LEN)) { 1810 log_to_screen("User has chosen not to backup the PC"); 1811 finish(1); 1812 } 1813 } 1814 /* Initiate bkpinfo isodir path from running environment if mount already done */ 1815 if (is_this_device_mounted(bkpinfo->netfs_mount)) { 1816 strcpy(bkpinfo->isodir, 1817 call_program_and_get_last_line_of_output 1818 ("mount | grep \":\" | cut -d' ' -f3 | head -n1")); 1819 } else { 1820 sprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir); 1821 sprintf(command, "mkdir -p %s", bkpinfo->isodir); 1822 run_program_and_log_output(command, 5); 1823 if (bkpinfo->restore_data) { 1824 if (strstr(bkpinfo->netfs_proto, "sshfs")) { 1825 mr_asprintf(&tmp, "sshfs -o ro %s %s", bkpinfo->netfs_mount, bkpinfo->isodir); 1826 } else { 1827 mr_asprintf(&tmp, "mount -t %s -o nolock,ro %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir); 1828 } 1829 } else { 1830 if (strstr(bkpinfo->netfs_proto, "sshfs")) { 1831 mr_asprintf(&tmp, "sshfs %s %s", bkpinfo->netfs_mount, bkpinfo->isodir); 1832 } else { 1833 mr_asprintf(&tmp, "mount -t %s -o nolock %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir); 1834 } 1835 } 1836 run_program_and_log_output(tmp, 3); 1837 mr_free(tmp); 1838 1839 malloc_string(g_selfmounted_isodir); 1840 strcpy(g_selfmounted_isodir, bkpinfo->isodir); 1841 } 1842 if (!is_this_device_mounted(bkpinfo->netfs_mount)) { 1843 popup_and_OK 1844 ("Please mount that partition before you try to backup to or restore from it."); 1845 finish(1); 1846 } 1847 strcpy(tmp1, bkpinfo->netfs_remote_dir); 1848 if (!popup_and_get_string 1849 ("Directory", "Which directory within that mountpoint?", tmp1, 1850 MAX_STR_LEN)) { 1851 log_to_screen("User has chosen not to backup the PC"); 1852 finish(1); 1853 } 1854 strcpy(bkpinfo->netfs_remote_dir, tmp1); 1855 1856 // check whether writable - we better remove surrounding spaces for this 1857 strip_spaces(bkpinfo->netfs_remote_dir); 1858 1859 if (!popup_and_get_string 1860 ("Prefix.", 1861 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files", 1862 bkpinfo->prefix, MAX_STR_LEN / 4)) { 1863 log_to_screen("User has chosen not to backup the PC"); 1864 finish(1); 1865 } 1866 log_msg(3, "prefix set to %s", bkpinfo->prefix); 1867 1868 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 1869 bkpinfo->media_size[i] = 650; 1870 } 1871 log_msg(3, "Just set netfs_remote_dir to %s", 1872 bkpinfo->netfs_remote_dir); 1873 log_msg(3, "isodir is still %s", bkpinfo->isodir); 1874 break; 1875 1876 case iso: 1877 if (!bkpinfo->disaster_recovery) { 1878 if (!popup_and_get_string 1879 ("Storage dir.", 1880 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0", 1881 bkpinfo->isodir, MAX_STR_LEN / 4)) { 1882 log_to_screen("User has chosen not to backup the PC"); 1883 finish(1); 1884 } 1885 if (archiving_to_media) { 1886 if ((bkpinfo->compression_level = 1887 which_compression_level()) == -1) { 1888 log_to_screen("User has chosen not to backup the PC"); 1889 finish(1); 1890 } 1891 if (!popup_and_get_string 1892 ("ISO size.", 1893 "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 or DVD's you plan to backup to.", 1894 sz_size, 16)) { 1895 log_to_screen("User has chosen not to backup the PC"); 1896 finish(1); 1897 } 1898 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 1899 bkpinfo->media_size[i] = atoi(sz_size); 1900 } 1901 } else { 1902 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 1903 bkpinfo->media_size[i] = 650; 1904 } 1905 } 1906 } 1907 if (!popup_and_get_string 1908 ("Prefix.", 1909 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files", 1910 bkpinfo->prefix, MAX_STR_LEN / 4)) { 1911 log_to_screen("User has chosen not to backup the PC"); 1912 finish(1); 1913 } 1914 log_msg(3, "prefix set to %s", bkpinfo->prefix); 1915 break; 1916 default: 1917 fatal_error 1918 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!"); 1919 } 1920 1921 if (archiving_to_media) { 1922 1923 #ifdef __FreeBSD__ 1924 strcpy(bkpinfo->boot_device, 1925 call_program_and_get_last_line_of_output 1926 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'")); 1927 #else 1928 strcpy(bkpinfo->boot_device, 1929 call_program_and_get_last_line_of_output 1930 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'")); 1931 #endif 1932 i = which_boot_loader(bkpinfo->boot_device); 1933 if (i == 'U') // unknown 1934 { 1935 1936 #ifdef __FreeBSD__ 1937 if (!popup_and_get_string 1938 ("Boot device", 1939 "What is your boot device? (e.g. /dev/ad0)", 1940 bkpinfo->boot_device, MAX_STR_LEN / 4)) { 1941 log_to_screen("User has chosen not to backup the PC"); 1942 finish(1); 1943 } 1944 i = which_boot_loader(bkpinfo->boot_device); 1945 #else 1946 if (!popup_and_get_string 1947 ("Boot device", 1948 "What is your boot device? (e.g. /dev/hda)", 1949 bkpinfo->boot_device, MAX_STR_LEN / 4)) { 1950 log_to_screen("User has chosen not to backup the PC"); 1951 finish(1); 1952 } 1953 if (does_string_exist_in_boot_block 1954 (bkpinfo->boot_device, "LILO")) { 1955 i = 'L'; 1956 } else 1957 if (does_string_exist_in_boot_block 1958 (bkpinfo->boot_device, "ELILO")) { 1959 i = 'E'; 1960 } else 1961 if (does_string_exist_in_boot_block 1962 (bkpinfo->boot_device, "GRUB")) { 1963 i = 'G'; 1964 } else { 1965 i = 'U'; 1966 } 1967 #endif 1968 if (i == 'U') { 1969 if (ask_me_yes_or_no 1970 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")) 1971 { 1972 i = 'R'; // raw 1973 } else { 1974 log_to_screen 1975 ("I cannot find your boot loader. Please run mondoarchive with parameters."); 1976 finish(1); 1977 } 1978 } 1979 } 1980 bkpinfo->boot_loader = i; 1981 strcpy(bkpinfo->include_paths, "/"); 1982 if (!popup_and_get_string 1983 ("Backup paths", 1984 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).", 1985 bkpinfo->include_paths, MAX_STR_LEN)) { 1986 log_to_screen("User has chosen not to backup the PC"); 1987 finish(1); 1988 } 1989 mr_asprintf(&tmp, "%s", list_of_NETFS_mounts_only()); 1990 if (strlen(tmp) > 2) { 1991 if (bkpinfo->exclude_paths[0]) { 1992 strcat(bkpinfo->exclude_paths, " "); 1993 } 1994 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN); 1995 } 1996 mr_free(tmp); 1997 // NTFS 1998 strcpy(tmp1, call_program_and_get_last_line_of_output("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'")); 1999 if (strlen(tmp1) > 2) { 2000 if (!popup_and_get_string 2001 ("NTFS partitions", 2002 "Please enter/confirm the NTFS partitions you wish to backup as well.", 2003 tmp1, MAX_STR_LEN / 4)) { 2004 log_to_screen("User has chosen not to backup the PC"); 2005 finish(1); 2006 } 2007 strncpy(bkpinfo->image_devs, tmp1, MAX_STR_LEN / 4); 2008 } 2009 2010 2011 if (!popup_and_get_string 2012 ("Exclude paths", 2013 "Please enter paths which you do NOT want to backup. Separate them with spaces. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.", 2014 bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) { 2015 log_to_screen("User has chosen not to backup the PC"); 2016 finish(1); 2017 } 2018 if (!popup_and_get_string 2019 ("Temporary directory", 2020 "Please enter your temporary directory.", 2021 bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) { 2022 log_to_screen("User has chosen not to backup the PC"); 2023 finish(1); 2024 } 2025 if (!popup_and_get_string 2026 ("Scratch directory", 2027 "Please enter your scratch directory.", 2028 bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) { 2029 log_to_screen("User has chosen not to backup the PC"); 2030 finish(1); 2031 } 2032 // Interactive mode: 2033 #ifdef __IA64__ 2034 bkpinfo->make_cd_use_lilo = TRUE; 2035 #else 2036 bkpinfo->make_cd_use_lilo = FALSE; 2037 #endif 2038 bkpinfo->backup_data = TRUE; 2039 bkpinfo->verify_data = 2040 ask_me_yes_or_no 2041 ("Will you want to verify your backups after Mondo has created them?"); 2042 2043 #ifndef __FreeBSD__ 2044 if (!ask_me_yes_or_no 2045 ("Are you confident that your kernel is a sane, sensible, standard Linux kernel? Say 'no' if you are using a Gentoo <1.4 or Debian <3.0, please.")) 2046 #endif 2047 { 2048 strcpy(bkpinfo->kernel_path, "FAILSAFE"); 2049 } 2050 2051 if (!ask_me_yes_or_no 2052 ("Are you sure you want to proceed? Hit 'no' to abort.")) { 2053 log_to_screen("User has chosen not to backup the PC"); 2054 finish(1); 2055 } 1463 /** 1464 * Creates a singly linked list of all of the non-NETFS mounted file systems. 1465 * @param DSFptr A pointer to the structure MOUNTED_FS_STRUCT used to hold 1466 * the list of mounted file systems. 1467 * @return None. 1468 */ 1469 static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr) 1470 { 1471 assert (DSFptr); 1472 if (DSF_Head == NULL) { 1473 DSF_Head = DSFptr; 2056 1474 } else { 2057 bkpinfo->restore_data = TRUE; // probably... 2058 } 2059 2060 if (bkpinfo->backup_media_type == iso 2061 || bkpinfo->backup_media_type == netfs) { 2062 g_ISO_restore_mode = TRUE; 2063 } 2064 #ifdef __FreeSD__ 2065 // skip 2066 #else 2067 if (bkpinfo->backup_media_type == netfs) { 2068 log_msg(3, "I think the Remote mount is mounted at %s", 2069 bkpinfo->isodir); 2070 } 2071 log_it("isodir = %s", bkpinfo->isodir); 2072 log_it("netfs_mount = '%s'", bkpinfo->netfs_mount); 2073 log_it("netfs_proto = '%s'", bkpinfo->netfs_proto); 2074 if (bkpinfo->netfs_user) { 2075 log_it("netfs_user = '%s'", bkpinfo->netfs_user); 2076 } 2077 #endif 2078 2079 log_it("media device = %s", bkpinfo->media_device); 2080 log_it("media size = %ld", bkpinfo->media_size[1]); 2081 log_it("media type = %s", 2082 bkptype_to_string(bkpinfo->backup_media_type)); 2083 log_it("prefix = %s", bkpinfo->prefix); 2084 log_it("compression = %ld", bkpinfo->compression_level); 2085 2086 /* Handle devices passed in bkpinfo and print result */ 2087 mr_make_devlist_from_pathlist(bkpinfo->exclude_paths, 'E'); 2088 mr_make_devlist_from_pathlist(bkpinfo->include_paths, 'I'); 2089 2090 log_it("scratchdir = '%s'", bkpinfo->scratchdir); 2091 log_it("tmpdir = '%s'", bkpinfo->tmpdir); 2092 log_it("image_devs = '%s'", bkpinfo->image_devs); 2093 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device, 2094 bkpinfo->boot_loader); 2095 if (bkpinfo->media_size[0] < 0) { 2096 if (archiving_to_media) { 2097 fatal_error("Media size is less than zero."); 2098 } else { 2099 log_msg(2, "Warning - media size is less than zero."); 2100 bkpinfo->media_size[0] = 0; 2101 } 2102 } 2103 paranoid_free(sz_size); 2104 paranoid_free(tmp1); 2105 paranoid_free(command); 2106 paranoid_free(comment); 2107 paranoid_free(prompt); 2108 return (0); 2109 } 2110 2111 2112 2113 2114 /** 2115 * @addtogroup utilityGroup 2116 * @{ 2117 */ 2118 /** 2119 * Get a space-separated list of NETFS devices and mounts. 2120 * @return The list created. 2121 * @note The return value points to static data that will be overwritten with each call. 2122 */ 2123 char *list_of_NETFS_devices_and_mounts(void) 2124 { 2125 char *exclude_these_devices = NULL; 2126 char *exclude_these_directories = NULL; 2127 static char result_sz[1024]; 2128 2129 mr_asprintf(&exclude_these_directories,"%s",list_of_NETFS_mounts_only()); 2130 mr_asprintf(&exclude_these_devices,"%s", 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;}'")); 2131 snprintf(result_sz, 1023, "%s %s", exclude_these_directories, exclude_these_devices); 2132 mr_free(exclude_these_devices); 2133 mr_free(exclude_these_directories); 2134 return (result_sz); 2135 } 2136 2137 2138 2139 2140 /** 2141 * Get a space-separated list of NETFS mounts. 2142 * @return The list created. 2143 * @note The return value points to static data that will be overwritten with each call. 2144 * @bug Even though we only want the mounts, the devices are still checked. 2145 */ 2146 char *list_of_NETFS_mounts_only(void) 2147 { 2148 char *exclude_these_directories = NULL; 2149 static char result_sz[512]; 2150 2151 mr_asprintf(&exclude_these_directories,"%s", 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;}'")); 2152 snprintf(result_sz, 511, "%s", exclude_these_directories); 2153 mr_free(exclude_these_directories); 2154 return (result_sz); 2155 } 2156 2157 /* @} - end of utilityGroup */ 2158 2159 2160 2161 2162 2163 /** 2164 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where 2165 * [random] is a random number between 1 and 32767. 2166 * @param store_name_here Where to store the new filename. 2167 * @param stub A random number will be appended to this to make the FIFO's name. 2168 * @ingroup deviceGroup 2169 */ 2170 void make_fifo(char *store_name_here, char *stub) 2171 { 2172 char *tmp; 2173 2174 malloc_string(tmp); 2175 assert_string_is_neither_NULL_nor_zerolength(stub); 2176 2177 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768), 2178 (int) (random() % 32768)); 2179 make_hole_for_file(store_name_here); 2180 mkfifo(store_name_here, S_IRWXU | S_IRWXG); 2181 sprintf(tmp, "chmod 770 %s", store_name_here); 2182 paranoid_system(tmp); 2183 paranoid_free(tmp); 2184 } 2185 2186 2187 2188 2189 2190 2191 /** 2192 * Set the tmpdir and scratchdir to reside on the partition with the most free space. 2193 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems. 2194 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set. 2195 * @ingroup utilityGroup 2196 */ 2197 void sensibly_set_tmpdir_and_scratchdir() 2198 { 2199 char *tmp = NULL; 2200 char *command = NULL; 2201 char *sz = NULL; 2202 2203 assert(bkpinfo != NULL); 2204 2205 #ifdef __FreeBSD__ 2206 mr_asprintf(&tmp, "%s", 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;}'")); 2207 #else 2208 mr_asprintf(&tmp, "%s", 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;}'")); 2209 #endif 2210 2211 if (tmp[0] != '/') { 2212 mr_asprintf(&sz, "%s", tmp); 2213 paranoid_free(tmp); 2214 mr_asprintf(&tmp, "/%s", sz); 2215 mr_free(sz); 2216 } 2217 if (!tmp[0]) { 2218 fatal_error("I couldn't figure out the tempdir!"); 2219 } 2220 setup_tmpdir(tmp); 2221 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir); 2222 2223 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp, 2224 (int) (random() % 32768)); 2225 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir); 2226 2227 mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp); 2228 paranoid_free(tmp); 2229 2230 paranoid_system(command); 2231 mr_free(command); 2232 } 2233 2234 2235 2236 2237 2238 2239 /** 2240 * @addtogroup deviceGroup 2241 * @{ 2242 */ 2243 /** 2244 * If we can read @p dev, set @p output to it. 2245 * If @p dev cannot be read, set @p output to "". 2246 * @param dev The device to check for. 2247 * @param output Set to @p dev if @p dev exists, "" otherwise. 2248 * @return TRUE if @p dev exists, FALSE if it doesn't. 2249 */ 2250 bool set_dev_to_this_if_rx_OK(char *output, char *dev) 2251 { 2252 char *command; 2253 2254 malloc_string(command); 2255 if (!dev || dev[0] == '\0') { 2256 output[0] = '\0'; 2257 return (FALSE); 2258 } 2259 // assert_string_is_neither_NULL_nor_zerolength(dev); 2260 log_msg(10, "Injecting %s", dev); 2261 inject_device(dev); 2262 if (!does_file_exist(dev)) { 2263 log_msg(10, "%s doesn't exist. Returning FALSE.", dev); 2264 return (FALSE); 2265 } 2266 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null", 2267 512L, dev); 2268 if (!run_program_and_log_output(command, FALSE) 2269 && !run_program_and_log_output(command, FALSE)) { 2270 strcpy(output, dev); 2271 log_msg(4, "Found it - %s", dev); 2272 return (TRUE); 2273 } else { 2274 output[0] = '\0'; 2275 log_msg(4, "It's not %s", dev); 2276 return (FALSE); 2277 } 2278 } 2279 2280 2281 2282 2283 2284 /** 2285 * Find out what number CD is in the drive. 2286 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used. 2287 * @return The current CD number, or -1 if it could not be found. 2288 * @note If the CD is not mounted, it will be mounted 2289 * (and remain mounted after this function returns). 2290 */ 2291 int what_number_cd_is_this() 2292 { 2293 int cd_number = -1; 2294 char *mountdev = NULL; 2295 char *tmp = NULL; 2296 2297 assert(bkpinfo != NULL); 2298 // log_it("Asking what_number_cd_is_this"); 2299 if (g_ISO_restore_mode) { 2300 mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'"); 2301 2302 mr_asprintf(&mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER"); 2303 cd_number = atoi(last_line_of_file(mountdev)); 2304 paranoid_free(mountdev); 2305 paranoid_free(tmp); 2306 2307 return (cd_number); 2308 } 2309 2310 mr_asprintf(&mountdev, "%s", bkpinfo->media_device); 2311 if (!mountdev[0]) { 2312 log_it 2313 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out..."); 2314 find_cdrom_device(bkpinfo->media_device, FALSE); 2315 } 2316 if (!is_this_device_mounted(MNT_CDROM)) { 2317 if (bkpinfo->backup_media_type == usb) { 2318 mount_USB_here(mountdev, MNT_CDROM); 2319 } else { 2320 mount_CDROM_here(mountdev, MNT_CDROM); 2321 } 2322 } 2323 paranoid_free(mountdev); 2324 2325 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER")); 2326 return (cd_number); 2327 } 2328 2329 2330 2331 2332 2333 2334 2335 /** 2336 * Find out what device is mounted as root (/). 2337 * @return Root device. 2338 * @note The returned string points to static storage and will be overwritten with every call. 2339 * @bug A bit of a misnomer; it's actually finding out the root device. 2340 * The mountpoint (where it's mounted) will obviously be '/'. 2341 */ 2342 char *where_is_root_mounted() 2343 { 2344 /*@ buffers **************** */ 2345 static char tmp[MAX_STR_LEN]; 2346 2347 2348 #ifdef __FreeBSD__ 2349 strcpy(tmp, call_program_and_get_last_line_of_output 2350 ("mount | grep \" on / \" | cut -d' ' -f1")); 2351 #else 2352 strcpy(tmp, call_program_and_get_last_line_of_output 2353 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//")); 2354 if (strstr(tmp, "/dev/cciss/")) { 2355 strcpy(tmp, call_program_and_get_last_line_of_output 2356 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1")); 2357 } 2358 if (strstr(tmp, "/dev/md")) { 2359 strcpy(tmp, 2360 call_program_and_get_last_line_of_output 2361 ("mount | grep \" on / \" | cut -d' ' -f1")); 2362 } 2363 #endif 2364 2365 return (tmp); 2366 } 2367 2368 2369 /** 2370 * Find out which boot loader is in use. 2371 * @param which_device Device to look for the boot loader on. 2372 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown. 2373 * @note Under Linux, all drives are examined, not just @p which_device. 2374 */ 2375 #ifdef __FreeBSD__ 2376 char which_boot_loader(char *which_device) 2377 { 2378 int count_lilos = 0; 2379 int count_grubs = 0; 2380 int count_boot0s = 0; 2381 int count_dangerouslydedicated = 0; 2382 2383 log_it("looking at drive %s's MBR", which_device); 2384 if (does_string_exist_in_boot_block(which_device, "GRUB")) { 2385 count_grubs++; 2386 } 2387 if (does_string_exist_in_boot_block(which_device, "LILO")) { 2388 count_lilos++; 2389 } 2390 if (does_string_exist_in_boot_block(which_device, "Drive")) { 2391 count_boot0s++; 2392 } 2393 if (does_string_exist_in_first_N_blocks 2394 (which_device, "FreeBSD/i386", 17)) { 2395 count_dangerouslydedicated++; 2396 } 2397 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n", 2398 count_grubs, count_lilos, count_elilos, count_boot0s, 2399 count_dangerouslydedicated); 2400 2401 if (count_grubs && !count_lilos) { 2402 return ('G'); 2403 } else if (count_lilos && !count_grubs) { 2404 return ('L'); 2405 } else if (count_grubs == 1 && count_lilos == 1) { 2406 log_it("I'll bet you used to use LILO but switched to GRUB..."); 2407 return ('G'); 2408 } else if (count_boot0s == 1) { 2409 return ('B'); 2410 } else if (count_dangerouslydedicated) { 2411 return ('D'); 2412 } else { 2413 log_it("Unknown boot loader"); 2414 return ('U'); 2415 } 2416 } 2417 2418 #else 2419 2420 char which_boot_loader(char *which_device) 2421 { 2422 /*@ buffer ***************************************************** */ 2423 char *list_drives_cmd = NULL; 2424 char *current_drive; 2425 2426 /*@ pointers *************************************************** */ 2427 FILE *pdrives; 2428 2429 /*@ int ******************************************************** */ 2430 int count_lilos = 0; 2431 int count_grubs = 0; 2432 2433 /*@ end vars *************************************************** */ 2434 2435 malloc_string(current_drive); 2436 2437 #ifdef __IA64__ 2438 /* No choice for it */ 2439 return ('E'); 2440 #endif 2441 assert(which_device != NULL); 2442 2443 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s", where_is_root_mounted()); 2444 log_it("list_drives_cmd = %s", list_drives_cmd); 2445 2446 if (!(pdrives = popen(list_drives_cmd, "r"))) { 2447 log_OS_error("Unable to open list of drives"); 2448 mr_free(list_drives_cmd); 2449 paranoid_free(current_drive); 2450 return ('\0'); 2451 } 2452 mr_free(list_drives_cmd); 2453 2454 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives); 2455 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) { 2456 strip_spaces(current_drive); 2457 log_it("looking at drive %s's MBR", current_drive); 2458 if (does_string_exist_in_boot_block(current_drive, "GRUB")) { 2459 count_grubs++; 2460 strcpy(which_device, current_drive); 1475 DSF_Tail->next = DSFptr; 1476 } 1477 DSFptr->next = NULL; 1478 DSF_Tail = DSFptr; 1479 } 1480 1481 /** 1482 * Find the structure, in the singly linked list of all of the non-NETFS 1483 * mounted file systems, that contains the specified device. 1484 * @param device The device to find 1485 * @return NULL if it didn't find the device, a pointer to the 1486 * structure if it did. 1487 */ 1488 static MOUNTED_FS_STRUCT *find_device_in_list (char *device) 1489 { 1490 MOUNTED_FS_STRUCT *DSFptr = NULL; 1491 1492 DSFptr = DSF_Head; 1493 while (DSFptr != NULL) { 1494 if (!strcmp(DSFptr->device, device)) { 2461 1495 break; 2462 1496 } 2463 if (does_string_exist_in_boot_block(current_drive, "LILO")) { 2464 count_lilos++; 2465 strcpy(which_device, current_drive); 1497 DSFptr = DSFptr->next; 1498 } 1499 return (DSFptr); 1500 } 1501 1502 /** 1503 * Find the structure, in the singly linked list of all of the non-NETFS 1504 * mounted file systems, that contains the specified mount point. 1505 * @param mount_point The mount point to find 1506 * @return NULL is it didn't find the mount point, a pointer to the 1507 * structure if it did. 1508 */ 1509 static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point) 1510 { 1511 MOUNTED_FS_STRUCT *DSFptr = NULL; 1512 1513 DSFptr = DSF_Head; 1514 while (DSFptr != NULL) { 1515 if (!strcmp(DSFptr->mount_point, mount_point)) { 2466 1516 break; 2467 1517 } 2468 } 2469 if (pclose(pdrives)) { 2470 log_OS_error("Cannot pclose pdrives"); 2471 } 2472 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos); 2473 if (count_grubs && !count_lilos) { 2474 paranoid_free(current_drive); 2475 return ('G'); 2476 } else if (count_lilos && !count_grubs) { 2477 paranoid_free(current_drive); 2478 return ('L'); 2479 } else if (count_grubs == 1 && count_lilos == 1) { 2480 log_it("I'll bet you used to use LILO but switched to GRUB..."); 2481 paranoid_free(current_drive); 2482 return ('G'); 2483 } else { 2484 // We need to look on each partition then 2485 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/"); 2486 log_it("list_drives_cmd = %s", list_drives_cmd); 2487 2488 if (!(pdrives = popen(list_drives_cmd, "r"))) { 2489 log_OS_error("Unable to open list of drives"); 2490 mr_free(list_drives_cmd); 2491 paranoid_free(current_drive); 2492 return ('\0'); 2493 } 2494 mr_free(list_drives_cmd); 2495 2496 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives); 2497 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) { 2498 strip_spaces(current_drive); 2499 log_it("looking at partition %s's BR", current_drive); 2500 if (does_string_exist_in_boot_block(current_drive, "GRUB")) { 2501 count_grubs++; 2502 strcpy(which_device, current_drive); 2503 break; 2504 } 2505 if (does_string_exist_in_boot_block(current_drive, "LILO")) { 2506 count_lilos++; 2507 strcpy(which_device, current_drive); 2508 break; 2509 } 2510 } 2511 if (pclose(pdrives)) { 2512 log_OS_error("Cannot pclose pdrives"); 2513 } 2514 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos); 2515 paranoid_free(current_drive); 2516 if (count_grubs && !count_lilos) { 2517 return ('G'); 2518 } else if (count_lilos && !count_grubs) { 2519 return ('L'); 2520 } else if (count_grubs == 1 && count_lilos == 1) { 2521 log_it("I'll bet you used to use LILO but switched to GRUB..."); 2522 return ('G'); 2523 } else { 2524 log_it("Unknown boot loader"); 2525 return ('U'); 2526 } 2527 } 2528 } 2529 #endif 2530 2531 2532 2533 2534 /** 2535 * Write zeroes over the first 16K of @p device. 2536 * @param device The device to zero. 2537 * @return 0 for success, 1 for failure. 2538 */ 2539 int zero_out_a_device(char *device) 2540 { 2541 FILE *fout; 2542 int i; 2543 2544 assert_string_is_neither_NULL_nor_zerolength(device); 2545 2546 log_it("Zeroing drive %s", device); 2547 if (!(fout = fopen(device, "w"))) { 2548 log_OS_error("Unable to open/write to device"); 2549 return (1); 2550 } 2551 for (i = 0; i < 16384; i++) { 2552 fputc('\0', fout); 2553 } 2554 paranoid_fclose(fout); 2555 log_it("Device successfully zeroed."); 2556 return (0); 2557 } 2558 2559 /** 2560 * Return the device pointed to by @p incoming. 2561 * @param incoming The device to resolve symlinks for. 2562 * @return The path to the real device file. 2563 * @note The returned string points to static storage that will be overwritten with each call. 2564 * @bug Won't work with file v4.0; needs to be written in C. 2565 */ 2566 char *resolve_softlinks_to_get_to_actual_device_file(char *incoming) 2567 { 2568 static char output[MAX_STR_LEN]; 2569 char *command; 2570 char *curr_fname; 2571 char *scratch = NULL; 2572 char *tmp = NULL; 2573 char *p; 2574 2575 struct stat statbuf; 2576 command = malloc(1000); 2577 malloc_string(curr_fname); 2578 if (!does_file_exist(incoming)) { 2579 log_it 2580 ("resolve_softlinks_to_get_to_actual_device_file --- device not found"); 2581 strcpy(output, incoming); 2582 } else { 2583 strcpy(curr_fname, incoming); 2584 lstat(curr_fname, &statbuf); 2585 while (S_ISLNK(statbuf.st_mode)) { 2586 log_msg(1, "curr_fname = %s", curr_fname); 2587 sprintf(command, "file %s", curr_fname); 2588 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command)); 2589 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' '; 2590 p--); 2591 p++; 2592 mr_asprintf(&scratch, "%s", p); 2593 for (p = scratch; *p != '\0' && *p != '\''; p++); 2594 *p = '\0'; 2595 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch); 2596 mr_free(tmp); 2597 2598 if (scratch[0] == '/') { 2599 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink 2600 } else { // copy over the basename cos it's a relative softlink 2601 p = curr_fname + strlen(curr_fname); 2602 while (p != curr_fname && *p != '/') { 2603 p--; 2604 } 2605 if (*p == '/') { 2606 p++; 2607 } 2608 strcpy(p, scratch); 2609 } 2610 mr_free(scratch); 2611 lstat(curr_fname, &statbuf); 2612 } 2613 strcpy(output, curr_fname); 2614 log_it("resolved %s to %s", incoming, output); 2615 } 2616 paranoid_free(command); 2617 paranoid_free(curr_fname); 2618 return (output); 2619 } 2620 2621 /* @} - end of deviceGroup */ 2622 2623 /** 2624 * Return the type of partition format (GPT or MBR) 2625 */ 2626 char *which_partition_format(const char *drive) 2627 { 2628 static char output[4]; 2629 char *tmp = NULL; 2630 char *command; 2631 char *fdisk; 2632 #ifdef __IA64__ 2633 struct stat buf; 2634 #endif 2635 malloc_string(command); 2636 malloc_string(fdisk); 2637 sprintf(fdisk, "/sbin/parted2fdisk"); 2638 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive); 2639 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command)); 2640 if (strstr(tmp, "GPT") == NULL) { 2641 strcpy(output, "MBR"); 2642 } else { 2643 strcpy(output, "GPT"); 2644 } 2645 mr_free(tmp); 2646 2647 log_msg(0, "Found %s partition table format type", output); 2648 paranoid_free(command); 2649 paranoid_free(fdisk); 2650 return (output); 1518 DSFptr = DSFptr->next; 1519 } 1520 return (DSFptr); 2651 1521 } 2652 1522 … … 2669 1539 } 2670 1540 2671 /**2672 * Creates a singly linked list of all of the non-NETFS mounted file systems.2673 * @param DSFptr A pointer to the structure MOUNTED_FS_STRUCT used to hold2674 * the list of mounted file systems.2675 * @return None.2676 */2677 static void add_mounted_fs_struct (MOUNTED_FS_STRUCT *DSFptr)2678 {2679 assert (DSFptr);2680 if (DSF_Head == NULL) {2681 DSF_Head = DSFptr;2682 } else {2683 DSF_Tail->next = DSFptr;2684 }2685 DSFptr->next = NULL;2686 DSF_Tail = DSFptr;2687 }2688 2689 /**2690 * Find the structure, in the singly linked list of all of the non-NETFS2691 * mounted file systems, that contains the specified device.2692 * @param device The device to find2693 * @return NULL if it didn't find the device, a pointer to the2694 * structure if it did.2695 */2696 static MOUNTED_FS_STRUCT *find_device_in_list (char *device)2697 {2698 MOUNTED_FS_STRUCT *DSFptr = NULL;2699 2700 DSFptr = DSF_Head;2701 while (DSFptr != NULL) {2702 if (!strcmp(DSFptr->device, device)) {2703 break;2704 }2705 DSFptr = DSFptr->next;2706 }2707 return (DSFptr);2708 }2709 2710 /**2711 * Find the structure, in the singly linked list of all of the non-NETFS2712 * mounted file systems, that contains the specified mount point.2713 * @param mount_point The mount point to find2714 * @return NULL is it didn't find the mount point, a pointer to the2715 * structure if it did.2716 */2717 static MOUNTED_FS_STRUCT *find_mount_point_in_list (char *mount_point)2718 {2719 MOUNTED_FS_STRUCT *DSFptr = NULL;2720 2721 DSFptr = DSF_Head;2722 while (DSFptr != NULL) {2723 if (!strcmp(DSFptr->mount_point, mount_point)) {2724 break;2725 }2726 DSFptr = DSFptr->next;2727 }2728 return (DSFptr);2729 }2730 1541 2731 1542 /** … … 3116 1927 3117 1928 1929 1930 1931 3118 1932 /* Update the bkpinfo structure for exclude & include paths 3119 1933 * in order to handle correctly paths corresponding to devices */ … … 3191 2005 3192 2006 2007 /** 2008 * Ask user for details of backup/restore information. 2009 * Called when @c mondoarchive doesn't get any parameters. 2010 * @param bkpinfo The backup information structure to fill out with the user's data. 2011 * @param archiving_to_media TRUE if archiving, FALSE if restoring. 2012 * @return 0, always. 2013 * @bug No point of `int' return value. 2014 * @ingroup archiveGroup 2015 */ 2016 int interactively_obtain_media_parameters_from_user(bool archiving_to_media) 2017 // archiving_to_media is TRUE if I'm being called by mondoarchive 2018 // archiving_to_media is FALSE if I'm being called by mondorestore 2019 { 2020 char *tmp = NULL; 2021 char *tmp1 = NULL; 2022 char *mds = NULL; 2023 char *sz_size; 2024 char *command; 2025 char *comment; 2026 char *prompt; 2027 int i; 2028 FILE *fin; 2029 2030 malloc_string(sz_size); 2031 malloc_string(command); 2032 malloc_string(comment); 2033 malloc_string(prompt); 2034 malloc_string(tmp1); 2035 assert(bkpinfo != NULL); 2036 sz_size[0] = '\0'; 2037 bkpinfo->nonbootable_backup = FALSE; 2038 2039 // Tape, CD, NETFS, ...? 2040 srandom(getpid()); 2041 bkpinfo->backup_media_type = 2042 (g_restoring_live_from_cd) ? cdr : 2043 which_backup_media_type(bkpinfo->restore_data); 2044 if (bkpinfo->backup_media_type == none) { 2045 log_to_screen("User has chosen not to backup the PC"); 2046 finish(1); 2047 } 2048 /* Why asking to remove the media with tape ? 2049 if (bkpinfo->backup_media_type == tape && bkpinfo->restore_data) { 2050 popup_and_OK("Please remove media from drive(s)"); 2051 } 2052 */ 2053 log_msg(3, "media type = %s", 2054 bkptype_to_string(bkpinfo->backup_media_type)); 2055 if (archiving_to_media) { 2056 sensibly_set_tmpdir_and_scratchdir(); 2057 } 2058 bkpinfo->cdrw_speed = (bkpinfo->backup_media_type == cdstream) ? 2 : 4; 2059 bkpinfo->compression_level = 2060 (bkpinfo->backup_media_type == cdstream) ? 1 : 5; 2061 bkpinfo->use_lzo = 2062 (bkpinfo->backup_media_type == cdstream) ? TRUE : FALSE; 2063 mvaddstr_and_log_it(2, 0, " "); 2064 2065 // Find device's /dev (or SCSI) entry 2066 switch (bkpinfo->backup_media_type) { 2067 case cdr: 2068 case cdrw: 2069 case dvd: 2070 case usb: 2071 /* Never try to eject a USB device */ 2072 if (bkpinfo->backup_media_type == usb) { 2073 bkpinfo->please_dont_eject = TRUE; 2074 } 2075 if (archiving_to_media) { 2076 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) { 2077 if (ask_me_yes_or_no 2078 ("Is your computer a laptop, or does the CD writer incorporate BurnProof technology?")) 2079 { 2080 bkpinfo->manual_cd_tray = TRUE; 2081 } 2082 } 2083 if ((bkpinfo->compression_level = 2084 which_compression_level()) == -1) { 2085 log_to_screen("User has chosen not to backup the PC"); 2086 finish(1); 2087 } 2088 mds = media_descriptor_string(bkpinfo->backup_media_type); 2089 sprintf(comment, "What speed is your %s (re)writer?", mds); 2090 if (bkpinfo->backup_media_type == dvd) { 2091 find_dvd_device(bkpinfo->media_device, FALSE); 2092 strcpy(tmp1, "1"); 2093 sprintf(sz_size, "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4482 MB 2094 log_msg(1, "Setting to DVD defaults"); 2095 } else { 2096 strcpy(bkpinfo->media_device, VANILLA_SCSI_CDROM); 2097 strcpy(tmp1, "4"); 2098 strcpy(sz_size, "650"); 2099 log_msg(1, "Setting to CD defaults"); 2100 } 2101 if ((bkpinfo->backup_media_type != dvd) && (bkpinfo->backup_media_type != usb)) { 2102 if (!popup_and_get_string("Speed", comment, tmp1, 4)) { 2103 log_to_screen("User has chosen not to backup the PC"); 2104 finish(1); 2105 } 2106 } 2107 bkpinfo->cdrw_speed = atoi(tmp1); // if DVD then this shouldn't ever be used anyway :) 2108 2109 sprintf(comment, 2110 "How much data (in Megabytes) will each %s store?", mds); 2111 mr_free(mds); 2112 if (!popup_and_get_string("Size", comment, sz_size, 5)) { 2113 log_to_screen("User has chosen not to backup the PC"); 2114 finish(1); 2115 } 2116 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 2117 bkpinfo->media_size[i] = atoi(sz_size); 2118 } 2119 if (bkpinfo->media_size[0] <= 0) { 2120 log_to_screen("User has chosen not to backup the PC"); 2121 finish(1); 2122 } 2123 } 2124 /* No break because we continue even for usb */ 2125 case cdstream: 2126 mds = media_descriptor_string(bkpinfo->backup_media_type); 2127 2128 if ((bkpinfo->disaster_recovery) && (bkpinfo->backup_media_type != usb)) { 2129 strcpy(bkpinfo->media_device, "/dev/cdrom"); 2130 log_msg(2, "CD-ROM device assumed to be at %s", 2131 bkpinfo->media_device); 2132 } else if ((bkpinfo->restore_data && (bkpinfo->backup_media_type != usb)) 2133 || bkpinfo->backup_media_type == dvd) { 2134 if (!bkpinfo->media_device[0]) { 2135 strcpy(bkpinfo->media_device, "/dev/cdrom"); 2136 } // just for the heck of it :) 2137 log_msg(1, "bkpinfo->media_device = %s", 2138 bkpinfo->media_device); 2139 if (bkpinfo->backup_media_type == dvd 2140 || find_cdrom_device(bkpinfo->media_device, FALSE)) { 2141 log_msg(1, "bkpinfo->media_device = %s", 2142 bkpinfo->media_device); 2143 sprintf(comment, 2144 "Please specify your %s drive's /dev entry", mds); 2145 if (!popup_and_get_string 2146 ("Device?", comment, bkpinfo->media_device, 2147 MAX_STR_LEN / 4)) { 2148 log_to_screen("User has chosen not to backup the PC"); 2149 finish(1); 2150 } 2151 } 2152 log_msg(2, "%s device found at %s", mds, bkpinfo->media_device); 2153 } else { 2154 if ((find_cdrw_device(bkpinfo->media_device)) && (bkpinfo->backup_media_type != usb)) { 2155 bkpinfo->media_device[0] = '\0'; 2156 } 2157 if (bkpinfo->media_device[0]) { 2158 if (bkpinfo->backup_media_type == usb) { 2159 mr_asprintf(&tmp, "I think your %s media corresponds to %s. Is this correct?", mds, bkpinfo->media_device); 2160 } else { 2161 mr_asprintf(&tmp, "I think I've found your %s burner at SCSI node %s. Is this correct? (Say no if you have an IDE burner and you are running a 2.6 kernel. You will then be prompted for further details.)", mds, bkpinfo->media_device); 2162 } 2163 if (!ask_me_yes_or_no(tmp)) { 2164 bkpinfo->media_device[0] = '\0'; 2165 } 2166 mr_free(tmp); 2167 } 2168 if (!bkpinfo->media_device[0]) { 2169 if (bkpinfo->backup_media_type == usb) { 2170 i = popup_and_get_string("/dev entry?", 2171 "What is the /dev entry of your USB Disk/Key, please?", 2172 bkpinfo->media_device, 2173 MAX_STR_LEN / 4); 2174 } else { 2175 if (g_kernel_version < 2.6) { 2176 i = popup_and_get_string("Device node?", 2177 "What is the SCSI node of your CD (re)writer, please?", 2178 bkpinfo->media_device, 2179 MAX_STR_LEN / 4); 2180 } else { 2181 i = popup_and_get_string("/dev entry?", 2182 "What is the /dev entry of your CD (re)writer, please?", 2183 bkpinfo->media_device, 2184 MAX_STR_LEN / 4); 2185 } 2186 } 2187 if (!i) { 2188 log_to_screen("User has chosen not to backup the PC"); 2189 finish(1); 2190 } 2191 } 2192 } 2193 mr_free(mds); 2194 2195 if (bkpinfo->backup_media_type == cdstream) { 2196 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 2197 bkpinfo->media_size[i] = 650; 2198 } 2199 } 2200 break; 2201 case udev: 2202 if (!ask_me_yes_or_no 2203 ("This option is for advanced users only. Are you sure?")) { 2204 log_to_screen("User has chosen not to backup the PC"); 2205 finish(1); 2206 } 2207 case tape: 2208 2209 if ((!bkpinfo->restore_mode) && (find_tape_device_and_size(bkpinfo->media_device, sz_size))) { 2210 log_msg(3, "Ok, using vanilla scsi tape."); 2211 strcpy(bkpinfo->media_device, VANILLA_SCSI_TAPE); 2212 if ((fin = fopen(bkpinfo->media_device, "r"))) { 2213 paranoid_fclose(fin); 2214 } else { 2215 strcpy(bkpinfo->media_device, "/dev/osst0"); 2216 } 2217 } 2218 if (bkpinfo->media_device[0]) { 2219 if ((fin = fopen(bkpinfo->media_device, "r"))) { 2220 paranoid_fclose(fin); 2221 } else { 2222 if (does_file_exist("/tmp/mondo-restore.cfg")) { 2223 read_cfg_var("/tmp/mondo-restore.cfg", "media-dev", 2224 bkpinfo->media_device); 2225 } 2226 } 2227 } 2228 if (bkpinfo->media_device[0]) { 2229 mr_asprintf(&tmp, "I think I've found your tape streamer at %s; am I right on the money?", bkpinfo->media_device); 2230 if (!ask_me_yes_or_no(tmp)) { 2231 bkpinfo->media_device[0] = '\0'; 2232 } 2233 mr_free(tmp); 2234 } 2235 if (!bkpinfo->media_device[0]) { 2236 if (!popup_and_get_string 2237 ("Device name?", 2238 "What is the /dev entry of your tape streamer?", 2239 bkpinfo->media_device, MAX_STR_LEN / 4)) { 2240 log_to_screen("User has chosen not to backup the PC"); 2241 finish(1); 2242 } 2243 } 2244 mr_asprintf(&tmp, "ls -l %s", bkpinfo->media_device); 2245 if (run_program_and_log_output(tmp, FALSE)) { 2246 log_to_screen("User has not specified a valid /dev entry"); 2247 finish(1); 2248 } 2249 mr_free(tmp); 2250 log_msg(4, "sz_size = %s", sz_size); 2251 sz_size[0] = '\0'; 2252 2253 bkpinfo->use_obdr = ask_me_yes_or_no 2254 ("Do you want to activate OBDR support for your tapes ?"); 2255 if (sz_size[0] == '\0') { 2256 bkpinfo->media_size[0] = 0; 2257 } else { 2258 bkpinfo->media_size[0] = 2259 friendly_sizestr_to_sizelong(sz_size) / 2 - 50; 2260 } 2261 log_msg(4, "media_size[0] = %ld", bkpinfo->media_size[0]); 2262 if (bkpinfo->media_size[0] <= 0) { 2263 bkpinfo->media_size[0] = 0; 2264 } 2265 for (i = 1; i <= MAX_NOOF_MEDIA; i++) { 2266 bkpinfo->media_size[i] = bkpinfo->media_size[0]; 2267 } 2268 if (archiving_to_media) { 2269 if ((bkpinfo->compression_level = 2270 which_compression_level()) == -1) { 2271 log_to_screen("User has chosen not to backup the PC"); 2272 finish(1); 2273 } 2274 } 2275 break; 2276 2277 2278 2279 case netfs: 2280 /* Never try to eject a NETFS device */ 2281 bkpinfo->please_dont_eject = TRUE; 2282 2283 /* Initiate bkpinfo netfs_mount path from running environment if not already done */ 2284 if (!bkpinfo->netfs_mount[0]) { 2285 strcpy(bkpinfo->netfs_mount, 2286 call_program_and_get_last_line_of_output 2287 ("mount | grep \":\" | cut -d' ' -f1 | head -n1")); 2288 } 2289 #ifdef __FreeBSD__ 2290 if (TRUE) 2291 #else 2292 if (!bkpinfo->disaster_recovery) 2293 #endif 2294 { 2295 if (!popup_and_get_string 2296 ("Network shared dir.", 2297 "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.)", 2298 bkpinfo->netfs_mount, MAX_STR_LEN / 4)) { 2299 log_to_screen("User has chosen not to backup the PC"); 2300 finish(1); 2301 } 2302 if (!bkpinfo->restore_data) { 2303 if ((bkpinfo->compression_level = 2304 which_compression_level()) == -1) { 2305 log_to_screen("User has chosen not to backup the PC"); 2306 finish(1); 2307 } 2308 } 2309 // check whether already mounted - we better remove 2310 // surrounding spaces and trailing '/' for this 2311 strip_spaces(bkpinfo->netfs_mount); 2312 if (bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] == '/') 2313 bkpinfo->netfs_mount[strlen(bkpinfo->netfs_mount) - 1] = '\0'; 2314 sprintf(command, "mount | grep \"%s \" | cut -d' ' -f3", 2315 bkpinfo->netfs_mount); 2316 strcpy(bkpinfo->isodir, 2317 call_program_and_get_last_line_of_output(command)); 2318 2319 if (!bkpinfo->restore_data) { 2320 sprintf(comment, 2321 "How much data (in Megabytes) will each media store?"); 2322 if (!popup_and_get_string("Size", comment, sz_size, 5)) { 2323 log_to_screen("User has chosen not to backup the PC"); 2324 finish(1); 2325 } 2326 } else { 2327 strcpy(sz_size, "0"); 2328 } 2329 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 2330 bkpinfo->media_size[i] = atoi(sz_size); 2331 } 2332 if (bkpinfo->media_size[0] < 0) { 2333 log_to_screen("User has chosen not to backup the PC"); 2334 finish(1); 2335 } 2336 } 2337 if (bkpinfo->disaster_recovery) { 2338 sprintf(command ,"umount %s/isodir 2> /dev/null", bkpinfo->tmpdir); 2339 (void)system(command); 2340 strcpy(tmp1, bkpinfo->netfs_proto); 2341 if (!popup_and_get_string 2342 ("Network protocol", "Which protocol should I use?", 2343 tmp1, MAX_STR_LEN)) { 2344 log_to_screen("User has chosen not to backup the PC"); 2345 finish(1); 2346 } 2347 mr_free(bkpinfo->netfs_proto); 2348 mr_asprintf(&(bkpinfo->netfs_proto), "%s", tmp1); 2349 if (!popup_and_get_string 2350 ("Network share", "Which remote share should I mount?", 2351 bkpinfo->netfs_mount, MAX_STR_LEN)) { 2352 log_to_screen("User has chosen not to backup the PC"); 2353 finish(1); 2354 } 2355 } 2356 /* Initiate bkpinfo isodir path from running environment if mount already done */ 2357 if (is_this_device_mounted(bkpinfo->netfs_mount)) { 2358 strcpy(bkpinfo->isodir, 2359 call_program_and_get_last_line_of_output 2360 ("mount | grep \":\" | cut -d' ' -f3 | head -n1")); 2361 } else { 2362 sprintf(bkpinfo->isodir, "%s/netfsdir", bkpinfo->tmpdir); 2363 sprintf(command, "mkdir -p %s", bkpinfo->isodir); 2364 run_program_and_log_output(command, 5); 2365 if (bkpinfo->restore_data) { 2366 if (strstr(bkpinfo->netfs_proto, "sshfs")) { 2367 mr_asprintf(&tmp, "sshfs -o ro %s %s", bkpinfo->netfs_mount, bkpinfo->isodir); 2368 } else { 2369 mr_asprintf(&tmp, "mount -t %s -o nolock,ro %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir); 2370 } 2371 } else { 2372 if (strstr(bkpinfo->netfs_proto, "sshfs")) { 2373 mr_asprintf(&tmp, "sshfs %s %s", bkpinfo->netfs_mount, bkpinfo->isodir); 2374 } else { 2375 mr_asprintf(&tmp, "mount -t %s -o nolock %s %s", bkpinfo->netfs_proto, bkpinfo->netfs_mount, bkpinfo->isodir); 2376 } 2377 } 2378 run_program_and_log_output(tmp, 3); 2379 mr_free(tmp); 2380 2381 malloc_string(g_selfmounted_isodir); 2382 strcpy(g_selfmounted_isodir, bkpinfo->isodir); 2383 } 2384 if (!is_this_device_mounted(bkpinfo->netfs_mount)) { 2385 popup_and_OK 2386 ("Please mount that partition before you try to backup to or restore from it."); 2387 finish(1); 2388 } 2389 strcpy(tmp1, bkpinfo->netfs_remote_dir); 2390 if (!popup_and_get_string 2391 ("Directory", "Which directory within that mountpoint?", tmp1, 2392 MAX_STR_LEN)) { 2393 log_to_screen("User has chosen not to backup the PC"); 2394 finish(1); 2395 } 2396 strcpy(bkpinfo->netfs_remote_dir, tmp1); 2397 2398 // check whether writable - we better remove surrounding spaces for this 2399 strip_spaces(bkpinfo->netfs_remote_dir); 2400 2401 if (!popup_and_get_string 2402 ("Prefix.", 2403 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files", 2404 bkpinfo->prefix, MAX_STR_LEN / 4)) { 2405 log_to_screen("User has chosen not to backup the PC"); 2406 finish(1); 2407 } 2408 log_msg(3, "prefix set to %s", bkpinfo->prefix); 2409 2410 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 2411 bkpinfo->media_size[i] = 650; 2412 } 2413 log_msg(3, "Just set netfs_remote_dir to %s", 2414 bkpinfo->netfs_remote_dir); 2415 log_msg(3, "isodir is still %s", bkpinfo->isodir); 2416 break; 2417 2418 case iso: 2419 if (!bkpinfo->disaster_recovery) { 2420 if (!popup_and_get_string 2421 ("Storage dir.", 2422 "Please enter the full path name to the directory for your ISO images. Example: /mnt/raid0_0", 2423 bkpinfo->isodir, MAX_STR_LEN / 4)) { 2424 log_to_screen("User has chosen not to backup the PC"); 2425 finish(1); 2426 } 2427 if (archiving_to_media) { 2428 if ((bkpinfo->compression_level = 2429 which_compression_level()) == -1) { 2430 log_to_screen("User has chosen not to backup the PC"); 2431 finish(1); 2432 } 2433 if (!popup_and_get_string 2434 ("ISO size.", 2435 "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 or DVD's you plan to backup to.", 2436 sz_size, 16)) { 2437 log_to_screen("User has chosen not to backup the PC"); 2438 finish(1); 2439 } 2440 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 2441 bkpinfo->media_size[i] = atoi(sz_size); 2442 } 2443 } else { 2444 for (i = 0; i <= MAX_NOOF_MEDIA; i++) { 2445 bkpinfo->media_size[i] = 650; 2446 } 2447 } 2448 } 2449 if (!popup_and_get_string 2450 ("Prefix.", 2451 "Please enter the prefix that will be prepended to your ISO filename. Example: machine1 to obtain machine1-[1-9]*.iso files", 2452 bkpinfo->prefix, MAX_STR_LEN / 4)) { 2453 log_to_screen("User has chosen not to backup the PC"); 2454 finish(1); 2455 } 2456 log_msg(3, "prefix set to %s", bkpinfo->prefix); 2457 break; 2458 default: 2459 fatal_error 2460 ("I, Mojo Jojo, shall defeat those pesky Powerpuff Girls!"); 2461 } 2462 2463 if (archiving_to_media) { 2464 2465 #ifdef __FreeBSD__ 2466 strcpy(bkpinfo->boot_device, 2467 call_program_and_get_last_line_of_output 2468 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/\\([0-9]\\).*/\\1/'")); 2469 #else 2470 strcpy(bkpinfo->boot_device, 2471 call_program_and_get_last_line_of_output 2472 ("mount | grep ' / ' | head -1 | cut -d' ' -f1 | sed 's/[0-9].*//'")); 2473 #endif 2474 i = which_boot_loader(bkpinfo->boot_device); 2475 if (i == 'U') // unknown 2476 { 2477 2478 #ifdef __FreeBSD__ 2479 if (!popup_and_get_string 2480 ("Boot device", 2481 "What is your boot device? (e.g. /dev/ad0)", 2482 bkpinfo->boot_device, MAX_STR_LEN / 4)) { 2483 log_to_screen("User has chosen not to backup the PC"); 2484 finish(1); 2485 } 2486 i = which_boot_loader(bkpinfo->boot_device); 2487 #else 2488 if (!popup_and_get_string 2489 ("Boot device", 2490 "What is your boot device? (e.g. /dev/hda)", 2491 bkpinfo->boot_device, MAX_STR_LEN / 4)) { 2492 log_to_screen("User has chosen not to backup the PC"); 2493 finish(1); 2494 } 2495 if (does_string_exist_in_boot_block 2496 (bkpinfo->boot_device, "LILO")) { 2497 i = 'L'; 2498 } else 2499 if (does_string_exist_in_boot_block 2500 (bkpinfo->boot_device, "ELILO")) { 2501 i = 'E'; 2502 } else 2503 if (does_string_exist_in_boot_block 2504 (bkpinfo->boot_device, "GRUB")) { 2505 i = 'G'; 2506 } else { 2507 i = 'U'; 2508 } 2509 #endif 2510 if (i == 'U') { 2511 if (ask_me_yes_or_no 2512 ("Unidentified boot loader. Shall I restore it byte-for-byte at restore time and hope for the best?")) 2513 { 2514 i = 'R'; // raw 2515 } else { 2516 log_to_screen 2517 ("I cannot find your boot loader. Please run mondoarchive with parameters."); 2518 finish(1); 2519 } 2520 } 2521 } 2522 bkpinfo->boot_loader = i; 2523 strcpy(bkpinfo->include_paths, "/"); 2524 if (!popup_and_get_string 2525 ("Backup paths", 2526 "Please enter paths which you want me to backup. The default is '/' (i.e. everything).", 2527 bkpinfo->include_paths, MAX_STR_LEN)) { 2528 log_to_screen("User has chosen not to backup the PC"); 2529 finish(1); 2530 } 2531 mr_asprintf(&tmp, "%s", list_of_NETFS_mounts_only()); 2532 if (strlen(tmp) > 2) { 2533 if (bkpinfo->exclude_paths[0]) { 2534 strcat(bkpinfo->exclude_paths, " "); 2535 } 2536 strncpy(bkpinfo->exclude_paths, tmp, MAX_STR_LEN); 2537 } 2538 mr_free(tmp); 2539 // NTFS 2540 strcpy(tmp1, call_program_and_get_last_line_of_output("parted2fdisk -l | grep -i ntfs | awk '{ print $1};' | tr -s '\\n' ' ' | awk '{ print $0};'")); 2541 if (strlen(tmp1) > 2) { 2542 if (!popup_and_get_string 2543 ("NTFS partitions", 2544 "Please enter/confirm the NTFS partitions you wish to backup as well.", 2545 tmp1, MAX_STR_LEN / 4)) { 2546 log_to_screen("User has chosen not to backup the PC"); 2547 finish(1); 2548 } 2549 strncpy(bkpinfo->image_devs, tmp1, MAX_STR_LEN / 4); 2550 } 2551 2552 2553 if (!popup_and_get_string 2554 ("Exclude paths", 2555 "Please enter paths which you do NOT want to backup. Separate them with spaces. NB: /tmp and /proc are always excluded. :-) Just hit 'Enter' if you want to do a full system backup.", 2556 bkpinfo->exclude_paths, (4*MAX_STR_LEN)-1)) { 2557 log_to_screen("User has chosen not to backup the PC"); 2558 finish(1); 2559 } 2560 if (!popup_and_get_string 2561 ("Temporary directory", 2562 "Please enter your temporary directory.", 2563 bkpinfo->tmpdir, (4*MAX_STR_LEN)-1)) { 2564 log_to_screen("User has chosen not to backup the PC"); 2565 finish(1); 2566 } 2567 if (!popup_and_get_string 2568 ("Scratch directory", 2569 "Please enter your scratch directory.", 2570 bkpinfo->scratchdir, (4*MAX_STR_LEN)-1)) { 2571 log_to_screen("User has chosen not to backup the PC"); 2572 finish(1); 2573 } 2574 // Interactive mode: 2575 #ifdef __IA64__ 2576 bkpinfo->make_cd_use_lilo = TRUE; 2577 #else 2578 bkpinfo->make_cd_use_lilo = FALSE; 2579 #endif 2580 bkpinfo->backup_data = TRUE; 2581 bkpinfo->verify_data = 2582 ask_me_yes_or_no 2583 ("Will you want to verify your backups after Mondo has created them?"); 2584 2585 #ifndef __FreeBSD__ 2586 if (!ask_me_yes_or_no 2587 ("Are you confident that your kernel is a sane, sensible, standard Linux kernel? Say 'no' if you are using a Gentoo <1.4 or Debian <3.0, please.")) 2588 #endif 2589 { 2590 strcpy(bkpinfo->kernel_path, "FAILSAFE"); 2591 } 2592 2593 if (!ask_me_yes_or_no 2594 ("Are you sure you want to proceed? Hit 'no' to abort.")) { 2595 log_to_screen("User has chosen not to backup the PC"); 2596 finish(1); 2597 } 2598 } else { 2599 bkpinfo->restore_data = TRUE; // probably... 2600 } 2601 2602 if (bkpinfo->backup_media_type == iso 2603 || bkpinfo->backup_media_type == netfs) { 2604 g_ISO_restore_mode = TRUE; 2605 } 2606 #ifdef __FreeSD__ 2607 // skip 2608 #else 2609 if (bkpinfo->backup_media_type == netfs) { 2610 log_msg(3, "I think the Remote mount is mounted at %s", 2611 bkpinfo->isodir); 2612 } 2613 log_it("isodir = %s", bkpinfo->isodir); 2614 log_it("netfs_mount = '%s'", bkpinfo->netfs_mount); 2615 log_it("netfs_proto = '%s'", bkpinfo->netfs_proto); 2616 if (bkpinfo->netfs_user) { 2617 log_it("netfs_user = '%s'", bkpinfo->netfs_user); 2618 } 2619 #endif 2620 2621 log_it("media device = %s", bkpinfo->media_device); 2622 log_it("media size = %ld", bkpinfo->media_size[1]); 2623 log_it("media type = %s", 2624 bkptype_to_string(bkpinfo->backup_media_type)); 2625 log_it("prefix = %s", bkpinfo->prefix); 2626 log_it("compression = %ld", bkpinfo->compression_level); 2627 2628 /* Handle devices passed in bkpinfo and print result */ 2629 mr_make_devlist_from_pathlist(bkpinfo->exclude_paths, 'E'); 2630 mr_make_devlist_from_pathlist(bkpinfo->include_paths, 'I'); 2631 2632 log_it("scratchdir = '%s'", bkpinfo->scratchdir); 2633 log_it("tmpdir = '%s'", bkpinfo->tmpdir); 2634 log_it("image_devs = '%s'", bkpinfo->image_devs); 2635 log_it("boot_device = '%s' (loader=%c)", bkpinfo->boot_device, 2636 bkpinfo->boot_loader); 2637 if (bkpinfo->media_size[0] < 0) { 2638 if (archiving_to_media) { 2639 fatal_error("Media size is less than zero."); 2640 } else { 2641 log_msg(2, "Warning - media size is less than zero."); 2642 bkpinfo->media_size[0] = 0; 2643 } 2644 } 2645 paranoid_free(sz_size); 2646 paranoid_free(tmp1); 2647 paranoid_free(command); 2648 paranoid_free(comment); 2649 paranoid_free(prompt); 2650 return (0); 2651 } 2652 2653 2654 2655 2656 /** 2657 * @addtogroup utilityGroup 2658 * @{ 2659 */ 2660 /** 2661 * Get a space-separated list of NETFS devices and mounts. 2662 * @return The list created. 2663 * @note The return value points to static data that will be overwritten with each call. 2664 */ 2665 char *list_of_NETFS_devices_and_mounts(void) 2666 { 2667 char *exclude_these_devices = NULL; 2668 char *exclude_these_directories = NULL; 2669 static char result_sz[1024]; 2670 2671 mr_asprintf(&exclude_these_directories,"%s",list_of_NETFS_mounts_only()); 2672 mr_asprintf(&exclude_these_devices,"%s", 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;}'")); 2673 snprintf(result_sz, 1023, "%s %s", exclude_these_directories, exclude_these_devices); 2674 mr_free(exclude_these_devices); 2675 mr_free(exclude_these_directories); 2676 return (result_sz); 2677 } 2678 2679 2680 2681 2682 /** 2683 * Get a space-separated list of NETFS mounts. 2684 * @return The list created. 2685 * @note The return value points to static data that will be overwritten with each call. 2686 * @bug Even though we only want the mounts, the devices are still checked. 2687 */ 2688 char *list_of_NETFS_mounts_only(void) 2689 { 2690 char *exclude_these_directories = NULL; 2691 static char result_sz[512]; 2692 2693 mr_asprintf(&exclude_these_directories,"%s", 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;}'")); 2694 snprintf(result_sz, 511, "%s", exclude_these_directories); 2695 mr_free(exclude_these_directories); 2696 return (result_sz); 2697 } 2698 2699 /* @} - end of utilityGroup */ 2700 2701 2702 2703 2704 2705 /** 2706 * Create a randomly-named FIFO. The format is @p stub "." [random] [random] where 2707 * [random] is a random number between 1 and 32767. 2708 * @param store_name_here Where to store the new filename. 2709 * @param stub A random number will be appended to this to make the FIFO's name. 2710 * @ingroup deviceGroup 2711 */ 2712 void make_fifo(char *store_name_here, char *stub) 2713 { 2714 char *tmp; 2715 2716 malloc_string(tmp); 2717 assert_string_is_neither_NULL_nor_zerolength(stub); 2718 2719 sprintf(store_name_here, "%s%d%d", stub, (int) (random() % 32768), 2720 (int) (random() % 32768)); 2721 make_hole_for_file(store_name_here); 2722 mkfifo(store_name_here, S_IRWXU | S_IRWXG); 2723 sprintf(tmp, "chmod 770 %s", store_name_here); 2724 paranoid_system(tmp); 2725 paranoid_free(tmp); 2726 } 2727 2728 2729 2730 2731 2732 2733 /** 2734 * Set the tmpdir and scratchdir to reside on the partition with the most free space. 2735 * Automatically excludes DOS, NTFS, SMB, and NFS filesystems. 2736 * @param bkpinfo The backup information structure. @c bkpinfo->tmpdir and @c bkpinfo->scratchdir will be set. 2737 * @ingroup utilityGroup 2738 */ 2739 void sensibly_set_tmpdir_and_scratchdir() 2740 { 2741 char *tmp = NULL; 2742 char *command = NULL; 2743 char *sz = NULL; 2744 2745 assert(bkpinfo != NULL); 2746 2747 #ifdef __FreeBSD__ 2748 mr_asprintf(&tmp, "%s", 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;}'")); 2749 #else 2750 mr_asprintf(&tmp, "%s", 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;}'")); 2751 #endif 2752 2753 if (tmp[0] != '/') { 2754 mr_asprintf(&sz, "%s", tmp); 2755 paranoid_free(tmp); 2756 mr_asprintf(&tmp, "/%s", sz); 2757 mr_free(sz); 2758 } 2759 if (!tmp[0]) { 2760 fatal_error("I couldn't figure out the tempdir!"); 2761 } 2762 setup_tmpdir(tmp); 2763 log_it("bkpinfo->tmpdir is being set to %s", bkpinfo->tmpdir); 2764 2765 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%d", tmp, 2766 (int) (random() % 32768)); 2767 log_it("bkpinfo->scratchdir is being set to %s", bkpinfo->scratchdir); 2768 2769 mr_asprintf(&command, "rm -Rf %s/tmp.mondo.* %s/mondo.scratch.*", tmp, tmp); 2770 paranoid_free(tmp); 2771 2772 paranoid_system(command); 2773 mr_free(command); 2774 } 2775 2776 2777 2778 2779 2780 2781 /** 2782 * @addtogroup deviceGroup 2783 * @{ 2784 */ 2785 /** 2786 * If we can read @p dev, set @p output to it. 2787 * If @p dev cannot be read, set @p output to "". 2788 * @param dev The device to check for. 2789 * @param output Set to @p dev if @p dev exists, "" otherwise. 2790 * @return TRUE if @p dev exists, FALSE if it doesn't. 2791 */ 2792 bool set_dev_to_this_if_rx_OK(char *output, char *dev) 2793 { 2794 char *command; 2795 2796 malloc_string(command); 2797 if (!dev || dev[0] == '\0') { 2798 output[0] = '\0'; 2799 return (FALSE); 2800 } 2801 // assert_string_is_neither_NULL_nor_zerolength(dev); 2802 log_msg(10, "Injecting %s", dev); 2803 inject_device(dev); 2804 if (!does_file_exist(dev)) { 2805 log_msg(10, "%s doesn't exist. Returning FALSE.", dev); 2806 return (FALSE); 2807 } 2808 sprintf(command, "dd bs=%ld count=1 if=%s of=/dev/null &> /dev/null", 2809 512L, dev); 2810 if (!run_program_and_log_output(command, FALSE) 2811 && !run_program_and_log_output(command, FALSE)) { 2812 strcpy(output, dev); 2813 log_msg(4, "Found it - %s", dev); 2814 return (TRUE); 2815 } else { 2816 output[0] = '\0'; 2817 log_msg(4, "It's not %s", dev); 2818 return (FALSE); 2819 } 2820 } 2821 2822 2823 2824 2825 2826 /** 2827 * Find out what number CD is in the drive. 2828 * @param bkpinfo The backup information structure. The @c bkpinfo->media_device field is the only one used. 2829 * @return The current CD number, or -1 if it could not be found. 2830 * @note If the CD is not mounted, it will be mounted 2831 * (and remain mounted after this function returns). 2832 */ 2833 int what_number_cd_is_this() 2834 { 2835 int cd_number = -1; 2836 char *mountdev = NULL; 2837 char *tmp = NULL; 2838 2839 assert(bkpinfo != NULL); 2840 // log_it("Asking what_number_cd_is_this"); 2841 if (g_ISO_restore_mode) { 2842 mr_asprintf(&tmp, "mount | grep iso9660 | awk '{print $3;}'"); 2843 2844 mr_asprintf(&mountdev, "%s%s", call_program_and_get_last_line_of_output(tmp), "/archives/THIS-CD-NUMBER"); 2845 cd_number = atoi(last_line_of_file(mountdev)); 2846 paranoid_free(mountdev); 2847 paranoid_free(tmp); 2848 2849 return (cd_number); 2850 } 2851 2852 mr_asprintf(&mountdev, "%s", bkpinfo->media_device); 2853 if (!mountdev[0]) { 2854 log_it 2855 ("(what_number_cd_is_this) Warning - media_device unknown. Finding out..."); 2856 find_cdrom_device(bkpinfo->media_device, FALSE); 2857 } 2858 if (!is_this_device_mounted(MNT_CDROM)) { 2859 if (bkpinfo->backup_media_type == usb) { 2860 mount_USB_here(mountdev, MNT_CDROM); 2861 } else { 2862 mount_CDROM_here(mountdev, MNT_CDROM); 2863 } 2864 } 2865 paranoid_free(mountdev); 2866 2867 cd_number = atoi(last_line_of_file(MNT_CDROM "/archives/THIS-CD-NUMBER")); 2868 return (cd_number); 2869 } 2870 2871 2872 2873 2874 2875 2876 2877 /** 2878 * Find out what device is mounted as root (/). 2879 * @return Root device. 2880 * @note The returned string points to static storage and will be overwritten with every call. 2881 * @bug A bit of a misnomer; it's actually finding out the root device. 2882 * The mountpoint (where it's mounted) will obviously be '/'. 2883 */ 2884 char *where_is_root_mounted() 2885 { 2886 /*@ buffers **************** */ 2887 static char tmp[MAX_STR_LEN]; 2888 2889 2890 #ifdef __FreeBSD__ 2891 strcpy(tmp, call_program_and_get_last_line_of_output 2892 ("mount | grep \" on / \" | cut -d' ' -f1")); 2893 #else 2894 strcpy(tmp, call_program_and_get_last_line_of_output 2895 ("mount | grep \" on / \" | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]//")); 2896 if (strstr(tmp, "/dev/cciss/")) { 2897 strcpy(tmp, call_program_and_get_last_line_of_output 2898 ("mount | grep \" on / \" | cut -d' ' -f1 | cut -dp -f1")); 2899 } 2900 if (strstr(tmp, "/dev/md")) { 2901 strcpy(tmp, 2902 call_program_and_get_last_line_of_output 2903 ("mount | grep \" on / \" | cut -d' ' -f1")); 2904 } 2905 #endif 2906 2907 return (tmp); 2908 } 2909 2910 2911 /** 2912 * Find out which boot loader is in use. 2913 * @param which_device Device to look for the boot loader on. 2914 * @return 'L' for LILO, 'E'for ELILO, 'G' for GRUB, 'B' or 'D' for FreeBSD boot loaders, or 'U' for Unknown. 2915 * @note Under Linux, all drives are examined, not just @p which_device. 2916 */ 2917 #ifdef __FreeBSD__ 2918 char which_boot_loader(char *which_device) 2919 { 2920 int count_lilos = 0; 2921 int count_grubs = 0; 2922 int count_boot0s = 0; 2923 int count_dangerouslydedicated = 0; 2924 2925 log_it("looking at drive %s's MBR", which_device); 2926 if (does_string_exist_in_boot_block(which_device, "GRUB")) { 2927 count_grubs++; 2928 } 2929 if (does_string_exist_in_boot_block(which_device, "LILO")) { 2930 count_lilos++; 2931 } 2932 if (does_string_exist_in_boot_block(which_device, "Drive")) { 2933 count_boot0s++; 2934 } 2935 if (does_string_exist_in_first_N_blocks 2936 (which_device, "FreeBSD/i386", 17)) { 2937 count_dangerouslydedicated++; 2938 } 2939 log_it("%d grubs and %d lilos and %d elilos and %d boot0s and %d DD\n", 2940 count_grubs, count_lilos, count_elilos, count_boot0s, 2941 count_dangerouslydedicated); 2942 2943 if (count_grubs && !count_lilos) { 2944 return ('G'); 2945 } else if (count_lilos && !count_grubs) { 2946 return ('L'); 2947 } else if (count_grubs == 1 && count_lilos == 1) { 2948 log_it("I'll bet you used to use LILO but switched to GRUB..."); 2949 return ('G'); 2950 } else if (count_boot0s == 1) { 2951 return ('B'); 2952 } else if (count_dangerouslydedicated) { 2953 return ('D'); 2954 } else { 2955 log_it("Unknown boot loader"); 2956 return ('U'); 2957 } 2958 } 2959 2960 #else 2961 2962 char which_boot_loader(char *which_device) 2963 { 2964 /*@ buffer ***************************************************** */ 2965 char *list_drives_cmd = NULL; 2966 char *current_drive; 2967 2968 /*@ pointers *************************************************** */ 2969 FILE *pdrives; 2970 2971 /*@ int ******************************************************** */ 2972 int count_lilos = 0; 2973 int count_grubs = 0; 2974 2975 /*@ end vars *************************************************** */ 2976 2977 malloc_string(current_drive); 2978 2979 #ifdef __IA64__ 2980 /* No choice for it */ 2981 return ('E'); 2982 #endif 2983 assert(which_device != NULL); 2984 2985 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep \"/dev/.*:\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/; echo %s", where_is_root_mounted()); 2986 log_it("list_drives_cmd = %s", list_drives_cmd); 2987 2988 if (!(pdrives = popen(list_drives_cmd, "r"))) { 2989 log_OS_error("Unable to open list of drives"); 2990 mr_free(list_drives_cmd); 2991 paranoid_free(current_drive); 2992 return ('\0'); 2993 } 2994 mr_free(list_drives_cmd); 2995 2996 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives); 2997 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) { 2998 strip_spaces(current_drive); 2999 log_it("looking at drive %s's MBR", current_drive); 3000 if (does_string_exist_in_boot_block(current_drive, "GRUB")) { 3001 count_grubs++; 3002 strcpy(which_device, current_drive); 3003 break; 3004 } 3005 if (does_string_exist_in_boot_block(current_drive, "LILO")) { 3006 count_lilos++; 3007 strcpy(which_device, current_drive); 3008 break; 3009 } 3010 } 3011 if (pclose(pdrives)) { 3012 log_OS_error("Cannot pclose pdrives"); 3013 } 3014 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos); 3015 if (count_grubs && !count_lilos) { 3016 paranoid_free(current_drive); 3017 return ('G'); 3018 } else if (count_lilos && !count_grubs) { 3019 paranoid_free(current_drive); 3020 return ('L'); 3021 } else if (count_grubs == 1 && count_lilos == 1) { 3022 log_it("I'll bet you used to use LILO but switched to GRUB..."); 3023 paranoid_free(current_drive); 3024 return ('G'); 3025 } else { 3026 // We need to look on each partition then 3027 mr_asprintf(&list_drives_cmd, "parted2fdisk -l 2>/dev/null | grep -E \"^/dev/\" | tr -s ':' ' ' | tr -s ' ' '\n' | grep /dev/"); 3028 log_it("list_drives_cmd = %s", list_drives_cmd); 3029 3030 if (!(pdrives = popen(list_drives_cmd, "r"))) { 3031 log_OS_error("Unable to open list of drives"); 3032 mr_free(list_drives_cmd); 3033 paranoid_free(current_drive); 3034 return ('\0'); 3035 } 3036 mr_free(list_drives_cmd); 3037 3038 for ((void)fgets(current_drive, MAX_STR_LEN, pdrives); !feof(pdrives); 3039 (void)fgets(current_drive, MAX_STR_LEN, pdrives)) { 3040 strip_spaces(current_drive); 3041 log_it("looking at partition %s's BR", current_drive); 3042 if (does_string_exist_in_boot_block(current_drive, "GRUB")) { 3043 count_grubs++; 3044 strcpy(which_device, current_drive); 3045 break; 3046 } 3047 if (does_string_exist_in_boot_block(current_drive, "LILO")) { 3048 count_lilos++; 3049 strcpy(which_device, current_drive); 3050 break; 3051 } 3052 } 3053 if (pclose(pdrives)) { 3054 log_OS_error("Cannot pclose pdrives"); 3055 } 3056 log_it("%d grubs and %d lilos\n", count_grubs, count_lilos); 3057 paranoid_free(current_drive); 3058 if (count_grubs && !count_lilos) { 3059 return ('G'); 3060 } else if (count_lilos && !count_grubs) { 3061 return ('L'); 3062 } else if (count_grubs == 1 && count_lilos == 1) { 3063 log_it("I'll bet you used to use LILO but switched to GRUB..."); 3064 return ('G'); 3065 } else { 3066 log_it("Unknown boot loader"); 3067 return ('U'); 3068 } 3069 } 3070 } 3071 #endif 3072 3073 3074 3075 3076 /** 3077 * Write zeroes over the first 16K of @p device. 3078 * @param device The device to zero. 3079 * @return 0 for success, 1 for failure. 3080 */ 3081 int zero_out_a_device(char *device) 3082 { 3083 FILE *fout; 3084 int i; 3085 3086 assert_string_is_neither_NULL_nor_zerolength(device); 3087 3088 log_it("Zeroing drive %s", device); 3089 if (!(fout = fopen(device, "w"))) { 3090 log_OS_error("Unable to open/write to device"); 3091 return (1); 3092 } 3093 for (i = 0; i < 16384; i++) { 3094 fputc('\0', fout); 3095 } 3096 paranoid_fclose(fout); 3097 log_it("Device successfully zeroed."); 3098 return (0); 3099 } 3100 3101 /** 3102 * Return the device pointed to by @p incoming. 3103 * @param incoming The device to resolve symlinks for. 3104 * @return The path to the real device file. 3105 * @note The returned string points to static storage that will be overwritten with each call. 3106 * @bug Won't work with file v4.0; needs to be written in C. 3107 */ 3108 char *resolve_softlinks_to_get_to_actual_device_file(char *incoming) 3109 { 3110 static char output[MAX_STR_LEN]; 3111 char *command; 3112 char *curr_fname; 3113 char *scratch = NULL; 3114 char *tmp = NULL; 3115 char *p; 3116 3117 struct stat statbuf; 3118 command = malloc(1000); 3119 malloc_string(curr_fname); 3120 if (!does_file_exist(incoming)) { 3121 log_it 3122 ("resolve_softlinks_to_get_to_actual_device_file --- device not found"); 3123 strcpy(output, incoming); 3124 } else { 3125 strcpy(curr_fname, incoming); 3126 lstat(curr_fname, &statbuf); 3127 while (S_ISLNK(statbuf.st_mode)) { 3128 log_msg(1, "curr_fname = %s", curr_fname); 3129 sprintf(command, "file %s", curr_fname); 3130 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command)); 3131 for (p = tmp + strlen(tmp); p != tmp && *p != '`' && *p != ' '; 3132 p--); 3133 p++; 3134 mr_asprintf(&scratch, "%s", p); 3135 for (p = scratch; *p != '\0' && *p != '\''; p++); 3136 *p = '\0'; 3137 log_msg(0, "curr_fname %s --> '%s' --> %s", curr_fname, tmp, scratch); 3138 mr_free(tmp); 3139 3140 if (scratch[0] == '/') { 3141 strcpy(curr_fname, scratch); // copy whole thing because it's an absolute softlink 3142 } else { // copy over the basename cos it's a relative softlink 3143 p = curr_fname + strlen(curr_fname); 3144 while (p != curr_fname && *p != '/') { 3145 p--; 3146 } 3147 if (*p == '/') { 3148 p++; 3149 } 3150 strcpy(p, scratch); 3151 } 3152 mr_free(scratch); 3153 lstat(curr_fname, &statbuf); 3154 } 3155 strcpy(output, curr_fname); 3156 log_it("resolved %s to %s", incoming, output); 3157 } 3158 paranoid_free(command); 3159 paranoid_free(curr_fname); 3160 return (output); 3161 } 3162 3193 3163 /* @} - end of deviceGroup */ 3164 3165 /** 3166 * Return the type of partition format (GPT or MBR) 3167 */ 3168 char *which_partition_format(const char *drive) 3169 { 3170 static char output[4]; 3171 char *tmp = NULL; 3172 char *command; 3173 char *fdisk; 3174 #ifdef __IA64__ 3175 struct stat buf; 3176 #endif 3177 malloc_string(command); 3178 malloc_string(fdisk); 3179 sprintf(fdisk, "/sbin/parted2fdisk"); 3180 sprintf(command, "%s -l %s | grep 'EFI GPT'", fdisk, drive); 3181 mr_asprintf(&tmp, "%s", call_program_and_get_last_line_of_output(command)); 3182 if (strstr(tmp, "GPT") == NULL) { 3183 strcpy(output, "MBR"); 3184 } else { 3185 strcpy(output, "GPT"); 3186 } 3187 mr_free(tmp); 3188 3189 log_msg(0, "Found %s partition table format type", output); 3190 paranoid_free(command); 3191 paranoid_free(fdisk); 3192 return (output); 3193 } 3194 /* @} - end of deviceGroup */
Note:
See TracChangeset
for help on using the changeset viewer.