~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to lib/dndGuest/copyPaste.cc

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*********************************************************
2
 
 * Copyright (C) 2007 VMware, Inc. All rights reserved.
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify it
5
 
 * under the terms of the GNU Lesser General Public License as published
6
 
 * by the Free Software Foundation version 2.1 and no later version.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful, but
9
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
11
 
 * License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU Lesser General Public License
14
 
 * along with this program; if not, write to the Free Software Foundation, Inc.,
15
 
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
16
 
 *
17
 
 *********************************************************/
18
 
 
19
 
/*
20
 
 * copyPaste.cc --
21
 
 *
22
 
 *     Implementation of common layer CopyPaste object for guest.
23
 
 */
24
 
 
25
 
#include "copyPaste.hh"
26
 
#include "copyPasteRpcV3.hh"
27
 
#include "dndFileList.hh"
28
 
 
29
 
extern "C" {
30
 
   #include "util.h"
31
 
   #include "debug.h"
32
 
   #include "file.h"
33
 
   #include "str.h"
34
 
   #include "cpNameUtil.h"
35
 
   #include "hostinfo.h"
36
 
   #include "dndClipboard.h"
37
 
}
38
 
 
39
 
/*
40
 
 *---------------------------------------------------------------------
41
 
 *
42
 
 * CopyPaste::CopyPaste --
43
 
 *
44
 
 *      Constructor for CopyPaste.
45
 
 *
46
 
 * Results:
47
 
 *      None.
48
 
 *
49
 
 * Side effects:
50
 
 *      None.
51
 
 *
52
 
 *---------------------------------------------------------------------
53
 
 */
54
 
 
55
 
CopyPaste::CopyPaste(void) // IN
56
 
   : mRpc(NULL),
57
 
     mVmxCopyPasteVersion(0)
58
 
{
59
 
   mState = CPSTATE_INVALID;
60
 
}
61
 
 
62
 
 
63
 
/*
64
 
 *---------------------------------------------------------------------
65
 
 *
66
 
 * CopyPaste::~CopyPaste --
67
 
 *
68
 
 *      Destructor.
69
 
 *
70
 
 * Results:
71
 
 *      None.
72
 
 *
73
 
 * Side effects:
74
 
 *      None.
75
 
 *
76
 
 *---------------------------------------------------------------------
77
 
 */
78
 
 
79
 
CopyPaste::~CopyPaste(void)
80
 
{
81
 
   delete mRpc;
82
 
}
83
 
 
84
 
 
85
 
/*
86
 
 *-----------------------------------------------------------------------------
87
 
 *
88
 
 * CopyPaste::VmxCopyPasteVersionChanged --
89
 
 *
90
 
 *      Vmx CopyPaste version changed so should create corresponding Rpc and
91
 
 *      register callbacks for signals if version changed.
92
 
 *
93
 
 * Results:
94
 
 *      None
95
 
 *
96
 
 * Side effects:
97
 
 *      None
98
 
 *
99
 
 *-----------------------------------------------------------------------------
100
 
 */
101
 
 
102
 
void
103
 
CopyPaste::VmxCopyPasteVersionChanged(struct RpcIn *rpcIn, // IN
104
 
                                      uint32 version)      // IN
105
 
{
106
 
   /* Do nothing if version is not changed. */
107
 
   if (mVmxCopyPasteVersion == version) {
108
 
      return;
109
 
   }
110
 
 
111
 
   mVmxCopyPasteVersion = version;
112
 
   Debug("%s: Version: %d", __FUNCTION__, version);
113
 
 
114
 
   delete mRpc;
115
 
   mRpc = NULL;
116
 
 
117
 
   mState = CPSTATE_INVALID;
118
 
   Hostinfo_GetTimeOfDay(&mStateChangeTime);
119
 
 
120
 
   switch (version) {
121
 
   case 1:
122
 
   case 2:
123
 
      /* Here should create CopyPasteRpcV2 for version 1 & 2. */
124
 
      break;
125
 
   case 3:
126
 
      mRpc = new CopyPasteRpcV3(rpcIn);
127
 
      break;
128
 
   default:
129
 
      Debug("%s: got unsupported guest CopyPaste version %u.\n",
130
 
            __FUNCTION__, version);
131
 
      return;
132
 
   }
133
 
 
134
 
   if (mRpc) {
135
 
      mRpc->ghGetClipboardChanged.connect(
136
 
         sigc::mem_fun(this, &CopyPaste::OnGetLocalClipboard));
137
 
      mRpc->hgSetClipboardChanged.connect(
138
 
         sigc::mem_fun(this, &CopyPaste::OnGetRemoteClipboardDone));
139
 
      mRpc->hgFileCopyDoneChanged.connect(
140
 
         sigc::mem_fun(this, &CopyPaste::OnHGFileCopyDone));
141
 
      mState = CPSTATE_READY;
142
 
   }
143
 
}
144
 
 
145
 
 
146
 
