152
115
static int gDaemonSignal;
153
116
static int gCommandLineRpciSignal;
155
#ifdef VM_GUESTD_MOUNTS_HGFS
156
typedef struct HgfsMountState {
157
const char *mountPoint; /* Mount point for hgfs filesystem */
158
Bool mounted; /* TRUE if mounted, FALSE if not */
162
#ifdef VM_GUESTD_RUNS_HGFS_PSERVER
163
/* Hgfs state needed per mounted filesystem */
164
typedef struct PserverState {
165
HgfsMountState mountState;
166
char *requestPacket; /* Buffer for request packets */
167
RpcOut *out; /* Backdoor communications channel */
168
int fd; /* Hgfs device fd (communication with kernel) */
171
static PserverState globalHgfsState = {
172
{NULL, FALSE}, /* mountState */
173
NULL, /* requestPacket */
177
#elif defined(VM_GUESTD_MOUNTS_HGFS)
178
static HgfsMountState globalHgfsState = {
179
NULL, /* mountPoint */
184
#ifdef VM_GUESTD_MOUNTS_HGFS
186
*-----------------------------------------------------------------------------
188
* HgfsMountState_Cleanup --
190
* Unmounts the hgfs filesystem
194
* FALSE if one or more steps failed.
197
* Unmounts the filesystem and cleans up the HgfsMountState structure.
199
*-----------------------------------------------------------------------------
203
HgfsMountState_Cleanup(HgfsMountState *state) // IN: Hgfs mount state
210
/* Try to unmount hgfs */
211
if (state->mounted) {
212
Debug("HgfsMountState_Cleanup: attempting to unmount %s\n",
215
result = umount(state->mountPoint);
219
Debug("HgfsMountState_Cleanup: error %d (%s) unmounting filesystem\n",
224
state->mounted = FALSE;
225
Debug("HgfsMountState_Cleanup: unmount succeeded\n");
228
if (state->mountPoint) {
229
free((void *)state->mountPoint);
230
state->mountPoint = NULL;
237
*-----------------------------------------------------------------------------
239
* HgfsMountState_Init --
241
* Mounts the hgfs filesystem
245
* FALSE if one or more steps failed.
248
* Allocates a copy of the mount point string, updates the HgfsMountState structure,
249
* and mounts the filesystem.
251
*-----------------------------------------------------------------------------
255
HgfsMountState_Init(HgfsMountState *state, // IN: Hgfs mount state
256
const char *pMountPoint, // IN: Shared folder mount target
257
int fd) // IN: Pserver file descriptor, or -1
264
state->mountPoint = strdup(pMountPoint);
265
state->mounted = FALSE;
269
HgfsMountInfo mntInfo; /* Data to pass to kernel when mounting */
272
mntInfo.version = HGFS_PROTOCOL_VERSION;
273
mntInfo.magicNumber = HGFS_SUPER_MAGIC;
275
Debug("HgfsMountState_Init: trying to mount %s...\n", state->mountPoint);
276
mntRes = mount(HGFS_MOUNT_SRC, state->mountPoint, HGFS_MOUNT_FLAGS,
277
HGFS_FS_NAME, &mntInfo, sizeof mntInfo);
283
Debug("HgfsMountState_Init: mount failed: %s\n", strerror(error));
284
HgfsMountState_Cleanup(state);
287
state->mounted = TRUE;
288
Debug("HgfsMountState_Init: mount succeeded\n");
295
* Hgfs pserver functions
298
#ifdef VM_GUESTD_RUNS_HGFS_PSERVER
300
*-----------------------------------------------------------------------------
302
* HgfsPserver_Cleanup --
304
* Teardown the communication channel with the server, unmount this
305
* hgfs filesystem, and close the driver proc file.
309
* FALSE if one or more steps failed.
314
*-----------------------------------------------------------------------------
318
HgfsPserver_Cleanup(PserverState *state) // IN: State for this mount
325
/* Try to close the backdoor */
326
if (!HgfsBd_CloseBackdoor(&state->out)) {
327
Debug("HgfsPserver_Cleanup: failed to close backdoor\n");
332
/* Release the request packet buffer */
333
if (state->requestPacket) {
334
HgfsBd_PutBuf(state->requestPacket);
335
state->requestPacket = NULL;
339
* XXX The unmount should be done in the driver (NOT here), in case
340
* the pserver gets killed or is misbehaved.
342
if (!HgfsMountState_Cleanup(&state->mountState)) {
346
/* Try to close the hgfs device */
347
if (state->fd >= 0) {
348
result = close(state->fd);
351
Debug("HgfsPserver_Cleanup: failed to close file: %s\n",
363
*-----------------------------------------------------------------------------
365
* HgfsPserver_Init --
367
* Set up pserver communication state.
369
* Specifically: open the proc file, try to mount the filesystem,
370
* get a request packet buffer from the backdoor layer and open the
371
* backdoor communication channel.
380
*-----------------------------------------------------------------------------
384
HgfsPserver_Init(PserverState *state, // IN/OUT: State for this mount
385
const char *pMountPoint) // IN: Shared folder mount target
392
state->requestPacket = NULL;
394
state->fd = open(HGFS_DEVICE, O_RDWR | O_NONBLOCK);
397
Debug("HgfsPserver_Init: error opening proc file: %s\n",
399
HgfsPserver_Cleanup(state);
404
* We need to make sure children of guestd do not inherit
405
* this file descriptor, otherwise they'll keep references to
408
if ((fcntl(state->fd, F_SETFD, FD_CLOEXEC)) < 0) {
410
Debug("HgfsPserver_Init: error setting proc file flags: %s\n",
412
HgfsPserver_Cleanup(state);
416
if (HgfsMountState_Init(&state->mountState, pMountPoint, state->fd) == FALSE) {
417
HgfsPserver_Cleanup(state);
422
* Eventually we may want to frob /etc/mtab here to reflect the
426
state->requestPacket = HgfsBd_GetBuf();
427
if (!state->requestPacket) {
428
Debug("HgfsPserver_Init: couldn't get bd buffer\n");
429
HgfsPserver_Cleanup(state);
438
*-----------------------------------------------------------------------------
440
* HgfsPserverHandleRequest --
442
* Read a request from the driver, send it to the server, and
443
* pass the reply back to the driver.
452
*-----------------------------------------------------------------------------
456
HgfsPserverHandleRequest(PserverState *pState) // IN: Pserver state
458
char const *replyPacket; // Buffer returned by HgfsBd_Dispatch
465
/* Get the request from the driver. */
466
n = read(pState->fd, pState->requestPacket, HGFS_PACKET_MAX);
469
Debug("HgfsPserverHandleRequest: Read error from hgfs fd: %s\n",
477
* Ensure the backdoor is open and then attempt to send the request across it
478
* to the hgfs server.
480
* Failure of either action may indicate that Shared Folders have been disabled,
481
* in which case we send an error response to the fs module and clean up the
482
* backdoor (so that it might be re-opened with a subsequent request).
484
* If both actions succeed, the replyPacket will have a valid reply and the
485
* packetSize will be set to the size of the replyPacket contents.
487
if (!HgfsBd_OpenBackdoor(&pState->out) ||
488
(HgfsBd_Dispatch(pState->out,
489
pState->requestPacket,
491
&replyPacket) < 0)) {
492
HgfsRequest *request = (HgfsRequest *)pState->requestPacket;
493
HgfsReply errorReply;
495
Debug("HgfsPserverHandleRequest: Problem sending request across backdoor\n");
497
errorReply.id = request->id;
498
errorReply.status = HGFS_STATUS_PROTOCOL_ERROR;
500
n = write(pState->fd, &errorReply, sizeof errorReply);
503
Debug("HgfsPserverHandleRequest: Problem writing error reply: %s\n",
507
if (!HgfsBd_CloseBackdoor(&pState->out)) {
508
Debug("HgfsPserverHandleRequest: Problem closing backdoor\n");
517
/* Send reply to driver */
518
n = write(pState->fd, replyPacket, packetSize);
521
Debug("HgfsPserverHandleRequest: Write error to file: %s\n", strerror(error));
529
#if defined(VM_GUESTD_MOUNTS_HGFS)
531
*-----------------------------------------------------------------------------
533
* GuestdGetValidMountPt --
535
* Return returns the shared folder mount point from the configuration
536
* dictionary with trailing /'s removed. The caller is responsible for
537
* freeing the returned string.
540
* NULL on failure (No entry in configuration dictionary or the entry
541
* consisted of 0 or more consecutive /'s.
542
* non-NULL on success (Pointer to valid name, with trailing /'s
548
*-----------------------------------------------------------------------------
552
GuestdGetValidMountPt(GuestApp_Dict *Dict) // IN: Configuration dictionary
554
const char *pMount = GuestApp_GetDictEntry(Dict, CONFNAME_MOUNT_POINT);
563
len = strlen(pMount);
568
for (end = &pMount[len - 1]; end > pMount; end--) {
575
* Pathological case string consisting of all /'s
581
* end points to the last non-/ (and non-'\0') character in pMount.
585
p[end - pMount + 1] = '\0';
589
#endif /* VM_GUESTD_MOUNTS_HGFS */
593
120
*-----------------------------------------------------------------------------