Beispiel #1
0
int
CPNameEscapeAndConvertFrom(char const **bufIn, // IN/OUT: Input to convert
                           size_t *inSize,     // IN/OUT: Size of input
                           size_t *outSize,    // IN/OUT: Size of output buffer
                           char **bufOut,      // IN/OUT: Output buffer
                           char pathSep)       // IN: Path separator character
{
   int result;
   int inputSize;
   inputSize = HgfsEscape_GetSize(*bufIn, *inSize);
   if (inputSize < 0) {
      result = -1;
   } else if (inputSize != 0) {
      char *savedBufOut = *bufOut;
      char const *savedOutConst = savedBufOut;
      size_t savedOutSize = *outSize;
      if (inputSize > *outSize) {
         Log("%s: error: not enough room for escaping\n", __FUNCTION__);
         return -1;
      }

      /* Leaving space for the leading path separator, thus output to savedBufOut + 1. */
      *inSize = HgfsEscape_Do(*bufIn, *inSize, savedOutSize, savedBufOut + 1);
      result = CPNameConvertFrom(&savedOutConst, inSize, outSize, bufOut, pathSep);
      *bufIn += *inSize;
      *inSize = 0;
   } else {
      result = CPNameConvertFrom(bufIn, inSize, outSize, bufOut, pathSep);
   }
   return result;
}
static Bool
HgfsClient_PrintShares(void)
{
   Bool success = FALSE;
   int offset = 0;
   char escapedName[PATH_MAX + 1];
   HgfsHandle rootHandle;
   HgfsFileName *fileName;

   if (!HgfsClient_Open(&rootHandle)) {
      return success;
   }

   while (TRUE) {
      fileName = HgfsClient_Read(rootHandle, offset++);
      if (fileName == NULL) {
         break;
      }
  
      /* Are we done? */
      if (fileName->length == 0) {
         success = TRUE;
         break;
      }

      /* 
       * Escape this filename. If we get back a negative result, it means that
       * the escaped filename is too big, so skip this share.
       */
      if (HgfsEscape_Do(fileName->name, fileName->length,
                           sizeof escapedName, escapedName) < 0) {
         continue;
      } 

      /* Skip "." and ".." which can be returned. */
      if (strcmp(".", escapedName) == 0 ||
          strcmp("..", escapedName) == 0) {
         continue;
      }
      printf("%s\n", escapedName);

   }
   
   if (!HgfsClient_Close(rootHandle)) {
      success = FALSE;
   }
   return success;
}
Beispiel #3
0
static int
HgfsReaddirNextEntry(struct file *file,              // IN: file
                     loff_t entryPos,                // IN: position
                     Bool dotAndDotDotIgnore,        // IN: ignore "." and ".."
                     size_t entryNameBufLen,         // IN: name buffer length
                     char *entryName,                // OUT: entry name
                     uint32 *entryNameLength,        // OUT: max name length
                     ino_t *entryIno,                // OUT: inode entry number
                     uint32 *entryType,              // OUT: entry type
                     Bool *entryIgnore,              // OUT: ignore this entry or not
                     Bool *entryEnd)                 // OUT: no more entries
{
   HgfsSuperInfo *si;
   HgfsAttrInfo entryAttrs;
   char *fileName = NULL;
   int result;

   ASSERT(file->f_dentry->d_inode->i_sb);

#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
   si = HGFS_SB_TO_COMMON(file->f_dentry->d_inode->i_sb);
#else
   si = HGFS_SB_TO_COMMON(file->f_path.dentry->d_inode->i_sb);
#endif
   *entryIgnore = FALSE;

   /*
    * Nonzero result = we failed to get valid reply from server.
    * Zero result:
    *     - done == TRUE means we hit the end of the directory
    *     - Otherwise, fileName has the name of the next dirent
    *
    */

   result = HgfsGetNextDirEntry(si,
                                FILE_GET_FI_P(file)->handle,
                                (uint32)entryPos,
                                &entryAttrs,
                                &fileName,
                                entryEnd);
   if (result == -ENAMETOOLONG) {
      /*
       * Skip dentry if its name is too long (see below).
       *
       * XXX: If a bad server sends us bad packets, we can loop here
       * forever, as I did while testing *grumble*. Maybe we should error
       * in that case.
       */
      LOG(4, (KERN_DEBUG "VMware hgfs: %s: error getnextdentry name %d\n",
               __func__, result));
      *entryIgnore = TRUE;
      result = 0;
      goto exit;
   } else if (result) {
      /* Error  */
      LOG(4, (KERN_DEBUG "VMware hgfs: %s: error getnextdentry %d\n",
               __func__, result));
      goto exit;
   }

   if (*entryEnd) {
      LOG(10, (KERN_DEBUG "VMware hgfs: %s: end of dir reached\n", __func__));
      goto exit;
   }

   /*
    * Escape all non-printable characters (which for linux is just
    * "/").
    *
    * Note that normally we would first need to convert from the
    * CP name format, but that is done implicitely here since we
    * are guaranteed to have just one path component per dentry.
    */
   result = HgfsEscape_Do(fileName, strlen(fileName),
                          entryNameBufLen, entryName);
   kfree(fileName);
   fileName = NULL;

   /*
    * Check the filename length.
    *
    * If the name is too long to be represented in linux, we simply
    * skip it (i.e., that file is not visible to our filesystem).
    *
    * HgfsEscape_Do returns a negative value if the escaped
    * output didn't fit in the specified output size, so we can
    * just check its return value.
    */
   if (result < 0) {
      /*
       * XXX: Another area where a bad server could cause us to loop
       * forever.
       */
      *entryIgnore = TRUE;
      result = 0;
      goto exit;
   }

   *entryNameLength = result;
   result = 0;

   /*
    * It is unfortunate, but the HGFS server sends back '.' and ".."
    * when we do a SearchRead. In an ideal world, these would be faked
    * on the client, but it would be a real backwards-compatibility
    * hassle to change the behavior at this point.
    *
    * So instead, we'll take the '.' and ".." and modify their inode
    * numbers so they match what the client expects.
    */
   if (!strncmp(entryName, ".", sizeof ".")) {
      if (!dotAndDotDotIgnore) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
         *entryIno = file->f_dentry->d_inode->i_ino;
#else
         *entryIno = file->f_path.dentry->d_inode->i_ino;
#endif
      } else {
         *entryIgnore = TRUE;
      }
   } else if (!strncmp(entryName, "..", sizeof "..")) {
      if (!dotAndDotDotIgnore) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
         *entryIno = compat_parent_ino(file->f_dentry);
#else
         *entryIno = compat_parent_ino(file->f_path.dentry);
#endif
      } else {
         *entryIgnore = TRUE;
      }
   } else {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
     *entryIno = HgfsGetFileInode(&entryAttrs, file->f_dentry->d_inode->i_sb);
#else
     *entryIno = HgfsGetFileInode(&entryAttrs, file->f_path.dentry->d_inode->i_sb);
#endif
   }

   if (*entryIgnore) {
      goto exit;
   }

   /* Assign the correct dentry type. */
   *entryType = HgfsGetFileType(&entryAttrs);

exit:
   return result;
}