/*
147
 
 *----------------------------------------------------------------------
148
 
 *
149
 
 * CopyPaste::OnGetRemoteClipboardDone --
150
 
 *
151
 
 *      Got clipboard data from host. Put it into local buffer and
152
 
 *      inform UI to process the clipboard data.
153
 
 *
154
 
 * Results:
155
 
 *      None.
156
 
 *
157
 
 * Side effects:
158
 
 *      None.
159
 
 *
160
 
 *----------------------------------------------------------------------
161
 
 */
162
 
 
163
 
void
164
 
CopyPaste::OnGetRemoteClipboardDone(const CPClipboard *clip) // IN: new clipboard
165
 
{
166
 
   newClipboard.emit(clip);
167
 
   mState = CPSTATE_READY;
168
 
   Hostinfo_GetTimeOfDay(&mStateChangeTime);
169
 
}
170
 
 
171
 
 
172
 
/*
173
 
 *----------------------------------------------------------------------
174
 
 *
175
 
 * CopyPaste::OnGetLocalClipboard --
176
 
 *
177
 
 *      Host is asking for guest clipboard data. Try to get it from local
178
 
 *      UI and send to host with GHGetClipboardDone.
179
 
 *
180
 
 * Results:
181
 
 *      None.
182
 
 *
183
 
 * Side effects:
184
 
 *      None.
185
 
 *
186
 
 *----------------------------------------------------------------------
187
 
 */
188
 
 
189
 
void
190
 
CopyPaste::OnGetLocalClipboard(void)
191
 
{
192
 
   CPClipboard clip;
193
 
   bool ready;
194
 
 
195
 
   CPClipboard_Init(&clip);
196
 
   ready = localGetClipboard.emit(&clip);
197
 
   /*
198
 
    * if caller decided to handle this asyncronously, it is responsible for
199
 
    * calling SetRemoteClipboard() when it has completed. Otherwise, call it
200
 
    * now.
201
 
    */
202
 
   if (ready) {
203
 
      SetRemoteClipboard(&clip);
204
 
   }
205
 
   CPClipboard_Destroy(&clip);
206
 
}
207
 
 
208
 
 
209
 
/*
210
 
 *----------------------------------------------------------------------
211
 
 *
212
 
 * CopyPaste::OnHGFileCopyDone --
213
 
 *
214
 
 *      Host finished file copy. Inform UI to remove the block.
215
 
 *
216
 
 * Results:
217
 
 *      None.
218
 
 *
219
 
 * Side effects:
220
 
 *      None.
221
 
 *
222
 
 *----------------------------------------------------------------------
223
 
 */
224
 
 
225
 
void
226
 
CopyPaste::OnHGFileCopyDone(bool success)
227
 
{
228
 
   if (!success && !mStagingDir.empty()) {
229
 
      /* Delete all files if host canceled the file transfer. */
230
 
      DnD_DeleteStagingFiles(mStagingDir.c_str(), FALSE);
231
 
      mStagingDir.clear();
232
 
   }
233
 
   localGetFilesDoneChanged.emit(success);
234
 
}
235
 
 
236
 
 
237
 
/*
238
 
 *----------------------------------------------------------------------------
239
 
 *
240
 
 * CopyPaste::SetRemoteClipboard --
241
 
 *
242
 
 *      Sets the internal clipboard. Also synchronizes remote clipboard with
243
 
 *      the guest clipboard.
244
 
 *
245
 
 * Results:
246
 
 *      True if success, false otherwise.
247
 
 *
248
 
 * Side effects:
249
 
 *      None.
250
 
 *
251
 
 *----------------------------------------------------------------------------
252
 
 */
253
 
 
254
 
bool
255
 
CopyPaste::SetRemoteClipboard(const CPClipboard* clip)  // IN: new clipboard
256
 
