OSDN Git Service

Defined the request argument of ioctl() as unsigned long
authorJean-Pierre André <jean-pierre.andre@wanadoo.fr>
Sat, 7 Mar 2020 09:31:12 +0000 (10:31 +0100)
committerJean-Pierre André <jean-pierre.andre@wanadoo.fr>
Sat, 7 Mar 2020 09:31:12 +0000 (10:31 +0100)
On linux the request argument of ioctl() is defined as an unsigned long,
but the fuse protocol squashes it into a signed int. As a consequence
the value received by ntfs-3g may appear as negative and different from
the value defined by the corresponding macro.
So define the request argument as unsigned long in ntfs-3g. It has
however to be fed as unsigned from fuse until the fuse protocol is
updated.

include/fuse-lite/fuse.h
include/fuse-lite/fuse_lowlevel.h
include/ntfs-3g/device.h
include/ntfs-3g/ioctl.h
libntfs-3g/unix_io.c
libntfs-3g/win32_io.c
src/lowntfs-3g.c
src/ntfs-3g.c

index 2e3d53d..b4ec232 100644 (file)
@@ -432,6 +432,9 @@ struct fuse_operations {
         * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes.
         *
         * Introduced in version 2.8
+        *
+        * Note : the unsigned long request submitted by the application        
+        * is truncated to 32 bits, and forwarded as a signed int.
         */
        int (*ioctl) (const char *, int cmd, void *arg,
                      struct fuse_file_info *, unsigned int flags, void *data); 
index 8c84d96..3b10c35 100644 (file)
@@ -814,6 +814,9 @@ struct fuse_lowlevel_ops {
         *
         * Introduced in version 2.8
         *
+        * Note : the unsigned long request submitted by the application        
+        * is truncated to 32 bits, and forwarded as a signed int.
+        *
         * Valid replies:
         *   fuse_reply_ioctl_retry
         *   fuse_reply_ioctl
index c7cc9b6..709cb4f 100644 (file)
@@ -111,7 +111,8 @@ struct ntfs_device_operations {
                        s64 offset);
        int (*sync)(struct ntfs_device *dev);
        int (*stat)(struct ntfs_device *dev, struct stat *buf);
-       int (*ioctl)(struct ntfs_device *dev, int request, void *argp);
+       int (*ioctl)(struct ntfs_device *dev, unsigned long request,
+                       void *argp);
 };
 
 extern struct ntfs_device *ntfs_device_alloc(const char *name, const long state,
index 4ed6c01..2b25c78 100644 (file)
 #ifndef IOCTL_H
 #define IOCTL_H
 
-int ntfs_ioctl(ntfs_inode *ni, int cmd, void *arg,
+/*
+ * Using an "unsigned long cmd" internally, like in <sys/ioctl.h> for Linux
+ * Note however that fuse truncates the arg to 32 bits, and that
+ * some commands (e.g. FITRIM) do not fit in a signed 32 bit field.
+ */
+int ntfs_ioctl(ntfs_inode *ni, unsigned long cmd, void *arg,
                         unsigned int flags, void *data);
 
 #endif /* IOCTL_H */
index 1103c7e..5495a6a 100644 (file)
@@ -369,8 +369,8 @@ static int ntfs_device_unix_io_stat(struct ntfs_device *dev, struct stat *buf)
  *
  * Returns:
  */
-static int ntfs_device_unix_io_ioctl(struct ntfs_device *dev, int request,
-               void *argp)
+static int ntfs_device_unix_io_ioctl(struct ntfs_device *dev,
+               unsigned long request, void *argp)
 {
        return ioctl(DEV_FD(dev), request, argp);
 }
index e5cfb64..9c72dee 100644 (file)
@@ -1847,14 +1847,14 @@ static __inline__ int ntfs_win32_blksszget(struct ntfs_device *dev,int *argp)
        return -1;
 }
 
-static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,
-               void *argp)
+static int ntfs_device_win32_ioctl(struct ntfs_device *dev,
+               unsigned long request, void *argp)
 {
 #if defined(BLKGETSIZE) | defined(BLKGETSIZE64)
        win32_fd *fd = (win32_fd *)dev->d_private;
 #endif
 
-       ntfs_log_trace("win32_ioctl(%d) called.\n", request);
+       ntfs_log_trace("win32_ioctl(0x%lx) called.\n", request);
        switch (request) {
 #if defined(BLKGETSIZE)
        case BLKGETSIZE:
@@ -1897,7 +1897,7 @@ static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,
                return 0;
 #endif
        default:
-               ntfs_log_debug("unimplemented ioctl %d.\n", request);
+               ntfs_log_debug("unimplemented ioctl 0x%lx.\n", request);
                errno = EOPNOTSUPP;
                return -1;
        }
index 983ab01..7fa0b19 100644 (file)
@@ -3036,7 +3036,14 @@ static void ntfs_fuse_ioctl(fuse_req_t req __attribute__((unused)),
                        }
                        memcpy(buf, data, in_bufsz);
                }
-               ret = ntfs_ioctl(ni, cmd, arg, flags, buf);
+               /*
+                * Linux defines the request argument of ioctl() to be an
+                * unsigned long, which fuse 2.x forwards as a signed int
+                * into which the request sometimes does not fit.
+                * So we must expand the value and make sure it is not
+                * sign-extended.
+                */
+               ret = ntfs_ioctl(ni, (unsigned int)cmd, arg, flags, buf);
                if (ntfs_inode_close (ni))
                        set_fuse_error(&ret);
        }
index 465f152..5b3cfc8 100644 (file)
@@ -2777,7 +2777,13 @@ static int ntfs_fuse_ioctl(const char *path,
        if (!ni)
                return -errno;
 
-       ret = ntfs_ioctl(ni, cmd, arg, flags, data);
+       /*
+        * Linux defines the request argument of ioctl() to be an
+        * unsigned long, which fuse 2.x forwards as a signed int into
+        * which the request sometimes does not fit.
+        * So we must expand the value and make sure it is not sign-extended.
+        */
+       ret = ntfs_ioctl(ni, (unsigned int)cmd, arg, flags, data);
 
        if (ntfs_inode_close (ni))
                set_fuse_error(&ret);