7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/* $Id$ */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/** @file
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * IPRT - PKZIP archive I/O.
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/*
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * Copyright (C) 2014 Oracle Corporation
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync *
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * available from http://www.virtualbox.org. This file is free software;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * General Public License (GPL) as published by the Free Software
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync *
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * The contents of this file may alternatively be used under the terms
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * of the Common Development and Distribution License Version 1.0
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * CDDL are applicable instead of those of the GPL.
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync *
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * You may elect to license modified versions of this file under the
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * terms and conditions of either the GPL or the CDDL or both.
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/******************************************************************************
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * Header Files *
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync ******************************************************************************/
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync#include <iprt/zip.h>
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync#include <iprt/file.h>
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync#include <iprt/fs.h>
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync#include <iprt/mem.h>
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync#include <iprt/string.h>
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync#include <iprt/vfs.h>
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync#include <iprt/vfslowlevel.h>
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/*******************************************************************************
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync* Structures and Typedefs *
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync*******************************************************************************/
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/**
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * Memory stream private data.
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsynctypedef struct MEMIOSTREAM
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync{
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync /** Size of the memory buffer. */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync size_t cbBuf;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync /** Pointer to the memory buffer. */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync uint8_t *pu8Buf;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync /** Current offset. */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync size_t off;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync} MEMIOSTREAM;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsynctypedef MEMIOSTREAM *PMEMIOSTREAM;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync/**
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync */
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsyncstatic DECLCALLBACK(int) memFssIos_Close(void *pvThis)
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync{
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync NOREF(pvThis);
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync return VINF_SUCCESS;
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/**
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsyncstatic DECLCALLBACK(int) memFssIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync{
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync PMEMIOSTREAM pThis = (PMEMIOSTREAM)pvThis;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync switch (enmAddAttr)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync case RTFSOBJATTRADD_NOTHING:
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync case RTFSOBJATTRADD_UNIX:
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RT_ZERO(*pObjInfo);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync pObjInfo->cbObject = pThis->cbBuf;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync break;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync default:
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync return VERR_NOT_SUPPORTED;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync return VINF_SUCCESS;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync}
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/**
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsyncstatic DECLCALLBACK(int) memFssIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync{
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync PMEMIOSTREAM pThis = (PMEMIOSTREAM)pvThis;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync Assert(pSgBuf->cSegs == 1);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (off < 0)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync off = pThis->off;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (off >= (RTFOFF)pThis->cbBuf)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync return pcbRead ? VINF_EOF : VERR_EOF;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync size_t cbLeft = pThis->cbBuf - off;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync size_t cbToRead = pSgBuf->paSegs[0].cbSeg;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (cbToRead > cbLeft)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (!pcbRead)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync return VERR_EOF;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync cbToRead = (size_t)cbLeft;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync memcpy(pSgBuf->paSegs[0].pvSeg, pThis->pu8Buf + off, cbToRead);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync pThis->off = off + cbToRead;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (pcbRead)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync *pcbRead = cbToRead;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync return VINF_SUCCESS;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync}
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync/**
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync */
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsyncstatic DECLCALLBACK(int) memFssIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync{
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync return VERR_NOT_IMPLEMENTED;
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync/**
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync */
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsyncstatic DECLCALLBACK(int) memFssIos_Flush(void *pvThis)
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync{
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync return VERR_NOT_IMPLEMENTED;
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync/**
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync */
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsyncstatic DECLCALLBACK(int) memFssIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, uint32_t *pfRetEvents)
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync{
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync return VERR_NOT_IMPLEMENTED;
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync/**
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync */
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsyncstatic DECLCALLBACK(int) memFssIos_Tell(void *pvThis, PRTFOFF poffActual)
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync{
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync PMEMIOSTREAM pThis = (PMEMIOSTREAM)pvThis;
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync *poffActual = pThis->off;
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync return VINF_SUCCESS;
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync}
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync/**
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * Memory I/O object stream operations.
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsyncstatic const RTVFSIOSTREAMOPS g_memFssIosOps =
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync{
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync { /* Obj */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSOBJOPS_VERSION,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSOBJTYPE_IO_STREAM,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync "MemFsStream::IoStream",
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync memFssIos_Close,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync memFssIos_QueryInfo,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSOBJOPS_VERSION
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync },
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSIOSTREAMOPS_VERSION,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSIOSTREAMOPS_FEAT_NO_SG,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync memFssIos_Read,
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync memFssIos_Write,
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync memFssIos_Flush,
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync memFssIos_PollOne,
96e8e3254d9f53263d49e275e71bbd028481ebc3vboxsync memFssIos_Tell,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync NULL /*Skip*/,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync NULL /*ZeroFill*/,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSIOSTREAMOPS_VERSION
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync};
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync
feea0c2d3825b3d2c170987ccb14e8c2c8ae865dvboxsyncRTDECL(int) RTZipPkzipMemDecompress(void **ppvDst, size_t *pcbDst, const void *pvSrc, size_t cbSrc, const char *pszObject)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync{
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync PMEMIOSTREAM pIosData;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSIOSTREAM hVfsIos;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync int rc = RTVfsNewIoStream(&g_memFssIosOps,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync sizeof(*pIosData),
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync NIL_RTVFS,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync NIL_RTVFSLOCK,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync &hVfsIos,
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync (void **)&pIosData);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (RT_SUCCESS(rc))
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync pIosData->pu8Buf = (uint8_t*)pvSrc;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync pIosData->cbBuf = cbSrc;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync pIosData->off = 0;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSFSSTREAM hVfsFss;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync rc = RTZipPkzipFsStreamFromIoStream(hVfsIos, 0 /*fFlags*/, &hVfsFss);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVfsIoStrmRelease(hVfsIos);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (RT_SUCCESS(rc))
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync /*
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * Loop through all objects. Actually this wouldn't be required
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync * for .zip files but we opened it as I/O stream.
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync */
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync for (bool fFound = false; !fFound;)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync char *pszName;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSOBJ hVfsObj;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync rc = RTVfsFsStrmNext(hVfsFss, &pszName, NULL /*penmType*/, &hVfsObj);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (RT_FAILURE(rc))
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync break;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync fFound = !strcmp(pszName, pszObject);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (fFound)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTFSOBJINFO UnixInfo;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync rc = RTVfsObjQueryInfo(hVfsObj, &UnixInfo, RTFSOBJATTRADD_UNIX);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (RT_SUCCESS(rc))
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync size_t cb = UnixInfo.cbObject;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync void *pv = RTMemAlloc(cb);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (pv)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVFSIOSTREAM hVfsIosObj = RTVfsObjToIoStream(hVfsObj);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (hVfsIos)
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync rc = RTVfsIoStrmRead(hVfsIosObj, pv, cb, true /*fBlocking*/, NULL);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync if (RT_SUCCESS(rc))
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync {
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync *ppvDst = pv;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync *pcbDst = cb;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync else
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTMemFree(pv);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVfsObjRelease(hVfsObj);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTStrFree(pszName);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync RTVfsFsStrmRelease(hVfsFss);
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync }
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync return rc;
7b7908c296ee464d45619cc2969413a934cfacc9vboxsync}