DnDURIList.cpp revision 82391de567696f10b21a762fde6a06fe3c266d28
82391de567696f10b21a762fde6a06fe3c266d28vboxsync/* $Id$ */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync/** @file
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * DnD: URI list class.
82391de567696f10b21a762fde6a06fe3c266d28vboxsync */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync/*
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * Copyright (C) 2014 Oracle Corporation
82391de567696f10b21a762fde6a06fe3c266d28vboxsync *
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * available from http://www.virtualbox.org. This file is free software;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * you can redistribute it and/or modify it under the terms of the GNU
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * General Public License (GPL) as published by the Free Software
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
82391de567696f10b21a762fde6a06fe3c266d28vboxsync */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync/******************************************************************************
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * Header Files *
82391de567696f10b21a762fde6a06fe3c266d28vboxsync ******************************************************************************/
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#include <iprt/dir.h>
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#include <iprt/file.h>
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#include <iprt/fs.h>
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#include <iprt/path.h>
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#include <iprt/uri.h>
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#ifdef LOG_GROUP
82391de567696f10b21a762fde6a06fe3c266d28vboxsync #undef LOG_GROUP
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#endif
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#define LOG_GROUP LOG_GROUP_GUEST_DND
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#include <VBox/log.h>
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#include <VBox/GuestHost/DragAndDrop.h>
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsyncDnDURIList::DnDURIList(void)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync : m_cbTotal(0)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync{
82391de567696f10b21a762fde6a06fe3c266d28vboxsync}
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsyncDnDURIList::~DnDURIList(void)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync{
82391de567696f10b21a762fde6a06fe3c266d28vboxsync}
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsyncint DnDURIList::appendPathRecursive(const char *pcszPath, size_t cbBaseLen,
82391de567696f10b21a762fde6a06fe3c266d28vboxsync uint32_t fFlags)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync{
82391de567696f10b21a762fde6a06fe3c266d28vboxsync AssertPtrReturn(pcszPath, VERR_INVALID_POINTER);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync AssertReturn(cbBaseLen, VERR_INVALID_PARAMETER);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTFSOBJINFO objInfo;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync int rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (RT_FAILURE(rc))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return rc;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync /*
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * These are the types we currently support. Symlinks are not directly
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * supported. First the guest could be an OS which doesn't support it and
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * second the symlink could point to a file which is out of the base tree.
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * Both things are hard to support. For now we just copy the target file in
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * this case.
82391de567696f10b21a762fde6a06fe3c266d28vboxsync */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (!( RTFS_IS_DIRECTORY(objInfo.Attr.fMode)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync || RTFS_IS_FILE(objInfo.Attr.fMode)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync || RTFS_IS_SYMLINK(objInfo.Attr.fMode)))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return VINF_SUCCESS;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync uint64_t cbSize = 0;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = RTFileQuerySize(pcszPath, &cbSize);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (rc == VERR_IS_A_DIRECTORY)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = VINF_SUCCESS;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (RT_FAILURE(rc))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return rc;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_lstTree.append(DnDURIPath(pcszPath, &pcszPath[cbBaseLen],
82391de567696f10b21a762fde6a06fe3c266d28vboxsync objInfo.Attr.fMode, cbSize));
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_cbTotal += cbSize;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#ifdef DEBUG_andy
82391de567696f10b21a762fde6a06fe3c266d28vboxsync LogFlowFunc(("strHostPath=%s, strGuestPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n",
82391de567696f10b21a762fde6a06fe3c266d28vboxsync pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize, m_cbTotal));
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#endif
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync PRTDIR hDir;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync /* We have to try to open even symlinks, cause they could
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * be symlinks to directories. */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = RTDirOpen(&hDir, pcszPath);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync /* The following error happens when this was a symlink
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * to an file or a regular file. */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if ( rc == VERR_PATH_NOT_FOUND
82391de567696f10b21a762fde6a06fe3c266d28vboxsync || rc == VERR_NOT_A_DIRECTORY)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return VINF_SUCCESS;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (RT_FAILURE(rc))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return rc;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync while (RT_SUCCESS(rc))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTDIRENTRY DirEntry;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = RTDirRead(hDir, &DirEntry, NULL);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (RT_FAILURE(rc))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (rc == VERR_NO_MORE_FILES)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = VINF_SUCCESS;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync break;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync switch (DirEntry.enmType)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync case RTDIRENTRYTYPE_DIRECTORY:
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync /* Skip "." and ".." entries. */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if ( RTStrCmp(DirEntry.szName, ".") == 0
82391de567696f10b21a762fde6a06fe3c266d28vboxsync || RTStrCmp(DirEntry.szName, "..") == 0)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync break;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync char *pszRecDir = RTStrAPrintf2("%s%c%s", pcszPath,
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTPATH_DELIMITER, DirEntry.szName);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (pszRecDir)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = appendPathRecursive(pszRecDir, cbBaseLen, fFlags);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTStrFree(pszRecDir);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync else
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = VERR_NO_MEMORY;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync break;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync case RTDIRENTRYTYPE_SYMLINK:
82391de567696f10b21a762fde6a06fe3c266d28vboxsync case RTDIRENTRYTYPE_FILE:
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync char *pszNewFile = RTStrAPrintf2("%s%c%s",
82391de567696f10b21a762fde6a06fe3c266d28vboxsync pcszPath, RTPATH_DELIMITER, DirEntry.szName);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (pszNewFile)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync /* We need the size and the mode of the file. */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTFSOBJINFO objInfo1;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = RTPathQueryInfo(pszNewFile, &objInfo1, RTFSOBJATTRADD_NOTHING);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (RT_FAILURE(rc))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return rc;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = RTFileQuerySize(pszNewFile, &cbSize);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (RT_FAILURE(rc))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync break;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_lstTree.append(DnDURIPath(pszNewFile, &pszNewFile[cbBaseLen],
82391de567696f10b21a762fde6a06fe3c266d28vboxsync objInfo1.Attr.fMode, cbSize));
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_cbTotal += cbSize;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#ifdef DEBUG_andy
82391de567696f10b21a762fde6a06fe3c266d28vboxsync LogFlowFunc(("strHostPath=%s, strGuestPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n",
82391de567696f10b21a762fde6a06fe3c266d28vboxsync pszNewFile, &pszNewFile[cbBaseLen], objInfo1.Attr.fMode, cbSize, m_cbTotal));
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#endif
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTStrFree(pszNewFile);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync else
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = VERR_NO_MEMORY;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync break;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync default:
82391de567696f10b21a762fde6a06fe3c266d28vboxsync break;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTDirClose(hDir);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return rc;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync}
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsyncint DnDURIList::AppendPath(const char *pszPath, uint32_t fFlags)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync{
82391de567696f10b21a762fde6a06fe3c266d28vboxsync AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#ifdef DEBUG_andy
82391de567696f10b21a762fde6a06fe3c266d28vboxsync LogFlowFunc(("pszPath=%s, fFlags=0x%x\n", pszPath, fFlags));
82391de567696f10b21a762fde6a06fe3c266d28vboxsync#endif
82391de567696f10b21a762fde6a06fe3c266d28vboxsync int rc = VINF_SUCCESS;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync /* Query the path component of a file URI. If this hasn't a
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * file scheme NULL is returned. */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync char *pszFilePath = RTUriFilePath(pszPath, URI_FILE_FORMAT_AUTO);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (pszFilePath)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync /* Add the path to our internal file list (recursive in
82391de567696f10b21a762fde6a06fe3c266d28vboxsync * the case of a directory). */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync char *pszFileName = RTPathFilename(pszFilePath);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (pszFileName)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync char *pszNewURI = RTUriFileCreate(pszFileName);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (pszNewURI)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_lstRoot.append(pszNewURI);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTStrFree(pszNewURI);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = appendPathRecursive(pszFilePath,
82391de567696f10b21a762fde6a06fe3c266d28vboxsync pszFileName - pszFilePath,
82391de567696f10b21a762fde6a06fe3c266d28vboxsync fFlags);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync RTStrFree(pszFilePath);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync else /* Just append the raw data. */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_lstRoot.append(pszPath);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync LogFlowFuncLeaveRC(rc);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return rc;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync}
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsyncint DnDURIList::AppendPathsFromList(const RTCList<RTCString> &lstURI,
82391de567696f10b21a762fde6a06fe3c266d28vboxsync uint32_t fFlags)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync{
82391de567696f10b21a762fde6a06fe3c266d28vboxsync int rc = VINF_SUCCESS;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync for (size_t i = 0; i < lstURI.size(); i++)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync {
82391de567696f10b21a762fde6a06fe3c266d28vboxsync const RTCString &strURI = lstURI.at(i);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync rc = AppendPath(strURI.c_str(), fFlags);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync if (RT_FAILURE(rc))
82391de567696f10b21a762fde6a06fe3c266d28vboxsync break;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync }
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync LogFlowFuncLeaveRC(rc);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync return rc;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync}
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsyncvoid DnDURIList::Clear(void)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync{
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_lstRoot.clear();
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_lstTree.clear();
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_cbTotal = 0;
82391de567696f10b21a762fde6a06fe3c266d28vboxsync}
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsyncvoid DnDURIList::RemoveFirst(void)
82391de567696f10b21a762fde6a06fe3c266d28vboxsync{
82391de567696f10b21a762fde6a06fe3c266d28vboxsync const DnDURIPath &curPath = m_lstTree.first();
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync Assert(m_cbTotal >= curPath.m_cbSize);
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_cbTotal -= curPath.m_cbSize; /* Adjust total size. */
82391de567696f10b21a762fde6a06fe3c266d28vboxsync
82391de567696f10b21a762fde6a06fe3c266d28vboxsync m_lstTree.removeFirst();
82391de567696f10b21a762fde6a06fe3c266d28vboxsync}
82391de567696f10b21a762fde6a06fe3c266d28vboxsync