diff --git a/components/dfs/dfs_v1/src/dfs_file.c b/components/dfs/dfs_v1/src/dfs_file.c index f1c4e7ee4d2a..7034b335cc34 100644 --- a/components/dfs/dfs_v1/src/dfs_file.c +++ b/components/dfs/dfs_v1/src/dfs_file.c @@ -371,6 +371,15 @@ int dfs_file_close(struct dfs_file *fd) /** * this function will perform an io control on a file descriptor. * + * F_GETFL(=3) collides numerically with RT_DEVICE_CTRL_CONFIG, and + * F_SETFL(=4) collides with RT_DEVICE_CTRL_CLOSE. Disambiguate by the + * POSIX-vs-RT-Thread convention on `args`: + * - F_GETFL (POSIX) ignores args -> caller passes NULL/0. CONFIG needs a + * struct pointer, so args != NULL means RT_DEVICE_CTRL_CONFIG. + * - F_SETFL (POSIX) carries the new flags, so args != NULL means F_SETFL. + * CLOSE needs no args, so args == NULL means RT_DEVICE_CTRL_CLOSE. + * The fall-through path (FT_SOCKET / FT_USER / ...) is unchanged. + * * @param fd the file descriptor. * @param cmd the command to send to file descriptor. * @param args the argument to send to file descriptor. @@ -391,8 +400,25 @@ int dfs_file_ioctl(struct dfs_file *fd, int cmd, void *args) switch (cmd) { case F_GETFL: - return fd->flags; /* return flags */ + if (args != RT_NULL && fd->vnode->fops != RT_NULL && fd->vnode->fops->ioctl != RT_NULL) + { + /* args != NULL: treat cmd=3 as RT_DEVICE_CTRL_CONFIG and forward + * to the driver with the supplied config struct. */ + return fd->vnode->fops->ioctl(fd, cmd, args); + } + else + { + /* args == NULL: POSIX F_GETFL, return current fd flags. */ + return fd->flags; /* return flags */ + } case F_SETFL: + if (args == RT_NULL && fd->vnode->fops != RT_NULL && fd->vnode->fops->ioctl != RT_NULL) + { + /* args == NULL: treat cmd=4 as RT_DEVICE_CTRL_CLOSE and forward + * to the driver. */ + return fd->vnode->fops->ioctl(fd, cmd, args); + } + else { int flags = (int)(rt_base_t)args; int mask = O_NONBLOCK | O_APPEND; diff --git a/components/dfs/dfs_v2/filesystems/devfs/devfs.c b/components/dfs/dfs_v2/filesystems/devfs/devfs.c index 38e9a2e4550f..c7dcc02ca14c 100644 --- a/components/dfs/dfs_v2/filesystems/devfs/devfs.c +++ b/components/dfs/dfs_v2/filesystems/devfs/devfs.c @@ -228,6 +228,44 @@ static int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args) if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0')) return -RT_ENOSYS; + /* Disambiguate F_GETFL(=3)/F_SETFL(=4) vs RT_DEVICE_CTRL_CONFIG(=3)/ + * RT_DEVICE_CTRL_CLOSE(=4) by args nullness. POSIX ignores args on + * F_GETFL (caller passes NULL/0) and carries the new flags on + * F_SETFL (args != NULL); the RTT cmds take a non-NULL struct + * pointer on CONFIG and no args on CLOSE. */ + if (cmd == F_GETFL) + { + if (args != RT_NULL) + { + /* args != NULL: treat cmd=3 as RT_DEVICE_CTRL_CONFIG and + * fall through to the driver/device. */ + } + else + { + /* args == NULL: POSIX F_GETFL, return current fd flags. */ + return file->flags; + } + } + else if (cmd == F_SETFL) + { + if (args == RT_NULL) + { + /* args == NULL: treat cmd=4 as RT_DEVICE_CTRL_CLOSE and + * fall through to the driver/device. */ + } + else + { + /* args != NULL: POSIX F_SETFL, update fd flags in place. */ + int flags = (int)(rt_base_t)args; + int mask = O_NONBLOCK | O_APPEND; + + flags &= mask; + file->flags &= ~mask; + file->flags |= flags; + return RT_EOK; + } + } + #ifdef RT_USING_POSIX_DEVIO if (device->fops && device->fops->ioctl) { diff --git a/components/dfs/dfs_v2/src/dfs_file.c b/components/dfs/dfs_v2/src/dfs_file.c index 970b74c6caee..f32fff71c70c 100644 --- a/components/dfs/dfs_v2/src/dfs_file.c +++ b/components/dfs/dfs_v2/src/dfs_file.c @@ -1722,7 +1722,16 @@ int dfs_file_fcntl(int fd, int cmd, unsigned long arg) file->mode = arg; break; case F_GETFL: - ret = file->flags; + if (arg != RT_NULL && file->fops != RT_NULL && file->fops->ioctl != RT_NULL) + { + /* cmd=3 with args != NULL: treat as RT_DEVICE_CTRL_CONFIG and forward to the driver with the config struct. */ + ret = file->fops->ioctl(file, cmd, (void *)(rt_base_t)arg); + } + else + { + /* args == NULL: POSIX F_GETFL, return current fd flags. */ + ret = file->flags; + } break; case F_SETFL: { @@ -1739,6 +1748,12 @@ int dfs_file_fcntl(int fd, int cmd, unsigned long arg) #endif O_APPEND | O_NONBLOCK; + if (arg == RT_NULL && file->fops != RT_NULL && file->fops->ioctl != RT_NULL) + { + /* cmd=4 with args == NULL: treat as RT_DEVICE_CTRL_CLOSE and forward to the driver. */ + ret = file->fops->ioctl(file, cmd, (void *)(rt_base_t)arg); + break; + } flags &= mask; if (file->vnode->type == FT_SOCKET && file->fops != RT_NULL && file->fops->ioctl != RT_NULL)