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

« back to all changes in this revision

Viewing changes to modules/linux/vmhgfs/dir.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-10-18 12:28:19 UTC
  • mfrom: (1.1.7 upstream) (2.4.9 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091018122819-00vqew6m0ztpqcqp
Tags: 2009.10.15-201664-1
MergingĀ upstreamĀ versionĀ 2009.10.15-201664.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
#include "compat_fs.h"
31
31
#include "compat_kernel.h"
32
32
#include "compat_slab.h"
 
33
#include "compat_mutex.h"
33
34
 
34
35
#include "cpName.h"
35
36
#include "hgfsEscape.h"
42
43
#include "vm_basic_types.h"
43
44
 
44
45
/* Private functions. */
 
46
static int HgfsPrivateDirReOpen(struct file *file);
 
47
static int HgfsPrivateDirOpen(struct file *file,
 
48
                              HgfsHandle *handle);
 
49
static int HgfsPrivateDirRelease(struct file *file,
 
50
                                 HgfsHandle handle);
45
51
static int HgfsUnpackSearchReadReply(HgfsReq *req,
46
 
                                     HgfsAttrInfo *attr);
 
52
                                     HgfsAttrInfo *attr,
 
53
                                     char **entryName);
47
54
static int HgfsGetNextDirEntry(HgfsSuperInfo *si,
48
55
                               HgfsHandle searchHandle,
49
56
                               uint32 offset,
50
57
                               HgfsAttrInfo *attr,
 
58
                               char **entryName,
51
59
                               Bool *done);
52
 
static int HgfsPackDirOpenRequest(struct inode *inode,
53
 
                                  struct file *file,
54
 
                                  HgfsOp opUsed,
 
60
static int HgfsPackDirOpenRequest(struct file *file,
 
61
                                  HgfsOp opUsed,
55
62
                                  HgfsReq *req);
56
63
 
57
64
/* HGFS file operations for directories. */
62
69
                       filldir_t filldir);
63
70
static int HgfsDirRelease(struct inode *inode,
64
71
                          struct file *file);
 
72
static loff_t HgfsDirLlseek(struct file *file,
 
73
                            loff_t offset,
 
74
                            int origin);
65
75
 
66
76
/* HGFS file operations structure for directories. */
67
77
struct file_operations HgfsDirFileOperations = {
 
78
   .llseek      = HgfsDirLlseek,
68
79
   .owner       = THIS_MODULE,
69
80
   .open        = HgfsDirOpen,
70
81
   .read        = generic_read_dir,
98
109
 */
99
110
static int
100
111
HgfsUnpackSearchReadReply(HgfsReq *req,        // IN: Reply packet
101
 
                          HgfsAttrInfo *attr)  // IN/OUT: Attributes
 
112
                          HgfsAttrInfo *attr,  // IN/OUT: Attributes
 
113
                          char **entryName)    // OUT: file name
102
114
{
103
115
   char *fileName;
104
116
   uint32 fileNameLength;
175
187
                 fileNameLength, strlen(fileName), fileName));
176
188
         return -EPROTO;
177
189
      }
178
 
      attr->fileName = kmalloc(fileNameLength + 1, GFP_KERNEL);
179
 
      if (attr->fileName == NULL) {
 
190
      *entryName = kmalloc(fileNameLength + 1, GFP_KERNEL);
 
191
      if (*entryName == NULL) {
180
192
         LOG(4, (KERN_DEBUG "VMware hgfs: HgfsUnpackSearchReadReply: out of "
181
193
                 "memory allocating filename, ignoring\n"));
182
194
         return -ENOMEM;
183
195
      }
184
 
      memcpy(attr->fileName, fileName, fileNameLength + 1);
 
196
      memcpy(*entryName, fileName, fileNameLength + 1);
185
197
   } else {
186
 
      attr->fileName = NULL;
 
198
      *entryName = NULL;
187
199
   }
188
200
   return 0;
189
201
}
196
208
 *
