vbsf.cpp revision 3e04f45aeb634f1256d0510780bf77d4fdefd926
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @file
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Shared Folders:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VBox Shared Folders.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync/*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copyright (C) 2006-2007 innotek GmbH
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License as published by the Free Software Foundation,
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync */
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync#include "mappings.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "vbsf.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "shflhandle.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/alloc.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/assert.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/fs.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/dir.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/file.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/path.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/string.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/uni.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync#undef LogFlow
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define LogFlow Log
48d60b042893290a747d3abeda71a3085d9133fdvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncvoid vbsfStripLastComponent (char *pszFullPath, uint32_t cbFullPathRoot)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTUNICP cp;
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Do not strip root. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *s = pszFullPath + cbFullPathRoot;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *delimSecondLast = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *delimLast = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("%s -> %s\n", pszFullPath, s));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (;;)
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cp = RTStrGetCp(s);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cp == RTUNICP_INVALID || cp == 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync }
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cp == RTPATH_DELIMITER)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (delimLast != NULL)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync delimSecondLast = delimLast;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync delimLast = s;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync s = RTStrNextCp (s);
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync if (cp == 0)
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync {
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync if (delimLast + 1 == s)
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync {
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync if (delimSecondLast)
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync {
48d60b042893290a747d3abeda71a3085d9133fdvboxsync *delimSecondLast = 0;
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else if (delimLast)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *delimLast = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (delimLast)
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *delimLast = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowFunc(("%s, %s, %s\n", pszFullPath, delimLast, delimSecondLast));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsyncstatic int vbsfCorrectCasing(char *pszFullPath, char *pszStartComponent)
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync{
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync PRTDIRENTRYEX pDirEntry = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t cbDirEntry, cbComponent;
6c83eb6b98d1dd1b1d9795c16801ee2f53d2cc31vboxsync int rc = VERR_FILE_NOT_FOUND;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTDIR hSearch = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char szWildCard[4];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log2(("vbsfCorrectCasing: %s %s\n", pszFullPath, pszStartComponent));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cbComponent = strlen(pszStartComponent);
86b620001857a05e9e7b83b11525094c34637e23vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cbDirEntry = 4096;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pDirEntry = (PRTDIRENTRYEX)RTMemAlloc(cbDirEntry);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pDirEntry == 0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertFailed();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_NO_MEMORY;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo this is quite inefficient, especially for directories with many files */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pszFullPath < pszStartComponent-1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(*(pszStartComponent-1) == RTPATH_DELIMITER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *(pszStartComponent-1) = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync strcpy(pDirEntry->szName, pszFullPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync szWildCard[0] = RTPATH_DELIMITER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync szWildCard[1] = '*';
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync szWildCard[2] = 0;
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync strcat(pDirEntry->szName, szWildCard);
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync rc = RTDirOpenFiltered (&hSearch, pDirEntry->szName, RTDIRFILTER_WINNT);
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync *(pszStartComponent-1) = RTPATH_DELIMITER;
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync if (VBOX_FAILURE(rc))
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync goto end;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for(;;)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t cbDirEntrySize = cbDirEntry;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTDirReadEx(hSearch, pDirEntry, &cbDirEntrySize, RTFSOBJATTRADD_NOTHING);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc == VERR_NO_MORE_FILES)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VINF_SUCCESS != rc && rc != VWRN_NO_DIRENT_INFO)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertFailed();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc != VERR_NO_TRANSLATION)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync continue;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log2(("vbsfCorrectCasing: found %s\n", &pDirEntry->szName[0]));
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync if ( pDirEntry->cbName == cbComponent
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync && !RTStrICmp(pszStartComponent, &pDirEntry->szName[0]))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync Log(("Found original name %s (%s)\n", &pDirEntry->szName[0], pszStartComponent));
48d60b042893290a747d3abeda71a3085d9133fdvboxsync strcpy(pszStartComponent, &pDirEntry->szName[0]);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncend:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("vbsfCorrectCasing %s failed with %d\n", pszStartComponent, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pDirEntry)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMemFree(pDirEntry);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (hSearch)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTDirClose(hSearch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vbsfBuildFullPath (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pPath,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t cbPath, char **ppszFullPath, uint32_t *pcbFullPathRoot, bool fWildCard = false)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszFullPath = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Query UCS2 root prefix for the path, cbRoot is the length in bytes including trailing (RTUCS2)0. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t cbRoot = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const RTUCS2 *pszRoot = vbsfMappingsQueryHostRoot (root, &cbRoot);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pszRoot || cbRoot == 0)
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_INVALID_PARAMETER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *utf8Root;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTUtf16ToUtf8 (pszRoot, &utf8Root);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_SUCCESS (rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync size_t cbUtf8Root, cbUtf8FullPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *utf8FullPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cbUtf8Root = strlen (utf8Root);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cbUtf8FullPath = cbUtf8Root + 1 + pPath->u16Length + 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync utf8FullPath = (char *) RTMemAllocZ (cbUtf8FullPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!utf8FullPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_NO_MEMORY;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *ppszFullPath = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy (utf8FullPath, utf8Root, cbUtf8Root);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy (utf8FullPath + cbUtf8Root + 1,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync &pPath->String.utf8[0],
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pPath->u16Length);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync utf8FullPath[cbUtf8Root] = '/';
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync utf8FullPath[cbUtf8FullPath - 1] = 0;
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync pszFullPath = utf8FullPath;
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync if (pcbFullPathRoot)
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync *pcbFullPathRoot = cbUtf8Root; /* Must index the path delimiter. */
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync }
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync RTStrFree (utf8Root);
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log (("vbsfBuildFullPath: RTUtf16ToUtf8 failed with %Vrc\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Client sends us UCS2, so convert it to UTF8. */
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync Log(("Root %ls path %.*ls\n", pszRoot, pPath->u16Length/sizeof(pPath->String.ucs2[0]), pPath->String.ucs2));
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync /* Allocate buffer that will be able to contain
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the root prefix and the pPath converted to UTF8.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Expect a 2 bytes UCS2 to be converted to 8 bytes UTF8
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * in worst case.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t cbFullPath = (cbRoot/sizeof (RTUCS2) + ShflStringLength (pPath)) * 4;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszFullPath = (char *)RTMemAllocZ (cbFullPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pszFullPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_NO_MEMORY;
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t cb = cbFullPath;
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTStrUcs2ToUtf8Ex (&pszFullPath, cb, pszRoot);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync AssertFailed();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *dst = pszFullPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cbRoot = strlen(dst);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (dst[cbRoot - 1] != RTPATH_DELIMITER)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync dst[cbRoot] = RTPATH_DELIMITER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cbRoot++;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pcbFullPathRoot)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *pcbFullPathRoot = cbRoot - 1; /* Must index the path delimiter. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync dst += cbRoot;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cb -= cbRoot;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pPath->u16Length)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Convert and copy components. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTUCS2 *src = &pPath->String.ucs2[0];
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Correct path delimiters */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pClient->PathDelimiter != RTPATH_DELIMITER)
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("Correct path delimiter in %ls\n", src));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while (*src)
fa92c704624def98d3c4aca86d65182effb98e04vboxsync {
fa92c704624def98d3c4aca86d65182effb98e04vboxsync if (*src == pClient->PathDelimiter)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *src = RTPATH_DELIMITER;
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync src++;
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync src = &pPath->String.ucs2[0];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("Corrected string %ls\n", src));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (*src == RTPATH_DELIMITER)
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync src++; /* we already appended a delimiter to the first part */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTStrUcs2ToUtf8Ex (&dst, cb, src);
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync if (VBOX_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertFailed();
fa92c704624def98d3c4aca86d65182effb98e04vboxsync return rc;
fa92c704624def98d3c4aca86d65182effb98e04vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync uint32_t l = strlen (dst);
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cb -= l;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync dst += l;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(cb > 0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Nul terminate the string */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *dst = 0;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_SUCCESS (rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* When the host file system is case sensitive and the guest expects a case insensitive fs, then problems can occur */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( vbsfIsHostMappingCaseSensitive (root)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && !vbsfIsGuestMappingCaseSensitive(root))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTFSOBJINFO info;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *pszWildCardComponent = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (fWildCard)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync /* strip off the last path component, that contains the wildcard(s) */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t len = strlen(pszFullPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *src = pszFullPath + len - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while(src > pszFullPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (*src == RTPATH_DELIMITER)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync src--;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync if (*src == RTPATH_DELIMITER)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fHaveWildcards = false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *temp = src;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync while(*temp)
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync {
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync char uc = *temp;
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync if (uc == '*' || uc == '?' || uc == '>' || uc == '<' || uc == '"')
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync {
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync fHaveWildcards = true;
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync break;
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync }
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync temp++;
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync }
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync if (fHaveWildcards)
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync {
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync pszWildCardComponent = src;
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync *pszWildCardComponent = 0;
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync }
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync }
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync }
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync /** @todo don't check when creating files or directories; waste of time */
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync rc = RTPathQueryInfo(pszFullPath, &info, RTFSOBJATTRADD_NOTHING);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t len = strlen(pszFullPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync char *src = pszFullPath + len - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("Handle case insenstive guest fs on top of host case sensitive fs for %s\n", pszFullPath));
ada08ea58e7613c10d4c40669fd4fb955324bfdfvboxsync
ada08ea58e7613c10d4c40669fd4fb955324bfdfvboxsync /* Find partial path that's valid */
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync while(src > pszFullPath)
ada08ea58e7613c10d4c40669fd4fb955324bfdfvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (*src == RTPATH_DELIMITER)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
5cd35366dd244ca8c8c583904fc6ff2a0c60fa0fvboxsync *src = 0;
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync rc = RTPathQueryInfo (pszFullPath, &info, RTFSOBJATTRADD_NOTHING);
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync *src = RTPATH_DELIMITER;
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync if (rc == VINF_SUCCESS)
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync {
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync#ifdef DEBUG
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync *src = 0;
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync Log(("Found valid partial path %s\n", pszFullPath));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *src = RTPATH_DELIMITER;
43d3e60a2bcef646da0887a845e67c3a47759158vboxsync#endif
48d60b042893290a747d3abeda71a3085d9133fdvboxsync break;
48d60b042893290a747d3abeda71a3085d9133fdvboxsync }
48d60b042893290a747d3abeda71a3085d9133fdvboxsync }
48d60b042893290a747d3abeda71a3085d9133fdvboxsync
48d60b042893290a747d3abeda71a3085d9133fdvboxsync src--;
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync }
48d60b042893290a747d3abeda71a3085d9133fdvboxsync Assert(*src == RTPATH_DELIMITER && VBOX_SUCCESS(rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( *src == RTPATH_DELIMITER
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && VBOX_SUCCESS(rc))
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync {
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync src++;
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync for(;;)
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync {
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync char *end = src;
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync bool fEndOfString = true;
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync while(*end)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
5cd35366dd244ca8c8c583904fc6ff2a0c60fa0fvboxsync if (*end == RTPATH_DELIMITER)
43d3e60a2bcef646da0887a845e67c3a47759158vboxsync break;
f20f327b65009074292a4b9ad44a02b6bfb2de8avboxsync end++;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (*end == RTPATH_DELIMITER)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync {
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync fEndOfString = false;
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync *end = 0;
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync rc = RTPathQueryInfo(src, &info, RTFSOBJATTRADD_NOTHING);
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync Assert(rc == VINF_SUCCESS || rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND);
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync }
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync else
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync if (end == src)
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync rc = VINF_SUCCESS; /* trailing delimiter */
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync else
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync rc = VERR_FILE_NOT_FOUND;
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync {
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync /* path component is invalid; try to correct the casing */
da2ac963e5567d049d02bad0ad7783a0b9181637vboxsync rc = vbsfCorrectCasing(pszFullPath, src);
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync if (VBOX_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!fEndOfString)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *end = RTPATH_DELIMITER; /* restore the original full path */
f20f327b65009074292a4b9ad44a02b6bfb2de8avboxsync break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync if (fEndOfString)
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync break;
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync *end = RTPATH_DELIMITER;
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync src = end + 1;
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync }
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync if (VBOX_FAILURE(rc))
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync Log(("Unable to find suitable component rc=%d\n", rc));
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync }
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync else
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync rc = VERR_FILE_NOT_FOUND;
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync }
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync if (pszWildCardComponent)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync *pszWildCardComponent = RTPATH_DELIMITER;
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync /* might be a new file so don't fail here! */
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *ppszFullPath = pszFullPath;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vbsfBuildFullPath: %s\n", pszFullPath));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void vbsfFreeFullPath (char *pszFullPath)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMemFree (pszFullPath);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsyncstatic int vbsfOpenFile (SHFLHANDLE *phHandle, const char *pszPath, SHFLCREATEPARMS *pParms, bool fCreate)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vbsfOpenFile: pszPath = %s, pParms = %p, fCreate = %d\n",
f20f327b65009074292a4b9ad44a02b6bfb2de8avboxsync pszPath, pParms, fCreate));
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo r=bird: You should've requested a better RTFileOpen API! This code could certainly have
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * benefitted from it. I've done the long overdue adjustment of RTFileOpen so it better reflect
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * what a decent OS should be able to do. I've also added some OS specific flags (non-blocking,
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * delete sharing), and I'm not picky about adding more if that required. (I'm only picky about
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * how they are treated on platforms which doesn't support them.)
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync * Because of the restrictions in the old version of RTFileOpen this code contains dangerous race
10eaaac806009b8336cc5d746fe5072f6c9f58c0vboxsync * conditions. File creation is one example where you may easily kill a file just created by
ef5b48babdb77b6bcc17a490cbbd0eef5e46e9fcvboxsync * another user.
ef5b48babdb77b6bcc17a490cbbd0eef5e46e9fcvboxsync */
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync /* Open or create a file. */
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync unsigned fOpen;
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync Log(("SHFL create flags %08x\n", pParms->CreateFlags));
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY))
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync {
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync fOpen = RTFILE_O_OPEN;
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync }
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync else
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync fOpen = fCreate? RTFILE_O_CREATE_REPLACE: RTFILE_O_OPEN;
3c292c68aeb0a95090706381edf33b886c81afd1vboxsync
3c292c68aeb0a95090706381edf33b886c81afd1vboxsync switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACCESS_MASK_RW))
3c292c68aeb0a95090706381edf33b886c81afd1vboxsync {
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync default:
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync case SHFL_CF_ACCESS_NONE:
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync {
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync /** @todo treat this as read access, but theoretically this could be a no access requested. */
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync fOpen |= RTFILE_O_READ;
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync Log(("FLAG: SHFL_CF_ACCESS_NONE\n"));
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync break;
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync }
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync case SHFL_CF_ACCESS_READ:
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync {
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync fOpen |= RTFILE_O_READ;
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync Log(("FLAG: SHFL_CF_ACCESS_READ\n"));
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync break;
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync }
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync case SHFL_CF_ACCESS_WRITE:
395ac8a20a012656020c61a3975493a65fee0e77vboxsync {
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync fOpen |= RTFILE_O_WRITE;
395ac8a20a012656020c61a3975493a65fee0e77vboxsync Log(("FLAG: SHFL_CF_ACCESS_WRITE\n"));
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync break;
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SHFL_CF_ACCESS_READWRITE:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
f20f327b65009074292a4b9ad44a02b6bfb2de8avboxsync fOpen |= RTFILE_O_READWRITE;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync Log(("FLAG: SHFL_CF_ACCESS_READWRITE\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync }
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync /* Sharing mask */
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACCESS_MASK_DENY))
10eaaac806009b8336cc5d746fe5072f6c9f58c0vboxsync {
1bc5a31ae6d57c2b4731a23205f3958678b60193vboxsync default:
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync case SHFL_CF_ACCESS_DENYNONE:
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync fOpen |= RTFILE_O_DENY_NONE;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync Log(("FLAG: SHFL_CF_ACCESS_DENYNONE\n"));
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync break;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync case SHFL_CF_ACCESS_DENYREAD:
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync fOpen |= RTFILE_O_DENY_READ;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync Log(("FLAG: SHFL_CF_ACCESS_DENYREAD\n"));
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync break;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync case SHFL_CF_ACCESS_DENYWRITE:
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync fOpen |= RTFILE_O_DENY_WRITE;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync Log(("FLAG: SHFL_CF_ACCESS_DENYWRITE\n"));
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync break;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SHFL_CF_ACCESS_DENYALL:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync fOpen |= RTFILE_O_DENY_ALL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("FLAG: SHFL_CF_ACCESS_DENYALL\n"));
f20f327b65009074292a4b9ad44a02b6bfb2de8avboxsync break;
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SHFLHANDLE handle;
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync SHFLFILEHANDLE *pHandle;
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync
b0d29fd0a868929a608ff72658aac997cc95319avboxsync if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY))
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync {
b0d29fd0a868929a608ff72658aac997cc95319avboxsync handle = vbsfAllocDirHandle();
b0d29fd0a868929a608ff72658aac997cc95319avboxsync pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_DIR);
b0d29fd0a868929a608ff72658aac997cc95319avboxsync }
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync else
b0d29fd0a868929a608ff72658aac997cc95319avboxsync {
b0d29fd0a868929a608ff72658aac997cc95319avboxsync handle = vbsfAllocFileHandle();
b0d29fd0a868929a608ff72658aac997cc95319avboxsync pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_FILE);
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync }
b0d29fd0a868929a608ff72658aac997cc95319avboxsync
b0d29fd0a868929a608ff72658aac997cc95319avboxsync if (pHandle == NULL)
b0d29fd0a868929a608ff72658aac997cc95319avboxsync {
b0d29fd0a868929a608ff72658aac997cc95319avboxsync rc = VERR_NO_MEMORY;
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync }
b0d29fd0a868929a608ff72658aac997cc95319avboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Must obviously create the directory, before trying to open it. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (fCreate)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo render supplied attributes.
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync * bird: The guest should specify this. For windows guests RTFS_DOS_DIRECTORY should suffice. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTFMODE fMode = 0777;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTDirCreate(pszPath, fMode);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vbsfFreeHandle (handle);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Open the directory now */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_SUCCESS(rc))
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync {
6c83eb6b98d1dd1b1d9795c16801ee2f53d2cc31vboxsync rc = RTDirOpen (&pHandle->dir.Handle, pszPath);
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync if (VBOX_FAILURE (rc))
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync {
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync vbsfFreeHandle (handle);
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync *phHandle = SHFL_HANDLE_NIL;
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync return rc;
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync }
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync }
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync }
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
86b620001857a05e9e7b83b11525094c34637e23vboxsync rc = RTFileOpen(&pHandle->file.Handle, pszPath, fOpen);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_SUCCESS (rc))
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *phHandle = handle;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
86b620001857a05e9e7b83b11525094c34637e23vboxsync vbsfFreeHandle (handle);
86b620001857a05e9e7b83b11525094c34637e23vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vbsfOpenFile: rc = %Vrc\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vbsfOpenExisting (const char *pszFullPath, SHFLCREATEPARMS *pParms)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vbsfOpenExisting: pszFullPath = %s, pParms = %p\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszFullPath, pParms));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync /* Open file. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SHFLHANDLE handle;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = vbsfOpenFile (&handle, pszFullPath, pParms, false);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_SUCCESS (rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pParms->Handle = handle;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vbsfOpenExisting: rc = %d\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vbsfOpenReplace (const char *pszPath, SHFLCREATEPARMS *pParms, bool bReplace, RTFSOBJINFO *pInfo)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vbsfOpenReplace: pszPath = %s, pParms = %p, bReplace = %d\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszPath, pParms, bReplace));
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Replace operation is not applicable to a directory. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_INVALID_PARAMETER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync SHFLHANDLE handle = SHFL_HANDLE_NIL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SHFLFILEHANDLE *pHandle;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = vbsfOpenFile (&handle, pszPath, pParms, true);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync // We are loosing an information regarding the cause of failure here
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync // -- malc
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_FILE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pHandle)
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertFailed();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_INVALID_HANDLE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_SUCCESS (rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Set new file attributes */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTFileSetSize(pHandle->file.Handle, pParms->Info.cbObject);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc != VINF_SUCCESS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg(rc == VINF_SUCCESS, ("RTFileSetSize failed with %d\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (bReplace)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if 0
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* @todo */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Set new attributes. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTFileSetTimes(pHandle->file.Handle,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync &pParms->Info.AccessTime,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync &pParms->Info.ModificationTime,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync &pParms->Info.ChangeTime,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync &pParms->Info.BirthTime
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync );
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTFileSetMode (pHandle->file.Handle, pParms->Info.Attr.fMode);
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync#endif
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pParms->Result = SHFL_FILE_REPLACED;
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync pParms->Handle = handle;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync LogFlow(("vbsfOpenReplace: rc = %Vrc\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int vbsfOpenCreate (const char *pszPath, SHFLCREATEPARMS *pParms)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("vbsfOpenCreate: pszPath = %s, pParms = %p\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pszPath, pParms));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SHFLHANDLE handle = SHFL_HANDLE_NIL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync SHFLFILEHANDLE *pHandle;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = vbsfOpenFile (&handle, pszPath, pParms, true);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(handle, SHFL_HF_TYPE_FILE | SHFL_HF_TYPE_DIR);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pHandle)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertFailed();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VERR_INVALID_HANDLE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (VBOX_SUCCESS (rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#if 0
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync if (!BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* @todo */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTFileSetSize(pHandle->file.Handle, pParms->Info.cbObject);
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTFileSetTimes(pHandle->file.Handle,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync &pParms->Info.AccessTime,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync &pParms->Info.ModificationTime,
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync &pParms->Info.ChangeTime,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync &pParms->Info.BirthTime
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync );
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTFileSetMode (pHandle->file.Handle, pParms->Info.Attr.fMode);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync#endif
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync pParms->Result = SHFL_FILE_CREATED;
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync pParms->Handle = handle;
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync }
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync LogFlow(("vbsfOpenCreate: rc = %Vrc\n", rc));
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync return rc;
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync}
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsyncstatic int vbsfCloseDir (SHFLFILEHANDLE *pHandle)
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync{
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync int rc = VINF_SUCCESS;
LogFlow(("vbsfCloseDir: Handle = %08X Search Handle = %08X\n",
pHandle->dir.Handle, pHandle->dir.SearchHandle));
RTDirClose (pHandle->dir.Handle);
if (pHandle->dir.SearchHandle)
RTDirClose(pHandle->dir.SearchHandle);
if (pHandle->dir.pLastValidEntry)
{
RTMemFree(pHandle->dir.pLastValidEntry);
pHandle->dir.pLastValidEntry = NULL;
}
LogFlow(("vbsfCloseDir: rc = %d\n", rc));
return rc;
}
static int vbsfCloseFile (SHFLFILEHANDLE *pHandle)
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfCloseFile: Handle = %08X\n",
pHandle->file.Handle));
rc = RTFileClose (pHandle->file.Handle);
LogFlow(("vbsfCloseFile: rc = %d\n", rc));
return rc;
}
int vbsfCreate (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pPath, uint32_t cbPath, SHFLCREATEPARMS *pParms)
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfCreate: pClient = %p, pPath = %p, cbPath = %d, pParms = %p\n",
pClient, pPath, cbPath, pParms));
/* Check the client access rights to the root. */
/** @todo */
/* Build a host full path for the given path
* and convert ucs2 to utf8 if necessary.
*/
char *pszFullPath = NULL;
uint32_t cbFullPathRoot = 0;
rc = vbsfBuildFullPath (pClient, root, pPath, cbPath, &pszFullPath, &cbFullPathRoot);
/* @todo This mess needs to change. RTFileOpen supports all the open/creation methods */
if (VBOX_SUCCESS (rc))
{
/* Reset return values in case client forgot to do so. */
pParms->Result = SHFL_NO_RESULT;
pParms->Handle = SHFL_HANDLE_NIL;
/* Query path information. */
RTFSOBJINFO info;
/** r=bird: This is likely to create race conditions.
* What is a file now can be a directory when you open it. */
rc = RTPathQueryInfo (pszFullPath, &info, RTFSOBJATTRADD_NOTHING);
Log2(("RTPathQueryInfo returned %Vrc\n", rc));
if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_LOOKUP))
{
Log2(("SHFL_CF_LOOKUP\n"));
/* Client just wants to know if the object exists. */
switch (rc)
{
case VINF_SUCCESS:
{
pParms->Info = info;
pParms->Result = SHFL_FILE_EXISTS;
break;
}
case VERR_FILE_NOT_FOUND:
{
pParms->Result = SHFL_FILE_NOT_FOUND;
rc = VINF_SUCCESS;
break;
}
case VERR_PATH_NOT_FOUND:
{
pParms->Result = SHFL_PATH_NOT_FOUND;
rc = VINF_SUCCESS;
break;
}
}
}
else if (rc == VINF_SUCCESS)
{
/* File object exists. */
pParms->Result = SHFL_FILE_EXISTS;
/* Mark it as a directory in case the caller didn't. */
if (BIT_FLAG(info.Attr.fMode, RTFS_DOS_DIRECTORY))
{
pParms->CreateFlags |= SHFL_CF_DIRECTORY;
}
if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_OPEN_TARGET_DIRECTORY))
{
pParms->Info = info;
vbsfStripLastComponent (pszFullPath, cbFullPathRoot);
rc = vbsfOpenExisting (pszFullPath, pParms);
}
else
{
if ( BIT_FLAG(pParms->CreateFlags, SHFL_CF_DIRECTORY)
&& !BIT_FLAG(info.Attr.fMode, RTFS_DOS_DIRECTORY))
{
/* Caller wanted a directory but the existing object is not a directory.
* Do not open the object then.
*/
; /* do nothing */
}
else
{
switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_EXISTS))
{
case SHFL_CF_ACT_OPEN_IF_EXISTS:
{
pParms->Info = info;
rc = vbsfOpenExisting (pszFullPath, pParms);
break;
}
case SHFL_CF_ACT_FAIL_IF_EXISTS:
{
/* NIL handle value will tell client that object was not opened.
* Just copy information about the object.
*/
pParms->Info = info;
break;
}
case SHFL_CF_ACT_REPLACE_IF_EXISTS:
{
rc = vbsfOpenReplace (pszFullPath, pParms, true, &info);
break;
}
case SHFL_CF_ACT_OVERWRITE_IF_EXISTS:
{
rc = vbsfOpenReplace (pszFullPath, pParms, false, &info);
pParms->Info = info;
break;
}
default:
{
rc = VERR_INVALID_PARAMETER;
}
}
}
}
}
else
if (rc == VERR_FILE_NOT_FOUND)
{
Log2(("pParms->CreateFlags = %x\n", pParms->CreateFlags));
rc = VINF_SUCCESS;
/* File object does not exist. */
pParms->Result = SHFL_FILE_NOT_FOUND;
if (BIT_FLAG(pParms->CreateFlags, SHFL_CF_OPEN_TARGET_DIRECTORY))
{
switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_NEW))
{
case SHFL_CF_ACT_CREATE_IF_NEW:
{
rc = vbsfOpenCreate (pszFullPath, pParms);
break;
}
case SHFL_CF_ACT_FAIL_IF_NEW:
{
/* NIL handle value will tell client that object was not created. */
pParms->Result = SHFL_PATH_NOT_FOUND;
break;
}
default:
{
rc = VERR_INVALID_PARAMETER;
break;
}
}
}
else
{
switch (BIT_FLAG(pParms->CreateFlags, SHFL_CF_ACT_MASK_IF_NEW))
{
case SHFL_CF_ACT_CREATE_IF_NEW:
{
rc = vbsfOpenCreate (pszFullPath, pParms);
break;
}
case SHFL_CF_ACT_FAIL_IF_NEW:
{
/* NIL handle value will tell client that object was not created. */
break;
}
default:
{
rc = VERR_INVALID_PARAMETER;
}
}
}
}
else
if (rc == VERR_PATH_NOT_FOUND)
{
rc = VINF_SUCCESS;
pParms->Result = SHFL_PATH_NOT_FOUND;
}
if (rc == VINF_SUCCESS && pParms->Handle != SHFL_HANDLE_NIL)
{
uint32_t bufsize = sizeof(pParms->Info);
rc = vbsfQueryFileInfo(pClient, root, pParms->Handle, SHFL_INFO_GET|SHFL_INFO_FILE, &bufsize, (uint8_t *)&pParms->Info);
AssertRC(rc);
}
/* free the path string */
vbsfFreeFullPath(pszFullPath);
}
Log(("vbsfCreate: handle = %RX64 rc = %Vrc\n", (uint64_t)pParms->Handle, rc));
return rc;
}
int vbsfClose (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle)
{
int rc = VINF_SUCCESS;
LogFlow(("vbsfClose: pClient = %p, Handle = %RX64\n",
pClient, Handle));
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE);
Assert(pHandle);
if (!pHandle)
return VERR_INVALID_HANDLE;
switch (ShflHandleType (&pHandle->Header))
{
case SHFL_HF_TYPE_DIR:
{
rc = vbsfCloseDir (pHandle);
break;
}
case SHFL_HF_TYPE_FILE:
{
rc = vbsfCloseFile (pHandle);
break;
}
}
vbsfFreeHandle(Handle);
Log(("vbsfClose: rc = %Rrc\n", rc));
return rc;
}
int vbsfRead (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_FILE);
size_t count = 0;
int rc;
if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
Log(("vbsfRead %RX64 offset %RX64 bytes %x\n", Handle, offset, *pcbBuffer));
if (*pcbBuffer == 0)
return VINF_SUCCESS; /* @todo correct? */
rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL);
if (rc != VINF_SUCCESS)
{
AssertRC(rc);
return rc;
}
rc = RTFileRead(pHandle->file.Handle, pBuffer, *pcbBuffer, &count);
*pcbBuffer = (uint32_t)count;
Log(("RTFileRead returned %Vrc bytes read %x\n", rc, count));
return rc;
}
int vbsfWrite (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_FILE);
size_t count = 0;
int rc;
if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
Log(("vbsfWrite %RX64 offset %RX64 bytes %x\n", Handle, offset, *pcbBuffer));
if (*pcbBuffer == 0)
return VINF_SUCCESS; /** @todo correct? */
rc = RTFileSeek(pHandle->file.Handle, offset, RTFILE_SEEK_BEGIN, NULL);
if (rc != VINF_SUCCESS)
{
AssertRC(rc);
return rc;
}
rc = RTFileWrite(pHandle->file.Handle, pBuffer, *pcbBuffer, &count);
*pcbBuffer = (uint32_t)count;
Log(("RTFileWrite returned %Vrc bytes written %x\n", rc, count));
return rc;
}
int vbsfFlush(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_FILE);
int rc = VINF_SUCCESS;
if (pHandle == 0)
{
AssertFailed();
return VERR_INVALID_HANDLE;
}
Log(("vbsfFlush %RX64\n", Handle));
rc = RTFileFlush(pHandle->file.Handle);
AssertRC(rc);
return rc;
}
int vbsfDirList(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, SHFLSTRING *pPath, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer,
uint32_t *pIndex, uint32_t *pcFiles)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR);
PRTDIRENTRYEX pDirEntry = 0, pDirEntryOrg;
uint32_t cbDirEntry, cbBufferOrg;
int rc = VINF_SUCCESS;
PSHFLDIRINFO pSFDEntry;
PRTUCS2 puszString;
PRTDIR DirHandle;
bool fUtf8;
fUtf8 = BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8) != 0;
if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
Assert(pIndex && *pIndex == 0);
DirHandle = pHandle->dir.Handle;
cbDirEntry = 4096;
pDirEntryOrg = pDirEntry = (PRTDIRENTRYEX)RTMemAlloc(cbDirEntry);
if (pDirEntry == 0)
{
AssertFailed();
return VERR_NO_MEMORY;
}
cbBufferOrg = *pcbBuffer;
*pcbBuffer = 0;
pSFDEntry = (PSHFLDIRINFO)pBuffer;
*pIndex = 1; /* not yet complete */
*pcFiles = 0;
if (pPath)
{
if (pHandle->dir.SearchHandle == 0)
{
/* Build a host full path for the given path
* and convert ucs2 to utf8 if necessary.
*/
char *pszFullPath = NULL;
Assert(pHandle->dir.pLastValidEntry == 0);
rc = vbsfBuildFullPath (pClient, root, pPath, pPath->u16Size, &pszFullPath, NULL, true);
if (VBOX_SUCCESS (rc))
{
rc = RTDirOpenFiltered (&pHandle->dir.SearchHandle, pszFullPath, RTDIRFILTER_WINNT);
/* free the path string */
vbsfFreeFullPath(pszFullPath);
if (VBOX_FAILURE (rc))
goto end;
}
else
goto end;
}
Assert(pHandle->dir.SearchHandle);
DirHandle = pHandle->dir.SearchHandle;
}
while(cbBufferOrg)
{
uint32_t cbDirEntrySize = cbDirEntry;
uint32_t cbNeeded;
/* Do we still have a valid last entry for the active search? If so, then return it here */
if (pHandle->dir.pLastValidEntry)
{
pDirEntry = pHandle->dir.pLastValidEntry;
}
else
{
pDirEntry = pDirEntryOrg;
rc = RTDirReadEx(DirHandle, pDirEntry, &cbDirEntrySize, RTFSOBJATTRADD_NOTHING);
if (rc == VERR_NO_MORE_FILES)
{
*pIndex = 0; /* listing completed */
break;
}
if (VINF_SUCCESS != rc && rc != VWRN_NO_DIRENT_INFO)
{
AssertFailed();
if (rc != VERR_NO_TRANSLATION)
break;
else
continue;
}
}
cbNeeded = RT_OFFSETOF (SHFLDIRINFO, name.String);
if (fUtf8)
cbNeeded += pDirEntry->cbName + 1;
else
/* Overestimating, but that's ok */
cbNeeded += (pDirEntry->cbName + 1) * 2;
if (cbBufferOrg < cbNeeded)
{
/* No room, so save this directory entry, or else it's lost forever */
pHandle->dir.pLastValidEntry = pDirEntry;
if (*pcFiles == 0)
{
AssertFailed();
return VINF_BUFFER_OVERFLOW; /* Return directly and don't free pDirEntry */
}
return VINF_SUCCESS; /* Return directly and don't free pDirEntry */
}
pSFDEntry->Info = pDirEntry->Info;
pSFDEntry->cucShortName = 0;
if (fUtf8)
{
void *src, *dst;
src = &pDirEntry->szName[0];
dst = &pSFDEntry->name.String.utf8[0];
memcpy (dst, src, pDirEntry->cbName + 1);
pSFDEntry->name.u16Size = pDirEntry->cbName + 1;
pSFDEntry->name.u16Length = pDirEntry->cbName;
}
else
{
pSFDEntry->name.String.ucs2[0] = 0;
puszString = pSFDEntry->name.String.ucs2;
int rc2 = RTStrUtf8ToUcs2Ex(&puszString, pDirEntry->cbName+1, pDirEntry->szName);
AssertRC(rc2);
pSFDEntry->name.u16Length = RTStrUcs2Len (pSFDEntry->name.String.ucs2) * 2;
pSFDEntry->name.u16Size = pSFDEntry->name.u16Length + 2;
Log(("SHFL: File name size %d\n", pSFDEntry->name.u16Size));
Log(("SHFL: File name %ls\n", &pSFDEntry->name.String.ucs2));
// adjust cbNeeded (it was overestimated before)
cbNeeded = RT_OFFSETOF (SHFLDIRINFO, name.String) + pSFDEntry->name.u16Size;
}
pSFDEntry = (PSHFLDIRINFO)((uintptr_t)pSFDEntry + cbNeeded);
*pcbBuffer += cbNeeded;
cbBufferOrg-= cbNeeded;
*pcFiles += 1;
/* Free the saved last entry, that we've just returned */
if (pHandle->dir.pLastValidEntry)
{
RTMemFree(pHandle->dir.pLastValidEntry);
pHandle->dir.pLastValidEntry = NULL;
}
if (flags & SHFL_LIST_RETURN_ONE)
break; /* we're done */
}
Assert(rc != VINF_SUCCESS || *pcbBuffer > 0);
end:
if (pDirEntry)
RTMemFree(pDirEntry);
return rc;
}
int vbsfQueryFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE);
int rc = VINF_SUCCESS;
RTFSOBJINFO *pObjInfo = (RTFSOBJINFO *)pBuffer;
if (pHandle == 0 || pcbBuffer == 0 || pObjInfo == 0 || *pcbBuffer < sizeof(RTFSOBJINFO))
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* @todo other options */
Assert(flags == (SHFL_INFO_GET|SHFL_INFO_FILE));
*pcbBuffer = 0;
if (pHandle->Header.u32Flags & SHFL_HF_TYPE_DIR)
{
rc = RTDirQueryInfo(pHandle->dir.Handle, pObjInfo, RTFSOBJATTRADD_NOTHING);
}
else
{
rc = RTFileQueryInfo(pHandle->file.Handle, pObjInfo, RTFSOBJATTRADD_NOTHING);
}
if (rc == VINF_SUCCESS)
{
*pcbBuffer = sizeof(RTFSOBJINFO);
}
else
AssertFailed();
return rc;
}
int vbsfSetFileInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE);
int rc = VINF_SUCCESS;
RTFSOBJINFO *pSFDEntry;
if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0 || *pcbBuffer < sizeof(RTFSOBJINFO))
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
*pcbBuffer = 0;
pSFDEntry = (RTFSOBJINFO *)pBuffer;
Assert(flags == (SHFL_INFO_SET | SHFL_INFO_FILE));
/* Change only the time values that are not zero */
if (pHandle->Header.u32Flags & SHFL_HF_TYPE_DIR)
{
rc = RTDirSetTimes(pHandle->dir.Handle,
(RTTimeSpecGetNano(&pSFDEntry->AccessTime)) ? &pSFDEntry->AccessTime : NULL,
(RTTimeSpecGetNano(&pSFDEntry->ModificationTime)) ? &pSFDEntry->ModificationTime: NULL,
(RTTimeSpecGetNano(&pSFDEntry->ChangeTime)) ? &pSFDEntry->ChangeTime: NULL,
(RTTimeSpecGetNano(&pSFDEntry->BirthTime)) ? &pSFDEntry->BirthTime: NULL
);
}
else
{
rc = RTFileSetTimes(pHandle->file.Handle,
(RTTimeSpecGetNano(&pSFDEntry->AccessTime)) ? &pSFDEntry->AccessTime : NULL,
(RTTimeSpecGetNano(&pSFDEntry->ModificationTime)) ? &pSFDEntry->ModificationTime: NULL,
(RTTimeSpecGetNano(&pSFDEntry->ChangeTime)) ? &pSFDEntry->ChangeTime: NULL,
(RTTimeSpecGetNano(&pSFDEntry->BirthTime)) ? &pSFDEntry->BirthTime: NULL
);
}
if (rc != VINF_SUCCESS)
{
Log(("RTFileSetTimes failed with %Vrc\n", rc));
Log(("AccessTime %VX64\n", RTTimeSpecGetNano(&pSFDEntry->AccessTime)));
Log(("ModificationTime %VX64\n", RTTimeSpecGetNano(&pSFDEntry->ModificationTime)));
Log(("ChangeTime %VX64\n", RTTimeSpecGetNano(&pSFDEntry->ChangeTime)));
Log(("BirthTime %VX64\n", RTTimeSpecGetNano(&pSFDEntry->AccessTime)));
/* temporary hack */
rc = VINF_SUCCESS;
}
if (pHandle->Header.u32Flags & SHFL_HF_TYPE_FILE)
{
/* Change file attributes if necessary */
if (pSFDEntry->Attr.fMode)
{
rc = RTFileSetMode((RTFILE)pHandle->file.Handle, pSFDEntry->Attr.fMode);
if (rc != VINF_SUCCESS)
{
Log(("RTFileSetMode %x failed with %Vrc\n", pSFDEntry->Attr.fMode, rc));
/* silent failure, because this tends to fail with e.g. windows guest & linux host */
rc = VINF_SUCCESS;
}
}
}
if (rc == VINF_SUCCESS)
{
uint32_t bufsize = sizeof(*pSFDEntry);
rc = vbsfQueryFileInfo(pClient, root, Handle, SHFL_INFO_GET|SHFL_INFO_FILE, &bufsize, (uint8_t *)pSFDEntry);
if (rc == VINF_SUCCESS)
{
*pcbBuffer = sizeof(RTFSOBJINFO);
}
else
AssertFailed();
}
return rc;
}
int vbsfSetEndOfFile(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_FILE);
int rc = VINF_SUCCESS;
RTFSOBJINFO *pSFDEntry;
if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0 || *pcbBuffer < sizeof(RTFSOBJINFO))
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
*pcbBuffer = 0;
pSFDEntry = (RTFSOBJINFO *)pBuffer;
if (flags & SHFL_INFO_SIZE)
{
rc = RTFileSetSize(pHandle->file.Handle, pSFDEntry->cbObject);
if (rc != VINF_SUCCESS)
AssertFailed();
}
else
AssertFailed();
if (rc == VINF_SUCCESS)
{
RTFSOBJINFO fileinfo;
/* Query the new object info and return it */
rc = RTFileQueryInfo(pHandle->file.Handle, &fileinfo, RTFSOBJATTRADD_NOTHING);
if (rc == VINF_SUCCESS)
{
*pSFDEntry = fileinfo;
*pcbBuffer = sizeof(RTFSOBJINFO);
}
else
AssertFailed();
}
return rc;
}
int vbsfQueryVolumeInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE|SHFL_HF_TYPE_VOLUME);
int rc = VINF_SUCCESS;
SHFLVOLINFO *pSFDEntry;
char *pszFullPath = NULL;
SHFLSTRING dummy;
if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0 || *pcbBuffer < sizeof(SHFLVOLINFO))
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* @todo other options */
Assert(flags == (SHFL_INFO_GET|SHFL_INFO_VOLUME));
*pcbBuffer = 0;
pSFDEntry = (PSHFLVOLINFO)pBuffer;
ShflStringInitBuffer(&dummy, sizeof(dummy));
rc = vbsfBuildFullPath (pClient, root, &dummy, 0, &pszFullPath, NULL);
if (VBOX_SUCCESS (rc))
{
rc = RTFsQuerySizes(pszFullPath, &pSFDEntry->ullTotalAllocationBytes, &pSFDEntry->ullAvailableAllocationBytes, &pSFDEntry->ulBytesPerAllocationUnit, &pSFDEntry->ulBytesPerSector);
if (rc != VINF_SUCCESS)
goto exit;
rc = RTFsQuerySerial(pszFullPath, &pSFDEntry->ulSerial);
if (rc != VINF_SUCCESS)
goto exit;
rc = RTFsQueryProperties(pszFullPath, &pSFDEntry->fsProperties);
if (rc != VINF_SUCCESS)
goto exit;
*pcbBuffer = sizeof(SHFLVOLINFO);
}
else AssertFailed();
exit:
AssertMsg(rc == VINF_SUCCESS, ("failure: rc = %Vrc\n", rc));
/* free the path string */
vbsfFreeFullPath(pszFullPath);
return rc;
}
int vbsfQueryFSInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE|SHFL_HF_TYPE_VOLUME);
if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
if (flags & SHFL_INFO_FILE)
return vbsfQueryFileInfo(pClient, root, Handle, flags, pcbBuffer, pBuffer);
if (flags & SHFL_INFO_VOLUME)
return vbsfQueryVolumeInfo(pClient, root, Handle, flags, pcbBuffer, pBuffer);
AssertFailed();
return VERR_INVALID_PARAMETER;
}
int vbsfSetFSInfo(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint32_t flags, uint32_t *pcbBuffer, uint8_t *pBuffer)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_DIR|SHFL_HF_TYPE_FILE|SHFL_HF_TYPE_VOLUME);
if (pHandle == 0 || pcbBuffer == 0 || pBuffer == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
if (flags & SHFL_INFO_FILE)
return vbsfSetFileInfo(pClient, root, Handle, flags, pcbBuffer, pBuffer);
if (flags & SHFL_INFO_SIZE)
return vbsfSetEndOfFile(pClient, root, Handle, flags, pcbBuffer, pBuffer);
// if (flags & SHFL_INFO_VOLUME)
// return vbsfVolumeInfo(pClient, root, Handle, flags, pcbBuffer, pBuffer);
AssertFailed();
return VERR_INVALID_PARAMETER;
}
int vbsfLock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_FILE);
uint32_t fRTLock = 0;
int rc;
Assert((flags & SHFL_LOCK_MODE_MASK) != SHFL_LOCK_CANCEL);
if (pHandle == 0)
{
AssertFailed();
return VERR_INVALID_HANDLE;
}
if ( ((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL)
|| (flags & SHFL_LOCK_ENTIRE)
)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* Lock type */
switch(flags & SHFL_LOCK_MODE_MASK)
{
case SHFL_LOCK_SHARED:
fRTLock = RTFILE_LOCK_READ;
break;
case SHFL_LOCK_EXCLUSIVE:
fRTLock = RTFILE_LOCK_READ | RTFILE_LOCK_WRITE;
break;
default:
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* Lock wait type */
if (flags & SHFL_LOCK_WAIT)
fRTLock |= RTFILE_LOCK_WAIT;
else
fRTLock |= RTFILE_LOCK_IMMEDIATELY;
rc = RTFileLock(pHandle->file.Handle, fRTLock, offset, length);
if (rc != VINF_SUCCESS)
Log(("RTFileUnlock %RTfile %RX64 %RX64 failed with %Rrc\n", pHandle->file.Handle, offset, length, rc));
return rc;
}
int vbsfUnlock(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLHANDLE Handle, uint64_t offset, uint64_t length, uint32_t flags)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(Handle, SHFL_HF_TYPE_FILE);
int rc;
Assert((flags & SHFL_LOCK_MODE_MASK) == SHFL_LOCK_CANCEL);
if (pHandle == 0)
{
return VERR_INVALID_HANDLE;
}
if ( ((flags & SHFL_LOCK_MODE_MASK) != SHFL_LOCK_CANCEL)
|| (flags & SHFL_LOCK_ENTIRE)
)
{
return VERR_INVALID_PARAMETER;
}
rc = RTFileUnlock(pHandle->file.Handle, offset, length);
if (rc != VINF_SUCCESS)
Log(("RTFileUnlock %RTfile %RX64 %RTX64 failed with %Rrc\n", pHandle->file.Handle, offset, length, rc));
return rc;
}
int vbsfRemove(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pPath, uint32_t cbPath, uint32_t flags)
{
int rc = VINF_SUCCESS;
/* Validate input */
if ( flags & ~(SHFL_REMOVE_FILE|SHFL_REMOVE_DIR)
|| cbPath == 0
|| pPath == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* Build a host full path for the given path
* and convert ucs2 to utf8 if necessary.
*/
char *pszFullPath = NULL;
rc = vbsfBuildFullPath (pClient, root, pPath, cbPath, &pszFullPath, NULL);
if (VBOX_SUCCESS (rc))
{
if (flags & SHFL_REMOVE_FILE)
rc = RTFileDelete(pszFullPath);
else
rc = RTDirRemove(pszFullPath);
Assert(rc == VINF_SUCCESS || rc == VERR_DIR_NOT_EMPTY);
/* free the path string */
vbsfFreeFullPath(pszFullPath);
}
return rc;
}
int vbsfRename(SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pSrc, SHFLSTRING *pDest, uint32_t flags)
{
int rc = VINF_SUCCESS;
/* Validate input */
if ( flags & ~(SHFL_REMOVE_FILE|SHFL_REMOVE_DIR|SHFL_RENAME_REPLACE_IF_EXISTS)
|| pSrc == 0
|| pDest == 0)
{
AssertFailed();
return VERR_INVALID_PARAMETER;
}
/* Build a host full path for the given path
* and convert ucs2 to utf8 if necessary.
*/
char *pszFullPathSrc = NULL;
char *pszFullPathDest = NULL;
rc = vbsfBuildFullPath (pClient, root, pSrc, pSrc->u16Size, &pszFullPathSrc, NULL);
if (rc != VINF_SUCCESS)
return rc;
rc = vbsfBuildFullPath (pClient, root, pDest, pDest->u16Size, &pszFullPathDest, NULL);
if (VBOX_SUCCESS (rc))
{
Log(("Rename %s to %s\n", pszFullPathSrc, pszFullPathDest));
if (flags & SHFL_RENAME_FILE)
{
rc = RTFileMove(pszFullPathSrc, pszFullPathDest, (flags & SHFL_RENAME_REPLACE_IF_EXISTS) ? RTFILEMOVE_FLAGS_REPLACE : 0);
}
else
{
/* NT ignores the REPLACE flag and simply return and already exists error. */
rc = RTDirRename(pszFullPathSrc, pszFullPathDest, (flags & SHFL_RENAME_REPLACE_IF_EXISTS) ? RTPATHRENAME_FLAGS_REPLACE : 0);
}
AssertRC(rc);
/* free the path string */
vbsfFreeFullPath(pszFullPathDest);
}
/* free the path string */
vbsfFreeFullPath(pszFullPathSrc);
return rc;
}
/*
* Clean up our mess by freeing all handles that are still valid.
*
*/
int vbsfDisconnect(SHFLCLIENTDATA *pClient)
{
for (int i=0;i<SHFLHANDLE_MAX;i++)
{
SHFLFILEHANDLE *pHandle = (SHFLFILEHANDLE *)vbsfQueryHandle(i, SHFL_HF_TYPE_MASK);
if (pHandle)
{
Log(("Open handle %08x\n", i));
vbsfClose(pClient, SHFL_HANDLE_ROOT /* incorrect, but it's not important */, (SHFLHANDLE)i);
}
}
return VINF_SUCCESS;
}