1f96defca77af991e72fed46159433af9ae6b73evboxsync/* $Id$ */
1f96defca77af991e72fed46159433af9ae6b73evboxsync/** @file
1f96defca77af991e72fed46159433af9ae6b73evboxsync * IPRT Disk Volume Management API (DVM) - VFS glue.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Copyright (C) 2012 Oracle Corporation
1f96defca77af991e72fed46159433af9ae6b73evboxsync *
1f96defca77af991e72fed46159433af9ae6b73evboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1f96defca77af991e72fed46159433af9ae6b73evboxsync * available from http://www.virtualbox.org. This file is free software;
1f96defca77af991e72fed46159433af9ae6b73evboxsync * you can redistribute it and/or modify it under the terms of the GNU
1f96defca77af991e72fed46159433af9ae6b73evboxsync * General Public License (GPL) as published by the Free Software
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1f96defca77af991e72fed46159433af9ae6b73evboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1f96defca77af991e72fed46159433af9ae6b73evboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1f96defca77af991e72fed46159433af9ae6b73evboxsync *
1f96defca77af991e72fed46159433af9ae6b73evboxsync * The contents of this file may alternatively be used under the terms
1f96defca77af991e72fed46159433af9ae6b73evboxsync * of the Common Development and Distribution License Version 1.0
1f96defca77af991e72fed46159433af9ae6b73evboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
1f96defca77af991e72fed46159433af9ae6b73evboxsync * VirtualBox OSE distribution, in which case the provisions of the
1f96defca77af991e72fed46159433af9ae6b73evboxsync * CDDL are applicable instead of those of the GPL.
1f96defca77af991e72fed46159433af9ae6b73evboxsync *
1f96defca77af991e72fed46159433af9ae6b73evboxsync * You may elect to license modified versions of this file under the
1f96defca77af991e72fed46159433af9ae6b73evboxsync * terms and conditions of either the GPL or the CDDL or both.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/*******************************************************************************
1f96defca77af991e72fed46159433af9ae6b73evboxsync* Header Files *
1f96defca77af991e72fed46159433af9ae6b73evboxsync*******************************************************************************/
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/types.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/assert.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/mem.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/dvm.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/err.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/asm.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/string.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/file.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/sg.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/vfslowlevel.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include <iprt/poll.h>
1f96defca77af991e72fed46159433af9ae6b73evboxsync#include "internal/dvm.h"
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/*******************************************************************************
1f96defca77af991e72fed46159433af9ae6b73evboxsync* Structures and Typedefs *
1f96defca77af991e72fed46159433af9ae6b73evboxsync*******************************************************************************/
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * The internal data of a DVM volume I/O stream.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsynctypedef struct RTVFSDVMFILE
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync /** The volume the VFS file belongs to. */
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTDVMVOLUME hVol;
1f96defca77af991e72fed46159433af9ae6b73evboxsync /** Current position. */
1f96defca77af991e72fed46159433af9ae6b73evboxsync uint64_t offCurPos;
1f96defca77af991e72fed46159433af9ae6b73evboxsync} RTVFSDVMFILE;
1f96defca77af991e72fed46159433af9ae6b73evboxsync/** Pointer to a the internal data of a DVM volume file. */
1f96defca77af991e72fed46159433af9ae6b73evboxsynctypedef RTVFSDVMFILE *PRTVFSDVMFILE;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSOBJOPS,pfnClose}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_Close(void *pvThis)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync PRTVFSDVMFILE pThis = (PRTVFSDVMFILE)pvThis;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTDvmVolumeRelease(pThis->hVol);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VINF_SUCCESS;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pvThis);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pObjInfo);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(enmAddAttr);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_NOT_SUPPORTED;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync PRTVFSDVMFILE pThis = (PRTVFSDVMFILE)pvThis;
1f96defca77af991e72fed46159433af9ae6b73evboxsync int rc = VINF_SUCCESS;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync Assert(pSgBuf->cSegs == 1);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(fBlocking);
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Find the current position and check if it's within the volume.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync uint64_t offUnsigned = off < 0 ? pThis->offCurPos : (uint64_t)off;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (offUnsigned >= RTDvmVolumeGetSize(pThis->hVol))
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (pcbRead)
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync *pcbRead = 0;
1f96defca77af991e72fed46159433af9ae6b73evboxsync pThis->offCurPos = offUnsigned;
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VINF_EOF;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_EOF;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync size_t cbLeftToRead;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (offUnsigned + pSgBuf->paSegs[0].cbSeg > RTDvmVolumeGetSize(pThis->hVol))
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (!pcbRead)
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_EOF;
1f96defca77af991e72fed46159433af9ae6b73evboxsync *pcbRead = cbLeftToRead = (size_t)(RTDvmVolumeGetSize(pThis->hVol) - offUnsigned);
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync else
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync cbLeftToRead = pSgBuf->paSegs[0].cbSeg;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (pcbRead)
1f96defca77af991e72fed46159433af9ae6b73evboxsync *pcbRead = cbLeftToRead;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Ok, we've got a valid stretch within the file. Do the reading.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (cbLeftToRead > 0)
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync rc = RTDvmVolumeRead(pThis->hVol, (uint64_t)off, pSgBuf->paSegs[0].pvSeg, cbLeftToRead);
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (RT_SUCCESS(rc))
1f96defca77af991e72fed46159433af9ae6b73evboxsync offUnsigned += cbLeftToRead;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync pThis->offCurPos = offUnsigned;
1f96defca77af991e72fed46159433af9ae6b73evboxsync return rc;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync PRTVFSDVMFILE pThis = (PRTVFSDVMFILE)pvThis;
1f96defca77af991e72fed46159433af9ae6b73evboxsync int rc = VINF_SUCCESS;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync Assert(pSgBuf->cSegs == 1);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(fBlocking);
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Find the current position and check if it's within the volume.
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Writing beyond the end of a volume is not supported.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync uint64_t offUnsigned = off < 0 ? pThis->offCurPos : (uint64_t)off;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (offUnsigned >= RTDvmVolumeGetSize(pThis->hVol))
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (pcbWritten)
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync *pcbWritten = 0;
1f96defca77af991e72fed46159433af9ae6b73evboxsync pThis->offCurPos = offUnsigned;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_NOT_SUPPORTED;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync size_t cbLeftToWrite;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (offUnsigned + pSgBuf->paSegs[0].cbSeg > RTDvmVolumeGetSize(pThis->hVol))
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (!pcbWritten)
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_EOF;
1f96defca77af991e72fed46159433af9ae6b73evboxsync *pcbWritten = cbLeftToWrite = (size_t)(RTDvmVolumeGetSize(pThis->hVol) - offUnsigned);
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync else
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync cbLeftToWrite = pSgBuf->paSegs[0].cbSeg;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (pcbWritten)
1f96defca77af991e72fed46159433af9ae6b73evboxsync *pcbWritten = cbLeftToWrite;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Ok, we've got a valid stretch within the file. Do the reading.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (cbLeftToWrite > 0)
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync rc = RTDvmVolumeWrite(pThis->hVol, (uint64_t)off, pSgBuf->paSegs[0].pvSeg, cbLeftToWrite);
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (RT_SUCCESS(rc))
1f96defca77af991e72fed46159433af9ae6b73evboxsync offUnsigned += cbLeftToWrite;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync pThis->offCurPos = offUnsigned;
1f96defca77af991e72fed46159433af9ae6b73evboxsync return rc;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_Flush(void *pvThis)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pvThis);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VINF_SUCCESS; /* @todo: Implement missing DVM API. */
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
1f96defca77af991e72fed46159433af9ae6b73evboxsync uint32_t *pfRetEvents)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pvThis);
1f96defca77af991e72fed46159433af9ae6b73evboxsync int rc;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (fEvents != RTPOLL_EVT_ERROR)
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync *pfRetEvents = fEvents & ~RTPOLL_EVT_ERROR;
1f96defca77af991e72fed46159433af9ae6b73evboxsync rc = VINF_SUCCESS;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync else
1f96defca77af991e72fed46159433af9ae6b73evboxsync rc = RTVfsUtilDummyPollOne(fEvents, cMillies, fIntr, pfRetEvents);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return rc;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_Tell(void *pvThis, PRTFOFF poffActual)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync PRTVFSDVMFILE pThis = (PRTVFSDVMFILE)pvThis;
1f96defca77af991e72fed46159433af9ae6b73evboxsync *poffActual = pThis->offCurPos;
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VINF_SUCCESS;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pvThis);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(fMode);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(fMask);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_NOT_SUPPORTED;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
1f96defca77af991e72fed46159433af9ae6b73evboxsync PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pvThis);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pAccessTime);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pModificationTime);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pChangeTime);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pBirthTime);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_NOT_SUPPORTED;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(pvThis);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(uid);
1f96defca77af991e72fed46159433af9ae6b73evboxsync NOREF(gid);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_NOT_SUPPORTED;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync PRTVFSDVMFILE pThis = (PRTVFSDVMFILE)pvThis;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Seek relative to which position.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync uint64_t offWrt;
1f96defca77af991e72fed46159433af9ae6b73evboxsync switch (uMethod)
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync case RTFILE_SEEK_BEGIN:
1f96defca77af991e72fed46159433af9ae6b73evboxsync offWrt = 0;
1f96defca77af991e72fed46159433af9ae6b73evboxsync break;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync case RTFILE_SEEK_CURRENT:
1f96defca77af991e72fed46159433af9ae6b73evboxsync offWrt = pThis->offCurPos;
1f96defca77af991e72fed46159433af9ae6b73evboxsync break;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync case RTFILE_SEEK_END:
1f96defca77af991e72fed46159433af9ae6b73evboxsync offWrt = RTDvmVolumeGetSize(pThis->hVol);
1f96defca77af991e72fed46159433af9ae6b73evboxsync break;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync default:
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VERR_INTERNAL_ERROR_5;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Calc new position, take care to stay within bounds.
1f96defca77af991e72fed46159433af9ae6b73evboxsync *
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @todo: Setting position beyond the end of the volume does not make sense.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync uint64_t offNew;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (offSeek == 0)
1f96defca77af991e72fed46159433af9ae6b73evboxsync offNew = offWrt;
1f96defca77af991e72fed46159433af9ae6b73evboxsync else if (offSeek > 0)
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync offNew = offWrt + offSeek;
1f96defca77af991e72fed46159433af9ae6b73evboxsync if ( offNew < offWrt
1f96defca77af991e72fed46159433af9ae6b73evboxsync || offNew > RTFOFF_MAX)
1f96defca77af991e72fed46159433af9ae6b73evboxsync offNew = RTFOFF_MAX;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync else if ((uint64_t)-offSeek < offWrt)
1f96defca77af991e72fed46159433af9ae6b73evboxsync offNew = offWrt + offSeek;
1f96defca77af991e72fed46159433af9ae6b73evboxsync else
1f96defca77af991e72fed46159433af9ae6b73evboxsync offNew = 0;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Update the state and set return value.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync pThis->offCurPos = offNew;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync *poffActual = offNew;
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VINF_SUCCESS;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncstatic DECLCALLBACK(int) rtDvmVfsFile_QuerySize(void *pvThis, uint64_t *pcbFile)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync PRTVFSDVMFILE pThis = (PRTVFSDVMFILE)pvThis;
1f96defca77af991e72fed46159433af9ae6b73evboxsync *pcbFile = RTDvmVolumeGetSize(pThis->hVol);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VINF_SUCCESS;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync/**
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Standard file operations.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsyncDECL_HIDDEN_CONST(const RTVFSFILEOPS) g_rtDvmVfsStdFileOps =
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync { /* Stream */
1f96defca77af991e72fed46159433af9ae6b73evboxsync { /* Obj */
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSOBJOPS_VERSION,
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSOBJTYPE_FILE,
1f96defca77af991e72fed46159433af9ae6b73evboxsync "DvmFile",
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_Close,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_QueryInfo,
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSOBJOPS_VERSION
1f96defca77af991e72fed46159433af9ae6b73evboxsync },
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSIOSTREAMOPS_VERSION,
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSIOSTREAMOPS_FEAT_NO_SG,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_Read,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_Write,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_Flush,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_PollOne,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_Tell,
1f96defca77af991e72fed46159433af9ae6b73evboxsync NULL /*Skip*/,
1f96defca77af991e72fed46159433af9ae6b73evboxsync NULL /*ZeroFill*/,
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSIOSTREAMOPS_VERSION,
1f96defca77af991e72fed46159433af9ae6b73evboxsync },
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSFILEOPS_VERSION,
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*RTVFSIOFILEOPS_FEAT_NO_AT_OFFSET*/ 0,
1f96defca77af991e72fed46159433af9ae6b73evboxsync { /* ObjSet */
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSOBJSETOPS_VERSION,
1f96defca77af991e72fed46159433af9ae6b73evboxsync RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_SetMode,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_SetTimes,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_SetOwner,
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSOBJSETOPS_VERSION
1f96defca77af991e72fed46159433af9ae6b73evboxsync },
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_Seek,
1f96defca77af991e72fed46159433af9ae6b73evboxsync rtDvmVfsFile_QuerySize,
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSFILEOPS_VERSION
1f96defca77af991e72fed46159433af9ae6b73evboxsync};
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsyncRTDECL(int) RTDvmVolumeCreateVfsFile(RTDVMVOLUME hVol, PRTVFSFILE phVfsFileOut)
1f96defca77af991e72fed46159433af9ae6b73evboxsync{
1f96defca77af991e72fed46159433af9ae6b73evboxsync AssertPtrReturn(hVol, VERR_INVALID_HANDLE);
1f96defca77af991e72fed46159433af9ae6b73evboxsync AssertPtrReturn(phVfsFileOut, VERR_INVALID_POINTER);
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync uint32_t cRefs = RTDvmVolumeRetain(hVol);
1f96defca77af991e72fed46159433af9ae6b73evboxsync AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync /*
1f96defca77af991e72fed46159433af9ae6b73evboxsync * Create the volume file.
1f96defca77af991e72fed46159433af9ae6b73evboxsync */
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTVFSFILE hVfsFile;
1f96defca77af991e72fed46159433af9ae6b73evboxsync PRTVFSDVMFILE pThis;
1f96defca77af991e72fed46159433af9ae6b73evboxsync int rc = RTVfsNewFile(&g_rtDvmVfsStdFileOps, sizeof(*pThis), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_WRITE,
1f96defca77af991e72fed46159433af9ae6b73evboxsync NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pThis);
1f96defca77af991e72fed46159433af9ae6b73evboxsync if (RT_SUCCESS(rc))
1f96defca77af991e72fed46159433af9ae6b73evboxsync {
1f96defca77af991e72fed46159433af9ae6b73evboxsync pThis->offCurPos = 0;
1f96defca77af991e72fed46159433af9ae6b73evboxsync pThis->hVol = hVol;
1f96defca77af991e72fed46159433af9ae6b73evboxsync
1f96defca77af991e72fed46159433af9ae6b73evboxsync *phVfsFileOut = hVfsFile;
1f96defca77af991e72fed46159433af9ae6b73evboxsync return VINF_SUCCESS;
1f96defca77af991e72fed46159433af9ae6b73evboxsync }
1f96defca77af991e72fed46159433af9ae6b73evboxsync else
1f96defca77af991e72fed46159433af9ae6b73evboxsync RTDvmVolumeRelease(hVol);
1f96defca77af991e72fed46159433af9ae6b73evboxsync return rc;
1f96defca77af991e72fed46159433af9ae6b73evboxsync}
1f96defca77af991e72fed46159433af9ae6b73evboxsync