197
209
 *    Get the directory entry with the given offset from the server.
198
210
 *
199
 
 *    attr->fileName gets allocated and must be freed by the caller.
 
211
 *    fileName gets allocated and must be freed by the caller.
200
212
 *
201
213
 * Results:
202
214
 *    Returns zero on success, negative error on failure. If the
213
225
                    HgfsHandle searchHandle, // IN: Handle of dir
214
226
                    uint32 offset,           // IN: Offset of next dentry to get
215
227
                    HgfsAttrInfo *attr,      // OUT: File attributes of dentry
 
228
                    char **entryName,        // OUT: File name
216
229
                    Bool *done)              // OUT: Set true when there are
217
230
                                             // no more dentries
218
231
{
268
281
 
269
282
      switch(result) {
270
283
      case 0:
271
 
         result = HgfsUnpackSearchReadReply(req, attr);
272
 
         if (result == 0 && attr->fileName == NULL) {
 
284
         result = HgfsUnpackSearchReadReply(req, attr, entryName);
 
285
         if (result == 0 && *entryName == NULL) {
273
286
            /* We're at the end of the directory. */
274
287
            LOG(6, (KERN_DEBUG "VMware hgfs: HgfsGetNextDirEntry: end of "
275
288
                    "dir\n"));
327
340
 */
328
341
 
329
342
static int
330
 
HgfsPackDirOpenRequest(struct inode *inode, // IN: Inode of the file to open
331
 
                       struct file *file,   // IN: File pointer for this open
 
343
HgfsPackDirOpenRequest(struct file *file,   // IN: File pointer for this open
332
344
                       HgfsOp opUsed,       // IN: Op to be used
333
345
                       HgfsReq *req)        // IN/OUT: Packet to write into
334
346
{
337
349
   size_t requestSize;
338
350
   int result;
339
351
 
340
 
   ASSERT(inode);
341
352
   ASSERT(file);
342
353
   ASSERT(req);
343
354
 
389
400
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackDirOpenRequest: build path failed\n"));
390
401
      return -EINVAL;
391
402
   }
392
 
   LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPackDirOpenRequest: opening \"%s\"\n",
 
403
   LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPackDirOpenRequest: opening \"%s\"\n",
393
404
           name));
394
405
 
395
406
   /* Convert to CP name. */
409
420
 
410
421
 
411
422
/*
412
 
 * HGFS file operations for directories.
413
 
 */
414
 
 
415
 
/*
416
423
 *----------------------------------------------------------------------
417
424
 *
418
 
 * HgfsDirOpen --
419
 
 *
420
 
 *    Called whenever a process opens a directory in our filesystem.
421
 
 *
422
 
 *    We send a "Search Open" request to the server with the name
423
 
 *    stored in this file's inode. If the Open succeeds, we store the
424
 
 *    search handle sent by the server in the file struct so it can be
425
 
 *    accessed by readdir and close.
 
425
 * HgfsPrivateDirOpen --
 
426
 *
 
427
 *    Called by HgfsDirOpen() and HgfsReaddir() routines.
426
428
 *
427
429
 * Results:
428
430
 *    Returns zero if on success, error on failure.
434
436
 */
435
437
 
436
438
static int
437
 
HgfsDirOpen(struct inode *inode,  // IN: Inode of the dir to open
438
 
            struct file *file)    // IN: File pointer for this open
 
439
HgfsPrivateDirOpen(struct file *file,    // IN: File pointer for this open
 
440
                   HgfsHandle *handle)   // IN: Hgfs handle
439
441
{
440
442
   HgfsReq *req;
441
443
   int result;
443
445
   HgfsStatus replyStatus;
444
446
   HgfsHandle *replySearch;
445
447
 
446
 
   ASSERT(inode);
447
 
   ASSERT(inode->i_sb);
448
448
   ASSERT(file);
449
449
 
450
450
   req = HgfsGetNewRequest();
451
451
   if (!req) {
452
 
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: out of memory while "
 
452
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: out of memory while "
453
453
              "getting new request\n"));
454
454
      result = -ENOMEM;
455
455
      goto out;
463
463
      replySearch = &((HgfsReplySearchOpen *)HGFS_REQ_PAYLOAD(req))->search;
464
464
   }
465
465
 
466
 
   result = HgfsPackDirOpenRequest(inode, file, opUsed, req);
 
466
   result = HgfsPackDirOpenRequest(file, opUsed, req);
467
467
   if (result != 0) {
468
 
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: error packing request\n"));
 
468
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen error packing request\n"));
469
469
      goto out;
470
470
   }
471
471
 
478
478
 
479
479
      switch (result) {
480
480
      case 0:
481
 
         result = HgfsCreateFileInfo(file, *replySearch);
482
 
         if (result) {
483
 
           goto out;
484
 
         }
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",
486
484
                    *replySearch));
487
485
         break;
488
486
      case -EPROTO:
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;
494
492
            goto retry;
495
493
         }
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));
498
496
         break;
