]> Zhao Yanbai Git Server - minix.git/commitdiff
HGFS: move all VMware-specific code into libhgfs
authorDavid van Moolenbroek <david@minix3.org>
Mon, 9 Apr 2012 15:17:42 +0000 (17:17 +0200)
committerDavid van Moolenbroek <david@minix3.org>
Mon, 9 Apr 2012 15:32:36 +0000 (17:32 +0200)
17 files changed:
include/minix/hgfs.h
lib/libhgfs/Makefile
lib/libhgfs/attr.c
lib/libhgfs/const.h
lib/libhgfs/dir.c
lib/libhgfs/file.c
lib/libhgfs/info.c [new file with mode: 0644]
lib/libhgfs/misc.c
lib/libhgfs/rpc.c
servers/hgfs/const.h
servers/hgfs/inode.h
servers/hgfs/main.c
servers/hgfs/misc.c
servers/hgfs/mount.c
servers/hgfs/read.c
servers/hgfs/stat.c
servers/hgfs/write.c

index 22dc09db4401246b50e00dffbff0526c2189677e..06d630edb4cba9dad04ac1b14eb4a0dcc74b5d54 100644 (file)
@@ -26,22 +26,13 @@ struct hgfs_attr {
 #define HGFS_ATTR_MTIME                0x08    /* get/set file modification time */
 #define HGFS_ATTR_CTIME                0x10    /* get/set file change time */
 #define HGFS_ATTR_MODE         0x20    /* get/set file mode */
-#define HGFS_ATTR_ATIME_SET    0x40    /* set specific file access time */
-#define HGFS_ATTR_MTIME_SET    0x80    /* set specific file modify time */
-#define HGFS_ATTR_ALL          \
-       (HGFS_ATTR_SIZE | HGFS_ATTR_CRTIME | HGFS_ATTR_ATIME | \
-       HGFS_ATTR_MTIME | HGFS_ATTR_CTIME | HGFS_ATTR_MODE | \
-       HGFS_ATTR_ATIME_SET | HGFS_ATTR_MTIME_SET)
 
 int hgfs_init(void);
 void hgfs_cleanup(void);
 
-int hgfs_enabled(void);
-
 int hgfs_open(char *path, int flags, int mode, hgfs_file_t *handle);
 int hgfs_read(hgfs_file_t handle, char *buf, size_t size, u64_t offset);
-int hgfs_write(hgfs_file_t handle, const char *buf, size_t len, u64_t
-       offset, int append);
+int hgfs_write(hgfs_file_t handle, char *buf, size_t len, u64_t offset);
 int hgfs_close(hgfs_file_t handle);
 
 size_t hgfs_readbuf(char **ptr);
index da2ded5d35ee0b13ffd63f9b390b560b984f5611..d6d7a5292f4f4f71152873ef9f098ec1367351f7 100644 (file)
@@ -2,6 +2,6 @@
 
 LIB=    hgfs
 SRCS=  backdoor.S attr.c channel.c dir.c error.c file.c \
-       link.c misc.c path.c rpc.c time.c
+       info.c link.c misc.c path.c rpc.c time.c
 
 .include <bsd.lib.mk>
index 85004d443127b7dfc3af3048a2dac85cfd3a1f27..0043192b7e9ccbecf9c632dad0cc5cbd51e6d25e 100644 (file)
@@ -64,18 +64,34 @@ struct hgfs_attr *attr;
 {
 /* Set selected attributes of a file by path name.
  */
+  u8_t mask;
 
   RPC_REQUEST(HGFS_REQ_SETATTR);
 
-  RPC_NEXT8 = (attr->a_mask & HGFS_ATTR_ALL);
+  /* This library implements the HGFS v1 protocol, which is largely
+   * path-oriented. This is the only method to set the file size, and thus,
+   * truncating a deleted file is not possible. This has been fixed in later
+   * HGFS protocol version (v2/v3).
+   */
+  mask = 0;
+  if (attr->a_mask & HGFS_ATTR_MODE) mask |= HGFS_ATTR_MODE;
+  if (attr->a_mask & HGFS_ATTR_SIZE) mask |= HGFS_ATTR_SIZE;
+  if (attr->a_mask & HGFS_ATTR_CRTIME) mask |= HGFS_ATTR_CRTIME;
+  if (attr->a_mask & HGFS_ATTR_ATIME)
+       mask |= HGFS_ATTR_ATIME | HGFS_ATTR_ATIME_SET;
+  if (attr->a_mask & HGFS_ATTR_MTIME)
+       mask |= HGFS_ATTR_MTIME | HGFS_ATTR_MTIME_SET;
+  if (attr->a_mask & HGFS_ATTR_CTIME) mask |= HGFS_ATTR_CTIME;
+
+  RPC_NEXT8 = mask;
 
   RPC_NEXT32 = !!(S_ISDIR(attr->a_mode));
   RPC_NEXT32 = ex64lo(attr->a_size);
   RPC_NEXT32 = ex64hi(attr->a_size);
 
   time_put((attr->a_mask & HGFS_ATTR_CRTIME) ? &attr->a_crtime : NULL);
-  time_put((attr->a_mask & HGFS_ATTR_ATIME_SET) ? &attr->a_atime : NULL);
-  time_put((attr->a_mask & HGFS_ATTR_MTIME_SET) ? &attr->a_mtime : NULL);
+  time_put((attr->a_mask & HGFS_ATTR_ATIME) ? &attr->a_atime : NULL);
+  time_put((attr->a_mask & HGFS_ATTR_MTIME) ? &attr->a_mtime : NULL);
   time_put((attr->a_mask & HGFS_ATTR_CTIME) ? &attr->a_ctime : NULL);
 
   RPC_NEXT8 = HGFS_MODE_TO_PERM(attr->a_mode);
index 7e4772481443f658a28b2e1a79642db715b26299..b679fde3de860b60f8cec0f696e5c4b4087c2135 100644 (file)
@@ -60,3 +60,13 @@ enum {
 /* HGFS mode/perms conversion macros */
 #define HGFS_MODE_TO_PERM(m) (((m) & S_IRWXU) >> 6)
 #define HGFS_PERM_TO_MODE(p) (((p) << 6) & S_IRWXU)
+
+/* HGFS attribute flags */
+#define HGFS_ATTR_SIZE         0x01    /* get/set file size */
+#define HGFS_ATTR_CRTIME       0x02    /* get/set file creation time */
+#define HGFS_ATTR_ATIME                0x04    /* get/set file access time */
+#define HGFS_ATTR_MTIME                0x08    /* get/set file modification time */
+#define HGFS_ATTR_CTIME                0x10    /* get/set file change time */
+#define HGFS_ATTR_MODE         0x20    /* get/set file mode */
+#define HGFS_ATTR_ATIME_SET    0x40    /* set specific file access time */
+#define HGFS_ATTR_MTIME_SET    0x80    /* set specific file modify time */
index f2a220f2a8b9d42b090743de2f2da0af7ad430c8..c73bf52c2408187c599ba5924cfe70e4c5ce2c32 100644 (file)
@@ -39,7 +39,7 @@ struct hgfs_attr *attr;
  * number. Upon success, the resulting path name is stored in the given buffer
  * and the given attribute structure is filled selectively as requested. Upon
  * error, the contents of the path buffer and attribute structure are
- * undefined.
+ * undefined. ENOENT is returned upon end of directory.
  */
   int r;
 
@@ -47,12 +47,20 @@ struct hgfs_attr *attr;
   RPC_NEXT32 = (u32_t)handle;
   RPC_NEXT32 = index;
 
+  /* EINVAL signifies end of directory. */
   if ((r = rpc_query()) != OK)
-       return r;
+       return (r == EINVAL) ? ENOENT : OK;
 
   attr_get(attr);
 
-  return path_get(buf, size);
+  if ((r = path_get(buf, size)) != OK)
+       return r;
+
+  /* VMware Player 3 returns an empty name, instead of EINVAL, when reading
+   * from an EOF position right after opening the directory handle. Seems to be
+   * a newly introduced bug..
+   */
+  return (!buf[0]) ? ENOENT : OK;
 }
 
 /*===========================================================================*
index fb3447b22f2465b0700e73a34d9b406ba5f266f6..6fdeeb1b45f78ae516a59aa482909f79848a78eb 100644 (file)
@@ -74,8 +74,8 @@ u64_t off;                    /* file offset */
   len = RPC_NEXT32;
   if (len > max) len = max; /* sanity check */
 
-  /* Only copy out data if we're requested to do so. */
-  if (buf != NULL)
+  /* Only copy out data if we're not operating directly on the RPC buffer. */
+  if (buf != RPC_PTR)
        memcpy(buf, RPC_PTR, len);
 
   return len;
@@ -84,12 +84,11 @@ u64_t off;                  /* file offset */
 /*===========================================================================*
  *                             hgfs_write                                   *
  *===========================================================================*/
-int hgfs_write(handle, buf, len, off, append)
+int hgfs_write(handle, buf, len, off)
 hgfs_file_t handle;            /* handle to open file */
-const char *buf;               /* data buffer or NULL */
+char *buf;                     /* data buffer or NULL */
 size_t len;                    /* number of bytes to write */
 u64_t off;                     /* file offset */
-int append;                    /* if set, append to file (ignore offset) */
 {
 /* Write to an open file. Upon success, return the number of bytes written.
  */
@@ -97,22 +96,13 @@ int append;                 /* if set, append to file (ignore offset) */
 
   RPC_REQUEST(HGFS_REQ_WRITE);
   RPC_NEXT32 = (u32_t)handle;
-
-  if (append) {
-       RPC_NEXT8 = 1;
-       RPC_NEXT32 = 0;
-       RPC_NEXT32 = 0;
-  }
-  else {
-       RPC_NEXT8 = 0;
-       RPC_NEXT32 = ex64lo(off);
-       RPC_NEXT32 = ex64hi(off);
-  }
-
+  RPC_NEXT8 = 0;               /* append flag */
+  RPC_NEXT32 = ex64lo(off);
+  RPC_NEXT32 = ex64hi(off);
   RPC_NEXT32 = len;
 
-  /* Only copy in data if we're requested to do so. */
-  if (buf != NULL)
+  /* Only copy in data if we're not operating directly on the RPC buffer. */
+  if (RPC_PTR != buf)
        memcpy(RPC_PTR, buf, len);
   RPC_ADVANCE(len);
 
diff --git a/lib/libhgfs/info.c b/lib/libhgfs/info.c
new file mode 100644 (file)
index 0000000..f6d9258
--- /dev/null
@@ -0,0 +1,38 @@
+/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
+
+#include "inc.h"
+
+/*===========================================================================*
+ *                             hgfs_queryvol                                *
+ *===========================================================================*/
+int hgfs_queryvol(path, free, total)
+char *path;
+u64_t *free;
+u64_t *total;
+{
+/* Retrieve information about available and total volume space associated with
+ * a given path.
+ */
+  u32_t lo, hi;
+  int r;
+
+  RPC_REQUEST(HGFS_REQ_QUERYVOL);
+
+  path_put(path);
+
+  /* It appears that this call always fails with EACCES ("permission denied")
+   * on read-only folders. As far as I can tell, this is a VMware bug.
+   */
+  if ((r = rpc_query()) != OK)
+       return r;
+
+  lo = RPC_NEXT32;
+  hi = RPC_NEXT32;
+  *free = make64(lo, hi);
+
+  lo = RPC_NEXT32;
+  hi = RPC_NEXT32;
+  *total = make64(lo, hi);
+
+  return OK;
+}
index 9ddb4231cdd8296dfbbe26a7b82f69764a53d142..d81c5c71ec014a9ef98646fc4e030763d2960df1 100644 (file)
@@ -8,8 +8,7 @@
 int hgfs_init()
 {
 /* Initialize the library. Return OK on success, or a negative error code
- * otherwise. If EAGAIN is returned, shared folders are disabled; in that
- * case, other operations may be tried (and possibly succeed).
+ * otherwise. If EAGAIN is returned, shared folders are disabled.
  */
 
   time_init();
@@ -27,47 +26,3 @@ void hgfs_cleanup()
 
   rpc_close();
 }
-
-/*===========================================================================*
- *                             hgfs_enabled                                 *
- *===========================================================================*/
-int hgfs_enabled()
-{
-/* Check if shared folders are enabled. Return OK if so, EAGAIN if not, and
- * another negative error code on error.
- */
-
-  return rpc_test();
-}
-
-/*===========================================================================*
- *                             hgfs_queryvol                                *
- *===========================================================================*/
-int hgfs_queryvol(path, free, total)
-char *path;
-u64_t *free;
-u64_t *total;
-{
-/* Retrieve information about available and total volume space associated with
- * a given path.
- */
-  u32_t lo, hi;
-  int r;
-
-  RPC_REQUEST(HGFS_REQ_QUERYVOL);
-
-  path_put(path);
-
-  if ((r = rpc_query()) != OK)
-       return r;
-
-  lo = RPC_NEXT32;
-  hi = RPC_NEXT32;
-  *free = make64(lo, hi);
-
-  lo = RPC_NEXT32;
-  hi = RPC_NEXT32;
-  *total = make64(lo, hi);
-
-  return OK;
-}
index 08a6655d9e3536a2691866431ecff18d10a8b27f..479e8caf86bf1c3bc6fd56c5e55597ad0eb5405f 100644 (file)
@@ -13,7 +13,8 @@ static struct channel rpc_chan;
 int rpc_open()
 {
 /* Open a HGFS RPC backdoor channel to the VMware host, and make sure that it
- * is working. Return OK upon success, or a negative error code otherwise.
+ * is working. Return OK upon success, or a negative error code otherwise; in
+ * particular, return EAGAIN if shared folders are disabled.
  */
   int r;
 
@@ -22,7 +23,7 @@ int rpc_open()
 
   r = rpc_test();
 
-  if (r != OK && r != EAGAIN)
+  if (r != OK)
        channel_close(&rpc_chan);
 
   return r;
index c757d3c8c9a79a3359249267a0d0745d7f04ba7a..9b1bf337ffc24a60b0ced3b731fdd9dbc440d431 100644 (file)
@@ -7,6 +7,6 @@
 #define NUM_HASH_SLOTS 1023
 
 /* Arbitrary block size constant returned by fstatfs and statvfs.
- * Also used by getdents. This is not the actual HGFS data transfer unit size.
+ * Also used by getdents. This is not the underlying data transfer unit size.
  */
 #define BLOCK_SIZE     4096
index 12f6b4b062c51aa43ee76b0435fe334167d97fcc..42c820943ad409d946afdbf01a70a8667c3dc01c 100644 (file)
  * modifications on the host system are not part of the protocol, so sometimes
  * the server may discover that some files do not exist anymore. In that case,
  * they are marked as DELETED in the inode table. Such files may still be used
- * because of open file handles, but cannot be referenced by path anymore.
- * Unfortunately the HGFS v1 protocol is largely path-oriented, so even
- * truncating a deleted file is not possible. This has been fixed in v2/v3, but
- * we currently use the v1 protocol for VMware backwards compatibility reasons.
+ * because of open file handles, but cannot be referenced by path anymore. The
+ * underlying protocol may not support truncation of open files anyway. Since
+ * we currently cannot guarantee that a file is actually opened before it is
+ * deleted (as this would consistute opening every file being looked up), we
+ * effectively do not properly support open deleted files at all anyway.
  *
  * An inode is REFERENCED iff it has a reference count > 0 *or* has children.
  * An inode is LINKED IN iff it has a parent.
@@ -62,8 +63,8 @@ struct inode {
   unsigned short i_flags;              /* any combination of I_* flags */
   union {
        TAILQ_ENTRY(inode) u_free;      /* free list chain entry */
-       hgfs_file_t u_file;             /* handle to open HGFS file */
-       hgfs_dir_t u_dir;               /* handle to open HGFS directory */
+       hgfs_file_t u_file;             /* handle to open file */
+       hgfs_dir_t u_dir;               /* handle to open directory */
   } i_u;
   char i_name[NAME_MAX+1];             /* entry name in parent directory */
 };
index a0c94360f1227af11547073b32e71cdafc1a3dd8..7c2b7b93ab4e178c95bda8b2e1bccd460df79638 100644 (file)
@@ -60,8 +60,11 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
 
   /* Initialize the HGFS library. If this fails, exit immediately. */
   r = hgfs_init();
-  if (r != OK && r != EAGAIN) {
-       printf("HGFS: unable to initialize HGFS library (%d)\n", r);
+  if (r != OK) {
+       if (r == EAGAIN)
+               printf("HGFS: shared folders are disabled\n");
+       else
+               printf("HGFS: unable to initialize HGFS library (%d)\n", r);
 
        return r;
   }
index 7135941dc86556e3d0d77c8a186f0ebb5f790d72..ad9aca32dd5133645bed1b2f3059a2d26d900070 100644 (file)
@@ -43,7 +43,8 @@ int do_statvfs()
 
   /* Unfortunately, we cannot be any more specific than this, because we are
    * not given an inode number. Statistics of individual shared folders can
-   * only be obtained by using the "prefix=" option when mounting.
+   * only be obtained by making sure that the root of the file system is an
+   * actual share, and not a list of available shares.
    */
   if ((ino = find_inode(ROOT_INODE_NR)) == NULL)
        return EINVAL;
@@ -51,9 +52,6 @@ int do_statvfs()
   if ((r = verify_inode(ino, path, NULL)) != OK)
        return r;
 
-  /* It appears that this call always fails with EACCES ("permission denied")
-   * on read-only folders. As far as I can tell, this is a VMware bug.
-   */
   if ((r = hgfs_queryvol(path, &free, &total)) != OK)
        return r;
 
index ab154fe38ab27551bb8ffd011bfc78692676eae9..729ea01f6994ec7470191413a1b728fb4788a904 100644 (file)
@@ -44,9 +44,7 @@ int do_readsuper()
    * VFS. Print a (hopefully) helpful error message, and abort the mount.
    */
   if ((r = verify_inode(ino, path, &attr)) != OK) {
-       if (r == EAGAIN)
-               printf("HGFS: shared folders disabled\n");
-       else if (opt.prefix[0] && (r == ENOENT || r == EACCES))
+       if (opt.prefix[0] && (r == ENOENT || r == EACCES))
                printf("HGFS: unable to access the given prefix directory\n");
        else
                printf("HGFS: unable to access shared folders\n");
index 63c2313a2632472a2ccad3fced6050597cdb68d1..4f0eae527a0af68efafae8159b7544e487049d14 100644 (file)
@@ -48,7 +48,7 @@ int do_read()
   while (count > 0) {
        chunk = MIN(count, size);
 
-       if ((r = hgfs_read(ino->i_file, NULL, chunk, pos)) <= 0)
+       if ((r = hgfs_read(ino->i_file, ptr, chunk, pos)) <= 0)
                break;
 
        chunk = r;
@@ -117,7 +117,7 @@ int do_getdents()
    */
   for (pos = m_in.REQ_SEEK_POS_LO; ; pos++) {
        /* Determine which inode and name to use for this entry.
-        * We have no idea whether the HGFS host will give us "." and/or "..",
+        * We have no idea whether the host will give us "." and/or "..",
         * so generate our own and skip those from the host.
         */
        if (pos == 0) {
@@ -144,14 +144,9 @@ int do_getdents()
                r = hgfs_readdir(ino->i_dir, pos - 2, name, sizeof(name),
                        &attr);
 
-               if (r != OK || !name[0]) {
+               if (r != OK) {
                        /* No more entries? Then close the handle and stop. */
-                       /* VMware Player 3 returns an empty name, instead of
-                        * EINVAL, when reading from an EOF position right
-                        * after opening the directory handle. Seems to be a
-                        * newly introduced bug..
-                        */
-                       if (r == EINVAL || !name[0]) {
+                       if (r == ENOENT) {
                                put_handle(ino);
 
                                break;
index cdb6d5661b485bf8dce8e9901c0b5a6db6155c79..eb0a5dec33fd6f5f032c7ab7ba15329e32628ff1 100644 (file)
@@ -19,7 +19,7 @@ mode_t get_mode(ino, mode)
 struct inode *ino;
 int mode;
 {
-/* Return the mode for an inode, given the inode and the HGFS retrieved mode.
+/* Return the mode for an inode, given the inode and the retrieved mode.
  */
 
   mode &= S_IRWXU;
@@ -31,7 +31,7 @@ int mode;
        mode = S_IFREG | (mode & opt.file_mask);
 
   if (state.read_only)
-       mode &= ~0222;
+       mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
 
   return mode;
 }
@@ -158,8 +158,7 @@ int do_utime()
   if ((r = verify_inode(ino, path, NULL)) != OK)
        return r;
 
-  attr.a_mask = HGFS_ATTR_ATIME | HGFS_ATTR_MTIME | HGFS_ATTR_ATIME_SET |
-       HGFS_ATTR_MTIME_SET;
+  attr.a_mask = HGFS_ATTR_ATIME | HGFS_ATTR_MTIME;
   attr.a_atime.tv_sec = m_in.REQ_ACTIME;
   attr.a_atime.tv_nsec = 0;
   attr.a_mtime.tv_sec = m_in.REQ_MODTIME;
index 5fd5780d1a0cb16de298a8a5956d5c5f9a7ebdac..ab21bba2afee1fdcf348cd447c29602650f4693c 100644 (file)
@@ -59,7 +59,7 @@ cp_grant_id_t *grantp;
                memset(ptr, 0, chunk);
        }
 
-       if ((r = hgfs_write(ino->i_file, NULL, chunk, pos, FALSE)) <= 0)
+       if ((r = hgfs_write(ino->i_file, ptr, chunk, pos)) <= 0)
                break;
 
        count -= r;