Defined the request argument of ioctl() as unsigned long

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.
This commit is contained in:
Jean-Pierre André 2020-03-07 10:31:12 +01:00
parent 3433dd0b3c
commit 32c27a8a4f
8 changed files with 35 additions and 10 deletions

View 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);

View 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

View 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,

View File

@ -24,7 +24,12 @@
#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 */

View 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);
}

View 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;
}

View 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);
}

View 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);