/* $Id$ */
/** @file
* IPRT Disk Volume Management API (DVM) - VFS glue.
*/
/*
* Copyright (C) 2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/vfslowlevel.h>
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* The internal data of a DVM volume I/O stream.
*/
typedef struct RTVFSDVMFILE
{
/** The volume the VFS file belongs to. */
/** Current position. */
} RTVFSDVMFILE;
/** Pointer to a the internal data of a DVM volume file. */
/**
* @interface_method_impl{RTVFSOBJOPS,pfnClose}
*/
{
return VINF_SUCCESS;
}
/**
* @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
*/
static DECLCALLBACK(int) rtDvmVfsFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
{
return VERR_NOT_SUPPORTED;
}
/**
* @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
*/
static DECLCALLBACK(int) rtDvmVfsFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
{
/*
* Find the current position and check if it's within the volume.
*/
{
if (pcbRead)
{
*pcbRead = 0;
return VINF_EOF;
}
return VERR_EOF;
}
{
if (!pcbRead)
return VERR_EOF;
}
else
{
if (pcbRead)
*pcbRead = cbLeftToRead;
}
/*
* Ok, we've got a valid stretch within the file. Do the reading.
*/
if (cbLeftToRead > 0)
{
if (RT_SUCCESS(rc))
}
return rc;
}
/**
* @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
*/
static DECLCALLBACK(int) rtDvmVfsFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
{
/*
* Find the current position and check if it's within the volume.
* Writing beyond the end of a volume is not supported.
*/
{
if (pcbWritten)
{
*pcbWritten = 0;
}
return VERR_NOT_SUPPORTED;
}
{
if (!pcbWritten)
return VERR_EOF;
}
else
{
if (pcbWritten)
}
/*
* Ok, we've got a valid stretch within the file. Do the reading.
*/
if (cbLeftToWrite > 0)
{
if (RT_SUCCESS(rc))
}
return rc;
}
/**
* @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
*/
{
return VINF_SUCCESS; /* @todo: Implement missing DVM API. */
}
/**
* @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne}
*/
static DECLCALLBACK(int) rtDvmVfsFile_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
{
int rc;
if (fEvents != RTPOLL_EVT_ERROR)
{
rc = VINF_SUCCESS;
}
else
return rc;
}
/**
* @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell}
*/
{
return VINF_SUCCESS;
}
/**
* @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
*/
{
return VERR_NOT_SUPPORTED;
}
/**
* @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
*/
static DECLCALLBACK(int) rtDvmVfsFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
{
return VERR_NOT_SUPPORTED;
}
/**
* @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
*/
{
return VERR_NOT_SUPPORTED;
}
/**
* @interface_method_impl{RTVFSFILEOPS,pfnSeek}
*/
static DECLCALLBACK(int) rtDvmVfsFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
{
/*
* Seek relative to which position.
*/
switch (uMethod)
{
case RTFILE_SEEK_BEGIN:
offWrt = 0;
break;
case RTFILE_SEEK_CURRENT:
break;
case RTFILE_SEEK_END:
break;
default:
return VERR_INTERNAL_ERROR_5;
}
/*
* Calc new position, take care to stay within bounds.
*
* @todo: Setting position beyond the end of the volume does not make sense.
*/
if (offSeek == 0)
else if (offSeek > 0)
{
|| offNew > RTFOFF_MAX)
offNew = RTFOFF_MAX;
}
else
offNew = 0;
/*
* Update the state and set return value.
*/
*poffActual = offNew;
return VINF_SUCCESS;
}
/**
* @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
*/
{
return VINF_SUCCESS;
}
/**
* Standard file operations.
*/
{
{ /* Stream */
{ /* Obj */
"DvmFile",
},
NULL /*Skip*/,
NULL /*ZeroFill*/,
},
/*RTVFSIOFILEOPS_FEAT_NO_AT_OFFSET*/ 0,
{ /* ObjSet */
},
};
{
/*
* Create the volume file.
*/
int rc = RTVfsNewFile(&g_rtDvmVfsStdFileOps, sizeof(*pThis), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_WRITE,
if (RT_SUCCESS(rc))
{
*phVfsFileOut = hVfsFile;
return VINF_SUCCESS;
}
else
return rc;
}