VirtualBox

Changeset 67867 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Jul 8, 2017 6:22:12 PM (7 years ago)
Author:
vboxsync
Message:

isomaker: Adding --push-iso / --pop options for adding select files and/or directories from another ISO. Implemented adding directories from VFSs (real directories are not yet implemented).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp

    r67864 r67867  
    3838#include <iprt/ctype.h>
    3939#include <iprt/file.h>
     40#include <iprt/fsvfs.h>
    4041#include <iprt/err.h>
    4142#include <iprt/getopt.h>
     
    5758#define RTFSISOMAKERCMD_MAX_NAMES                       8
    5859
     60/** Maximum directory recursions when adding a directory tree. */
     61#define RTFSISOMAKERCMD_MAX_DIR_RECURSIONS              32
     62
    5963/** @name Name specifiers
    6064 * @{ */
     
    98102    RTFSISOMAKERCMD_OPT_NO_JOLIET,
    99103    RTFSISOMAKERCMD_OPT_IMPORT_ISO,
     104    RTFSISOMAKERCMD_OPT_PUSH_ISO,
     105    RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_JOLIET,
     106    RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_ROCK,
     107    RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_ROCK_NO_JOLIET,
     108    RTFSISOMAKERCMD_OPT_POP,
    100109
    101110    RTFSISOMAKERCMD_OPT_ELTORITO_NEW_ENTRY,
     
    318327    uint32_t            cbRandomOrderVerifciationBlock;
    319328
     329    /** The current source VFS, NIL_RTVFS if regular file system is used. */
     330    RTVFS               hSrcVfs;
     331    /** The specifier for hSrcVfs (error messages). */
     332    const char         *pszSrcVfs;
     333    /** The option for hSrcVfs. */
     334    const char         *pszSrcVfsOption;
     335
    320336    /** @name Processing of inputs
    321337     * @{ */
     
    398414
    399415
    400 
    401416/*********************************************************************************************************************************
    402417*   Global Variables                                                                                                             *
     
    423438    { "--no-joliet",                    RTFSISOMAKERCMD_OPT_NO_JOLIET,                      RTGETOPT_REQ_NOTHING },
    424439    { "--import-iso",                   RTFSISOMAKERCMD_OPT_IMPORT_ISO,                     RTGETOPT_REQ_STRING  },
     440    { "--push-iso",                     RTFSISOMAKERCMD_OPT_PUSH_ISO,                       RTGETOPT_REQ_STRING  },
     441    { "--push-iso-no-joliet",           RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_JOLIET,             RTGETOPT_REQ_STRING  },
     442    { "--push-iso-no-rock",             RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_ROCK,               RTGETOPT_REQ_STRING  },
     443    { "--push-iso-no-rock-no-joliet",   RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_ROCK_NO_JOLIET,     RTGETOPT_REQ_STRING  },
     444    { "--pop",                          RTFSISOMAKERCMD_OPT_POP,                            RTGETOPT_REQ_NOTHING },
     445
    425446
    426447    { "--eltorito-new-entry",           RTFSISOMAKERCMD_OPT_ELTORITO_NEW_ENTRY,             RTGETOPT_REQ_NOTHING },
     
    726747        RTFsIsoMakerRelease(pOpts->hIsoMaker);
    727748        pOpts->hIsoMaker = NIL_RTFSISOMAKER;
     749    }
     750
     751    if (pOpts->hSrcVfs != NIL_RTVFS)
     752    {
     753        RTVfsRelease(pOpts->hSrcVfs);
     754        pOpts->hSrcVfs = NIL_RTVFS;
    728755    }
    729756
     
    14991526
    15001527/**
     1528 * Enteres an object into the namespaces given the parent and single name.
     1529 *
     1530 * This is used by the directory tree recursion code.
     1531 *
     1532 * @returns IPRT status code.
     1533 * @param   pOpts           The ISO maker command instance.
     1534 * @param   idxObj          The configuration index of the object to be named.
     1535 * @param   idxParentObj    The configuration index of the parent directory.
     1536 * @param   pszName         The name of the object.
     1537 * @param   pParsed         The parsed names - only fNameSpecifies used, no
     1538 *                          names.
     1539 * @param   pszSrc          The full source path for error reporting.
     1540 */
     1541static int rtFsIsoMakerCmdSetNameAndParent(PRTFSISOMAKERCMDOPTS pOpts, uint32_t idxObj, uint32_t idxParentObj,
     1542                                           const char *pszName, PCRTFSISOMKCMDPARSEDNAMES pParsed, const char *pszSrc)
     1543{
     1544    int rc = VINF_SUCCESS;
     1545    for (uint32_t i = 0; i < pParsed->cNames; i++)
     1546        if (pParsed->aNames[i].cchPath > 0)
     1547        {
     1548            if (pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)
     1549            {
     1550                rc = RTFsIsoMakerObjSetNameAndParent(pOpts->hIsoMaker, idxObj, idxParentObj,
     1551                                                     pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,
     1552                                                     pszName);
     1553                if (RT_FAILURE(rc))
     1554                {
     1555                    rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error setting parent & name '%s' on '%s': %Rrc",
     1556                                                pszName, pszSrc, rc);
     1557                    break;
     1558                }
     1559            }
     1560            if (pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MINOR_MASK)
     1561            {
     1562                /** @todo add APIs for this.   */
     1563            }
     1564        }
     1565    return rc;
     1566}
     1567
     1568
     1569/**
    15011570 * Adds a file.
    15021571 *
     
    15111580                                  uint32_t *pidxObj)
    15121581{
    1513     uint32_t idxObj;
    1514     int rc = RTFsIsoMakerAddUnnamedFileWithSrcPath(pOpts->hIsoMaker, pszSrc, &idxObj);
     1582    int      rc;
     1583    uint32_t idxObj = UINT32_MAX;
     1584    if (   pOpts->hSrcVfs == NIL_RTVFS
     1585        || RTVfsChainIsSpec(pszSrc))
     1586    {
     1587        rc = RTFsIsoMakerAddUnnamedFileWithSrcPath(pOpts->hIsoMaker, pszSrc, &idxObj);
     1588        if (RT_FAILURE(rc))
     1589            return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s': %Rrc", pszSrc, rc);
     1590    }
     1591    else
     1592    {
     1593        RTVFSFILE hVfsFileSrc;
     1594        rc = RTVfsFileOpen(pOpts->hSrcVfs, pszSrc, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &hVfsFileSrc);
     1595        if (RT_FAILURE(rc))
     1596            return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error opening '%s' (inside '%s'): %Rrc", pszSrc, pOpts->pszSrcVfs, rc);
     1597
     1598        rc = RTFsIsoMakerAddUnnamedFileWithVfsFile(pOpts->hIsoMaker, hVfsFileSrc, &idxObj);
     1599        RTVfsFileRelease(hVfsFileSrc);
     1600        if (RT_FAILURE(rc))
     1601            return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s' (VFS): %Rrc", pszSrc, rc);
     1602    }
     1603
     1604    pOpts->cItemsAdded++;
     1605    if (pidxObj)
     1606        *pidxObj = idxObj;
     1607
     1608    return rtFsIsoMakerCmdSetObjPaths(pOpts, idxObj, pParsed, pszSrc);
     1609}
     1610
     1611static bool rtFsIsoMakerCmdIsFilteredOut(PRTFSISOMAKERCMDOPTS pOpts, const char *pszDir, const char *pszName, bool fIsDir)
     1612{
     1613    RT_NOREF(pOpts, pszDir, pszName, fIsDir);
     1614    return false;
     1615}
     1616
     1617/**
     1618 * Adds a directory, from a VFS chain or real file system.
     1619 *
     1620 * @returns IPRT status code.
     1621 * @param   pOpts               The ISO maker command instance.
     1622 * @param   pszSrc              The path to the source directory.
     1623 * @param   pParsed             The parsed names.
     1624 */
     1625static int rtFsIsoMakerCmdAddDir(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMKCMDPARSEDNAMES pParsed)
     1626{
     1627    RT_NOREF(pParsed);
     1628    return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding directory '%s' failed: not implemented", pszSrc);
     1629}
     1630
     1631
     1632/**
     1633 * Worker for rtFsIsoMakerCmdAddVfsDir that does the recursion.
     1634 *
     1635 * @returns IPRT status code.
     1636 * @param   pOpts               The ISO maker command instance.
     1637 * @param   hVfsDir             The directory to process.
     1638 * @param   idxDirObj           The configuration index of the directory.
     1639 * @param   pszSrc              Pointer to the source path buffer.  RTPATH_MAX
     1640 *                              in size.  Okay to modify beyond @a cchSrc.
     1641 * @param   cchSrc              Length of the path corresponding to @a hVfsDir.
     1642 * @param   fNamespaces         Which ISO maker namespaces to add the names to.
     1643 * @param   cDepth              Number of recursions.  Used to deal with loopy
     1644 *                              directories.
     1645 */
     1646static int rtFsIsoMakerCmdAddVfsDirRecursive(PRTFSISOMAKERCMDOPTS pOpts, RTVFSDIR hVfsDir, uint32_t idxDirObj,
     1647                                             char *pszSrc, size_t cchSrc, uint32_t fNamespaces, uint8_t cDepth)
     1648{
     1649    /*
     1650     * Check that we're not in too deep.
     1651     */
     1652    if (cDepth >= RTFSISOMAKERCMD_MAX_DIR_RECURSIONS)
     1653        return rtFsIsoMakerCmdErrorRc(pOpts, VERR_ISOMK_IMPORT_TOO_DEEP_DIR_TREE,
     1654                                      "Recursive (VFS) dir add too deep (depth=%u): %.*s", cDepth, cchSrc, pszSrc);
     1655    /*
     1656     * Enumerate the directory.
     1657     */
     1658    int           rc;
     1659    size_t        cbDirEntryAlloced = sizeof(RTDIRENTRYEX);
     1660    PRTDIRENTRYEX pDirEntry         = (PRTDIRENTRYEX)RTMemTmpAlloc(cbDirEntryAlloced);
     1661    if (pDirEntry)
     1662    {
     1663        for (;;)
     1664        {
     1665            /*
     1666             * Read the next entry.
     1667             */
     1668            size_t cbDirEntry = cbDirEntryAlloced;
     1669            rc = RTVfsDirReadEx(hVfsDir, pDirEntry, &cbDirEntry, RTFSOBJATTRADD_UNIX);
     1670            if (RT_FAILURE(rc))
     1671            {
     1672                if (rc == VERR_NO_MORE_FILES)
     1673                    rc = VINF_SUCCESS;
     1674                else if (rc == VERR_BUFFER_OVERFLOW)
     1675                {
     1676                    RTMemTmpFree(pDirEntry);
     1677                    cbDirEntryAlloced = RT_ALIGN_Z(RT_MIN(cbDirEntry, cbDirEntryAlloced) + 64, 64);
     1678                    pDirEntry  = (PRTDIRENTRYEX)RTMemTmpAlloc(cbDirEntryAlloced);
     1679                    if (pDirEntry)
     1680                        continue;
     1681                    rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_NO_TMP_MEMORY, "Out of memory (direntry buffer)");
     1682                }
     1683                else
     1684                    rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTVfsDirReadEx failed on %.*s: %Rrc", cchSrc, pszSrc, rc);
     1685                break;
     1686            }
     1687
     1688            /* Ignore '.' and '..' entries. */
     1689            if (RTDirEntryExIsStdDotLink(pDirEntry))
     1690                continue;
     1691
     1692            /*
     1693             * Process the entry.
     1694             */
     1695
     1696            /* Update the name. */
     1697            if (cchSrc + 1 + pDirEntry->cbName < RTPATH_MAX)
     1698            {
     1699                pszSrc[cchSrc] = '/'; /* VFS only groks unix slashes */
     1700                memcpy(&pszSrc[cchSrc + 1], pDirEntry->szName, pDirEntry->cbName);
     1701                pszSrc[cchSrc + 1 + pDirEntry->cbName] = '\0';
     1702            }
     1703            else
     1704                rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_FILENAME_TOO_LONG, "Filename is too long (depth %u): '%.*s/%s'",
     1705                                            cDepth, cchSrc, pszSrc, pDirEntry->szName);
     1706
     1707            /* Okay? Check name filtering. */
     1708            if (   RT_SUCCESS(rc)
     1709                && !rtFsIsoMakerCmdIsFilteredOut(pOpts, pszSrc, pDirEntry->szName, RTFS_IS_DIRECTORY(pDirEntry->Info.Attr.fMode)))
     1710            {
     1711                /* Do type specific adding. */
     1712                uint32_t idxObj = UINT32_MAX;
     1713                if (RTFS_IS_FILE(pDirEntry->Info.Attr.fMode))
     1714                {
     1715                    /*
     1716                     * Files are added with VFS file sources.
     1717                     * The ASSUMPTION is that we're working with a virtual file system
     1718                     * here and won't be wasting native file descriptors.
     1719                     */
     1720                    RTVFSFILE hVfsFileSrc;
     1721                    rc = RTVfsDirOpenFile(hVfsDir, pDirEntry->szName,
     1722                                          RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &hVfsFileSrc);
     1723                    if (RT_SUCCESS(rc))
     1724                    {
     1725                        rc = RTFsIsoMakerAddUnnamedFileWithVfsFile(pOpts->hIsoMaker, hVfsFileSrc, &idxObj);
     1726                        RTVfsFileRelease(hVfsFileSrc);
     1727                        if (RT_SUCCESS(rc))
     1728                        {
     1729                            pOpts->cItemsAdded++;
     1730                            rc = RTFsIsoMakerObjSetNameAndParent(pOpts->hIsoMaker, idxObj, idxDirObj, fNamespaces,
     1731                                                                 pDirEntry->szName);
     1732                            if (RT_FAILURE(rc))
     1733                                rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error setting parent & name on file '%s' to '%s': %Rrc",
     1734                                                            pszSrc, pDirEntry->szName, rc);
     1735                        }
     1736                        else
     1737                            rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding file '%s' (VFS recursive): %Rrc", pszSrc, rc);
     1738                    }
     1739                    else
     1740                        rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error opening file '%s' (VFS recursive): %Rrc", pszSrc, rc);
     1741                }
     1742                else if (RTFS_IS_DIRECTORY(pDirEntry->Info.Attr.fMode))
     1743                {
     1744                    /*
     1745                     * Open and add the sub-directory.
     1746                     */
     1747                    RTVFSDIR hVfsSubDirSrc;
     1748                    rc = RTVfsDirOpenDir(hVfsDir, pDirEntry->szName, 0 /*fFlags*/, &hVfsSubDirSrc);
     1749                    if (RT_SUCCESS(rc))
     1750                    {
     1751                        rc = RTFsIsoMakerAddUnnamedDir(pOpts->hIsoMaker, &pDirEntry->Info, &idxObj);
     1752                        if (RT_SUCCESS(rc))
     1753                        {
     1754                            pOpts->cItemsAdded++;
     1755                            rc = RTFsIsoMakerObjSetNameAndParent(pOpts->hIsoMaker, idxObj, idxDirObj, fNamespaces,
     1756                                                                 pDirEntry->szName);
     1757                            if (RT_SUCCESS(rc))
     1758                                /* Recurse into the sub-directory. */
     1759                                rc = rtFsIsoMakerCmdAddVfsDirRecursive(pOpts, hVfsSubDirSrc, idxObj, pszSrc,
     1760                                                                       cchSrc + 1 + pDirEntry->cbName, fNamespaces, cDepth + 1);
     1761                            else
     1762                                rc = rtFsIsoMakerCmdErrorRc(pOpts, rc,
     1763                                                            "Error setting parent & name on directory '%s' to '%s': %Rrc",
     1764                                                            pszSrc, pDirEntry->szName, rc);
     1765                        }
     1766                        else
     1767                            rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding directory '%s' (VFS recursive): %Rrc", pszSrc, rc);
     1768                        RTVfsDirRelease(hVfsSubDirSrc);
     1769                    }
     1770                    else
     1771                        rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error opening directory '%s' (VFS recursive): %Rrc", pszSrc, rc);
     1772                }
     1773                else if (RTFS_IS_SYMLINK(pDirEntry->Info.Attr.fMode))
     1774                {
     1775                    /*
     1776                     * TODO: ISO FS symlink support.
     1777                     */
     1778                    rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED,
     1779                                                "Adding symlink '%s' failed: not yet implemented", pszSrc);
     1780                }
     1781                else
     1782                    rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED,
     1783                                                "Adding special file '%s' failed: not implemented", pszSrc);
     1784            }
     1785            if (RT_FAILURE(rc))
     1786                break;
     1787        }
     1788
     1789        RTMemTmpFree(pDirEntry);
     1790    }
     1791    else
     1792        rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_NO_TMP_MEMORY, "Out of memory! (direntry buffer)");
     1793    return rc;
     1794}
     1795
     1796
     1797/**
     1798 * Adds a directory, from the source VFS.
     1799 *
     1800 * @returns IPRT status code.
     1801 * @param   pOpts               The ISO maker command instance.
     1802 * @param   pParsed             The parsed names.
     1803 * @param   pidxObj             Where to return the configuration index for the
     1804 *                              added file.  Optional.
     1805 */
     1806static int rtFsIsoMakerCmdAddVfsDir(PRTFSISOMAKERCMDOPTS pOpts, PCRTFSISOMKCMDPARSEDNAMES pParsed, PCRTFSOBJINFO pObjInfo)
     1807{
     1808    Assert(pParsed->cNames < pParsed->cNamesWithSrc);
     1809
     1810    /*
     1811     * Open the directory.
     1812     */
     1813    char    *pszDir = pParsed->aNames[pParsed->cNamesWithSrc - 1].szPath;
     1814    RTPathChangeToUnixSlashes(pszDir, true /*fForce*/); /* VFS currently only understand unix slashes. */
     1815    RTVFSDIR hVfsDirSrc;
     1816    int rc = RTVfsDirOpen(pOpts->hSrcVfs, pszDir, 0 /*fFlags*/, &hVfsDirSrc);
     1817    if (RT_FAILURE(rc))
     1818        return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error opening directory '%s' (inside '%s'): %Rrc",
     1819                                      pszDir, pOpts->pszSrcVfs, rc);
     1820
     1821    /*
     1822     * Add the directory if it doesn't exist.
     1823     */
     1824    uint32_t idxObj = UINT32_MAX;
     1825    for (uint32_t i = 0; i < pParsed->cNames; i++)
     1826        if (pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)
     1827        {
     1828            idxObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker,
     1829                                                  pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,
     1830                                                  pParsed->aNames[i].szPath);
     1831            if (idxObj != UINT32_MAX)
     1832            {
     1833                /** @todo make sure the directory is present in the other namespace. */
     1834                break;
     1835            }
     1836        }
     1837    if (idxObj == UINT32_MAX)
     1838    {
     1839        rc = RTFsIsoMakerAddUnnamedDir(pOpts->hIsoMaker, pObjInfo, &idxObj);
     1840        if (RT_SUCCESS(rc))
     1841            rc = rtFsIsoMakerCmdSetObjPaths(pOpts, idxObj, pParsed, pParsed->aNames[pParsed->cNames - 1].szPath);
     1842        else
     1843            rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTFsIsoMakerAddUnnamedDir failed: %Rrc", rc);
     1844    }
    15151845    if (RT_SUCCESS(rc))
    15161846    {
    1517         pOpts->cItemsAdded++;
    1518         if (pidxObj)
    1519             *pidxObj = idxObj;
    1520 
    1521         rc = rtFsIsoMakerCmdSetObjPaths(pOpts, idxObj, pParsed, pszSrc);
    1522     }
    1523     else
    1524         rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s': %Rrc", pszSrc, rc);
     1847        /*
     1848         * Add the directory content.
     1849         */
     1850        uint32_t fNamespaces = 0;
     1851        for (uint32_t i = 0; i < pParsed->cNames; i++)
     1852            fNamespaces |= pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK;
     1853        rc = rtFsIsoMakerCmdAddVfsDirRecursive(pOpts, hVfsDirSrc, idxObj, pszDir,
     1854                                               pParsed->aNames[pParsed->cNamesWithSrc - 1].cchPath, fNamespaces, 0 /*cDepth*/);
     1855    }
     1856    RTVfsDirRelease(hVfsDirSrc);
    15251857    return rc;
    15261858}
     1859
     1860
    15271861
    15281862
     
    15401874                                         uint32_t *pidxObj)
    15411875{
    1542     RTFSOBJINFO     ObjInfo;
    1543     uint32_t        offError;
    1544     RTERRINFOSTATIC ErrInfo;
    1545     int rc = RTVfsChainQueryInfo(pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX,
    1546                                  RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo));
    1547     if (RT_FAILURE(rc))
    1548         return rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainQueryInfo", pszSrc, rc, offError, &ErrInfo.Core);
     1876    int         rc;
     1877    RTFSOBJINFO ObjInfo;
     1878    if (   pOpts->hSrcVfs == NIL_RTVFS
     1879        || RTVfsChainIsSpec(pszSrc))
     1880    {
     1881        uint32_t        offError;
     1882        RTERRINFOSTATIC ErrInfo;
     1883        rc = RTVfsChainQueryInfo(pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX,
     1884                                     RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo));
     1885        if (RT_FAILURE(rc))
     1886            return rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainQueryInfo", pszSrc, rc, offError, &ErrInfo.Core);
     1887    }
     1888    else
     1889    {
     1890        rc = RTVfsQueryPathInfo(pOpts->hSrcVfs, pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_FOLLOW_LINK);
     1891        if (RT_FAILURE(rc))
     1892            return rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTVfsQueryPathInfo failed on %s (inside %s): %Rrc",
     1893                                          pszSrc, pOpts->pszSrcVfs, rc);
     1894    }
    15491895
    15501896    if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
     
    16061952        const char     *pszSrc = Parsed.aNames[Parsed.cNamesWithSrc - 1].szPath;
    16071953        RTFSOBJINFO     ObjInfo;
    1608         uint32_t        offError;
    1609         RTERRINFOSTATIC ErrInfo;
    1610         rc = RTVfsChainQueryInfo(pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX,
    1611                                  RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo));
    1612         if (RT_FAILURE(rc))
    1613             return rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainQueryInfo", pszSrc, rc, offError, &ErrInfo.Core);
     1954        if (   pOpts->hSrcVfs == NIL_RTVFS
     1955            || RTVfsChainIsSpec(pszSrc))
     1956        {
     1957            uint32_t        offError;
     1958            RTERRINFOSTATIC ErrInfo;
     1959            rc = RTVfsChainQueryInfo(pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX,
     1960                                     RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo));
     1961            if (RT_FAILURE(rc))
     1962                return rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainQueryInfo", pszSrc, rc, offError, &ErrInfo.Core);
     1963        }
     1964        else
     1965        {
     1966            rc = RTVfsQueryPathInfo(pOpts->hSrcVfs, pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_FOLLOW_LINK);
     1967            if (RT_FAILURE(rc))
     1968                return rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTVfsQueryPathInfo failed on %s (in %s): %Rrc",
     1969                                              pszSrc, pOpts->pszSrcVfs, rc);
     1970        }
    16141971
    16151972        if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
     
    16171974
    16181975        if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
    1619             return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding directory '%s' failed: not implemented", pszSpec);
     1976        {
     1977            if (   pOpts->hSrcVfs == NIL_RTVFS
     1978                || RTVfsChainIsSpec(pszSrc))
     1979                return rtFsIsoMakerCmdAddDir(pOpts, pszSrc, &Parsed);
     1980            return rtFsIsoMakerCmdAddVfsDir(pOpts, &Parsed, &ObjInfo);
     1981        }
    16201982
    16211983        if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
    1622             return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding symlink '%s' failed: not implemented", pszSpec);
     1984            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding symlink '%s' failed: not yet implemented", pszSpec);
    16231985
    16241986        return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding special file '%s' failed: not implemented", pszSpec);
     
    16261988
    16271989    return VINF_SUCCESS;
     1990}
     1991
     1992
     1993/**
     1994 * Opens an ISO and use it for subsequent file system accesses.
     1995 *
     1996 * This is handy for duplicating a part of an ISO in the new image.
     1997 *
     1998 * @returns IPRT status code.
     1999 * @param   pOpts               The ISO maker command instance.
     2000 * @param   pszIsoSpec          The ISO path specifier.
     2001 * @param   pszOption           The option we're being called on.
     2002 * @param   fFlags              RTFSISO9660_F_XXX
     2003 */
     2004static int rtFsIsoMakerCmdOptPushIso(PRTFSISOMAKERCMDOPTS pOpts, const char *pszIsoSpec, const char *pszOption, uint32_t fFlags)
     2005{
     2006    if (pOpts->hSrcVfs != NIL_RTVFS)
     2007        return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED,
     2008                                      "Nested %s usage is not supported (previous: %s %s)",
     2009                                      pszOption, pOpts->pszSrcVfsOption, pOpts->pszSrcVfs);
     2010
     2011    /*
     2012     * Try open the file.
     2013     */
     2014    RTVFSFILE       hVfsFileIso;
     2015    uint32_t        offError;
     2016    RTERRINFOSTATIC ErrInfo;
     2017    int rc = RTVfsChainOpenFile(pszIsoSpec, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE,
     2018                                &hVfsFileIso, &offError, RTErrInfoInitStatic(&ErrInfo));
     2019    if (RT_SUCCESS(rc))
     2020    {
     2021        RTVFS hSrcVfs;
     2022        rc = RTFsIso9660VolOpen(hVfsFileIso, fFlags, &hSrcVfs, RTErrInfoInitStatic(&ErrInfo));
     2023        RTVfsFileRelease(hVfsFileIso);
     2024        if (RT_SUCCESS(rc))
     2025        {
     2026            pOpts->hSrcVfs         = hSrcVfs;
     2027            pOpts->pszSrcVfs       = pszIsoSpec;
     2028            pOpts->pszSrcVfsOption = pszOption;
     2029            return VINF_SUCCESS;
     2030        }
     2031
     2032        if (RTErrInfoIsSet(&ErrInfo.Core))
     2033            rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to open '%s' as ISO FS: %Rrc - %s",
     2034                                        pszIsoSpec, rc, ErrInfo.Core.pszMsg);
     2035        else
     2036            rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to open '%s' as ISO FS: %Rrc", pszIsoSpec, rc);
     2037    }
     2038    else
     2039        rc = rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainOpenFile", pszIsoSpec, rc, offError, &ErrInfo.Core);
     2040    return rc;
     2041}
     2042
     2043
     2044/**
     2045 * Counter part to --push-iso and friends.
     2046 *
     2047 * @returns IPRT status code.
     2048 * @param   pOpts               The ISO maker command instance.
     2049 */
     2050static int rtFsIsoMakerCmdOptPop(PRTFSISOMAKERCMDOPTS pOpts)
     2051{
     2052    if (pOpts->hSrcVfs != NIL_RTVFS)
     2053    {
     2054        RTVfsRelease(pOpts->hSrcVfs);
     2055        pOpts->hSrcVfs         = NIL_RTVFS;
     2056        pOpts->pszSrcVfs       = NULL;
     2057        pOpts->pszSrcVfsOption = NULL;
     2058        return VINF_SUCCESS;
     2059    }
     2060    return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "--pop without --push-xxx");
    16282061}
    16292062
     
    23262759                break;
    23272760
     2761            case RTFSISOMAKERCMD_OPT_PUSH_ISO:
     2762                rc = rtFsIsoMakerCmdOptPushIso(pOpts, ValueUnion.psz, "--push-iso", 0);
     2763                break;
     2764
     2765            case RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_JOLIET:
     2766                rc = rtFsIsoMakerCmdOptPushIso(pOpts, ValueUnion.psz, "--push-iso-no-joliet", RTFSISO9660_F_NO_JOLIET);
     2767                break;
     2768
     2769            case RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_ROCK:
     2770                rc = rtFsIsoMakerCmdOptPushIso(pOpts, ValueUnion.psz, "--push-iso-no-rock", RTFSISO9660_F_NO_ROCK);
     2771                break;
     2772
     2773            case RTFSISOMAKERCMD_OPT_PUSH_ISO_NO_ROCK_NO_JOLIET:
     2774                rc = rtFsIsoMakerCmdOptPushIso(pOpts, ValueUnion.psz, "--push-iso-no-rock-no-joliet",
     2775                                               RTFSISO9660_F_NO_ROCK | RTFSISO9660_F_NO_JOLIET);
     2776                break;
     2777
     2778            case RTFSISOMAKERCMD_OPT_POP:
     2779                rc = rtFsIsoMakerCmdOptPop(pOpts);
     2780                break;
     2781
     2782
    23282783            case RTFSISOMAKERCMD_OPT_IMPORT_ISO:
    23292784                rc = rtFsIsoMakerCmdOptImportIso(pOpts, ValueUnion.psz);
     
    25042959    Opts.pErrInfo               = pErrInfo;
    25052960    Opts.fVirtualImageMaker     = phVfsFile != NULL;
     2961    Opts.hSrcVfs                = NIL_RTVFS;
    25062962    Opts.cNameSpecifiers        = 1;
    25072963    Opts.afNameSpecifiers[0]    = RTFSISOMAKERCMDNAME_MAJOR_MASK;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette