VirtualBox

Changeset 19624 in vbox for trunk/src


Ignore:
Timestamp:
May 12, 2009 1:49:50 PM (16 years ago)
Author:
vboxsync
Message:

added raw file serial driver

Location:
trunk/src/VBox
Files:
14 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Builtins.cpp

    r19351 r19624  
    256256    if (RT_FAILURE(rc))
    257257        return rc;
     258    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvRawFile);
     259    if (RT_FAILURE(rc))
     260        return rc;
    258261    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvChar);
    259262    if (RT_FAILURE(rc))
  • trunk/src/VBox/Devices/Builtins.h

    r19351 r19624  
    112112extern const PDMDRVREG g_DrvChar;
    113113extern const PDMDRVREG g_DrvNamedPipe;
     114extern const PDMDRVREG g_DrvRawFile;
    114115extern const PDMDRVREG g_DrvHostParallel;
    115116extern const PDMDRVREG g_DrvHostSerial;
  • trunk/src/VBox/Devices/Makefile.kmk

    r19464 r19624  
    660660        Serial/DrvChar.cpp \
    661661        Serial/DrvNamedPipe.cpp \
     662        Serial/DrvRawFile.cpp \
    662663        Storage/DrvBlock.cpp \
    663664        Storage/DrvHostBase.cpp \
  • trunk/src/VBox/Devices/Serial/DrvChar.cpp

    r11284 r19624  
    333333        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS, N_("Char#%d has no stream interface below"), pDrvIns->iInstance);
    334334
    335     rc = RTThreadCreate(&pThis->ReceiveThread, drvCharReceiveLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharRecv");
    336     if (RT_FAILURE(rc))
    337         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create receive thread"), pDrvIns->iInstance);
     335    /*
     336     * Don't start the receive thread if the driver doesn't support reading
     337     */
     338    if (pThis->pDrvStream->pfnRead)
     339    {
     340        rc = RTThreadCreate(&pThis->ReceiveThread, drvCharReceiveLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharRecv");
     341        if (RT_FAILURE(rc))
     342            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create receive thread"), pDrvIns->iInstance);
     343    }
    338344
    339345    rc = RTSemEventCreate(&pThis->SendSem);
  • trunk/src/VBox/Devices/Serial/DrvRawFile.cpp

    r19604 r19624  
    22 *
    33 * VBox stream devices:
    4  * Named pipe stream
     4 * Raw file output
    55 */
    66
     
    3636#include "Builtins.h"
    3737
    38 #ifdef RT_OS_WINDOWS
    39 #include <windows.h>
    40 #else /* !RT_OS_WINDOWS */
    41 #include <errno.h>
    42 #include <unistd.h>
    43 #include <sys/types.h>
    44 #include <sys/socket.h>
    45 #include <sys/un.h>
    46 #endif /* !RT_OS_WINDOWS */
    4738
    4839/*******************************************************************************
     
    5041*******************************************************************************/
    5142
    52 /** Converts a pointer to DRVNAMEDPIPE::IMedia to a PDRVNAMEDPIPE. */
    53 #define PDMISTREAM_2_DRVNAMEDPIPE(pInterface) ( (PDRVNAMEDPIPE)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAMEDPIPE, IStream)) )
     43/** Converts a pointer to DRVOUTPUTFILE::IMedia to a PDRVOUTPUTFILE. */
     44#define PDMISTREAM_2_DRVOUTPUTFILE(pInterface) ( (PDRVOUTPUTFILE)((uintptr_t)pInterface - RT_OFFSETOF(DRVOUTPUTFILE, IStream)) )
    5445
    5546/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
     
    6051*******************************************************************************/
    6152/**
    62  * Named pipe driver instance data.
    63  */
    64 typedef struct DRVNAMEDPIPE
     53 * Raw file output driver instance data.
     54 */
     55typedef struct DRVOUTPUTFILE
    6556{
    6657    /** The stream interface. */
     
    6859    /** Pointer to the driver instance. */
    6960    PPDMDRVINS          pDrvIns;
    70     /** Pointer to the named pipe file name. (Freed by MM) */
     61    /** Pointer to the file name. (Freed by MM) */
    7162    char                *pszLocation;
    7263    /** Flag whether VirtualBox represents the server or client side. */
    73     bool                fIsServer;
    74 #ifdef RT_OS_WINDOWS
    75     /* File handle of the named pipe. */
    76     HANDLE              NamedPipe;
    77     /* Overlapped structure for writes. */
    78     OVERLAPPED          OverlappedWrite;
    79     /* Overlapped structure for reads. */
    80     OVERLAPPED          OverlappedRead;
    81     /* Listen thread wakeup semaphore */
    82     RTSEMEVENT          ListenSem;
    83 #else /* !RT_OS_WINDOWS */
    84     /** Socket handle of the local socket for server. */
    85     RTSOCKET            LocalSocketServer;
    86     /** Socket handle of the local socket. */
    87     RTSOCKET            LocalSocket;
    88 #endif /* !RT_OS_WINDOWS */
    89     /** Thread for listening for new connections. */
    90     RTTHREAD            ListenThread;
     64    RTFILE              OutputFile;
    9165    /** Flag to signal listening thread to shut down. */
    9266    bool                fShutdown;
    93 } DRVNAMEDPIPE, *PDRVNAMEDPIPE;
     67} DRVOUTPUTFILE, *PDRVOUTPUTFILE;
    9468
    9569
     
    9973
    10074
    101 /** @copydoc PDMISTREAM::pfnRead */
    102 static DECLCALLBACK(int) drvNamedPipeRead(PPDMISTREAM pInterface, void *pvBuf, size_t *pcbRead)
     75/** @copydoc PDMISTREAM::pfnWrite */
     76static DECLCALLBACK(int) drvOutputFileWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
    10377{
    10478    int rc = VINF_SUCCESS;
    105     PDRVNAMEDPIPE pThis = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
    106     LogFlow(("%s: pvBuf=%p *pcbRead=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbRead, pThis->pszLocation));
     79    PDRVOUTPUTFILE pThis = PDMISTREAM_2_DRVOUTPUTFILE(pInterface);
     80    LogFlow(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbWrite, pThis->pszLocation));
    10781
    10882    Assert(pvBuf);
    109 #ifdef RT_OS_WINDOWS
    110     if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
    111     {
    112         DWORD cbReallyRead;
    113         pThis->OverlappedRead.Offset     = 0;
    114         pThis->OverlappedRead.OffsetHigh = 0;
    115         if (!ReadFile(pThis->NamedPipe, pvBuf, (DWORD)*pcbRead, &cbReallyRead, &pThis->OverlappedRead))
    116         {
    117             DWORD uError = GetLastError();
    118 
    119             if (   uError == ERROR_PIPE_LISTENING
    120                 || uError == ERROR_PIPE_NOT_CONNECTED)
    121             {
    122                 /* No connection yet/anymore */
    123                 cbReallyRead = 0;
    124 
    125                 /* wait a bit or else we'll be called right back. */
    126                 RTThreadSleep(100);
    127             }
    128             else
    129             {
    130                 if (uError == ERROR_IO_PENDING)
    131                 {
    132                     uError = 0;
    133 
    134                     /* Wait for incoming bytes. */
    135                     if (GetOverlappedResult(pThis->NamedPipe, &pThis->OverlappedRead, &cbReallyRead, TRUE) == FALSE)
    136                         uError = GetLastError();
    137                 }
    138 
    139                 rc = RTErrConvertFromWin32(uError);
    140                 Log(("drvNamedPipeRead: ReadFile returned %d (%Rrc)\n", uError, rc));
    141             }
    142         }
    143 
    144         if (RT_FAILURE(rc))
    145         {
    146             Log(("drvNamedPipeRead: FileRead returned %Rrc fShutdown=%d\n", rc, pThis->fShutdown));
    147             if (    !pThis->fShutdown
    148                 &&  (   rc == VERR_EOF
    149                      || rc == VERR_BROKEN_PIPE
    150                     )
    151                )
    152 
    153             {
    154                 FlushFileBuffers(pThis->NamedPipe);
    155                 DisconnectNamedPipe(pThis->NamedPipe);
    156                 if (!pThis->fIsServer)
    157                 {
    158                     CloseHandle(pThis->NamedPipe);
    159                     pThis->NamedPipe = INVALID_HANDLE_VALUE;
    160                 }
    161                 /* pretend success */
    162                 rc = VINF_SUCCESS;
    163             }
    164             cbReallyRead = 0;
    165         }
    166         *pcbRead = (size_t)cbReallyRead;
    167     }
    168 #else /* !RT_OS_WINDOWS */
    169     if (pThis->LocalSocket != NIL_RTSOCKET)
    170     {
    171         ssize_t cbReallyRead;
    172         cbReallyRead = recv(pThis->LocalSocket, pvBuf, *pcbRead, 0);
    173         if (cbReallyRead == 0)
    174         {
    175             RTSOCKET tmp = pThis->LocalSocket;
    176             pThis->LocalSocket = NIL_RTSOCKET;
    177             close(tmp);
    178         }
    179         else if (cbReallyRead == -1)
    180         {
    181             cbReallyRead = 0;
    182             rc = RTErrConvertFromErrno(errno);
    183         }
    184         *pcbRead = cbReallyRead;
    185     }
    186 #endif /* !RT_OS_WINDOWS */
    187     else
    188     {
    189         RTThreadSleep(100);
    190         *pcbRead = 0;
    191     }
    192 
    193     LogFlow(("%s: *pcbRead=%zu returns %Rrc\n", __FUNCTION__, *pcbRead, rc));
    194     return rc;
    195 }
    196 
    197 
    198 /** @copydoc PDMISTREAM::pfnWrite */
    199 static DECLCALLBACK(int) drvNamedPipeWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
    200 {
    201     int rc = VINF_SUCCESS;
    202     PDRVNAMEDPIPE pThis = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
    203     LogFlow(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbWrite, pThis->pszLocation));
    204 
    205     Assert(pvBuf);
    206 #ifdef RT_OS_WINDOWS
    207     if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
    208     {
    209         DWORD cbWritten = (DWORD)*pcbWrite;
    210         pThis->OverlappedWrite.Offset     = 0;
    211         pThis->OverlappedWrite.OffsetHigh = 0;
    212         if (!WriteFile(pThis->NamedPipe, pvBuf, cbWritten, NULL, &pThis->OverlappedWrite))
    213         {
    214             DWORD uError = GetLastError();
    215 
    216             if (   uError == ERROR_PIPE_LISTENING
    217                 || uError == ERROR_PIPE_NOT_CONNECTED)
    218             {
    219                 /* No connection yet/anymore; just discard the write (pretening everything was written). */;
    220             }
    221             else if (uError != ERROR_IO_PENDING)
    222             {
    223                 rc = RTErrConvertFromWin32(uError);
    224                 Log(("drvNamedPipeWrite: WriteFile returned %d (%Rrc)\n", uError, rc));
    225                 cbWritten = 0;
    226             }
    227             else
    228             {
    229                 /* Wait for the write to complete. */
    230                 if (GetOverlappedResult(pThis->NamedPipe, &pThis->OverlappedWrite, &cbWritten, TRUE /*bWait*/) == FALSE)
    231                     rc = RTErrConvertFromWin32(uError = GetLastError());
    232             }
    233         }
    234 
    235         if (RT_FAILURE(rc))
    236         {
    237             if (    rc == VERR_EOF
    238                 ||  rc == VERR_BROKEN_PIPE)
    239             {
    240                 FlushFileBuffers(pThis->NamedPipe);
    241                 DisconnectNamedPipe(pThis->NamedPipe);
    242                 if (!pThis->fIsServer)
    243                 {
    244                     CloseHandle(pThis->NamedPipe);
    245                     pThis->NamedPipe = INVALID_HANDLE_VALUE;
    246                 }
    247                 /* pretend success */
    248                 rc = VINF_SUCCESS;
    249             }
    250             cbWritten = 0;
    251         }
     83    if (pThis->OutputFile != NIL_RTFILE)
     84    {
     85        size_t cbWritten;
     86        rc = RTFileWrite(pThis->OutputFile, pvBuf, *pcbWrite, &cbWritten);
     87        if (RT_SUCCESS(rc))
     88            RTFileFlush(pThis->OutputFile);
    25289        *pcbWrite = cbWritten;
    25390    }
    254 #else /* !RT_OS_WINDOWS */
    255     if (pThis->LocalSocket != NIL_RTSOCKET)
    256     {
    257         ssize_t cbWritten;
    258         cbWritten = send(pThis->LocalSocket, pvBuf, *pcbWrite, 0);
    259         if (cbWritten == 0)
    260         {
    261             RTSOCKET tmp = pThis->LocalSocket;
    262             pThis->LocalSocket = NIL_RTSOCKET;
    263             close(tmp);
    264         }
    265         else if (cbWritten == -1)
    266         {
    267             cbWritten = 0;
    268             rc = RTErrConvertFromErrno(errno);
    269         }
    270         *pcbWrite = cbWritten;
    271     }
    272 #endif /* !RT_OS_WINDOWS */
    27391
    27492    LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     
    286104 * @thread  Any thread.
    287105 */
    288 static DECLCALLBACK(void *) drvNamedPipeQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
     106static DECLCALLBACK(void *) drvOutputFileQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
    289107{
    290108    PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
    291     PDRVNAMEDPIPE pDrv = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
     109    PDRVOUTPUTFILE pDrv = PDMINS_2_DATA(pDrvIns, PDRVOUTPUTFILE);
    292110    switch (enmInterface)
    293111    {
     
    302120
    303121
    304 /* -=-=-=-=- listen thread -=-=-=-=- */
    305 
    306 /**
    307  * Receive thread loop.
    308  *
    309  * @returns 0 on success.
    310  * @param   ThreadSelf  Thread handle to this thread.
    311  * @param   pvUser      User argument.
    312  */
    313 static DECLCALLBACK(int) drvNamedPipeListenLoop(RTTHREAD ThreadSelf, void *pvUser)
    314 {
    315     PDRVNAMEDPIPE   pThis = (PDRVNAMEDPIPE)pvUser;
    316     int             rc = VINF_SUCCESS;
    317 #ifdef RT_OS_WINDOWS
    318     HANDLE          NamedPipe = pThis->NamedPipe;
    319     HANDLE          hEvent = CreateEvent(NULL, TRUE, FALSE, 0);
    320 #endif
    321 
    322     while (RT_LIKELY(!pThis->fShutdown))
    323     {
    324 #ifdef RT_OS_WINDOWS
    325         OVERLAPPED overlapped;
    326 
    327         memset(&overlapped, 0, sizeof(overlapped));
    328         overlapped.hEvent = hEvent;
    329 
    330         BOOL fConnected = ConnectNamedPipe(NamedPipe, &overlapped);
    331         if (    !fConnected
    332             &&  !pThis->fShutdown)
    333         {
    334             DWORD hrc = GetLastError();
    335 
    336             if (hrc == ERROR_IO_PENDING)
    337             {
    338                 DWORD dummy;
    339 
    340                 hrc = 0;
    341                 if (GetOverlappedResult(pThis->NamedPipe, &overlapped, &dummy, TRUE) == FALSE)
    342                     hrc = GetLastError();
    343 
    344             }
    345 
    346             if (pThis->fShutdown)
    347                 break;
    348 
    349             if (hrc == ERROR_PIPE_CONNECTED)
    350             {
    351                 RTSemEventWait(pThis->ListenSem, 250);
    352             }
    353             else if (hrc != ERROR_SUCCESS)
    354             {
    355                 rc = RTErrConvertFromWin32(hrc);
    356                 LogRel(("NamedPipe%d: ConnectNamedPipe failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
    357                 break;
    358             }
    359         }
    360 #else /* !RT_OS_WINDOWS */
    361         if (listen(pThis->LocalSocketServer, 0) == -1)
    362         {
    363             rc = RTErrConvertFromErrno(errno);
    364             LogRel(("NamedPipe%d: listen failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
    365             break;
    366         }
    367         int s = accept(pThis->LocalSocketServer, NULL, NULL);
    368         if (s == -1)
    369         {
    370             rc = RTErrConvertFromErrno(errno);
    371             LogRel(("NamedPipe%d: accept failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
    372             break;
    373         }
    374         else
    375         {
    376             if (pThis->LocalSocket != NIL_RTSOCKET)
    377             {
    378                 LogRel(("NamedPipe%d: only single connection supported\n", pThis->pDrvIns->iInstance));
    379                 close(s);
    380             }
    381             else
    382                 pThis->LocalSocket = s;
    383         }
    384 #endif /* !RT_OS_WINDOWS */
    385     }
    386 
    387 #ifdef RT_OS_WINDOWS
    388     CloseHandle(hEvent);
    389 #endif
    390     pThis->ListenThread = NIL_RTTHREAD;
    391     return VINF_SUCCESS;
    392 }
    393 
    394 
    395 /**
    396  * Construct a named pipe stream driver instance.
     122/**
     123 * Construct a raw output stream driver instance.
    397124 *
    398125 * @returns VBox status.
     
    403130 *                      iInstance it's expected to be used a bit in this function.
    404131 */
    405 static DECLCALLBACK(int) drvNamedPipeConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
     132static DECLCALLBACK(int) drvOutputFileConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
    406133{
    407134    int rc;
    408135    char *pszLocation = NULL;
    409     PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
     136    PDRVOUTPUTFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVOUTPUTFILE);
    410137
    411138    /*
     
    414141    pThis->pDrvIns                      = pDrvIns;
    415142    pThis->pszLocation                  = NULL;
    416     pThis->fIsServer                    = false;
    417 #ifdef RT_OS_WINDOWS
    418     pThis->NamedPipe                    = INVALID_HANDLE_VALUE;
    419 #else /* !RT_OS_WINDOWS */
    420     pThis->LocalSocketServer            = NIL_RTSOCKET;
    421     pThis->LocalSocket                  = NIL_RTSOCKET;
    422 #endif /* !RT_OS_WINDOWS */
    423     pThis->ListenThread                 = NIL_RTTHREAD;
     143    pThis->OutputFile                   = NIL_RTFILE;
    424144    pThis->fShutdown                    = false;
    425145    /* IBase */
    426     pDrvIns->IBase.pfnQueryInterface    = drvNamedPipeQueryInterface;
     146    pDrvIns->IBase.pfnQueryInterface    = drvOutputFileQueryInterface;
    427147    /* IStream */
    428     pThis->IStream.pfnRead              = drvNamedPipeRead;
    429     pThis->IStream.pfnWrite             = drvNamedPipeWrite;
     148    pThis->IStream.pfnWrite             = drvOutputFileWrite;
    430149
    431150    /*
    432151     * Read the configuration.
    433152     */
    434     if (!CFGMR3AreValuesValid(pCfgHandle, "Location\0IsServer\0"))
     153    if (!CFGMR3AreValuesValid(pCfgHandle, "Location\0"))
    435154    {
    436155        rc = VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
     
    446165    pThis->pszLocation = pszLocation;
    447166
    448     bool fIsServer;
    449     rc = CFGMR3QueryBool(pCfgHandle, "IsServer", &fIsServer);
     167    rc = RTFileOpen(&pThis->OutputFile, pThis->pszLocation, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE);
    450168    if (RT_FAILURE(rc))
    451169    {
    452         AssertMsgFailed(("Configuration error: query \"IsServer\" resulted in %Rrc.\n", rc));
    453         goto out;
    454     }
    455     pThis->fIsServer = fIsServer;
    456 
    457 #ifdef RT_OS_WINDOWS
    458     if (fIsServer)
    459     {
    460         HANDLE hPipe = CreateNamedPipe(pThis->pszLocation, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 32, 32, 10000, NULL);
    461         if (hPipe == INVALID_HANDLE_VALUE)
    462         {
    463             rc = RTErrConvertFromWin32(GetLastError());
    464             LogRel(("NamedPipe%d: CreateNamedPipe failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
    465             return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create named pipe %s"), pDrvIns->iInstance, pszLocation);
    466         }
    467         pThis->NamedPipe = hPipe;
    468 
    469         rc = RTSemEventCreate(&pThis->ListenSem);
    470         AssertRC(rc);
    471 
    472         rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe");
    473         if RT_FAILURE(rc)
    474             return PDMDrvHlpVMSetError(pDrvIns, rc,  RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance);
    475 
    476     }
    477     else
    478     {
    479         /* Connect to the named pipe. */
    480         HANDLE hPipe = CreateFile(pThis->pszLocation, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    481         if (hPipe == INVALID_HANDLE_VALUE)
    482         {
    483             rc = RTErrConvertFromWin32(GetLastError());
    484             LogRel(("NamedPipe%d: CreateFile failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
    485             return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to connect to named pipe %s"), pDrvIns->iInstance, pszLocation);
    486         }
    487         pThis->NamedPipe = hPipe;
    488     }
    489 
    490     memset(&pThis->OverlappedWrite, 0, sizeof(pThis->OverlappedWrite));
    491     memset(&pThis->OverlappedRead, 0, sizeof(pThis->OverlappedRead));
    492     pThis->OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    493     pThis->OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    494 #else /* !RT_OS_WINDOWS */
    495     int s;
    496     struct sockaddr_un addr;
    497 
    498     if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
    499         return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to create local socket"), pDrvIns->iInstance);
    500 
    501     memset(&addr, 0, sizeof(addr));
    502     addr.sun_family = AF_UNIX;
    503     strncpy(addr.sun_path, pszLocation, sizeof(addr.sun_path)-1);
    504 
    505     if (fIsServer)
    506     {
    507         /* Bind address to the local socket. */
    508         RTFileDelete(pszLocation);
    509         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    510             return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to bind to local socket %s"), pDrvIns->iInstance, pszLocation);
    511         pThis->LocalSocketServer = s;
    512         rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe");
    513         if RT_FAILURE(rc)
    514             return PDMDrvHlpVMSetError(pDrvIns, rc,  RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance);
    515     }
    516     else
    517     {
    518         /* Connect to the local socket. */
    519         if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    520             return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to connect to local socket %s"), pDrvIns->iInstance, pszLocation);
    521         pThis->LocalSocket = s;
    522     }
    523 #endif /* !RT_OS_WINDOWS */
     170        LogRel(("RawFile%d: CreateFile failed rc=%Rrc\n", pThis->pDrvIns->iInstance));
     171        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("RawFile#%d failed to create the raw output file %s"), pDrvIns->iInstance, pszLocation);
     172    }
    524173
    525174out:
     
    528177        if (pszLocation)
    529178            MMR3HeapFree(pszLocation);
    530         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to initialize"), pDrvIns->iInstance);
    531     }
    532 
    533     LogFlow(("drvNamedPipeConstruct: location %s isServer %d\n", pszLocation, fIsServer));
    534     LogRel(("NamedPipe: location %s, %s\n", pszLocation, fIsServer ? "server" : "client"));
     179        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("RawFile#%d failed to initialize"), pDrvIns->iInstance);
     180    }
     181
     182    LogFlow(("drvOutputFileConstruct: location %s\n", pszLocation));
     183    LogRel(("RawFile: location %s\n", pszLocation));
    535184    return VINF_SUCCESS;
    536185}
     
    538187
    539188/**
    540  * Destruct a named pipe stream driver instance.
     189 * Destruct a raw output stream driver instance.
    541190 *
    542191 * Most VM resources are freed by the VM. This callback is provided so that
     
    545194 * @param   pDrvIns     The driver instance data.
    546195 */
    547 static DECLCALLBACK(void) drvNamedPipeDestruct(PPDMDRVINS pDrvIns)
    548 {
    549     PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
     196static DECLCALLBACK(void) drvOutputFileDestruct(PPDMDRVINS pDrvIns)
     197{
     198    PDRVOUTPUTFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVOUTPUTFILE);
    550199    LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
    551 
    552     if (pThis->ListenThread)
    553     {
    554         RTThreadWait(pThis->ListenThread, 250, NULL);
    555         if (pThis->ListenThread != NIL_RTTHREAD)
    556             LogRel(("NamedPipe%d: listen thread did not terminate\n", pDrvIns->iInstance));
    557     }
    558200
    559201    if (pThis->pszLocation)
     
    563205
    564206/**
    565  * Power off a named pipe stream driver instance.
     207 * Power off a raw output stream driver instance.
    566208 *
    567209 * This does most of the destruction work, to avoid ordering dependencies.
     
    569211 * @param   pDrvIns     The driver instance data.
    570212 */
    571 static DECLCALLBACK(void) drvNamedPipePowerOff(PPDMDRVINS pDrvIns)
    572 {
    573     PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE);
     213static DECLCALLBACK(void) drvOutputFilePowerOff(PPDMDRVINS pDrvIns)
     214{
     215    PDRVOUTPUTFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVOUTPUTFILE);
    574216    LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
    575217
    576218    pThis->fShutdown = true;
    577219
    578 #ifdef RT_OS_WINDOWS
    579     if (pThis->NamedPipe != INVALID_HANDLE_VALUE)
    580     {
    581         if (pThis->fIsServer)
    582         {
    583             FlushFileBuffers(pThis->NamedPipe);
    584             DisconnectNamedPipe(pThis->NamedPipe);
    585         }
    586 
    587         CloseHandle(pThis->NamedPipe);
    588         pThis->NamedPipe = INVALID_HANDLE_VALUE;
    589         CloseHandle(pThis->OverlappedRead.hEvent);
    590         CloseHandle(pThis->OverlappedWrite.hEvent);
    591     }
    592     if (pThis->fIsServer)
    593     {
    594         /* Wake up listen thread */
    595         RTSemEventSignal(pThis->ListenSem);
    596         RTSemEventDestroy(pThis->ListenSem);
    597     }
    598 #else /* !RT_OS_WINDOWS */
    599     if (pThis->fIsServer)
    600     {
    601         if (pThis->LocalSocketServer != NIL_RTSOCKET)
    602             close(pThis->LocalSocketServer);
    603         if (pThis->pszLocation)
    604             RTFileDelete(pThis->pszLocation);
    605     }
    606     else
    607     {
    608         if (pThis->LocalSocket != NIL_RTSOCKET)
    609             close(pThis->LocalSocket);
    610     }
    611 #endif /* !RT_OS_WINDOWS */
    612 }
    613 
    614 
    615 /**
    616  * Named pipe driver registration record.
    617  */
    618 const PDMDRVREG g_DrvNamedPipe =
     220    if (pThis->OutputFile != NIL_RTFILE)
     221        RTFileClose(pThis->OutputFile);
     222}
     223
     224
     225/**
     226 * Raw file driver registration record.
     227 */
     228const PDMDRVREG g_DrvRawFile =
    619229{
    620230    /* u32Version */
    621231    PDM_DRVREG_VERSION,
    622232    /* szDriverName */
    623     "NamedPipe",
     233    "RawFile",
    624234    /* pszDescription */
    625     "Named Pipe stream driver.",
     235    "RawFile stream driver.",
    626236    /* fFlags */
    627237    PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
     
    631241    ~0,
    632242    /* cbInstance */
    633     sizeof(DRVNAMEDPIPE),
     243    sizeof(DRVOUTPUTFILE),
    634244    /* pfnConstruct */
    635     drvNamedPipeConstruct,
     245    drvOutputFileConstruct,
    636246    /* pfnDestruct */
    637     drvNamedPipeDestruct,
     247    drvOutputFileDestruct,
    638248    /* pfnIOCtl */
    639249    NULL,
     
    649259    NULL,
    650260    /* pfnPowerOff */
    651     drvNamedPipePowerOff,
     261    drvOutputFilePowerOff,
    652262};
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp

    r19377 r19624  
    181181                 "                                             server <pipe>|\n"
    182182                 "                                             client <pipe>|\n"
     183                 "                                             file <file>|\n"
    183184                 "                                             <devicename>]\n"
    184185#ifdef VBOX_WITH_MEM_BALLOONING
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp

    r19622 r19624  
    849849                            RTPrintf(", disconnected\n");
    850850                        break;
     851                    case PortMode_RawFile:
     852                        if (details == VMINFO_MACHINEREADABLE)
     853                            RTPrintf("uartmode%d=\"%lS\"\n", currentUART + 1,
     854                                     path.raw());
     855                        else
     856                            RTPrintf(", attached to raw file '%lS'\n",
     857                                     path.raw());
     858                        break;
    851859                    case PortMode_HostPipe:
    852860                        if (details == VMINFO_MACHINEREADABLE)
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp

    r19377 r19624  
    17321732                        CHECK_ERROR_RET(uart, COMSETTER(Server) (FALSE), 1);
    17331733                    }
     1734                    else if (!strcmp(uarts_mode[n], "file"))
     1735                    {
     1736                        CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_RawFile), 1);
     1737                    }
    17341738                    else
    17351739                    {
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp

    r19258 r19624  
    19511951                        toCOMPortName (port.GetIRQ(), port.GetIOBase()) + ", ";
    19521952                    if (mode == KPortMode_HostPipe ||
    1953                         mode == KPortMode_HostDevice)
     1953                        mode == KPortMode_HostDevice ||
     1954                        mode == KPortMode_RawFile)
    19541955                        data += QString ("%1 (<nobr>%2</nobr>)")
    19551956                            .arg (vboxGlobal().toString (mode))
     
    28852886    mPortModeTypes [KPortMode_HostPipe] =       tr ("Host Pipe", "PortMode");
    28862887    mPortModeTypes [KPortMode_HostDevice] =     tr ("Host Device", "PortMode");
     2888    mPortModeTypes [KPortMode_RawFile] =        tr ("Raw File", "PortMode");
    28872889
    28882890    mUSBFilterActionTypes [KUSBDeviceFilterAction_Ignore] =
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsSerial.cpp

    r13580 r19624  
    5252    mCbMode->addItem (""); /* KPortMode_HostPipe */
    5353    mCbMode->addItem (""); /* KPortMode_HostDevice */
     54    mCbMode->addItem (""); /* KPortMode_RawFile */
    5455
    5556    /* Setup connections */
     
    147148    mCbNumber->setItemText (mCbNumber->count() - 1, vboxGlobal().toCOMPortName (0, 0));
    148149
     150    mCbMode->setItemText (3, vboxGlobal().toString (KPortMode_RawFile));
    149151    mCbMode->setItemText (2, vboxGlobal().toString (KPortMode_HostDevice));
    150152    mCbMode->setItemText (1, vboxGlobal().toString (KPortMode_HostPipe));
  • trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsSerial.ui

    r11951 r19624  
    184184       <widget class="QLabel" name="mLbPath" >
    185185        <property name="text" >
    186          <string>Port &amp;Path:</string>
     186         <string>Port/File &amp;Path:</string>
    187187        </property>
    188188        <property name="alignment" >
  • trunk/src/VBox/Main/ConsoleImpl2.cpp

    r19410 r19624  
    21052105                rc = CFGMR3InsertString(pLunL1,  "DevicePath", Utf8Str(path));      RC_CHECK();
    21062106            }
     2107            else if (HostMode == PortMode_RawFile)
     2108            {
     2109                rc = CFGMR3InsertString(pLunL0,  "Driver", "Char");                 RC_CHECK();
     2110                rc = CFGMR3InsertNode(pLunL0,    "AttachedDriver", &pLunL1);        RC_CHECK();
     2111                rc = CFGMR3InsertString(pLunL1,  "Driver", "RawFile");              RC_CHECK();
     2112                rc = CFGMR3InsertNode(pLunL1,    "Config", &pLunL2);                RC_CHECK();
     2113                rc = CFGMR3InsertString(pLunL2,  "Location", Utf8Str(path));        RC_CHECK();
     2114            }
    21072115        }
    21082116    }
  • trunk/src/VBox/Main/SerialPortImpl.cpp

    r16560 r19624  
    204204    /* host mode (required) */
    205205    const char *mode = aPortNode.stringValue ("hostMode");
    206     if (strcmp (mode, "HostPipe") == 0)
     206    if (strcmp (mode, "RawFile") == 0)
     207        mData->mHostMode = PortMode_RawFile;
     208    else if (strcmp (mode, "HostPipe") == 0)
    207209        mData->mHostMode = PortMode_HostPipe;
    208210    else if (strcmp (mode, "HostDevice") == 0)
     
    261263            mode = "HostDevice";
    262264            break;
     265        case PortMode_RawFile:
     266            mode = "RawFile";
     267            break;
    263268        default:
    264269            ComAssertMsgFailedRet (("Invalid serial port mode: %d",
     
    432437        switch (aHostMode)
    433438        {
     439            case PortMode_RawFile:
     440                if (mData->mPath.isEmpty())
     441                    return setError (E_INVALIDARG,
     442                        tr ("Cannot set the raw file mode of the serial port %d "
     443                            "because the file path is empty or null"),
     444                        mData->mSlot);
     445                break;
    434446            case PortMode_HostPipe:
    435447                if (mData->mPath.isEmpty())
     
    611623
    612624    if ((mData->mHostMode == PortMode_HostDevice ||
    613          mData->mHostMode == PortMode_HostPipe) &&
     625         mData->mHostMode == PortMode_HostPipe ||
     626         mData->mHostMode == PortMode_RawFile) &&
    614627        (aPath == NULL || *aPath == '\0'))
    615628        return setError (E_INVALIDARG,
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r19249 r19624  
    1109011090      <desc>Virtual device is attached to a host device.</desc>
    1109111091    </const>
     11092    <const name="RawFile"             value="3">
     11093      <desc>Virtual device is attached to a raw file.</desc>
     11094    </const>
    1109211095  </enum>
    1109311096
  • trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd

    r18591 r19624  
    247247  <xsd:restriction base="xsd:string">
    248248    <xsd:enumeration value="Disconnected"/>
     249    <xsd:enumeration value="RawFile"/>
    249250    <xsd:enumeration value="HostPipe"/>
    250251    <xsd:enumeration value="HostDevice"/>
Note: See TracChangeset for help on using the changeset viewer.

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