fs/pesudofile: support pseudo-file operation
Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
parent
917728bad9
commit
0f6d0eac52
@ -418,6 +418,28 @@ int foreach_inode(foreach_inode_t handler, FAR void *arg);
|
|||||||
|
|
||||||
int dir_allocate(FAR struct file *filep, FAR const char *relpath);
|
int dir_allocate(FAR struct file *filep, FAR const char *relpath);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pseudofile_create
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Create the pseudo-file with specified path and mode, and alloc inode
|
||||||
|
* of this pseudo-file.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int pseudofile_create(FAR struct inode **node, FAR const char *path,
|
||||||
|
mode_t mode);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: inode_is_pseudofile
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check inode whether is a pseudo file.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
bool inode_is_pseudofile(FAR struct inode *inode);
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ CSRCS += fs_fchstat.c fs_fstat.c fs_fstatfs.c fs_ioctl.c fs_lseek.c
|
|||||||
CSRCS += fs_mkdir.c fs_open.c fs_poll.c fs_pread.c fs_pwrite.c fs_read.c
|
CSRCS += fs_mkdir.c fs_open.c fs_poll.c fs_pread.c fs_pwrite.c fs_read.c
|
||||||
CSRCS += fs_rename.c fs_rmdir.c fs_select.c fs_sendfile.c fs_stat.c
|
CSRCS += fs_rename.c fs_rmdir.c fs_select.c fs_sendfile.c fs_stat.c
|
||||||
CSRCS += fs_statfs.c fs_unlink.c fs_write.c fs_dir.c fs_fsync.c
|
CSRCS += fs_statfs.c fs_unlink.c fs_write.c fs_dir.c fs_fsync.c
|
||||||
CSRCS += fs_truncate.c
|
CSRCS += fs_truncate.c fs_pseudofile.c
|
||||||
|
|
||||||
# Certain interfaces are not available if there is no mountpoint support
|
# Certain interfaces are not available if there is no mountpoint support
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ static int file_vopen(FAR struct file *filep, FAR const char *path,
|
|||||||
{
|
{
|
||||||
struct inode_search_s desc;
|
struct inode_search_s desc;
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
#ifndef CONFIG_DISABLE_MOUNTPOINT
|
#if !defined(CONFIG_DISABLE_MOUNTPOINT) || defined(CONFIG_PSEUDOFS_FILE)
|
||||||
mode_t mode = 0666;
|
mode_t mode = 0666;
|
||||||
#endif
|
#endif
|
||||||
int ret;
|
int ret;
|
||||||
@ -104,12 +104,22 @@ static int file_vopen(FAR struct file *filep, FAR const char *path,
|
|||||||
ret = inode_find(&desc);
|
ret = inode_find(&desc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
/* "O_CREAT is not set and the named file does not exist. Or, a
|
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||||
* directory component in pathname does not exist or is a dangling
|
if ((oflags & O_CREAT) != 0)
|
||||||
* symbolic link."
|
{
|
||||||
*/
|
ret = pseudofile_create(&desc.node, path, mode);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
goto errout_with_search;
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
/* "O_CREAT is not set and the named file does not exist. Or, a
|
||||||
|
* directory component in pathname does not exist or is a dangling
|
||||||
|
* symbolic link."
|
||||||
|
*/
|
||||||
|
|
||||||
|
goto errout_with_search;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the search results */
|
/* Get the search results */
|
||||||
|
454
fs/vfs/fs_pseudofile.c
Normal file
454
fs/vfs/fs_pseudofile.c
Normal file
@ -0,0 +1,454 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* fs/vfs/fs_pseudofile.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
#include <nuttx/fs/fs.h>
|
||||||
|
#include <nuttx/fs/ioctl.h>
|
||||||
|
#include <nuttx/lib/math32.h>
|
||||||
|
|
||||||
|
#include "inode/inode.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct fs_pseudofile_s
|
||||||
|
{
|
||||||
|
mutex_t lock;
|
||||||
|
uint8_t crefs;
|
||||||
|
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||||
|
bool unlinked;
|
||||||
|
#endif
|
||||||
|
FAR char *content;
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pseudofile_open(FAR struct file *filep);
|
||||||
|
static int pseudofile_close(FAR struct file *filep);
|
||||||
|
static ssize_t pseudofile_write(FAR struct file *filep,
|
||||||
|
FAR const char *buffer, size_t buflen);
|
||||||
|
static ssize_t pseudofile_read(FAR struct file *filep, FAR char *buffer,
|
||||||
|
size_t buflen);
|
||||||
|
static off_t pseudofile_seek(FAR struct file *filep, off_t offset,
|
||||||
|
int whence);
|
||||||
|
static int pseudofile_mmap(FAR struct file *filep,
|
||||||
|
FAR struct mm_map_entry_s *map);
|
||||||
|
static int pseudofile_truncate(FAR struct file *filep, off_t length);
|
||||||
|
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||||
|
static int pseudofile_unlink(FAR struct inode *inode);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static const struct file_operations g_pseudofile_ops =
|
||||||
|
{
|
||||||
|
pseudofile_open, /* open */
|
||||||
|
pseudofile_close, /* close */
|
||||||
|
pseudofile_read, /* read */
|
||||||
|
pseudofile_write, /* write */
|
||||||
|
pseudofile_seek, /* seek */
|
||||||
|
NULL, /* ioctl */
|
||||||
|
pseudofile_mmap, /* mmap */
|
||||||
|
pseudofile_truncate, /* truncate */
|
||||||
|
NULL, /* poll */
|
||||||
|
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||||
|
pseudofile_unlink, /* unlink */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pseudofile_open(FAR struct file *filep)
|
||||||
|
{
|
||||||
|
FAR struct inode *node = filep->f_inode;
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nxmutex_lock(&pf->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pf->crefs >= 255)
|
||||||
|
{
|
||||||
|
ret = -EMFILE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pf->crefs += 1;
|
||||||
|
ret = OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
|
||||||
|
node->i_atime.tv_sec = time(NULL);
|
||||||
|
#endif
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pseudofile_remove(FAR struct fs_pseudofile_s *pf)
|
||||||
|
{
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
nxmutex_destroy(&pf->lock);
|
||||||
|
kmm_free(pf->content);
|
||||||
|
kmm_free(pf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pseudofile_close(FAR struct file *filep)
|
||||||
|
{
|
||||||
|
FAR struct inode *node = filep->f_inode;
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nxmutex_lock(&pf->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pf->crefs--;
|
||||||
|
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||||
|
if (pf->crefs <= 0 && pf->unlinked)
|
||||||
|
#else
|
||||||
|
if (pf->crefs <= 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
pseudofile_remove(pf);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pseudofile_expand(FAR struct inode *node,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
FAR void *tmp;
|
||||||
|
|
||||||
|
if (pf->content && kmm_malloc_size(pf->content) >= size)
|
||||||
|
{
|
||||||
|
node->i_size = size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = kmm_realloc(pf->content, 1 << LOG2_CEIL(size));
|
||||||
|
if (tmp == NULL)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
pf->content = tmp;
|
||||||
|
node->i_size = size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t pseudofile_write(FAR struct file *filep,
|
||||||
|
FAR const char *buffer, size_t buflen)
|
||||||
|
{
|
||||||
|
FAR struct inode *node = filep->f_inode;
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nxmutex_lock(&pf->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filep->f_oflags & O_APPEND)
|
||||||
|
{
|
||||||
|
ret = pseudofile_expand(node, node->i_size + buflen);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
filep->f_pos = node->i_size - buflen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = pseudofile_expand(node, filep->f_pos + buflen);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pf->content + filep->f_pos, buffer, buflen);
|
||||||
|
filep->f_pos += buflen;
|
||||||
|
#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
|
||||||
|
node->i_mtime.tv_sec = time(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t pseudofile_read(FAR struct file *filep, FAR char *buffer,
|
||||||
|
size_t buflen)
|
||||||
|
{
|
||||||
|
FAR struct inode *node = filep->f_inode;
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (buffer == NULL || node->i_size < filep->f_pos)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxmutex_lock(&pf->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
buflen = MIN(node->i_size - filep->f_pos, buflen);
|
||||||
|
memcpy(buffer, pf->content + filep->f_pos, buflen);
|
||||||
|
filep->f_pos += buflen;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
|
||||||
|
node->i_atime.tv_sec = time(NULL);
|
||||||
|
#endif
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
|
||||||
|
return buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static off_t pseudofile_seek(FAR struct file *filep, off_t offset,
|
||||||
|
int whence)
|
||||||
|
{
|
||||||
|
FAR struct inode *node = filep->f_inode;
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nxmutex_lock(&pf->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map the offset according to the whence option */
|
||||||
|
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_CUR:
|
||||||
|
offset += filep->f_pos;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_END:
|
||||||
|
offset += node->i_size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
{
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
filep->f_pos = offset;
|
||||||
|
#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
|
||||||
|
node->i_atime.tv_sec = time(NULL);
|
||||||
|
#endif
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pseudofile_mmap(FAR struct file *filep,
|
||||||
|
FAR struct mm_map_entry_s *map)
|
||||||
|
{
|
||||||
|
FAR struct inode *node = filep->f_inode;
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
|
||||||
|
if (map->offset >= 0 && map->offset < node->i_size &&
|
||||||
|
map->length != 0 && map->offset + map->length <= node->i_size)
|
||||||
|
{
|
||||||
|
map->vaddr = pf->content + map->offset;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pseudofile_truncate(FAR struct file *filep, off_t length)
|
||||||
|
{
|
||||||
|
FAR struct inode *node = filep->f_inode;
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nxmutex_lock(&pf->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < node->i_size)
|
||||||
|
{
|
||||||
|
FAR void *tmp;
|
||||||
|
|
||||||
|
tmp = kmm_realloc(pf->content, length);
|
||||||
|
if (tmp == NULL)
|
||||||
|
{
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pf->content = tmp;
|
||||||
|
node->i_size = length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = pseudofile_expand(node, length);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pf->content + node->i_size, 0, length - node->i_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
|
||||||
|
node->i_mtime.tv_sec = time(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||||
|
static int pseudofile_unlink(FAR struct inode *node)
|
||||||
|
{
|
||||||
|
FAR struct fs_pseudofile_s *pf = node->i_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nxmutex_lock(&pf->lock);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pf->crefs <= 0)
|
||||||
|
{
|
||||||
|
pseudofile_remove(pf);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
pf->unlinked = true;
|
||||||
|
nxmutex_unlock(&pf->lock);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pseudofile_create
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Create the pseudo-file with specified path and mode, and alloc inode
|
||||||
|
* of this pseudo-file.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int pseudofile_create(FAR struct inode **node, FAR const char *path,
|
||||||
|
mode_t mode)
|
||||||
|
{
|
||||||
|
FAR struct fs_pseudofile_s *pf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (node == NULL || path == NULL)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pf = kmm_zalloc(sizeof(struct fs_pseudofile_s));
|
||||||
|
if (pf == NULL)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxmutex_init(&pf->lock);
|
||||||
|
|
||||||
|
ret = inode_lock();
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nxmutex_destroy(&pf->lock);
|
||||||
|
kmm_free(pf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
inode_reserve(path, mode, node);
|
||||||
|
(*node)->i_crefs = 0;
|
||||||
|
(*node)->i_flags = 1;
|
||||||
|
(*node)->u.i_ops = &g_pseudofile_ops;
|
||||||
|
(*node)->i_private = pf;
|
||||||
|
|
||||||
|
inode_unlock();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: inode_is_pseudofile
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check inode whether is a pseudo file.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
bool inode_is_pseudofile(FAR struct inode *inode)
|
||||||
|
{
|
||||||
|
return inode != NULL && inode->u.i_ops == &g_pseudofile_ops;
|
||||||
|
}
|
@ -416,7 +416,15 @@ int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve)
|
|||||||
{
|
{
|
||||||
/* What is it if it also has child inodes? */
|
/* What is it if it also has child inodes? */
|
||||||
|
|
||||||
buf->st_mode |= S_IFCHR;
|
buf->st_size = inode->i_size;
|
||||||
|
if (inode_is_pseudofile(inode))
|
||||||
|
{
|
||||||
|
buf->st_mode |= S_IFREG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buf->st_mode |= S_IFCHR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -405,6 +405,7 @@ struct inode
|
|||||||
uint16_t i_flags; /* Flags for inode */
|
uint16_t i_flags; /* Flags for inode */
|
||||||
union inode_ops_u u; /* Inode operations */
|
union inode_ops_u u; /* Inode operations */
|
||||||
ino_t i_ino; /* Inode serial number */
|
ino_t i_ino; /* Inode serial number */
|
||||||
|
size_t i_size; /* The size of per inode driver */
|
||||||
#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
|
#ifdef CONFIG_PSEUDOFS_ATTRIBUTES
|
||||||
mode_t i_mode; /* Access mode flags */
|
mode_t i_mode; /* Access mode flags */
|
||||||
uid_t i_owner; /* Owner */
|
uid_t i_owner; /* Owner */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user