479
479
switch (result) {
481
result = HgfsCreateFileInfo(file, *replySearch);
485
LOG(6, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: set handle to %u\n",
481
/* Save the handle value */
482
*handle = *replySearch;
483
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: Handle returned = %u\n",
489
487
/* Retry with older version(s). Set globally. */
490
488
if (opUsed == HGFS_OP_SEARCH_OPEN_V3) {
491
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: Version 3 not "
489
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: Version 3 not "
492
490
"supported. Falling back to version 1.\n"));
493
491
hgfsVersionSearchOpen = HGFS_OP_SEARCH_OPEN;
496
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: server "
494
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: server "
497
495
"returned error: %d\n", result));
501
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: server "
499
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: server "
502
500
"returned error: %d\n", result));
505
503
} else if (result == -EIO) {
506
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: timed out\n"));
507
} else if (result == -EPROTO) {
508
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: server "
509
"returned error: %d\n", result));
511
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: unknown error: "
516
HgfsFreeRequest(req);
504
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: timed out\n"));
505
} else if (result == -EPROTO) {
506
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: server "
507
"returned error: %d\n", result));
509
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: unknown error: "
514
HgfsFreeRequest(req);
520
*----------------------------------------------------------------------
522
* HgfsPrivateDirRelease --
524
* Called by HgfsDirRelease() and HgfsReaddir() routines.
527
* Returns zero on success, or an error on failure.
532
*----------------------------------------------------------------------
536
HgfsPrivateDirRelease(struct file *file, // IN: File for the dir getting released
537
HgfsHandle handle) // IN: Hgfs handle
540
HgfsStatus replyStatus;
545
ASSERT(file->f_dentry);
546
ASSERT(file->f_dentry->d_sb);
548
LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: close fh %u\n", handle));
550
req = HgfsGetNewRequest();
552
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: out of memory while "
553
"getting new request\n"));
559
opUsed = hgfsVersionSearchClose;
560
if (opUsed == HGFS_OP_SEARCH_CLOSE_V3) {
561
HgfsRequestSearchCloseV3 *request;
564
header = (HgfsRequest *)(HGFS_REQ_PAYLOAD(req));
565
header->id = req->id;
568
request = (HgfsRequestSearchCloseV3 *)(HGFS_REQ_PAYLOAD_V3(req));
569
request->search = handle;
570
request->reserved = 0;
571
req->payloadSize = HGFS_REQ_PAYLOAD_SIZE_V3(request);
573
HgfsRequestSearchClose *request;
575
request = (HgfsRequestSearchClose *)(HGFS_REQ_PAYLOAD(req));
576
request->header.id = req->id;
577
request->header.op = opUsed;
578
request->search = handle;
579
req->payloadSize = sizeof *request;
582
/* Send the request and process the reply. */
583
result = HgfsSendRequest(req);
586
replyStatus = HgfsReplyStatus(req);
587
result = HgfsStatusConvertToLinux(replyStatus);
591
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: release handle %u\n",
595
/* Retry with older version(s). Set globally. */
596
if (opUsed == HGFS_OP_SEARCH_CLOSE_V3) {
597
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: Version 3 not "
598
"supported. Falling back to version 1.\n"));
599
hgfsVersionSearchClose = HGFS_OP_SEARCH_CLOSE;
604
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: failed handle %u\n",
608
} else if (result == -EIO) {
609
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: timed out\n"));
610
} else if (result == -EPROTO) {
611
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: server "
612
"returned error: %d\n", result));
614
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: unknown error: "
619
HgfsFreeRequest(req);
625
*----------------------------------------------------------------------
627
* HgfsPrivateDirReOpen --
629
* Reopens the file. Called by HgfsReaddir() routine.
632
* Returns zero if on success, error on failure.
637
*----------------------------------------------------------------------
641
HgfsPrivateDirReOpen(struct file *file) // IN: File pointer for this open
644
HgfsHandle *handle = &FILE_GET_FI_P(file)->handle;
645
LOG(4, (KERN_DEBUG "HgfsPrivateDirReOpen: Directory handle in invalid;"
648
result = HgfsPrivateDirRelease(file, *handle);
653
result = HgfsPrivateDirOpen(file, handle);
658
FILE_GET_FI_P(file)->isStale = FALSE;
665
* HGFS file operations for directories.
669
*----------------------------------------------------------------------
673
* Called whenever a process does rewinddir() or telldir()/seekdir().
676
* Returns zero if on success, error on failure.
681
*----------------------------------------------------------------------
685
HgfsDirLlseek(struct file *file,
689
struct dentry *dentry = file->f_dentry;
690
struct inode *inode = dentry->d_inode;
693
LOG(4, (KERN_DEBUG "Got llseek call with origin = %d, offset = %u,"
694
"pos = %u\n", origin, (uint32)offset, (uint32)file->f_pos));
696
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
699
mtx = inode->i_mutex;
702
compat_mutex_lock(&mtx);
707
case 1: offset += file->f_pos;
714
default: offset = -EINVAL;
723
if (offset != file->f_pos) {
724
file->f_pos = offset;
728
* rewinddir() semantics says that It causes the directory stream
729
* to refer to the current state of the corresponding directory,
730
* as a call to opendir would have done. So when rewinddir() happens,
731
* we mark current directory as stale, so that subsequent readdir()
732
* call will reopen() the directory.
734
* XXX telldir()/seekdir() semantics does not say that we need to refer
735
* to the current state of a directory. However, an application that does
736
* following: telldir() -> rmdir(current_entry) -> seekdir() and checking
737
* whether entry was deleted or not, will break. I have no evidence of an
738
* application relying on above behavior, so let's not incur extra cost
739
* by reopening directory on telldir()/seekdir() combination. Note: A special
740
* case of telldir()/seekdir() to offset 0 will behave same as rewinddir().
743
FILE_GET_FI_P(file)->isStale = TRUE;
747
compat_mutex_unlock(&mtx);
753
*----------------------------------------------------------------------
757
* Called whenever a process opens a directory in our filesystem.
759
* We send a "Search Open" request to the server with the name
760
* stored in this file's inode. If the Open succeeds, we store the
761
* search handle sent by the server in the file struct so it can be
762
* accessed by readdir and close.
765
* Returns zero if on success, error on failure.
770
*----------------------------------------------------------------------
774
HgfsDirOpen(struct inode *inode, // IN: Inode of the dir to open
775
struct file *file) // IN: File pointer for this open
785
result = HgfsPrivateDirOpen(file, &handle);
787
result = HgfsCreateFileInfo(file, handle);
794
1093
ASSERT(file->f_dentry->d_sb);
796
1095
handle = FILE_GET_FI_P(file)->handle;
797
LOG(6, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: close fh %u\n", handle));
799
1097
HgfsReleaseFileInfo(file);
801
req = HgfsGetNewRequest();
803
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: out of memory while "
804
"getting new request\n"));
810
opUsed = hgfsVersionSearchClose;
811
if (opUsed == HGFS_OP_SEARCH_CLOSE_V3) {
812
HgfsRequestSearchCloseV3 *request;
815
header = (HgfsRequest *)(HGFS_REQ_PAYLOAD(req));
816
header->id = req->id;
819
request = (HgfsRequestSearchCloseV3 *)(HGFS_REQ_PAYLOAD_V3(req));
820
request->search = handle;
821
request->reserved = 0;
822
req->payloadSize = HGFS_REQ_PAYLOAD_SIZE_V3(request);
824
HgfsRequestSearchClose *request;
826
request = (HgfsRequestSearchClose *)(HGFS_REQ_PAYLOAD(req));
827
request->header.id = req->id;
828
request->header.op = opUsed;
829
request->search = handle;
830
req->payloadSize = sizeof *request;
833
/* Send the request and process the reply. */
834
result = HgfsSendRequest(req);
837
replyStatus = HgfsReplyStatus(req);
838
result = HgfsStatusConvertToLinux(replyStatus);
842
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: release handle %u\n",
846
/* Retry with older version(s). Set globally. */
847
if (opUsed == HGFS_OP_SEARCH_CLOSE_V3) {
848
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: Version 3 not "
849
"supported. Falling back to version 1.\n"));
850
hgfsVersionSearchClose = HGFS_OP_SEARCH_CLOSE;
855
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: failed handle %u\n",
859
} else if (result == -EIO) {
860
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: timed out\n"));
861
} else if (result == -EPROTO) {
862
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: server "
863
"returned error: %d\n", result));
865
LOG(4, (KERN_DEBUG "VMware hgfs: HgfsOpen: unknown error: "
870
HgfsFreeRequest(req);
1099
return HgfsPrivateDirRelease(file, handle);