/*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2018 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
#include "guestDnDCPMgr.hh"
#include "tracer.hh"
#include "vmblock.h"
+#include "fcntl.h"
#include "file.h"
#include "dnd.h"
#include "dndMsg.h"
mClipTime(0),
mPrimTime(0),
mLastTimestamp(0),
+ mThread(0),
mHGGetFileStatus(DND_FILE_TRANSFER_NOT_STARTED),
mBlockAdded(false),
mBlockCtrl(0),
mTotalFileSize(0),
mGetTimestampOnly(false)
{
+ TRACE_CALL();
GuestDnDCPMgr *p = GuestDnDCPMgr::GetInstance();
ASSERT(p);
mCP = p->GetCopyPasteMgr();
ASSERT(mCP);
+
+ mThreadParams.fileBlockCondExit = false;
+ pthread_mutex_init(&mThreadParams.fileBlockMutex, NULL);
+ pthread_cond_init(&mThreadParams.fileBlockCond, NULL);
+ mThreadParams.cp = this;
+ int ret = pthread_create(&mThread,
+ NULL,
+ FileBlockMonitorThread,
+ (void *)&(this->mThreadParams));
+ if (ret != 0) {
+ Warning("%s: Create thread failed, errno:%d.\n", __FUNCTION__, ret);
+ mThread = 0;
+ }
}
{
TRACE_CALL();
if (mInited) {
+ g_debug("%s: mInited is true\n", __FUNCTION__);
return true;
}
}
mBlockAdded = false;
}
+
+ TerminateThread();
+ pthread_mutex_destroy(&mThreadParams.fileBlockMutex);
+ pthread_cond_destroy(&mThreadParams.fileBlockCond);
}
guint info) // IN:
{
g_debug("%s: enter.\n", __FUNCTION__);
- VmTimeType curTime;
-
- curTime = GetCurrentTime();
-
- /*
- * Some applications may ask for clipboard contents right after clipboard
- * owner changed. So HG FCP will return nothing for some time after switch
- * from guest OS to host OS.
- */
- if ((curTime - mHGGetListTime) < FCP_COPY_DELAY) {
- g_debug("%s: time delta less than FCP_COPY_DELAY, returning.\n",
- __FUNCTION__);
- return;
- }
if (!mIsClipboardOwner || !mCP->IsCopyPasteAllowed()) {
g_debug("%s: not clipboard ownder, or copy paste not allowed, returning.\n",
utf::string post;
size_t index = 0;
- hgStagingDir = static_cast<utf::string>(mCP->SrcUIRequestFiles());
+ hgStagingDir = utf::CopyAndFree(DnD_CreateStagingDirectory());
g_debug("%s: Getting files. Staging dir: %s", __FUNCTION__,
hgStagingDir.c_str());
g_debug("%s: add block for %s.\n",
__FUNCTION__, hgStagingDir.c_str());
mBlockAdded = true;
+ pthread_mutex_lock(&mThreadParams.fileBlockMutex);
+ mThreadParams.fileBlockCondExit = false;
+ mThreadParams.fileBlockName = VMBLOCK_FUSE_NOTIFY_ROOT;
+ mThreadParams.fileBlockName += DIRSEPS;
+ mThreadParams.fileBlockName += GetLastDirName(hgStagingDir);
+ pthread_cond_signal(&mThreadParams.fileBlockCond);
+ pthread_mutex_unlock(&mThreadParams.fileBlockMutex);
} else {
g_debug("%s: unable to add block for %s.\n",
__FUNCTION__, hgStagingDir.c_str());
return;
}
+ if (mBlockAdded) {
+ if (DnD_BlockIsReady(mBlockCtrl)) {
+ mBlockCtrl->RemoveBlock(mBlockCtrl->fd, mHGStagingDir.c_str());
+ mBlockAdded = false;
+ }
+ }
+
/* Clear the clipboard contents if we are the owner. */
if (mIsClipboardOwner) {
refClipboard->clear();
TRACE_CALL();
/* Cancel any pending file transfer. */
}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * CopyPasteUIX11::FileBlockMonitorThread --
+ *
+ * This thread monitors the access to the files in the clipboard which owns
+ * by VMTools by using the notification mechanism of VMBlock.
+ * If any access to the file is detected, then this thread requests the file
+ * transfer from host to guest.
+ *
+ * Results:
+ * Always return NULL
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void*
+CopyPasteUIX11::FileBlockMonitorThread(void *arg) // IN
+{
+ TRACE_CALL();
+ ThreadParams *params = (ThreadParams *)arg;
+ pthread_mutex_lock(¶ms->fileBlockMutex);
+ while (true) {
+ g_debug("%s: waiting signal\n", __FUNCTION__);
+ pthread_cond_wait(¶ms->fileBlockCond, ¶ms->fileBlockMutex);
+ g_debug("%s: received signal. Exit:%d\n",
+ __FUNCTION__,
+ params->fileBlockCondExit);
+ if (params->fileBlockCondExit) {
+ break;
+ }
+ if (params->fileBlockName.bytes() == 0) {
+ continue;
+ }
+
+ int fd = open(params->fileBlockName.c_str(), O_RDONLY);
+ if (fd <= 0) {
+ g_debug("%s: Failed to open %s\n",
+ __FUNCTION__,
+ params->fileBlockName.c_str());
+ continue;
+ }
+
+ char buf[sizeof(VMBLOCK_FUSE_READ_RESPONSE)];
+ ssize_t size;
+ size = read(fd, buf, sizeof(VMBLOCK_FUSE_READ_RESPONSE));
+ /*
+ * The current thread will block in read function until
+ * any other application accesses the file params->fileBlockName
+ * or the block on the file params->fileBlockName is removed.
+ * Currently we don't need to check the response in buf, so
+ * just ignore it.
+ */
+
+ if (params->cp->IsBlockAdded()) {
+ g_debug("%s: Request files\n", __FUNCTION__);
+ params->cp->RequestFiles();
+ } else {
+ g_debug("%s: Block is not added\n", __FUNCTION__);
+ }
+ }
+ pthread_mutex_unlock(¶ms->fileBlockMutex);
+ return NULL;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * CopyPasteUIX11::TerminateThread --
+ *
+ * This is called when the monitor thread is asked to exit.
+ * Sets the global state and signals the monitor thread to exit and wait
+ * for the monitor thread to exit.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+CopyPasteUIX11::TerminateThread()
+{
+ TRACE_CALL();
+ if (mThread == 0) {
+ return;
+ }
+
+ pthread_mutex_lock(&mThreadParams.fileBlockMutex);
+ mThreadParams.fileBlockCondExit = true;
+ pthread_cond_signal(&mThreadParams.fileBlockCond);
+ pthread_mutex_unlock(&mThreadParams.fileBlockMutex);
+
+ pthread_join(mThread, NULL);
+
+ mThread = 0;
+}
/*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2018 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
#include <gdk/gdkx.h>
#include "vmware/guestrpc/tclodefs.h"
+class CopyPasteUIX11;
+
+struct ThreadParams
+{
+ pthread_mutex_t fileBlockMutex;
+ pthread_cond_t fileBlockCond;
+ bool fileBlockCondExit;
+ CopyPasteUIX11 *cp;
+ utf::string fileBlockName;
+};
+
class CopyPasteUIX11 : public sigc::trackable
{
public:
void SetBlockControl(DnDBlockControl *blockCtrl)
{ Debug("Setting mBlockCtrl to %p\n", blockCtrl);
mBlockCtrl = blockCtrl; }
+ bool IsBlockAdded() const
+ { return mBlockAdded; }
+ void RequestFiles()
+ { mCP->SrcUIRequestFiles(); }
private:
VmTimeType GetCurrentTime(void);
+ static void* FileBlockMonitorThread(void *arg);
+ void TerminateThread();
+
// Member variables
GuestCopyPasteMgr *mCP;
bool mClipboardEmpty;
uint64 mLastTimestamp;
GdkAtom mGHSelection;
CPClipboard mClipboard;
+ ThreadParams mThreadParams;
+ pthread_t mThread;
/* File vars. */
VmTimeType mHGGetListTime;