5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/* $Id$ */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/** @file
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * IPRT - ISO 9660 file system handling.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2010-2011 Oracle Corporation
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * available from http://www.virtualbox.org. This file is free software;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * you can redistribute it and/or modify it under the terms of the GNU
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * General Public License (GPL) as published by the Free Software
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * The contents of this file may alternatively be used under the terms
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * of the Common Development and Distribution License Version 1.0
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * VirtualBox OSE distribution, in which case the provisions of the
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * CDDL are applicable instead of those of the GPL.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * You may elect to license modified versions of this file under the
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * terms and conditions of either the GPL or the CDDL or both.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/*******************************************************************************
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync* Header Files *
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync*******************************************************************************/
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync#include <iprt/isofs.h>
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync#include <iprt/file.h>
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync#include <iprt/err.h>
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync#include <iprt/mem.h>
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync#include <iprt/path.h>
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync#include <iprt/string.h>
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/**
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync * Destroys the path cache.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pFile ISO handle.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic void rtIsoFsDestroyPathCache(PRTISOFSFILE pFile)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
c80170800394cbf2746e3136b41886c2d11617aevboxsync PRTISOFSPATHTABLEENTRY pNode = RTListGetFirst(&pFile->listPaths, RTISOFSPATHTABLEENTRY, Node);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync while (pNode)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync PRTISOFSPATHTABLEENTRY pNext = RTListNodeGetNext(&pNode->Node, RTISOFSPATHTABLEENTRY, Node);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync bool fLast = RTListNodeIsLast(&pFile->listPaths, &pNode->Node);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pNode->path)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTStrFree(pNode->path);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pNode->path_full)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTStrFree(pNode->path_full);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTListNodeRemove(&pNode->Node);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTMemFree(pNode);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (fLast)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pNode = pNext;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/**
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * Adds a path entry to the path table list.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @return IPRT status code.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pList Path table list to add the path entry to.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pszPath Path to add.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pHeader Path header information to add.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic int rtIsoFsAddToPathCache(PRTLISTNODE pList, const char *pszPath,
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync RTISOFSPATHTABLEHEADER *pHeader)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pList, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pHeader, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync PRTISOFSPATHTABLEENTRY pNode = (PRTISOFSPATHTABLEENTRY)RTMemAlloc(sizeof(RTISOFSPATHTABLEENTRY));
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pNode == NULL)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return VERR_NO_MEMORY;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pNode->path = NULL;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(RTStrAAppend(&pNode->path, pszPath)))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync memcpy((RTISOFSPATHTABLEHEADER*)&pNode->header,
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync (RTISOFSPATHTABLEHEADER*)pHeader, sizeof(pNode->header));
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pNode->path_full = NULL;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pNode->Node.pPrev = NULL;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pNode->Node.pNext = NULL;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTListAppend(pList, &pNode->Node);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return VINF_SUCCESS;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return VERR_NO_MEMORY;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/**
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * Retrieves the parent path of a given node, assuming that the path table
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * (still) is in sync with the node's index.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @return IPRT status code.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pList Path table list to use.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pNode Node of path table entry to lookup the full path for.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pszPathNode Current (partial) parent path; needed for recursion.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param ppszPath Pointer to a pointer to store the retrieved full path to.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic int rtIsoFsGetParentPathSub(PRTLISTNODE pList, PRTISOFSPATHTABLEENTRY pNode,
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync char *pszPathNode, char **ppszPath)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int rc = VINF_SUCCESS;
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync /* Do we have a parent? */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pNode->header.parent_index > 1)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync uint16_t idx = 1;
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync /* Get the parent of our current node (pNode) */
c80170800394cbf2746e3136b41886c2d11617aevboxsync PRTISOFSPATHTABLEENTRY pNodeParent = RTListGetFirst(pList, RTISOFSPATHTABLEENTRY, Node);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync while (idx++ < pNode->header.parent_index)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pNodeParent = RTListNodeGetNext(&pNodeParent->Node, RTISOFSPATHTABLEENTRY, Node);
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync /* Construct intermediate path (parent + current path). */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync char *pszPath = RTPathJoinA(pNodeParent->path, pszPathNode);
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync if (pszPath)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync /* ... and do the same with the parent's parent until we reached the root. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = rtIsoFsGetParentPathSub(pList, pNodeParent, pszPath, ppszPath);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTStrFree(pszPath);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync rc = VERR_NO_STR_MEMORY;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync else /* No parent (left), this must be the root path then. */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync *ppszPath = RTStrDup(pszPathNode);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return rc;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/**
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * Updates the path table cache of an ISO file.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @return IPRT status code.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pFile ISO handle.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic int rtIsoFsUpdatePathCache(PRTISOFSFILE pFile)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rtIsoFsDestroyPathCache(pFile);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTListInit(&pFile->listPaths);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Seek to path tables. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int rc = VINF_SUCCESS;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(pFile->pvd.path_table_start_first > 16);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync uint64_t uTableStart = (pFile->pvd.path_table_start_first * RTISOFS_SECTOR_SIZE);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(uTableStart % RTISOFS_SECTOR_SIZE == 0); /* Make sure it's aligned. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RTFileTell(pFile->file) != uTableStart)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileSeek(pFile->file, uTableStart, RTFILE_SEEK_BEGIN, &uTableStart);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /*
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * Since this is a sequential format, for performance it's best to read the
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * complete path table (every entry can have its own level (directory depth) first
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * and the actual directories of the path table afterwards.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Read in the path table ... */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync size_t cbLeft = pFile->pvd.path_table_size;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTISOFSPATHTABLEHEADER header;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync while ((cbLeft > 0) && RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync size_t cbRead;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileRead(pFile->file, (RTISOFSPATHTABLEHEADER*)&header, sizeof(RTISOFSPATHTABLEHEADER), &cbRead);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_FAILURE(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync cbLeft -= cbRead;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (header.length)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(cbLeft >= header.length);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(header.length <= 31);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Allocate and read in the actual path name. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync char *pszName = RTStrAlloc(header.length + 1);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileRead(pFile->file, (char*)pszName, header.length, &cbRead);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync cbLeft -= cbRead;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pszName[cbRead] = '\0'; /* Terminate string. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Add entry to cache ... */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = rtIsoFsAddToPathCache(&pFile->listPaths, pszName, &header);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTStrFree(pszName);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Read padding if required ... */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if ((header.length % 2) != 0) /* If we have an odd length, read/skip the padding byte. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileSeek(pFile->file, 1, RTFILE_SEEK_CURRENT, NULL);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync cbLeft--;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Transform path names into full paths. This is a bit ugly right now. */
c80170800394cbf2746e3136b41886c2d11617aevboxsync PRTISOFSPATHTABLEENTRY pNode = RTListGetLast(&pFile->listPaths, RTISOFSPATHTABLEENTRY, Node);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync while ( pNode
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync && !RTListNodeIsFirst(&pFile->listPaths, &pNode->Node)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync && RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = rtIsoFsGetParentPathSub(&pFile->listPaths, pNode,
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync pNode->path, &pNode->path_full);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pNode = RTListNodeGetPrev(&pNode->Node, RTISOFSPATHTABLEENTRY, Node);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return rc;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsyncRTR3DECL(int) RTIsoFsOpen(PRTISOFSFILE pFile, const char *pszFileName)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pszFileName, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTListInit(&pFile->listPaths);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync#if 0
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(sizeof(RTISOFSDATESHORT) == 7);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(sizeof(RTISOFSDATELONG) == 17);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int l = sizeof(RTISOFSDIRRECORD);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTPrintf("RTISOFSDIRRECORD=%ld\n", l);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(l == 33);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Each volume descriptor exactly occupies one sector. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync l = sizeof(RTISOFSPRIVOLDESC);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTPrintf("RTISOFSPRIVOLDESC=%ld\n", l);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(l == RTISOFS_SECTOR_SIZE);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync#endif
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int rc = RTFileOpen(&pFile->file, pszFileName, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync uint64_t cbSize;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileGetSize(pFile->file, &cbSize);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if ( RT_SUCCESS(rc)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync && cbSize > 16 * RTISOFS_SECTOR_SIZE)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync uint64_t cbOffset = 16 * RTISOFS_SECTOR_SIZE; /* Start reading at 32k. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync size_t cbRead;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTISOFSPRIVOLDESC pvd;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync bool fFoundPrimary = false;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync bool fIsValid = false;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync while (cbOffset < _1M)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Get primary descriptor. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileRead(pFile->file, (PRTISOFSPRIVOLDESC)&pvd, sizeof(RTISOFSPRIVOLDESC), &cbRead);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_FAILURE(rc) || cbRead < sizeof(RTISOFSPRIVOLDESC))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if ( RTStrStr((char*)pvd.name_id, RTISOFS_STANDARD_ID)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync && pvd.type == 0x1 /* Primary Volume Descriptor */)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync memcpy((PRTISOFSPRIVOLDESC)&pFile->pvd,
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync (PRTISOFSPRIVOLDESC)&pvd, sizeof(RTISOFSPRIVOLDESC));
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync fFoundPrimary = true;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else if(pvd.type == 0xff /* Termination Volume Descriptor */)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (fFoundPrimary)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync fIsValid = true;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync cbOffset += sizeof(RTISOFSPRIVOLDESC);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (fIsValid)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = rtIsoFsUpdatePathCache(pFile);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = VERR_INVALID_PARAMETER;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_FAILURE(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTIsoFsClose(pFile);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return rc;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsyncRTR3DECL(void) RTIsoFsClose(PRTISOFSFILE pFile)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pFile)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rtIsoFsDestroyPathCache(pFile);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTFileClose(pFile->file);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/**
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * Parses an extent given at the specified sector + size and
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * searches for a file name to return an allocated directory record.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @return IPRT status code.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pFile ISO handle.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pszFileName Absolute file name to search for.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param uExtentSector Sector of extent.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param cbExtent Size (in bytes) of extent.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param ppRec Pointer to a pointer to return the
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * directory record. Must be free'd with
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * rtIsoFsFreeDirectoryRecord().
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic int rtIsoFsFindEntry(PRTISOFSFILE pFile, const char *pszFileName,
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync uint32_t uExtentSector, uint32_t cbExtent /* Bytes */,
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync PRTISOFSDIRRECORD *ppRec)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(uExtentSector > 16);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int rc = RTFileSeek(pFile->file, uExtentSector * RTISOFS_SECTOR_SIZE,
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTFILE_SEEK_BEGIN, NULL);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = VERR_FILE_NOT_FOUND;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
2f7d372a31fd0f5515c2d307db549db16dd443f0vboxsync uint8_t abBuffer[RTISOFS_SECTOR_SIZE];
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync size_t cbLeft = cbExtent;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync while (!RT_SUCCESS(rc) && cbLeft > 0)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
2f7d372a31fd0f5515c2d307db549db16dd443f0vboxsync size_t cbRead = 0;
2f7d372a31fd0f5515c2d307db549db16dd443f0vboxsync int rc2 = RTFileRead(pFile->file, &abBuffer[0], sizeof(abBuffer), &cbRead);
2f7d372a31fd0f5515c2d307db549db16dd443f0vboxsync AssertRC(rc2);
2f7d372a31fd0f5515c2d307db549db16dd443f0vboxsync Assert(cbRead == RTISOFS_SECTOR_SIZE);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync cbLeft -= cbRead;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync uint32_t idx = 0;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync while (idx < cbRead)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
2f7d372a31fd0f5515c2d307db549db16dd443f0vboxsync PRTISOFSDIRRECORD pCurRecord = (PRTISOFSDIRRECORD)&abBuffer[idx];
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pCurRecord->record_length == 0)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync char *pszName = RTStrAlloc(pCurRecord->name_len + 1);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtr(pszName);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(idx + sizeof(RTISOFSDIRRECORD) < cbRead);
2f7d372a31fd0f5515c2d307db549db16dd443f0vboxsync memcpy(pszName, &abBuffer[idx + sizeof(RTISOFSDIRRECORD)], pCurRecord->name_len);
c31578d36637d7ab03bf8d8e9db2ab056ca7e692vboxsync pszName[pCurRecord->name_len] = '\0'; /* Force string termination. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if ( pCurRecord->name_len == 1
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync && pszName[0] == 0x0)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* This is a "." directory (self). */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else if ( pCurRecord->name_len == 1
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync && pszName[0] == 0x1)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* This is a ".." directory (parent). */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else /* Regular directory or file */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pCurRecord->flags & RT_BIT(1)) /* Directory */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* We don't recursively go into directories
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * because we already have the cached path table. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pszName[pCurRecord->name_len] = 0;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /*rc = rtIsoFsParseDir(pFile, pszFileName,
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pDirHdr->extent_location, pDirHdr->extent_data_length);*/
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else /* File */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync /* Get last occurrence of ";" and cut it off. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync char *pTerm = strrchr(pszName, ';');
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pTerm)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync pszName[pTerm - pszName] = 0;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Don't use case sensitive comparison here, in IS0 9660 all
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync * file / directory names are UPPERCASE. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (!RTStrICmp(pszName, pszFileName))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync PRTISOFSDIRRECORD pRec = (PRTISOFSDIRRECORD)RTMemAlloc(sizeof(RTISOFSDIRRECORD));
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pRec)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync memcpy(pRec, pCurRecord, sizeof(RTISOFSDIRRECORD));
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *ppRec = pRec;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = VINF_SUCCESS;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = VERR_NO_MEMORY;
701a45600245e42829e1187817299e812eebdec5vboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync idx += pCurRecord->record_length;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return rc;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/**
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * Retrieves the sector of a file extent given by the
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * full file path within the ISO.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @return IPRT status code.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pFile ISO handle.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pszPath File path to resolve.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param puSector Pointer where to store the found sector to.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic int rtIsoFsResolvePath(PRTISOFSFILE pFile, const char *pszPath, uint32_t *puSector)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(puSector, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int rc = VERR_FILE_NOT_FOUND;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync char *pszTemp = RTStrDup(pszPath);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pszTemp)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTPathStripFilename(pszTemp);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync bool bFound = false;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync PRTISOFSPATHTABLEENTRY pNode;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (!RTStrCmp(pszTemp, ".")) /* Root directory? Use first node! */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
c80170800394cbf2746e3136b41886c2d11617aevboxsync pNode = RTListGetFirst(&pFile->listPaths, RTISOFSPATHTABLEENTRY, Node);
d2fde0043ee3654809239533d8718ed4a2e22ed6vboxsync if (pNode)
d2fde0043ee3654809239533d8718ed4a2e22ed6vboxsync bFound = true;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTListForEach(&pFile->listPaths, pNode, RTISOFSPATHTABLEENTRY, Node)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if ( pNode->path_full != NULL /* Root does not have a path! */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync && !RTStrICmp(pNode->path_full, pszTemp))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync bFound = true;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (bFound)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
d2fde0043ee3654809239533d8718ed4a2e22ed6vboxsync AssertPtr(pNode);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *puSector = pNode->header.sector_dir_table;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = VINF_SUCCESS;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
d2fde0043ee3654809239533d8718ed4a2e22ed6vboxsync else
d2fde0043ee3654809239533d8718ed4a2e22ed6vboxsync rc = VERR_FILE_NOT_FOUND;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTStrFree(pszTemp);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = VERR_NO_MEMORY;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return rc;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync/**
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * Allocates a new directory record.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @return Pointer to the newly allocated directory record.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic PRTISOFSDIRRECORD rtIsoFsCreateDirectoryRecord(void)
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync{
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync PRTISOFSDIRRECORD pRecord = (PRTISOFSDIRRECORD)RTMemAlloc(sizeof(RTISOFSDIRRECORD));
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync return pRecord;
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync}
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync/**
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * Frees a previously allocated directory record.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @return IPRT status code.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic void rtIsoFsFreeDirectoryRecord(PRTISOFSDIRRECORD pRecord)
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync{
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync RTMemFree(pRecord);
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync}
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync/**
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * Returns an allocated directory record for a given file.
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @return IPRT status code.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pFile ISO handle.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param pszPath File path to resolve.
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * @param ppRecord Pointer to a pointer to return the
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * directory record. Must be free'd with
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync * rtIsoFsFreeDirectoryRecord().
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync */
a494f8cb9c33df07e260ac05855653c130f7b057vboxsyncstatic int rtIsoFsGetDirectoryRecord(PRTISOFSFILE pFile, const char *pszPath,
a494f8cb9c33df07e260ac05855653c130f7b057vboxsync PRTISOFSDIRRECORD *ppRecord)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(ppRecord, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync uint32_t uSector;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int rc = rtIsoFsResolvePath(pFile, pszPath, &uSector);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Seek and read the directory record of given file. */
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileSeek(pFile->file, uSector * RTISOFS_SECTOR_SIZE,
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTFILE_SEEK_BEGIN, NULL);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync size_t cbRead;
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync PRTISOFSDIRRECORD pRecord = rtIsoFsCreateDirectoryRecord();
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (pRecord)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileRead(pFile->file, (PRTISOFSDIRRECORD)pRecord, sizeof(RTISOFSDIRRECORD), &cbRead);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync Assert(cbRead == sizeof(RTISOFSDIRRECORD));
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *ppRecord = pRecord;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_FAILURE(rc))
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync rtIsoFsFreeDirectoryRecord(pRecord);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync else
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = VERR_NO_MEMORY;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return rc;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsyncRTR3DECL(int) RTIsoFsGetFileInfo(PRTISOFSFILE pFile, const char *pszPath,
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync uint32_t *pcbOffset, size_t *pcbLength)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pcbOffset, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync PRTISOFSDIRRECORD pDirRecord;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int rc = rtIsoFsGetDirectoryRecord(pFile, pszPath, &pDirRecord);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync /* Get actual file record. */
701a45600245e42829e1187817299e812eebdec5vboxsync PRTISOFSDIRRECORD pFileRecord = NULL; /* shut up gcc*/
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = rtIsoFsFindEntry(pFile,
701a45600245e42829e1187817299e812eebdec5vboxsync RTPathFilename(pszPath),
701a45600245e42829e1187817299e812eebdec5vboxsync pDirRecord->extent_location,
701a45600245e42829e1187817299e812eebdec5vboxsync pDirRecord->extent_data_length,
701a45600245e42829e1187817299e812eebdec5vboxsync &pFileRecord);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *pcbOffset = pFileRecord->extent_location * RTISOFS_SECTOR_SIZE;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync *pcbLength = pFileRecord->extent_data_length;
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync rtIsoFsFreeDirectoryRecord(pFileRecord);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
ebbcebe494da0e177ffb36f2a60fddb9e1816aadvboxsync rtIsoFsFreeDirectoryRecord(pDirRecord);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return rc;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsyncRTR3DECL(int) RTIsoFsExtractFile(PRTISOFSFILE pFile, const char *pszSource,
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync const char *pszDest)
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync{
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pFile, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pszSource, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync AssertPtrReturn(pszDest, VERR_INVALID_PARAMETER);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync uint32_t cbOffset;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync size_t cbLength;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync int rc = RTIsoFsGetFileInfo(pFile, pszSource, &cbOffset, &cbLength);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileSeek(pFile->file, cbOffset, RTFILE_SEEK_BEGIN, NULL);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTFILE fileDest;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileOpen(&fileDest, pszDest, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync size_t cbToRead, cbRead, cbWritten;
6a7b2d192c9950dc8d0d4dea2d0293e8b22298devboxsync uint8_t byBuffer[_64K];
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync while ( cbLength > 0
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync && RT_SUCCESS(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync {
6a7b2d192c9950dc8d0d4dea2d0293e8b22298devboxsync cbToRead = RT_MIN(cbLength, _64K);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileRead(pFile->file, (uint8_t*)byBuffer, cbToRead, &cbRead);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_FAILURE(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync rc = RTFileWrite(fileDest, (uint8_t*)byBuffer, cbRead, &cbWritten);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync if (RT_FAILURE(rc))
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync break;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync cbLength -= cbRead;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync RTFileClose(fileDest);
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync }
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync return rc;
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync}
5c2e23084fe3d3163d8f441b99cfd9d2f76b6b2avboxsync