499
497
 
500
498
      default:
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));
503
501
         break;
504
502
      }
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));
510
 
   } else {
511
 
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirOpen: unknown error: "
512
 
              "%d\n", result));
513
 
   }
514
 
 
515
 
out:
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));
 
508
   } else {
 
509
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirOpen: unknown error: "
 
510
              "%d\n", result));
 
511
   }
 
512
 
 
513
out:
 
514
   HgfsFreeRequest(req);
 
515
   return result;
 
516
}
 
517
 
 
518
 
 
519
/*
 
520
 *----------------------------------------------------------------------
 
521
 *
 
522
 * HgfsPrivateDirRelease --
 
523
 *
 
524
 *    Called by HgfsDirRelease() and HgfsReaddir() routines.
 
525
 *
 
526
 * Results:
 
527
 *    Returns zero on success, or an error on failure.
 
528
 *
 
529
 * Side effects:
 
530
 *    None
 
531
 *
 
532
 *----------------------------------------------------------------------
 
533
 */
 
534
 
 
535
static int
 
536
HgfsPrivateDirRelease(struct file *file,   // IN: File for the dir getting released
 
537
                      HgfsHandle handle)   // IN: Hgfs handle
 
538
{
 
539
   HgfsReq *req;
 
540
   HgfsStatus replyStatus;
 
541
   HgfsOp opUsed;
 
542
   int result = 0;
 
543
 
 
544
   ASSERT(file);
 
545
   ASSERT(file->f_dentry);
 
546
   ASSERT(file->f_dentry->d_sb);
 
547
 
 
548
   LOG(6, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: close fh %u\n", handle));
 
549
 
 
550
   req = HgfsGetNewRequest();
 
551
   if (!req) {
 
552
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: out of memory while "
 
553
              "getting new request\n"));
 
554
      result = -ENOMEM;
 
555
      goto out;
 
556
   }
 
557
 
 
558
 retry:
 
559
   opUsed = hgfsVersionSearchClose;
 
560
   if (opUsed == HGFS_OP_SEARCH_CLOSE_V3) {
 
561
      HgfsRequestSearchCloseV3 *request;
 
562
      HgfsRequest *header;
 
563
 
 
564
      header = (HgfsRequest *)(HGFS_REQ_PAYLOAD(req));
 
565
      header->id = req->id;
 
566
      header->op = opUsed;
 
567
 
 
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);
 
572
   } else {
 
573
      HgfsRequestSearchClose *request;
 
574
 
 
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;
 
580
   }
 
581
 
 
582
   /* Send the request and process the reply. */
 
583
   result = HgfsSendRequest(req);
 
584
   if (result == 0) {
 
585
      /* Get the reply. */
 
586
      replyStatus = HgfsReplyStatus(req);
 
587
      result = HgfsStatusConvertToLinux(replyStatus);
 
588
 
 
589
      switch (result) {
 
590
      case 0:
 
591
         LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: release handle %u\n",
 
592
                 handle));
 
