diff --git a/fs/Kconfig b/fs/Kconfig index e8f8b295614..d646d06c549 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -47,6 +47,14 @@ config DISABLE_PSEUDOFS_OPERATIONS However, in practical embedded system, they are seldom needed and you can save a little FLASH space by disabling the capability. +config PSEUDOFS_ATTRIBUTES + bool "Pseudo-filesystem attributes" + default n + depends on !DISABLE_PSEUDOFS_OPERATIONS + ---help--- + Enable support for attributes(e.g. mode, uid, gid and time) + in the pseudo file system. + config PSEUDOFS_SOFTLINKS bool "Pseudo-filesystem soft links" default n diff --git a/fs/driver/fs_registerblockdriver.c b/fs/driver/fs_registerblockdriver.c index 33a32c392b0..2c3e9c5b66f 100644 --- a/fs/driver/fs_registerblockdriver.c +++ b/fs/driver/fs_registerblockdriver.c @@ -46,7 +46,7 @@ * Input Parameters: * path - The path to the inode to create * bops - The block driver operations structure - * mode - inmode privileges (not used) + * mode - inmode privileges * priv - Private, user data that will be associated with the inode. * * Returned Value: @@ -79,7 +79,7 @@ int register_blockdriver(FAR const char *path, return ret; } - ret = inode_reserve(path, &node); + ret = inode_reserve(path, mode, &node); if (ret >= 0) { /* We have it, now populate it with block driver specific information. @@ -89,9 +89,6 @@ int register_blockdriver(FAR const char *path, INODE_SET_BLOCK(node); node->u.i_bops = bops; -#ifdef CONFIG_FILE_MODE - node->i_mode = mode; -#endif node->i_private = priv; ret = OK; } diff --git a/fs/driver/fs_registerdriver.c b/fs/driver/fs_registerdriver.c index 900364b2074..e663300e8ba 100644 --- a/fs/driver/fs_registerdriver.c +++ b/fs/driver/fs_registerdriver.c @@ -44,7 +44,7 @@ * Input Parameters: * path - The path to the inode to create * fops - The file operations structure - * mode - inmode privileges (not used) + * mode - inmode privileges * priv - Private, user data that will be associated with the inode. * * Returned Value: @@ -75,7 +75,7 @@ int register_driver(FAR const char *path, return ret; } - ret = inode_reserve(path, &node); + ret = inode_reserve(path, mode, &node); if (ret >= 0) { /* We have it, now populate it with driver specific information. @@ -85,9 +85,6 @@ int register_driver(FAR const char *path, INODE_SET_DRIVER(node); node->u.i_ops = fops; -#ifdef CONFIG_FILE_MODE - node->i_mode = mode; -#endif node->i_private = priv; ret = OK; } diff --git a/fs/driver/fs_registermtddriver.c b/fs/driver/fs_registermtddriver.c index 02c61404ea9..98e49d9ecda 100644 --- a/fs/driver/fs_registermtddriver.c +++ b/fs/driver/fs_registermtddriver.c @@ -47,7 +47,7 @@ * Input Parameters: * path - The path to the inode to create * mtd - The MTD driver structure - * mode - inode privileges (not used) + * mode - inode privileges * priv - Private, user data that will be associated with the inode. * * Returned Value: @@ -79,7 +79,7 @@ int register_mtddriver(FAR const char *path, FAR struct mtd_dev_s *mtd, return ret; } - ret = inode_reserve(path, &node); + ret = inode_reserve(path, mode, &node); if (ret >= 0) { /* We have it, now populate it with block driver specific information. @@ -89,9 +89,6 @@ int register_mtddriver(FAR const char *path, FAR struct mtd_dev_s *mtd, INODE_SET_MTD(node); node->u.i_mtd = mtd; -#ifdef CONFIG_FILE_MODE - node->i_mode = mode; -#endif node->i_private = priv; ret = OK; } diff --git a/fs/fat/fs_fat32.c b/fs/fat/fs_fat32.c index 7b58af1eb27..30cbd34bf9e 100644 --- a/fs/fat/fs_fat32.c +++ b/fs/fat/fs_fat32.c @@ -226,10 +226,6 @@ static int fat_open(FAR struct file *filep, FAR const char *relpath, goto errout_with_semaphore; } - /* TODO: if CONFIG_FILE_MODE=y, need check for privileges based on - * inode->i_mode - */ - /* Check if the caller has sufficient privileges to open the file */ readonly = ((DIR_GETATTRIBUTES(direntry) & FATATTR_READONLY) != 0); diff --git a/fs/inode/fs_inodereserve.c b/fs/inode/fs_inodereserve.c index 17b82cce5e9..ffbf509fde5 100644 --- a/fs/inode/fs_inodereserve.c +++ b/fs/inode/fs_inodereserve.c @@ -69,7 +69,7 @@ static void inode_namecpy(char *dest, const char *src) * Name: inode_alloc ****************************************************************************/ -static FAR struct inode *inode_alloc(FAR const char *name) +static FAR struct inode *inode_alloc(FAR const char *name, mode_t mode) { FAR struct inode *node; int namelen; @@ -78,6 +78,12 @@ static FAR struct inode *inode_alloc(FAR const char *name) node = (FAR struct inode *)kmm_zalloc(FSNODE_SIZE(namelen)); if (node) { +#ifdef CONFIG_PSEUDOFS_ATTRIBUTES + node->i_mode = mode; + clock_gettime(CLOCK_REALTIME, &node->i_atime); + node->i_mtime = node->i_atime; + node->i_ctime = node->i_atime; +#endif inode_namecpy(node->i_name, name); } @@ -128,7 +134,7 @@ static void inode_insert(FAR struct inode *node, void inode_root_reserve(void) { - g_root_inode = inode_alloc(""); + g_root_inode = inode_alloc("", 0777); } /**************************************************************************** @@ -140,6 +146,7 @@ void inode_root_reserve(void) * * Input Parameters: * path - The path to the inode to create + * mode - inmode privileges * inode - The location to return the inode pointer * * Returned Value: @@ -155,7 +162,8 @@ void inode_root_reserve(void) * ****************************************************************************/ -int inode_reserve(FAR const char *path, FAR struct inode **inode) +int inode_reserve(FAR const char *path, + mode_t mode, FAR struct inode **inode) { struct inode_search_s desc; FAR struct inode *left; @@ -208,7 +216,7 @@ int inode_reserve(FAR const char *path, FAR struct inode **inode) { /* Insert an operationless node */ - node = inode_alloc(name); + node = inode_alloc(name, 0777); if (node != NULL) { inode_insert(node, left, parent); @@ -223,7 +231,7 @@ int inode_reserve(FAR const char *path, FAR struct inode **inode) } else { - node = inode_alloc(name); + node = inode_alloc(name, mode); if (node != NULL) { inode_insert(node, left, parent); diff --git a/fs/inode/inode.h b/fs/inode/inode.h index a43993096b7..fc6a0a398e6 100644 --- a/fs/inode/inode.h +++ b/fs/inode/inode.h @@ -296,6 +296,7 @@ void inode_root_reserve(void); * * Input Parameters: * path - The path to the inode to create + * mode - inmode privileges * inode - The location to return the inode pointer * * Returned Value: @@ -308,7 +309,8 @@ void inode_root_reserve(void); * ****************************************************************************/ -int inode_reserve(FAR const char *path, FAR struct inode **inode); +int inode_reserve(FAR const char *path, + mode_t mode, FAR struct inode **inode); /**************************************************************************** * Name: inode_unlink diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c index 1057d71c98f..79477011eae 100644 --- a/fs/mount/fs_mount.c +++ b/fs/mount/fs_mount.c @@ -374,7 +374,7 @@ int nx_mount(FAR const char *source, FAR const char *target, */ { - ret = inode_reserve(target, &mountpt_inode); + ret = inode_reserve(target, 0777, &mountpt_inode); if (ret < 0) { /* inode_reserve can fail for a couple of reasons, but the most @@ -450,9 +450,6 @@ int nx_mount(FAR const char *source, FAR const char *target, INODE_SET_MOUNTPT(mountpt_inode); mountpt_inode->u.i_mops = mops; -#ifdef CONFIG_FILE_MODE - mountpt_inode->i_mode = mode; -#endif mountpt_inode->i_private = fshandle; inode_semgive(); diff --git a/fs/mqueue/mq_open.c b/fs/mqueue/mq_open.c index 2eadefd179e..7895abaa2a9 100644 --- a/fs/mqueue/mq_open.c +++ b/fs/mqueue/mq_open.c @@ -274,7 +274,7 @@ static int file_mq_vopen(FAR struct file *mq, FAR const char *mq_name, goto errout_with_lock; } - ret = inode_reserve(fullpath, &inode); + ret = inode_reserve(fullpath, mode, &inode); inode_semgive(); if (ret < 0) @@ -286,7 +286,7 @@ static int file_mq_vopen(FAR struct file *mq, FAR const char *mq_name, * be created with a reference count of zero. */ - msgq = (FAR struct mqueue_inode_s *)nxmq_alloc_msgq(mode, attr); + msgq = (FAR struct mqueue_inode_s *)nxmq_alloc_msgq(attr); if (!msgq) { ret = -ENOSPC; @@ -406,7 +406,7 @@ void nxmq_pollnotify(FAR struct mqueue_inode_s *msgq, pollevent_t eventset) * Optional parameters. When the O_CREAT flag is specified, two optional * parameters are expected: * - * 1. mode_t mode (ignored), and + * 1. mode_t mode, and * 2. struct mq_attr *attr. The mq_maxmsg attribute * is used at the time that the message queue is * created to determine the maximum number of @@ -453,7 +453,7 @@ int file_mq_open(FAR struct file *mq, * Optional parameters. When the O_CREAT flag is specified, two optional * parameters are expected: * - * 1. mode_t mode (ignored), and + * 1. mode_t mode, and * 2. struct mq_attr *attr. The mq_maxmsg attribute * is used at the time that the message queue is * created to determine the maximum number of @@ -495,7 +495,7 @@ mqd_t nxmq_open(FAR const char *mq_name, int oflags, ...) * Optional parameters. When the O_CREAT flag is specified, two optional * parameters are expected: * - * 1. mode_t mode (ignored), and + * 1. mode_t mode, and * 2. struct mq_attr *attr. The mq_maxmsg attribute * is used at the time that the message queue is * created to determine the maximum number of diff --git a/fs/nxffs/nxffs_open.c b/fs/nxffs/nxffs_open.c index 70b6e5f88d3..13c5a03f4cc 100644 --- a/fs/nxffs/nxffs_open.c +++ b/fs/nxffs/nxffs_open.c @@ -1003,10 +1003,6 @@ int nxffs_open(FAR struct file *filep, FAR const char *relpath, volume = (FAR struct nxffs_volume_s *)filep->f_inode->i_private; DEBUGASSERT(volume != NULL); -#ifdef CONFIG_FILE_MODE -# warning "Missing check for privileges based on inode->i_mode" -#endif - /* Limitation: A file must be opened for reading or writing, but not both. * There is no general way of extending the size of a file. Extending the * file size of possible if the file to be extended is the last in the diff --git a/fs/romfs/fs_romfs.c b/fs/romfs/fs_romfs.c index 76b95ff4c93..8be82ee8239 100644 --- a/fs/romfs/fs_romfs.c +++ b/fs/romfs/fs_romfs.c @@ -225,10 +225,6 @@ static int romfs_open(FAR struct file *filep, FAR const char *relpath, goto errout_with_semaphore; } -#ifdef CONFIG_FILE_MODE -# warning "Missing check for privileges based on inode->i_mode" -#endif - /* Create an instance of the file private data to describe the opened * file. */ diff --git a/fs/semaphore/sem_open.c b/fs/semaphore/sem_open.c index 11606fdbadb..3e34d1ef42f 100644 --- a/fs/semaphore/sem_open.c +++ b/fs/semaphore/sem_open.c @@ -74,7 +74,7 @@ * unless one of this name already exists. * Optional parameters. When the O_CREAT flag is specified, two optional * parameters are expected: - * 1. mode_t mode (ignored), and + * 1. mode_t mode, and * 2. unsigned int value. This initial value of the semaphore. Valid * initial values of the semaphore must be less than or equal to * SEM_VALUE_MAX. @@ -178,8 +178,6 @@ FAR sem_t *sem_open (FAR const char *name, int oflags, ...) value = va_arg(ap, unsigned); va_end(ap); - UNUSED(mode); - /* Check the semaphore value */ if (value > SEM_VALUE_MAX) @@ -199,7 +197,7 @@ FAR sem_t *sem_open (FAR const char *name, int oflags, ...) goto errout_with_lock; } - ret = inode_reserve(fullpath, &inode); + ret = inode_reserve(fullpath, mode, &inode); inode_semgive(); if (ret < 0) diff --git a/fs/unionfs/fs_unionfs.c b/fs/unionfs/fs_unionfs.c index d64b194927d..9ead2b1d6ff 100644 --- a/fs/unionfs/fs_unionfs.c +++ b/fs/unionfs/fs_unionfs.c @@ -2633,7 +2633,7 @@ int unionfs_mount(FAR const char *fspath1, FAR const char *prefix1, * for now, however. */ - ret = inode_reserve(mountpt, &mpinode); + ret = inode_reserve(mountpt, 0777, &mpinode); if (ret < 0) { /* inode_reserve can fail for a couple of reasons, but the most likely @@ -2652,10 +2652,7 @@ int unionfs_mount(FAR const char *fspath1, FAR const char *prefix1, INODE_SET_MOUNTPT(mpinode); - mpinode->u.i_mops = &unionfs_operations; -#ifdef CONFIG_FILE_MODE - mpinode->i_mode = 0755; -#endif + mpinode->u.i_mops = &unionfs_operations; /* Call unionfs_dobind to do the real work. */ diff --git a/fs/vfs/fs_mkdir.c b/fs/vfs/fs_mkdir.c index 5f18327074a..0ecf95ee3b0 100644 --- a/fs/vfs/fs_mkdir.c +++ b/fs/vfs/fs_mkdir.c @@ -137,7 +137,7 @@ int mkdir(const char *pathname, mode_t mode) goto errout_with_search; } - ret = inode_reserve(pathname, &inode); + ret = inode_reserve(pathname, mode, &inode); inode_semgive(); if (ret < 0) diff --git a/fs/vfs/fs_open.c b/fs/vfs/fs_open.c index 3619f4f4099..2804c2c0d63 100644 --- a/fs/vfs/fs_open.c +++ b/fs/vfs/fs_open.c @@ -51,7 +51,7 @@ static int file_vopen(FAR struct file *filep, { struct inode_search_s desc; FAR struct inode *inode; -#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT) +#ifndef CONFIG_DISABLE_MOUNTPOINT mode_t mode = 0666; #endif int ret; @@ -61,10 +61,7 @@ static int file_vopen(FAR struct file *filep, return -EINVAL; } -#ifdef CONFIG_FILE_MODE -# ifdef CONFIG_CPP_HAVE_WARNING -# warning "File creation not implemented" -# endif +#ifndef CONFIG_DISABLE_MOUNTPOINT /* If the file is opened for creation, then get the mode bits */ diff --git a/fs/vfs/fs_rename.c b/fs/vfs/fs_rename.c index c180b2b23fd..24854a1fa1a 100644 --- a/fs/vfs/fs_rename.c +++ b/fs/vfs/fs_rename.c @@ -177,7 +177,7 @@ next_subdir: goto errout; } - ret = inode_reserve(newpath, &newinode); + ret = inode_reserve(newpath, 0777, &newinode); if (ret < 0) { /* It is an error if a node at newpath already exists in the tree @@ -194,8 +194,13 @@ next_subdir: newinode->i_child = oldinode->i_child; /* Link to lower level inode */ newinode->i_flags = oldinode->i_flags; /* Flags for inode */ newinode->u.i_ops = oldinode->u.i_ops; /* Inode operations */ -#ifdef CONFIG_FILE_MODE +#ifdef CONFIG_PSEUDOFS_ATTRIBUTES newinode->i_mode = oldinode->i_mode; /* Access mode flags */ + newinode->i_owner = oldinode->i_owner; /* Owner */ + newinode->i_group = oldinode->i_group; /* Group */ + newinode->i_atime = oldinode->i_atime; /* Time of last access */ + newinode->i_mtime = oldinode->i_mtime; /* Time of last modification */ + newinode->i_ctime = oldinode->i_ctime; /* Time of last status change */ #endif newinode->i_private = oldinode->i_private; /* Per inode driver private data */ diff --git a/fs/vfs/fs_stat.c b/fs/vfs/fs_stat.c index 0e40cbfece8..e4048f89339 100644 --- a/fs/vfs/fs_stat.c +++ b/fs/vfs/fs_stat.c @@ -348,6 +348,8 @@ int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve) { RESET_BUF(buf); } + + return ret; } else { @@ -428,5 +430,14 @@ int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve) buf->st_mode |= S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR; } +#ifdef CONFIG_PSEUDOFS_ATTRIBUTES + buf->st_mode |= inode->i_mode; + buf->st_uid = inode->i_owner; + buf->st_gid = inode->i_group; + buf->st_atim = inode->i_atime; + buf->st_mtim = inode->i_mtime; + buf->st_ctim = inode->i_ctime; +#endif + return OK; } diff --git a/fs/vfs/fs_symlink.c b/fs/vfs/fs_symlink.c index 07a3f90e1de..8fc80fb936c 100644 --- a/fs/vfs/fs_symlink.c +++ b/fs/vfs/fs_symlink.c @@ -148,7 +148,7 @@ int symlink(FAR const char *path1, FAR const char *path2) goto errout_with_search; } - ret = inode_reserve(path2, &inode); + ret = inode_reserve(path2, 0777, &inode); inode_semgive(); if (ret < 0) diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 7bdf79c8d08..5210f4462b2 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -353,8 +354,13 @@ struct inode int16_t i_crefs; /* References to inode */ uint16_t i_flags; /* Flags for inode */ union inode_ops_u u; /* Inode operations */ -#ifdef CONFIG_FILE_MODE +#ifdef CONFIG_PSEUDOFS_ATTRIBUTES mode_t i_mode; /* Access mode flags */ + uid_t i_owner; /* Owner */ + gid_t i_group; /* Group */ + struct timespec i_atime; /* Time of last access */ + struct timespec i_mtime; /* Time of last modification */ + struct timespec i_ctime; /* Time of last status change */ #endif FAR void *i_private; /* Per inode driver private data */ char i_name[1]; /* Name of inode (variable) */ @@ -492,7 +498,7 @@ void fs_initialize(void); * Input Parameters: * path - The path to the inode to create * fops - The file operations structure - * mode - Access privileges (not used) + * mode - Access privileges * priv - Private, user data that will be associated with the inode. * * Returned Value: @@ -519,7 +525,7 @@ int register_driver(FAR const char *path, * Input Parameters: * path - The path to the inode to create * bops - The block driver operations structure - * mode - Access privileges (not used) + * mode - Access privileges * priv - Private, user data that will be associated with the inode. * * Returned Value: @@ -597,7 +603,7 @@ int unregister_blockdriver(FAR const char *path); * Input Parameters: * path - The path to the inode to create * mtd - The MTD driver structure - * mode - inode privileges (not used) + * mode - inode privileges * priv - Private, user data that will be associated with the inode. * * Returned Value: diff --git a/include/nuttx/mqueue.h b/include/nuttx/mqueue.h index 90688cdca06..81d79567004 100644 --- a/include/nuttx/mqueue.h +++ b/include/nuttx/mqueue.h @@ -144,7 +144,7 @@ struct task_group_s; /* Forward reference */ * Optional parameters. When the O_CREAT flag is specified, two optional * parameters are expected: * - * 1. mode_t mode (ignored), and + * 1. mode_t mode, and * 2. struct mq_attr *attr. The mq_maxmsg attribute * is used at the time that the message queue is * created to determine the maximum number of @@ -382,7 +382,6 @@ void nxmq_free_msgq(FAR struct mqueue_inode_s *msgq); * It allocates and initializes a struct mqueue_inode_s structure. * * Input Parameters: - * mode - mode_t value is ignored * attr - The mq_maxmsg attribute is used at the time that the message * queue is created to determine the maximum number of * messages that may be placed in the message queue. @@ -393,8 +392,7 @@ void nxmq_free_msgq(FAR struct mqueue_inode_s *msgq); * ****************************************************************************/ -FAR struct mqueue_inode_s *nxmq_alloc_msgq(mode_t mode, - FAR struct mq_attr *attr); +FAR struct mqueue_inode_s *nxmq_alloc_msgq(FAR struct mq_attr *attr); /**************************************************************************** * Name: nxmq_pollnotify @@ -434,7 +432,7 @@ void nxmq_pollnotify(FAR struct mqueue_inode_s *msgq, pollevent_t eventset); * Optional parameters. When the O_CREAT flag is specified, two optional * parameters are expected: * - * 1. mode_t mode (ignored), and + * 1. mode_t mode, and * 2. struct mq_attr *attr. The mq_maxmsg attribute * is used at the time that the message queue is * created to determine the maximum number of diff --git a/sched/mqueue/mq_msgqalloc.c b/sched/mqueue/mq_msgqalloc.c index e606ce6faa5..7209f433a9f 100644 --- a/sched/mqueue/mq_msgqalloc.c +++ b/sched/mqueue/mq_msgqalloc.c @@ -46,7 +46,6 @@ * It allocates and initializes a struct mqueue_inode_s structure. * * Input Parameters: - * mode - mode_t value is ignored * attr - The mq_maxmsg attribute is used at the time that the message * queue is created to determine the maximum number of * messages that may be placed in the message queue. @@ -57,8 +56,7 @@ * ****************************************************************************/ -FAR struct mqueue_inode_s *nxmq_alloc_msgq(mode_t mode, - FAR struct mq_attr *attr) +FAR struct mqueue_inode_s *nxmq_alloc_msgq(FAR struct mq_attr *attr) { FAR struct mqueue_inode_s *msgq;