{
257
 
   if (!mRpc) {
258
 
      Debug("%s: no valid rpc, guest version is %u.\n",
259
 
            __FUNCTION__, mVmxCopyPasteVersion);
260
 
      return false;
261
 
   }
262
 
 
263
 
   if (mState == CPSTATE_INVALID) {
264
 
      Debug("%s: Invalid state.", __FUNCTION__);
265
 
      return false;
266
 
   }
267
 
 
268
 
   if (!IsCopyPasteAllowed()) {
269
 
      Debug("%s: CopyPasteAllowed() returned false.", __FUNCTION__);
270
 
      return false;
271
 
   }
272
 
 
273
 
   /* Send clipboard data to remote side. */
274
 
   mRpc->GHGetClipboardDone(clip);
275
 
 
276
 
   return true;
277
 
}
278
 
 
279
 
 
280
 
/*
281
 
 *----------------------------------------------------------------------------
282
 
 *
283
 
 * CopyPaste::GetFiles --
284
 
 *
285
 
 *      Gets the files that are referenced on the clipboard.
286
 
 *
287
 
 * Results:
288
 
 *      The destination directory if we can start file copy, otherwise empty
289
 
 *      string.
290
 
 *
291
 
 * Side effects:
292
 
 *      None.
293
 
 *
294
 
 *----------------------------------------------------------------------------
295
 
 */
296
 
 
297
 
std::string
298
 
CopyPaste::GetFiles(std::string dir) // IN: suggested destination directory
299
 
                                     //     in local format
300
 
{
301
 
   std::string destDir;
302
 
   char cpName[FILE_MAXPATH];
303
 
   int32 cpNameSize;
304
 
 
305
 
   if (mState == CPSTATE_INVALID) {
306
 
      Debug("%s: Invalid state.", __FUNCTION__);
307
 
      return "";
308
 
   }
309
 
 
310
 
   /* Setup staging directory. */
311
 
   destDir = SetupDestDir(dir);
312
 
   if (destDir.empty()) {
313
 
      return "";
314
 
   }
315
 
 
316
 
   /* XXX Here should first convert encoding to precomposed UTF8. */
317
 
 
318
 
   /* Convert staging name to CP format. */
319
 
   cpNameSize = CPNameUtil_ConvertToRoot(destDir.c_str(),
320
 
                                         sizeof cpName,
321
 
                                         cpName);
322
 
   if (cpNameSize < 0) {
323
 
      Debug("%s: Error, could not convert to CPName.\n", __FUNCTION__);
324
 
      return "";
325
 
   }
326
 
 
327
 
   if (!mRpc->HGStartFileCopy(cpName, cpNameSize)) {
328
 
      return "";
329
 
   }
330
 
 
331
 
   mStagingDir = destDir;
332
 
 
333
 
   return destDir;
334
 
}
335
 
 
336
 
 
337
 
/*
338
 
 *----------------------------------------------------------------------------
339
 
 *
340
 
 * CopyPaste::SetupDestDir --
341
 
 *
342
 
 *      Creates a directory for file transfer. If the destination
343
 
 *      dir is provided, we will attempt to copy files to the directory.
344
 
 *
345
 
 *      Input directory will be in local format.
346
 
 *
347
 
 * Results:
348
 
 *      The destination directory on success, an empty string on failure.
349
 
 *
350
 
 * Side effects:
351
 
 *      None.
352
 
 *
353
 
 *----------------------------------------------------------------------------
354
 
 */
355
 
 
356
 
std::string
357
 
CopyPaste::SetupDestDir(const std::string &destDir)       // IN:
358
 
{
359
 
   static const std::string failDir = "";
360
 
 
361
 
   if (!destDir.empty() && File_Exists(destDir.c_str())) {
362
 
      mStagingDir = destDir;
363
 
      const char *lastSep = Str_Strrchr(mStagingDir.c_str(), DIRSEPC);
364
 
      if (lastSep && lastSep[1] != '\0') {
365
 
         mStagingDir += DIRSEPS;
366
 
      }
367
 
 
368
 
      return mStagingDir;
369
 
   } else {
370
 
      char *newDir;
371
 
 
372
 
      newDir = DnD_CreateStagingDirectory();
373
 
      if (newDir != NULL) {
374
 
         mStagingDir = newDir;
375
 
 
376
 
         char *lastSep = Str_Strrchr(newDir, DIRSEPC);
377
 
         if (lastSep && lastSep[1] != '\0') {
378
 
            mStagingDir += DIRSEPS;
379
 
         }
380
 
         free(newDir);
381
 
         Debug("%s: destdir: %s", __FUNCTION__, mStagingDir.c_str());
382
 
 
383
 
         return mStagingDir;
384
 
      } else {
385
 
         Debug("%s: destdir not created", __FUNCTION__);
386
 
         return failDir;
387
 
      }
388
 
   }
389
 
}
390
 
 
391