593
         break;
 
594
      case -EPROTO:
 
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;
 
600
            goto retry;
 
601
         }
 
602
         break;
 
603
      default:
 
604
         LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: failed handle %u\n",
 
605
                 handle));
 
606
         break;
 
607
      }
 
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));
 
613
   } else {
 
614
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsPrivateDirRelease: unknown error: "
 
615
              "%d\n", result));
 
616
   }
 
617
 
 
618
out:
 
619
   HgfsFreeRequest(req);
 
620
   return result;
 
621
}
 
622
 
 
623
 
 
624
/*
 
625
 *----------------------------------------------------------------------
 
626
 *
 
627
 * HgfsPrivateDirReOpen --
 
628
 *
 
629
 *    Reopens the file. Called by HgfsReaddir() routine.
 
630
 *
 
631
 * Results:
 
632
 *    Returns zero if on success, error on failure.
 
633
 *
 
634
 * Side effects:
 
635
 *    None
 
636
 *
 
637
 *----------------------------------------------------------------------
 
638
 */
 
639
 
 
640
static int
 
641
HgfsPrivateDirReOpen(struct file *file)   // IN: File pointer for this open
 
642
{
 
643
   int result = 0;
 
644
   HgfsHandle *handle = &FILE_GET_FI_P(file)->handle;
 
645
   LOG(4, (KERN_DEBUG "HgfsPrivateDirReOpen: Directory handle in invalid;"
 
646
           "Reopening ...\n"));
 
647
 
 
648
   result = HgfsPrivateDirRelease(file, *handle);
 
649
   if (result) {
 
650
      return result;
 
651
   }
 
652
 
 
653
   result = HgfsPrivateDirOpen(file, handle);
 
654
   if (result) {
 
655
      return result;
 
656
   }
 
657
 
 
658
   FILE_GET_FI_P(file)->isStale = FALSE;
 
659
 
 
660
   return result;
 
661
}
 
662
 
 
663
 
 
664
/*
 
665
 * HGFS file operations for directories.
 
666
 */
 
667
 
 
668
/*
 
669
 *----------------------------------------------------------------------
 
670
 *
 
671
 * HgfsDirLlseek --
 
672
 *
 
673
 *    Called whenever a process does rewinddir() or telldir()/seekdir().
 
674
 *
 
675
 * Results:
 
676
 *    Returns zero if on success, error on failure.
 
677
 *
 
678
 * Side effects:
 
679
 *    None
 
680
 *
 
681
 *----------------------------------------------------------------------
 
682
 */
 
683
 
 
684
static loff_t
 
685
HgfsDirLlseek(struct file *file,
 
686
              loff_t offset,
 
687
              int origin)
 
688
{
 
689
   struct dentry *dentry = file->f_dentry;
 
690
   struct inode *inode = dentry->d_inode;
 
691
   compat_mutex_t mtx;
 
692
 
 
693
   LOG(4, (KERN_DEBUG "Got llseek call with origin = %d, offset = %u,"
 
694
           "pos = %u\n", origin, (uint32)offset, (uint32)file->f_pos));
 
695
 
 
696
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
 
697
   mtx = inode->i_sem;
 
698
#else
 
699
   mtx = inode->i_mutex;
 
700
#endif
 
701
 
 
702
   compat_mutex_lock(&mtx);
 
703
 
 
704
   switch(origin) {
 
705
 
 
706
   /* SEEK_CUR */
 
707
   case 1: offset += file->f_pos;
 
708
           break;
 
709
   /* SEEK_SET */
 
710
   case 0: break;
 
711
 
 
712
   /* SEEK_END */
 
713
   case 2:
 
714
   default: offset = -EINVAL;
 
715
            break;
 
716
   }
 
717
 
 
718
   if (offset < 0) {
 
719
      offset = -EINVAL;
 
720
      goto out;
 
721
   }
 
722
 
 
723
   if (offset != file->f_pos) {
 
724
      file->f_pos = offset;
 
725
   }
 
726
 
 
727
   /*
 
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.
 
733
    *
 
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().
 
741
    */
 
742
   if (!file->f_pos) {
 
743
      FILE_GET_FI_P(file)->isStale = TRUE;
 
744
   }
 
745
 
 
746
out:
 
747
   compat_mutex_unlock(&mtx);
 
748
   return offset;
 
749
}
 
750
 
 
751
 
 
752
/*
 
753
 *----------------------------------------------------------------------
 
754
 *
 
755
 * HgfsDirOpen --
 
756
 *
 
757
 *    Called whenever a process opens a directory in our filesystem.
 
758
 *
 
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.
 
763
 *
 
764
 * Results:
 
765
 *    Returns zero if on success, error on failure.
 
766
 *
 
767
 * Side effects:
 
768
 *    None
 
769
 *
 
770
 *----------------------------------------------------------------------
 
771
 */
 
772
 
 
773
static int
 
774
HgfsDirOpen(struct inode *inode,  // IN: Inode of the dir to open
 
775
            struct file *file)    // IN: File pointer for this open
 
776
{
 
777
   int result;
 
778
 
 
779
   HgfsHandle handle;
 
780
 
 
781
   ASSERT(inode);
 
782
   ASSERT(inode->i_sb);
 
783
   ASSERT(file);
 
784
 
 
785
   result = HgfsPrivateDirOpen(file, &handle);
 
786
   if (!result) {
 
787
      result = HgfsCreateFileInfo(file, handle);
 
788
   }
 
789
 
517
790
   return result;
518
791
}
519
792
 
573
846
   HgfsSuperInfo *si;
574
847
   HgfsAttrInfo attr;
575
848
   uint32 d_type;    // type of dirent
 
849
   char *fileName = NULL;
576
850
   char *escName = NULL; // buf for escaped version of name
577
851
   size_t escNameLength = NAME_MAX + 1;
578
852
   int nameLength = 0;
579
853
   int result = 0;
580
854
   Bool done = FALSE;
 
855
   Bool isStale = FALSE;
581
856
   ino_t ino;
582
857
 
583
858
   ASSERT(file);
601
876
          file->f_pos));
602
877
 
603
878
   /*
 
879
    * rm -rf 6.10+ breaks because it does following:
 
880
    * an 'fd = open()' on a directory, followed by unlinkat()
 
881
    * which removes an entry from the directory it and then
 
882
    * fdopendir(fd). We get a call on open() but not on fdopendir(),
 
883
    * which means that we do not reflect the action of unlinkat(),
 
884
    * and thus rm -rf gets confused and marking entry as unremovable.
 
885
    * Note that this problem exists because hgfsServer reads all
 
886
    * the directory entries at open(). Interested reader may look at
 
887
    * coreutils/src/remove.c file.
 
888
    *
 
889
    * So as a workaround, we ask the server to populate entries on
 
890
    * first readdir() call rather than opendir(). This effect is
 
891
    * achieved by closing and reopening the directory. Grrr!
 
892
    *
 
893
    * XXX We should get rid of this code when/if we remove the above
 
894
    * behavior from hgfsServer.
 
895
    */
 
896
   isStale = FILE_GET_FI_P(file)->isStale;
 
897
   if (isStale) {
 
898
      result = HgfsPrivateDirReOpen(file);
 
899
      if (result) {
 
900
         return result;
 
901
      }
 
902
   }
 
903
 
 
904
   /*
604
905
    * Some day when we're out of things to do we can move this to a slab
605
906
    * allocator.
606
907
    */
616
917
       * Nonzero result = we failed to get valid reply from server.
617
918
       * Zero result:
618
919
       *     - done == TRUE means we hit the end of the directory
619
 
       *     - Otherwise, attr.fileName has the name of the next dirent
 
920
       *     - Otherwise, fileName has the name of the next dirent
620
921
       *
621
922
       */
 
923
 
622
924
      result = HgfsGetNextDirEntry(si,
623
925
                                   FILE_GET_FI_P(file)->handle,
624
926
                                   (uint32)file->f_pos,
625
927
                                   &attr,
 
928
                                   &fileName,
626
929
                                   &done);
627
930
      if (result == -ENAMETOOLONG) {
628
931
         /*
641
944
         kfree(escName);
642
945
         return result;
643
946
      }
 
947
 
644
948
      if (done == TRUE) {
645
949
         LOG(6, (KERN_DEBUG "VMware hgfs: HgfsReaddir: end of dir reached\n"));
646
950
         break;
654
958
       * CP name format, but that is done implicitely here since we
655
959
       * are guaranteed to have just one path component per dentry.
656
960
       */
657
 
      result = HgfsEscape_Do(attr.fileName,
658
 
                             strlen(attr.fileName),
659
 
                             escNameLength,
660
 
                             escName);
661
 
      kfree(attr.fileName);
 
961
      result = HgfsEscape_Do(fileName, strlen(fileName),
 
962
                             escNameLength, escName);
 
963
      kfree(fileName);
 
964
      fileName = NULL;
662
965
 
663
966
      /*
664
967
       * Check the filename length.
782
1085
HgfsDirRelease(struct inode *inode,  // IN: Inode that the file* points to
783
1086
               struct file *file)    // IN: File for the dir getting released
784
1087
{
785
 
   HgfsReq *req;
786
 
   HgfsStatus replyStatus;
787
1088
   HgfsHandle handle;
788
 
   HgfsOp opUsed;
789
 
   int result = 0;
790
1089
 
791
1090
   ASSERT(inode);
792
1091
   ASSERT(file);
794
1093
   ASSERT(file->f_dentry->d_sb);
795
1094
 
796
1095
   handle = FILE_GET_FI_P(file)->handle;
797
 
   LOG(6, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: close fh %u\n", handle));
798
1096
 
799
1097
   HgfsReleaseFileInfo(file);
800
1098
 
801
 
   req = HgfsGetNewRequest();
802
 
   if (!req) {
803
 
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: out of memory while "
804
 
              "getting new request\n"));
805
 
      result = -ENOMEM;
806
 
      goto out;
807
 
   }
808
 
 
809
 
 retry:
810
 
   opUsed = hgfsVersionSearchClose;
811
 
   if (opUsed == HGFS_OP_SEARCH_CLOSE_V3) {
812
 
      HgfsRequestSearchCloseV3 *request;
813
 
      HgfsRequest *header;
814
 
 
815
 
      header = (HgfsRequest *)(HGFS_REQ_PAYLOAD(req));
816
 
      header->id = req->id;
817
 
      header->op = opUsed;
818
 
 
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);
823
 
   } else {
824
 
      HgfsRequestSearchClose *request;
825
 
 
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;
831
 
   }
832
 
 
833
 
   /* Send the request and process the reply. */
834
 
   result = HgfsSendRequest(req);
835
 
   if (result == 0) {
836
 
      /* Get the reply. */
837
 
      replyStatus = HgfsReplyStatus(req);
838
 
      result = HgfsStatusConvertToLinux(replyStatus);
839
 
 
840
 
      switch (result) {
841
 
      case 0:
842
 
         LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: release handle %u\n",
843
 
                 handle));
844
 
         break;
845
 
      case -EPROTO:
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;
851
 
            goto retry;
852
 
         }
853
 
         break;
854
 
      default:
855
 
         LOG(4, (KERN_DEBUG "VMware hgfs: HgfsDirRelease: failed handle %u\n",
856
 
                 handle));
857
 
         break;
858
 
      }
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));
864
 
   } else {
865
 
      LOG(4, (KERN_DEBUG "VMware hgfs: HgfsOpen: unknown error: "
866
 
              "%d\n", result));
867
 
   }
868
 
 
869
 
out:
870
 
   HgfsFreeRequest(req);
871
 
   return result;
 
1099
   return HgfsPrivateDirRelease(file, handle);
872
1100
}