4
0
mirror of https://github.com/RT-Thread/rt-thread.git synced 2025-02-21 00:27:19 +08:00

[dfs] Add DFS v2.0 (#7606)

This commit is contained in:
Bernard Xiong 2023-06-10 21:35:25 +08:00 committed by GitHub
parent c33a21509a
commit 99e80f8d33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 5563 additions and 11680 deletions

View File

@ -16,6 +16,7 @@ if RT_USING_DFS
bool "Using working directory"
default y
if RT_USING_DFS_V1
config RT_USING_DFS_MNTTABLE
bool "Using mount table for file system"
default n
@ -27,6 +28,7 @@ if RT_USING_DFS
{0}
};
The mount_table must be terminated with NULL.
endif
config DFS_FD_MAX
int "The maximal number of opened files"
@ -44,8 +46,145 @@ if RT_USING_DFS
bool "DFS v2.0"
endchoice
source "$RTT_DIR/components/dfs/dfs_v1/Kconfig"
source "$RTT_DIR/components/dfs/dfs_v2/Kconfig"
if RT_USING_DFS_V1
config DFS_FILESYSTEMS_MAX
int "The maximal number of mounted file system"
default 4
config DFS_FILESYSTEM_TYPES_MAX
int "The maximal number of file system type"
default 4
endif
config RT_USING_DFS_ELMFAT
bool "Enable elm-chan fatfs"
default n
help
FatFs is a generic FAT/exFAT file system module for small embedded systems.
if RT_USING_DFS_ELMFAT
menu "elm-chan's FatFs, Generic FAT Filesystem Module"
config RT_DFS_ELM_CODE_PAGE
int "OEM code page"
default 437
config RT_DFS_ELM_WORD_ACCESS
bool "Using RT_DFS_ELM_WORD_ACCESS"
default y
choice
prompt "Support long file name"
default RT_DFS_ELM_USE_LFN_3
config RT_DFS_ELM_USE_LFN_0
bool "0: LFN disable"
config RT_DFS_ELM_USE_LFN_1
bool "1: LFN with static LFN working buffer"
config RT_DFS_ELM_USE_LFN_2
bool "2: LFN with dynamic LFN working buffer on the stack"
config RT_DFS_ELM_USE_LFN_3
bool "3: LFN with dynamic LFN working buffer on the heap"
endchoice
config RT_DFS_ELM_USE_LFN
int
default 0 if RT_DFS_ELM_USE_LFN_0
default 1 if RT_DFS_ELM_USE_LFN_1
default 2 if RT_DFS_ELM_USE_LFN_2
default 3 if RT_DFS_ELM_USE_LFN_3
choice
prompt "Support unicode for long file name"
default RT_DFS_ELM_LFN_UNICODE_0
config RT_DFS_ELM_LFN_UNICODE_0
bool "0: ANSI/OEM in current CP (TCHAR = char)"
config RT_DFS_ELM_LFN_UNICODE_1
bool "1: Unicode in UTF-16 (TCHAR = WCHAR)"
config RT_DFS_ELM_LFN_UNICODE_2
bool "2: Unicode in UTF-8 (TCHAR = char)"
config RT_DFS_ELM_LFN_UNICODE_3
bool "3: Unicode in UTF-32 (TCHAR = DWORD)"
endchoice
config RT_DFS_ELM_LFN_UNICODE
int
default 0 if RT_DFS_ELM_LFN_UNICODE_0
default 1 if RT_DFS_ELM_LFN_UNICODE_1
default 2 if RT_DFS_ELM_LFN_UNICODE_2
default 3 if RT_DFS_ELM_LFN_UNICODE_3
config RT_DFS_ELM_MAX_LFN
int "Maximal size of file name length"
range 12 255
default 255
config RT_DFS_ELM_DRIVES
int "Number of volumes (logical drives) to be used."
default 2
config RT_DFS_ELM_MAX_SECTOR_SIZE
int "Maximum sector size to be handled."
default 512
help
If you use some spi nor flash for fatfs, please set this the erase sector size, for example 4096.
config RT_DFS_ELM_USE_ERASE
bool "Enable sector erase feature"
default n
config RT_DFS_ELM_REENTRANT
bool "Enable the reentrancy (thread safe) of the FatFs module"
default y
config RT_DFS_ELM_MUTEX_TIMEOUT
int "Timeout of thread-safe protection mutex"
range 0 1000000
default 3000
depends on RT_DFS_ELM_REENTRANT
endmenu
endif
config RT_USING_DFS_DEVFS
bool "Using devfs for device objects"
default y
config RT_USING_DFS_ROMFS
bool "Enable ReadOnly file system on flash"
default n
if RT_USING_DFS_V1
config RT_USING_DFS_CROMFS
bool "Enable ReadOnly compressed file system on flash"
default n
# select PKG_USING_ZLIB
config RT_USING_DFS_RAMFS
bool "Enable RAM file system"
select RT_USING_MEMHEAP
default n
endif
config RT_USING_DFS_TMPFS
bool "Enable TMP file system"
default n
if RT_USING_DFS_V1
config RT_USING_DFS_NFS
bool "Using NFS v3 client file system"
depends on RT_USING_LWIP
default n
if RT_USING_DFS_NFS
config RT_NFS_HOST_EXPORT
string "NFSv3 host export"
default "192.168.1.5:/"
endif
endif
endif

View File

@ -1,138 +0,0 @@
if RT_USING_DFS_V1
config DFS_FILESYSTEMS_MAX
int "The maximal number of mounted file system"
default 4
config DFS_FILESYSTEM_TYPES_MAX
int "The maximal number of file system type"
default 4
config RT_USING_DFS_ELMFAT
bool "Enable elm-chan fatfs"
default n
help
FatFs is a generic FAT/exFAT file system module for small embedded systems.
if RT_USING_DFS_ELMFAT
menu "elm-chan's FatFs, Generic FAT Filesystem Module"
config RT_DFS_ELM_CODE_PAGE
int "OEM code page"
default 437
config RT_DFS_ELM_WORD_ACCESS
bool "Using RT_DFS_ELM_WORD_ACCESS"
default y
choice
prompt "Support long file name"
default RT_DFS_ELM_USE_LFN_3
config RT_DFS_ELM_USE_LFN_0
bool "0: LFN disable"
config RT_DFS_ELM_USE_LFN_1
bool "1: LFN with static LFN working buffer"
config RT_DFS_ELM_USE_LFN_2
bool "2: LFN with dynamic LFN working buffer on the stack"
config RT_DFS_ELM_USE_LFN_3
bool "3: LFN with dynamic LFN working buffer on the heap"
endchoice
config RT_DFS_ELM_USE_LFN
int
default 0 if RT_DFS_ELM_USE_LFN_0
default 1 if RT_DFS_ELM_USE_LFN_1
default 2 if RT_DFS_ELM_USE_LFN_2
default 3 if RT_DFS_ELM_USE_LFN_3
choice
prompt "Support unicode for long file name"
default RT_DFS_ELM_LFN_UNICODE_0
config RT_DFS_ELM_LFN_UNICODE_0
bool "0: ANSI/OEM in current CP (TCHAR = char)"
config RT_DFS_ELM_LFN_UNICODE_1
bool "1: Unicode in UTF-16 (TCHAR = WCHAR)"
config RT_DFS_ELM_LFN_UNICODE_2
bool "2: Unicode in UTF-8 (TCHAR = char)"
config RT_DFS_ELM_LFN_UNICODE_3
bool "3: Unicode in UTF-32 (TCHAR = DWORD)"
endchoice
config RT_DFS_ELM_LFN_UNICODE
int
default 0 if RT_DFS_ELM_LFN_UNICODE_0
default 1 if RT_DFS_ELM_LFN_UNICODE_1
default 2 if RT_DFS_ELM_LFN_UNICODE_2
default 3 if RT_DFS_ELM_LFN_UNICODE_3
config RT_DFS_ELM_MAX_LFN
int "Maximal size of file name length"
range 12 255
default 255
config RT_DFS_ELM_DRIVES
int "Number of volumes (logical drives) to be used."
default 2
config RT_DFS_ELM_MAX_SECTOR_SIZE
int "Maximum sector size to be handled."
default 512
help
If you use some spi nor flash for fatfs, please set this the erase sector size, for example 4096.
config RT_DFS_ELM_USE_ERASE
bool "Enable sector erase feature"
default n
config RT_DFS_ELM_REENTRANT
bool "Enable the reentrancy (thread safe) of the FatFs module"
default y
config RT_DFS_ELM_MUTEX_TIMEOUT
int "Timeout of thread-safe protection mutex"
range 0 1000000
default 3000
depends on RT_DFS_ELM_REENTRANT
endmenu
endif
config RT_USING_DFS_DEVFS
bool "Using devfs for device objects"
default y
config RT_USING_DFS_ROMFS
bool "Enable ReadOnly file system on flash"
default n
config RT_USING_DFS_CROMFS
bool "Enable ReadOnly compressed file system on flash"
default n
# select PKG_USING_ZLIB
config RT_USING_DFS_RAMFS
bool "Enable RAM file system"
select RT_USING_MEMHEAP
default n
config RT_USING_DFS_TMPFS
bool "Enable TMP file system"
default n
config RT_USING_DFS_NFS
bool "Using NFS v3 client file system"
depends on RT_USING_LWIP
default n
if RT_USING_DFS_NFS
config RT_NFS_HOST_EXPORT
string "NFSv3 host export"
default "192.168.1.5:/"
endif
endif

View File

@ -76,6 +76,8 @@ struct dfs_mmap2_args
};
void dfs_vnode_mgr_init(void);
int dfs_vnode_init(struct dfs_vnode *vnode, int type, const struct dfs_file_ops *fops);
int dfs_file_is_open(const char *pathname);
int dfs_file_open(struct dfs_file *fd, const char *path, int flags);
int dfs_file_close(struct dfs_file *fd);

View File

@ -47,6 +47,20 @@ void dfs_vnode_mgr_init(void)
}
}
int dfs_vnode_init(struct dfs_vnode *vnode, int type, const struct dfs_file_ops *fops)
{
if (vnode)
{
rt_memset(vnode, 0, sizeof(struct dfs_vnode));
vnode->type = type;
vnode->fops = fops;
rt_list_init(&(vnode->list));
vnode->ref_count = 1;
}
return 0;
}
/* BKDR Hash Function */
static unsigned int bkdr_hash(const char *str)
{

View File

@ -1,35 +0,0 @@
if RT_USING_DFS_V2
config RT_USING_DFS_DEVFS
bool "Using devfs for device objects"
default y
config RT_USING_DFS_ROMFS
bool "Enable ReadOnly file system on flash"
default n
config RT_USING_DFS_CROMFS
bool "Enable ReadOnly compressed file system on flash"
default n
# select PKG_USING_ZLIB
config RT_USING_DFS_RAMFS
bool "Enable RAM file system"
select RT_USING_MEMHEAP
default n
config RT_USING_DFS_TMPFS
bool "Enable TMP file system"
default n
config RT_USING_DFS_NFS
bool "Using NFS v3 client file system"
depends on RT_USING_LWIP
default n
if RT_USING_DFS_NFS
config RT_NFS_HOST_EXPORT
string "NFSv3 host export"
default "192.168.1.5:/"
endif
endif

View File

@ -2,19 +2,24 @@ from building import *
import os
# The set of source files associated with this SConscript file.
src = []
cwd = GetCurrentDir()
src = Split('''
src/dfs.c
src/dfs_file.c
src/dfs_fs.c
src/dfs_dentry.c
src/dfs_vnode.c
src/dfs_mnt.c
src/dfs_posix.c
''')
cwd = GetCurrentDir()
CPPPATH = [cwd + "/include"]
group = []
if GetDepend('RT_USING_POSIX'):
src += ['src/poll.c', 'src/select.c']
group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_V2'], CPPPATH = CPPPATH)
if GetDepend('RT_USING_DFS') and GetDepend('RT_USING_DFS_V2'):
src = ['src/dfs.c', 'src/dfs_file.c', 'src/dfs_fs.c']
if GetDepend('DFS_USING_POSIX'):
src += ['src/dfs_posix.c']
group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS'], CPPPATH = CPPPATH)
# search in the file system implementation
list = os.listdir(cwd)

View File

@ -8,38 +8,252 @@
* 2018-02-11 Bernard Ignore O_CREAT flag in open.
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdbg.h>
#include <rtdevice.h>
#include <fcntl.h>
#include <errno.h>
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_file.h>
#include <dfs_dentry.h>
#include <dfs_mnt.h>
#include "devfs.h"
struct device_dirent
{
rt_device_t *devices;
rt_uint16_t read_index;
rt_uint16_t device_count;
struct rt_device **devices;
uint32_t device_count;
};
int dfs_device_fs_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
int dfs_devfs_open(struct dfs_file *file);
int dfs_devfs_close(struct dfs_file *file);
int generic_dfs_lseek(struct dfs_file *file, off_t offset, int whence);
int dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos);
int dfs_devfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos);
int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args);
int dfs_devfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count);
static int dfs_devfs_poll(struct dfs_file *file, struct rt_pollreq *req);
int dfs_devfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data);
int dfs_devfs_umount(struct dfs_mnt *mnt);
int dfs_devfs_unlink(struct dfs_dentry *dentry);
int dfs_devfs_stat(struct dfs_dentry *dentry, struct stat *st);
int dfs_devfs_statfs(struct dfs_mnt *mnt, struct statfs *buf);
static struct dfs_vnode *dfs_devfs_lookup(struct dfs_dentry *dentry);
struct dfs_vnode *dfs_devfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode);
static int dfs_devfs_free_vnode(struct dfs_vnode *vnode);
static const struct dfs_file_ops _dev_fops =
{
.open = dfs_devfs_open,
.close = dfs_devfs_close,
.lseek = generic_dfs_lseek,
.read = dfs_devfs_read,
.write = dfs_devfs_write,
.ioctl = dfs_devfs_ioctl,
.getdents = dfs_devfs_getdents,
.poll = dfs_devfs_poll,
};
static const struct dfs_filesystem_ops _devfs_ops =
{
.name = "devfs",
.default_fops = &_dev_fops,
.mount = dfs_devfs_mount,
.umount = dfs_devfs_umount,
.unlink = dfs_devfs_unlink,
.stat = dfs_devfs_stat,
.statfs = dfs_devfs_statfs,
.lookup = dfs_devfs_lookup,
.create_vnode = dfs_devfs_create_vnode,
.free_vnode = dfs_devfs_free_vnode,
};
static struct dfs_filesystem_type _devfs =
{
.fs_ops = &_devfs_ops,
};
static int _device_to_mode(struct rt_device *device)
{
int mode = 0;
switch (device->type)
{
case RT_Device_Class_Char:
mode = S_IFCHR | 0777;
break;
case RT_Device_Class_Block:
mode = S_IFBLK | 0777;
break;
case RT_Device_Class_Pipe:
mode = S_IFIFO | 0777;
break;
default:
mode = S_IFCHR | 0777;
break;
}
return mode;
}
static int _devfs_root_dirent_update(struct dfs_vnode *vnode)
{
rt_err_t result = RT_EOK;
if (vnode)
{
// result = rt_mutex_take(&vnode->lock, RT_WAITING_FOREVER);
result = dfs_file_lock();
if (result == RT_EOK)
{
rt_uint32_t count = 0;
struct device_dirent *root_dirent = (struct device_dirent*) vnode->data;
if (root_dirent) rt_free(root_dirent);
count = rt_object_get_length(RT_Object_Class_Device);
root_dirent = (struct device_dirent *)rt_malloc(sizeof(struct device_dirent) + count * sizeof(rt_device_t));
if (root_dirent != RT_NULL)
{
root_dirent->device_count = count;
if (count != 0)
{
root_dirent->devices = (rt_device_t *)(root_dirent + 1);
rt_object_get_pointers(RT_Object_Class_Device, (rt_object_t *)root_dirent->devices, count);
}
else
{
root_dirent->devices = RT_NULL;
}
}
vnode->data = root_dirent;
result = count;
dfs_file_unlock();
}
}
return result;
}
static struct dfs_vnode *dfs_devfs_lookup(struct dfs_dentry *dentry)
{
rt_device_t device = RT_NULL;
struct dfs_vnode *vnode = RT_NULL;
const char *pathname = dentry->pathname;
DLOG(msg, "devfs", "vnode", DLOG_MSG, "dfs_vnode_create");
vnode = dfs_vnode_create();
if (vnode)
{
if (pathname[0] == '/' && pathname[1] == '\0')
{
int count = _devfs_root_dirent_update(vnode);
vnode->mode = S_IFDIR | 0644;
vnode->size = count;
vnode->nlink = 1;
vnode->fops = &_dev_fops;
vnode->mnt = dentry->mnt;
vnode->type = FT_DIRECTORY;
}
else
{
device = rt_device_find(&pathname[1]);
if (!device)
{
DLOG(msg, "devfs", "vnode", DLOG_MSG, "dfs_vnode_destroy(vnode), no-device");
dfs_vnode_destroy(vnode);
vnode = RT_NULL;
}
else
{
vnode->mode = _device_to_mode(device);
vnode->size = device->ref_count;
vnode->nlink = 1;
if (device->fops)
{
vnode->fops = device->fops;
}
else
{
vnode->fops = &_dev_fops;
}
vnode->data = device;
vnode->mnt = dentry->mnt;
vnode->type = FT_DEVICE;
}
}
}
return vnode;
}
struct dfs_vnode *dfs_devfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode)
{
#ifdef RT_USING_DEV_BUS
if (dentry && type == FT_DIRECTORY)
{
/* regester bus device */
if (rt_device_bus_create(&dentry->pathname[1], 0))
{
return dfs_devfs_lookup(dentry);
}
}
#endif
return RT_NULL;
}
int dfs_devfs_free_vnode(struct dfs_vnode *vnode)
{
if (S_ISDIR(vnode->mode))
{
struct device_dirent *root_dirent;
root_dirent = (struct device_dirent *)vnode->data;
RT_ASSERT(root_dirent != RT_NULL);
/* release dirent */
DLOG(msg, "devfs", "devfs", DLOG_MSG, "free root_dirent");
rt_free(root_dirent);
return RT_EOK;
}
/* which is a device */
vnode->data = RT_NULL;
return 0;
}
int dfs_devfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data)
{
RT_ASSERT(mnt != RT_NULL);
return RT_EOK;
}
int dfs_devfs_umount(struct dfs_mnt *mnt)
{
return RT_EOK;
}
int dfs_device_fs_statfs(struct dfs_filesystem *fs, struct statfs *buf)
int dfs_devfs_statfs(struct dfs_mnt *mnt, struct statfs *buf)
{
buf->f_bsize = 512;
buf->f_blocks = 2048 * 64; // 64M
buf->f_bfree = buf->f_blocks;
buf->f_bavail = buf->f_bfree;
if (mnt && buf)
{
buf->f_bsize = 512;
buf->f_blocks = 2048 * 64; // 64M
buf->f_bfree = buf->f_blocks;
buf->f_bavail = buf->f_bfree;
}
return RT_EOK;
}
int dfs_device_fs_ioctl(struct dfs_file *file, int cmd, void *args)
int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args)
{
rt_err_t result;
rt_device_t dev_id;
@ -50,7 +264,7 @@ int dfs_device_fs_ioctl(struct dfs_file *file, int cmd, void *args)
dev_id = (rt_device_t)file->vnode->data;
RT_ASSERT(dev_id != RT_NULL);
if ((file->vnode->path[0] == '/') && (file->vnode->path[1] == '\0'))
if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0'))
return -RT_ENOSYS;
/* close device handler */
@ -61,7 +275,7 @@ int dfs_device_fs_ioctl(struct dfs_file *file, int cmd, void *args)
return result;
}
int dfs_device_fs_read(struct dfs_file *file, void *buf, size_t count)
int dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{
int result;
rt_device_t dev_id;
@ -72,17 +286,17 @@ int dfs_device_fs_read(struct dfs_file *file, void *buf, size_t count)
dev_id = (rt_device_t)file->vnode->data;
RT_ASSERT(dev_id != RT_NULL);
if ((file->vnode->path[0] == '/') && (file->vnode->path[1] == '\0'))
if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0'))
return -RT_ENOSYS;
/* read device data */
result = rt_device_read(dev_id, file->pos, buf, count);
file->pos += result;
result = rt_device_read(dev_id, *pos, buf, count);
*pos += result;
return result;
}
int dfs_device_fs_write(struct dfs_file *file, const void *buf, size_t count)
int dfs_devfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
{
int result;
rt_device_t dev_id;
@ -93,184 +307,93 @@ int dfs_device_fs_write(struct dfs_file *file, const void *buf, size_t count)
dev_id = (rt_device_t)file->vnode->data;
RT_ASSERT(dev_id != RT_NULL);
if ((file->vnode->path[0] == '/') && (file->vnode->path[1] == '\0'))
if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0'))
return -RT_ENOSYS;
/* read device data */
result = rt_device_write(dev_id, file->pos, buf, count);
file->pos += result;
result = rt_device_write(dev_id, *pos, buf, count);
*pos += result;
return result;
}
int dfs_device_fs_close(struct dfs_file *file)
int dfs_devfs_close(struct dfs_file *file)
{
rt_err_t result;
rt_device_t dev_id;
RT_ASSERT(file != RT_NULL);
RT_ASSERT(file->vnode->ref_count > 0);
if (file->vnode->ref_count > 1)
{
return 0;
}
if (file->vnode->type == FT_DIRECTORY && (file->vnode->path[0] == '/') && (file->vnode->path[1] == '\0'))
{
struct device_dirent *root_dirent;
root_dirent = (struct device_dirent *)file->vnode->data;
RT_ASSERT(root_dirent != RT_NULL);
/* release dirent */
rt_free(root_dirent);
return RT_EOK;
}
/* get device handler */
dev_id = (rt_device_t)file->vnode->data;
RT_ASSERT(dev_id != RT_NULL);
/* close device handler */
result = rt_device_close(dev_id);
if (result == RT_EOK)
{
file->vnode->data = RT_NULL;
return RT_EOK;
}
return -EIO;
}
int dfs_device_fs_open(struct dfs_file *file)
{
rt_err_t result;
rt_err_t result = RT_EOK;
rt_device_t device;
RT_ASSERT(file->vnode->ref_count > 0);
if (file->vnode->ref_count > 1)
RT_ASSERT(file != RT_NULL);
if (!S_ISDIR(file->vnode->mode))
{
file->pos = 0;
return 0;
/* get device handler */
device = (rt_device_t)file->vnode->data;
RT_ASSERT(device != RT_NULL);
/* close device handler */
result = rt_device_close(device);
}
return result;
}
int dfs_devfs_open(struct dfs_file *file)
{
rt_err_t result = RT_EOK;
/* open root directory */
if ((file->vnode->path[0] == '/') && (file->vnode->path[1] == '\0') &&
(file->flags & O_DIRECTORY))
if ((file->dentry->pathname[0] == '/' && file->dentry->pathname[1] == '\0') ||
(S_ISDIR(file->vnode->mode)))
{
struct rt_object *object;
struct rt_list_node *node;
struct rt_object_information *information;
struct device_dirent *root_dirent;
rt_uint32_t count = 0;
/* lock scheduler */
rt_enter_critical();
/* traverse device object */
information = rt_object_get_information(RT_Object_Class_Device);
RT_ASSERT(information != RT_NULL);
for (node = information->object_list.next; node != &(information->object_list); node = node->next)
{
count ++;
}
rt_exit_critical();
root_dirent = (struct device_dirent *)rt_malloc(sizeof(struct device_dirent) +
count * sizeof(rt_device_t));
if (root_dirent != RT_NULL)
{
/* lock scheduler */
rt_enter_critical();
root_dirent->devices = (rt_device_t *)(root_dirent + 1);
root_dirent->read_index = 0;
root_dirent->device_count = count;
count = 0;
/* get all device node */
for (node = information->object_list.next; node != &(information->object_list); node = node->next)
{
/* avoid memory write through */
if (count == root_dirent->device_count)
{
rt_kprintf("warning: There are newly added devices that are not displayed!");
break;
}
object = rt_list_entry(node, struct rt_object, list);
root_dirent->devices[count] = (rt_device_t)object;
count ++;
}
rt_exit_critical();
}
/* set data */
file->vnode->data = root_dirent;
/* re-open the root directory for re-scan devices */
_devfs_root_dirent_update(file->vnode);
return RT_EOK;
}
#ifdef RT_USING_DEV_BUS
else if (file->flags & O_CREAT)
else
{
if (!(file->flags & O_DIRECTORY))
{
return -ENOSYS;
}
/* regester bus device */
if (rt_device_bus_create(&file->vnode->path[1], 0) == RT_NULL)
{
return -EEXIST;
}
}
#endif
device = rt_device_find(&file->vnode->path[1]);
if (device == RT_NULL)
{
return -ENODEV;
}
rt_device_t device = RT_NULL;
device = (struct rt_device *)file->vnode->data;
if (device)
{
#ifdef RT_USING_POSIX_DEVIO
if (device->fops)
{
/* use device fops */
file->vnode->fops = device->fops;
file->vnode->data = (void *)device;
/* use fops */
if (file->vnode->fops->open)
{
result = file->vnode->fops->open(file);
if (result == RT_EOK || result == -RT_ENOSYS)
if (device->fops)
{
file->vnode->type = FT_DEVICE;
return 0;
/* use device fops */
file->fops = device->fops;
/* use fops->open */
if (file->vnode->fops->open)
{
result = file->vnode->fops->open(file);
if (result == RT_EOK || result == -RT_ENOSYS)
{
return RT_EOK;
}
}
}
else
#endif /* RT_USING_POSIX_DEVIO */
{
result = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
if (result == RT_EOK || result == -RT_ENOSYS)
{
file->fops = &_dev_fops;
return RT_EOK;
}
}
}
}
else
#endif /* RT_USING_POSIX_DEVIO */
{
result = rt_device_open(device, RT_DEVICE_OFLAG_RDWR);
if (result == RT_EOK || result == -RT_ENOSYS)
{
file->vnode->data = device;
file->vnode->type = FT_DEVICE;
return RT_EOK;
}
}
file->vnode->data = RT_NULL;
/* open device failed. */
return -EIO;
}
int dfs_device_fs_unlink(struct dfs_filesystem *fs, const char *path)
int dfs_devfs_unlink(struct dfs_dentry *dentry)
{
#ifdef RT_USING_DEV_BUS
rt_device_t dev_id;
dev_id = rt_device_find(&path[1]);
dev_id = rt_device_find(&dentry->pathname[1]);
if (dev_id == RT_NULL)
{
return -1;
@ -284,57 +407,66 @@ int dfs_device_fs_unlink(struct dfs_filesystem *fs, const char *path)
return RT_EOK;
}
int dfs_device_fs_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
int dfs_devfs_stat(struct dfs_dentry *dentry, struct stat *st)
{
/* stat root directory */
if ((path[0] == '/') && (path[1] == '\0'))
int ret = RT_EOK;
const char *path = RT_NULL;
struct dfs_vnode *vnode = RT_NULL;
if (dentry && dentry->vnode)
{
st->st_dev = 0;
path = dentry->pathname;
vnode = dentry->vnode;
st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH;
st->st_mode &= ~S_IFREG;
st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
st->st_size = 0;
st->st_mtime = 0;
return RT_EOK;
}
else
{
rt_device_t dev_id;
dev_id = rt_device_find(&path[1]);
if (dev_id != RT_NULL)
/* stat root directory */
if ((path[0] == '/') && (path[1] == '\0'))
{
st->st_dev = 0;
st->st_gid = vnode->gid;
st->st_uid = vnode->uid;
st->st_ino = 0;
st->st_mode = vnode->mode;
st->st_nlink = vnode->nlink;
st->st_size = vnode->size;
st->st_mtim.tv_nsec = vnode->mtime.tv_nsec;
st->st_mtim.tv_sec = vnode->mtime.tv_sec;
st->st_ctim.tv_nsec = vnode->ctime.tv_nsec;
st->st_ctim.tv_sec = vnode->ctime.tv_sec;
st->st_atim.tv_nsec = vnode->atime.tv_nsec;
st->st_atim.tv_sec = vnode->atime.tv_sec;
}
else
{
rt_device_t dev_id;
st->st_mode = S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH;
if (dev_id->type == RT_Device_Class_Char)
st->st_mode |= S_IFCHR;
else if (dev_id->type == RT_Device_Class_Block)
st->st_mode |= S_IFBLK;
else if (dev_id->type == RT_Device_Class_Pipe)
st->st_mode |= S_IFIFO;
else if (dev_id->type == RT_Device_Class_Bus)
st->st_mode |= S_IFDIR;
dev_id = rt_device_find(&path[1]);
if (dev_id != RT_NULL)
{
st->st_dev = 0;
st->st_gid = vnode->gid;
st->st_uid = vnode->uid;
st->st_ino = 0;
st->st_mode = vnode->mode;
st->st_nlink = vnode->nlink;
st->st_size = vnode->size;
st->st_mtim.tv_nsec = vnode->mtime.tv_nsec;
st->st_mtim.tv_sec = vnode->mtime.tv_sec;
st->st_ctim.tv_nsec = vnode->ctime.tv_nsec;
st->st_ctim.tv_sec = vnode->ctime.tv_sec;
st->st_atim.tv_nsec = vnode->atime.tv_nsec;
st->st_atim.tv_sec = vnode->atime.tv_sec;
}
else
st->st_mode |= S_IFREG;
st->st_size = 0;
st->st_mtime = 0;
return RT_EOK;
{
ret = -ENOENT;
}
}
}
return -ENOENT;
return ret;
}
int dfs_device_fs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
int dfs_devfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
{
rt_uint32_t index;
rt_object_t object;
@ -349,68 +481,38 @@ int dfs_device_fs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t
if (count == 0)
return -EINVAL;
for (index = 0; index < count && index + root_dirent->read_index < root_dirent->device_count;
index ++)
for (index = 0; index < count && index + file->fpos < root_dirent->device_count; index ++)
{
object = (rt_object_t)root_dirent->devices[root_dirent->read_index + index];
object = (rt_object_t)root_dirent->devices[file->fpos + index];
d = dirp + index;
if ((((rt_device_t)object)->type) == RT_Device_Class_Bus)
{
d->d_type = DT_DIR;
}
else
{
d->d_type = DT_REG;
}
d->d_type = DT_REG;
d->d_namlen = RT_NAME_MAX;
d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_strncpy(d->d_name, object->name, RT_NAME_MAX);
d->d_name[RT_NAME_MAX] = '\0';
}
root_dirent->read_index += index;
file->fpos += index;
return index * sizeof(struct dirent);
}
static int dfs_device_fs_poll(struct dfs_file *fd, struct rt_pollreq *req)
static int dfs_devfs_poll(struct dfs_file *file, struct rt_pollreq *req)
{
int mask = 0;
return mask;
}
static const struct dfs_file_ops _device_fops =
int dfs_devfs_init(void)
{
dfs_device_fs_open,
dfs_device_fs_close,
dfs_device_fs_ioctl,
dfs_device_fs_read,
dfs_device_fs_write,
RT_NULL, /* flush */
RT_NULL, /* lseek */
dfs_device_fs_getdents,
dfs_device_fs_poll,
};
/* register devfs file system */
dfs_register(&_devfs);
static const struct dfs_filesystem_ops _device_fs =
{
"devfs",
DFS_FS_FLAG_DEFAULT,
&_device_fops,
dfs_device_fs_mount,
RT_NULL, /*unmount*/
RT_NULL, /*mkfs*/
dfs_device_fs_statfs,
dfs_device_fs_unlink,
dfs_device_fs_stat,
RT_NULL, /*rename*/
};
int devfs_init(void)
{
/* register device file system */
dfs_register(&_device_fs);
dfs_mount(RT_NULL, "/dev", "devfs", 0, RT_NULL);
return 0;
}
INIT_COMPONENT_EXPORT(dfs_devfs_init);

View File

@ -10,8 +10,6 @@
#ifndef __DEVICE_FS_H__
#define __DEVICE_FS_H__
#include <rtthread.h>
int devfs_init(void);
int dfs_devfs_init(void);
#endif

View File

@ -26,8 +26,11 @@
/* ELM FatFs provide a DIR struct */
#define HAVE_DIR_STRUCTURE
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_dentry.h>
#include <dfs_file.h>
#include <dfs_mnt.h>
#undef SS
#if FF_MAX_SS == FF_MIN_SS
@ -38,6 +41,8 @@
static rt_device_t disk[FF_VOLUMES] = {0};
int dfs_elm_unmount(struct dfs_mnt *mnt);
static int elm_result_to_dfs(FRESULT result)
{
int status = RT_EOK;
@ -102,7 +107,7 @@ static int get_disk(rt_device_t id)
return -1;
}
int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
static int dfs_elm_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data)
{
FATFS *fat;
FRESULT result;
@ -110,20 +115,31 @@ int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *d
struct rt_device_blk_geometry geometry;
char logic_nbr[3] = {'0',':', 0};
/* open device, but do not check the status of device */
if (mnt->dev_id == RT_NULL
|| rt_device_open(mnt->dev_id, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
{
return -ENODEV;
}
/* get an empty position */
index = get_disk(RT_NULL);
if (index == -1)
{
rt_device_close(mnt->dev_id);
return -ENOENT;
}
logic_nbr[0] = '0' + index;
/* save device */
disk[index] = fs->dev_id;
disk[index] = mnt->dev_id;
/* check sector size */
if (rt_device_control(fs->dev_id, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry) == RT_EOK)
if (rt_device_control(mnt->dev_id, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry) == RT_EOK)
{
if (geometry.bytes_per_sector > FF_MAX_SS)
{
rt_kprintf("The sector size of device is greater than the sector size of FAT.\n");
rt_device_close(mnt->dev_id);
return -EINVAL;
}
}
@ -132,6 +148,7 @@ int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *d
if (fat == RT_NULL)
{
disk[index] = RT_NULL;
rt_device_close(mnt->dev_id);
return -ENOMEM;
}
@ -149,6 +166,7 @@ int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *d
f_mount(RT_NULL, (const TCHAR *)logic_nbr, 1);
disk[index] = RT_NULL;
rt_free(fat);
rt_device_close(mnt->dev_id);
return -ENOMEM;
}
@ -158,31 +176,32 @@ int dfs_elm_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *d
goto __err;
/* mount succeed! */
fs->data = fat;
mnt->data = fat;
rt_free(dir);
return 0;
return RT_EOK;
}
__err:
f_mount(RT_NULL, (const TCHAR *)logic_nbr, 1);
disk[index] = RT_NULL;
rt_free(fat);
rt_device_close(mnt->dev_id);
return elm_result_to_dfs(result);
}
int dfs_elm_unmount(struct dfs_filesystem *fs)
int dfs_elm_unmount(struct dfs_mnt *mnt)
{
FATFS *fat;
FRESULT result;
int index;
char logic_nbr[3] = {'0',':', 0};
fat = (FATFS *)fs->data;
fat = (FATFS *)mnt->data;
RT_ASSERT(fat != RT_NULL);
/* find the device index and then umount it */
index = get_disk(fs->dev_id);
index = get_disk(mnt->dev_id);
if (index == -1) /* not found */
return -ENOENT;
@ -191,9 +210,10 @@ int dfs_elm_unmount(struct dfs_filesystem *fs)
if (result != FR_OK)
return elm_result_to_dfs(result);
fs->data = RT_NULL;
mnt->data = RT_NULL;
disk[index] = RT_NULL;
rt_free(fat);
rt_device_close(mnt->dev_id);
return RT_EOK;
}
@ -296,17 +316,17 @@ int dfs_elm_mkfs(rt_device_t dev_id, const char *fs_name)
return RT_EOK;
}
int dfs_elm_statfs(struct dfs_filesystem *fs, struct statfs *buf)
int dfs_elm_statfs(struct dfs_mnt *mnt, struct statfs *buf)
{
FATFS *f;
FRESULT res;
char driver[4];
DWORD fre_clust, fre_sect, tot_sect;
RT_ASSERT(fs != RT_NULL);
RT_ASSERT(mnt != RT_NULL);
RT_ASSERT(buf != RT_NULL);
f = (FATFS *)fs->data;
f = (FATFS *)mnt->data;
rt_snprintf(driver, sizeof(driver), "%d:", f->pdrv);
res = f_getfree(driver, &fre_clust, &f);
@ -337,7 +357,7 @@ int dfs_elm_open(struct dfs_file *file)
#if (FF_VOLUMES > 1)
int vol;
struct dfs_filesystem *fs = file->vnode->fs;
struct dfs_mnt *mnt = file->vnode->mnt;
extern int elm_get_vol(FATFS * fat);
RT_ASSERT(file->vnode->ref_count > 0);
@ -348,24 +368,24 @@ int dfs_elm_open(struct dfs_file *file)
{
return -ENOENT;
}
file->pos = 0;
file->fpos = 0;
return 0;
}
if (fs == NULL)
if (mnt == NULL)
return -ENOENT;
/* add path for ELM FatFS driver support */
vol = elm_get_vol((FATFS *)fs->data);
vol = elm_get_vol((FATFS *)mnt->data);
if (vol < 0)
return -ENOENT;
drivers_fn = (char *)rt_malloc(256);
if (drivers_fn == RT_NULL)
return -ENOMEM;
rt_snprintf(drivers_fn, 256, "%d:%s", vol, file->vnode->path);
rt_snprintf(drivers_fn, 256, "%d:%s", vol, file->dentry->pathname);
#else
drivers_fn = file->vnode->path;
drivers_fn = file->dentry->pathname;
#endif
if (file->flags & O_DIRECTORY)
@ -404,7 +424,7 @@ int dfs_elm_open(struct dfs_file *file)
return elm_result_to_dfs(result);
}
file->data = dir;
file->vnode->data = dir;
return RT_EOK;
}
else
@ -441,16 +461,16 @@ int dfs_elm_open(struct dfs_file *file)
#endif
if (result == FR_OK)
{
file->pos = fd->fptr;
file->fpos = fd->fptr;
file->vnode->size = f_size(fd);
file->vnode->type = FT_REGULAR;
file->data = fd;
file->vnode->data = fd;
if (file->flags & O_APPEND)
{
/* seek to the end of file */
f_lseek(fd, f_size(fd));
file->pos = fd->fptr;
file->fpos = fd->fptr;
}
}
else
@ -478,7 +498,7 @@ int dfs_elm_close(struct dfs_file *file)
{
DIR *dir = RT_NULL;
dir = (DIR *)(file->data);
dir = (DIR *)(file->vnode->data);
RT_ASSERT(dir != RT_NULL);
/* release memory */
@ -487,7 +507,7 @@ int dfs_elm_close(struct dfs_file *file)
else if (file->vnode->type == FT_REGULAR)
{
FIL *fd = RT_NULL;
fd = (FIL *)(file->data);
fd = (FIL *)(file->vnode->data);
RT_ASSERT(fd != RT_NULL);
result = f_close(fd);
@ -510,7 +530,7 @@ int dfs_elm_ioctl(struct dfs_file *file, int cmd, void *args)
FIL *fd;
FSIZE_t fptr, length;
FRESULT result = FR_OK;
fd = (FIL *)(file->data);
fd = (FIL *)(file->vnode->data);
RT_ASSERT(fd != RT_NULL);
/* save file read/write point */
@ -537,7 +557,7 @@ int dfs_elm_ioctl(struct dfs_file *file, int cmd, void *args)
return -ENOSYS;
}
int dfs_elm_read(struct dfs_file *file, void *buf, size_t len)
int dfs_elm_read(struct dfs_file *file, void *buf, size_t len, off_t *pos)
{
FIL *fd;
FRESULT result;
@ -548,19 +568,20 @@ int dfs_elm_read(struct dfs_file *file, void *buf, size_t len)
return -EISDIR;
}
fd = (FIL *)(file->data);
fd = (FIL *)(file->vnode->data);
RT_ASSERT(fd != RT_NULL);
result = f_read(fd, buf, len, &byte_read);
/* update position */
file->pos = fd->fptr;
file->fpos = fd->fptr;
*pos = file->fpos;
if (result == FR_OK)
return byte_read;
return elm_result_to_dfs(result);
}
int dfs_elm_write(struct dfs_file *file, const void *buf, size_t len)
int dfs_elm_write(struct dfs_file *file, const void *buf, size_t len, off_t *pos)
{
FIL *fd;
FRESULT result;
@ -571,12 +592,13 @@ int dfs_elm_write(struct dfs_file *file, const void *buf, size_t len)
return -EISDIR;
}
fd = (FIL *)(file->data);
fd = (FIL *)(file->vnode->data);
RT_ASSERT(fd != RT_NULL);
result = f_write(fd, buf, len, &byte_write);
/* update position and file size */
file->pos = fd->fptr;
file->fpos = fd->fptr;
*pos = file->fpos;
file->vnode->size = f_size(fd);
if (result == FR_OK)
return byte_write;
@ -589,14 +611,14 @@ int dfs_elm_flush(struct dfs_file *file)
FIL *fd;
FRESULT result;
fd = (FIL *)(file->data);
fd = (FIL *)(file->vnode->data);
RT_ASSERT(fd != RT_NULL);
result = f_sync(fd);
return elm_result_to_dfs(result);
}
int dfs_elm_lseek(struct dfs_file *file, off_t offset)
int dfs_elm_lseek(struct dfs_file *file, off_t offset, int wherece)
{
FRESULT result = FR_OK;
if (file->vnode->type == FT_REGULAR)
@ -604,14 +626,14 @@ int dfs_elm_lseek(struct dfs_file *file, off_t offset)
FIL *fd;
/* regular file type */
fd = (FIL *)(file->data);
fd = (FIL *)(file->vnode->data);
RT_ASSERT(fd != RT_NULL);
result = f_lseek(fd, offset);
if (result == FR_OK)
{
/* return current position */
file->pos = fd->fptr;
file->fpos = fd->fptr;
return fd->fptr;
}
}
@ -620,15 +642,15 @@ int dfs_elm_lseek(struct dfs_file *file, off_t offset)
/* which is a directory */
DIR *dir = RT_NULL;
dir = (DIR *)(file->data);
dir = (DIR *)(file->vnode->data);
RT_ASSERT(dir != RT_NULL);
result = f_seekdir(dir, offset / sizeof(struct dirent));
if (result == FR_OK)
{
/* update file position */
file->pos = offset;
return file->pos;
file->fpos = offset;
return file->fpos;
}
}
@ -643,7 +665,7 @@ int dfs_elm_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
rt_uint32_t index;
struct dirent *d;
dir = (DIR *)(file->data);
dir = (DIR *)(file->vnode->data);
RT_ASSERT(dir != RT_NULL);
/* make integer count */
@ -686,12 +708,12 @@ int dfs_elm_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
if (index == 0)
return elm_result_to_dfs(result);
file->pos += index * sizeof(struct dirent);
file->fpos += index * sizeof(struct dirent);
return index * sizeof(struct dirent);
}
int dfs_elm_unlink(struct dfs_filesystem *fs, const char *path)
int dfs_elm_unlink(struct dfs_dentry *dentry)
{
FRESULT result;
@ -701,14 +723,14 @@ int dfs_elm_unlink(struct dfs_filesystem *fs, const char *path)
extern int elm_get_vol(FATFS * fat);
/* add path for ELM FatFS driver support */
vol = elm_get_vol((FATFS *)fs->data);
vol = elm_get_vol((FATFS *)dentry->mnt->data);
if (vol < 0)
return -ENOENT;
drivers_fn = (char *)rt_malloc(256);
if (drivers_fn == RT_NULL)
return -ENOMEM;
rt_snprintf(drivers_fn, 256, "%d:%s", vol, path);
rt_snprintf(drivers_fn, 256, "%d:%s", vol, dentry->pathname);
#else
const char *drivers_fn;
drivers_fn = path;
@ -721,7 +743,7 @@ int dfs_elm_unlink(struct dfs_filesystem *fs, const char *path)
return elm_result_to_dfs(result);
}
int dfs_elm_rename(struct dfs_filesystem *fs, const char *oldpath, const char *newpath)
int dfs_elm_rename(struct dfs_dentry *old_dentry, struct dfs_dentry *new_dentry)
{
FRESULT result;
@ -732,21 +754,21 @@ int dfs_elm_rename(struct dfs_filesystem *fs, const char *oldpath, const char *n
extern int elm_get_vol(FATFS * fat);
/* add path for ELM FatFS driver support */
vol = elm_get_vol((FATFS *)fs->data);
vol = elm_get_vol((FATFS *)old_dentry->mnt->data);
if (vol < 0)
return -ENOENT;
drivers_oldfn = (char *)rt_malloc(256);
if (drivers_oldfn == RT_NULL)
return -ENOMEM;
drivers_newfn = newpath;
drivers_newfn = new_dentry->pathname;
rt_snprintf(drivers_oldfn, 256, "%d:%s", vol, oldpath);
rt_snprintf(drivers_oldfn, 256, "%d:%s", vol, old_dentry->pathname);
#else
const char *drivers_oldfn, *drivers_newfn;
drivers_oldfn = oldpath;
drivers_newfn = newpath;
drivers_oldfn = old_dentry->pathname;
drivers_newfn = new_dentry->pathname;
#endif
result = f_rename(drivers_oldfn, drivers_newfn);
@ -756,13 +778,13 @@ int dfs_elm_rename(struct dfs_filesystem *fs, const char *oldpath, const char *n
return elm_result_to_dfs(result);
}
int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
int dfs_elm_stat(struct dfs_dentry *dentry, struct stat *st)
{
FATFS *f;
FATFS *fat;
FILINFO file_info;
FRESULT result;
f = (FATFS *)fs->data;
fat = (FATFS *)dentry->mnt->data;
#if FF_VOLUMES > 1
int vol;
@ -770,17 +792,17 @@ int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
extern int elm_get_vol(FATFS * fat);
/* add path for ELM FatFS driver support */
vol = elm_get_vol((FATFS *)fs->data);
vol = elm_get_vol(fat);
if (vol < 0)
return -ENOENT;
drivers_fn = (char *)rt_malloc(256);
if (drivers_fn == RT_NULL)
return -ENOMEM;
rt_snprintf(drivers_fn, 256, "%d:%s", vol, path);
rt_snprintf(drivers_fn, 256, "%d:%s", vol, dentry->pathname);
#else
const char *drivers_fn;
drivers_fn = path;
drivers_fn = dentry->pathname;
#endif
result = f_stat(drivers_fn, &file_info);
@ -790,7 +812,8 @@ int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
if (result == FR_OK)
{
/* convert to dfs stat structure */
st->st_dev = 0;
st->st_dev = (dev_t)(size_t)(dentry->mnt->dev_id);
st->st_ino = (ino_t)dfs_dentry_full_path_crc32(dentry);
st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH;
@ -803,15 +826,15 @@ int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
st->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
st->st_size = file_info.fsize;
st->st_blksize = f->csize * SS(f);
st->st_blksize = fat->csize * SS(fat);
if (file_info.fattrib & AM_ARC)
{
st->st_blocks = file_info.fsize ? ((file_info.fsize - 1) / SS(f) / f->csize + 1) : 0;
st->st_blocks = file_info.fsize ? ((file_info.fsize - 1) / SS(f) / fat->csize + 1) : 0;
st->st_blocks *= (st->st_blksize / 512); // man say st_blocks is number of 512B blocks allocated
}
else
{
st->st_blocks = f->csize;
st->st_blocks = fat->csize;
}
/* get st_mtime. */
{
@ -848,39 +871,127 @@ int dfs_elm_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
return elm_result_to_dfs(result);
}
static struct dfs_vnode *dfs_elm_lookup(struct dfs_dentry *dentry)
{
struct stat st;
struct dfs_vnode *vnode = RT_NULL;
if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
{
return NULL;
}
if (dfs_elm_stat(dentry, &st) != 0)
{
return vnode;
}
vnode = dfs_vnode_create();
if (vnode)
{
if (S_ISDIR(st.st_mode))
{
vnode->mode = S_IFDIR | (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
vnode->type = FT_DIRECTORY;
}
else
{
vnode->mode = S_IFREG | (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
vnode->type = FT_REGULAR;
}
vnode->mnt = dentry->mnt;
vnode->data = NULL;
vnode->size = 0;
}
return vnode;
}
static struct dfs_vnode *dfs_elm_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode)
{
struct dfs_vnode *vnode = RT_NULL;
if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
{
return NULL;
}
vnode = dfs_vnode_create();
if (vnode)
{
if (type == FT_DIRECTORY)
{
vnode->mode = S_IFDIR | mode;
vnode->type = FT_DIRECTORY;
}
else
{
vnode->mode = S_IFREG | mode;
vnode->type = FT_REGULAR;
}
vnode->mnt = dentry->mnt;
vnode->data = NULL;
vnode->size = 0;
}
return vnode;
}
static int dfs_elm_free_vnode(struct dfs_vnode *vnode)
{
/* nothing to be freed */
if (vnode && vnode->ref_count <= 1)
{
vnode->data = NULL;
}
return 0;
}
static const struct dfs_file_ops dfs_elm_fops =
{
dfs_elm_open,
dfs_elm_close,
dfs_elm_ioctl,
dfs_elm_read,
dfs_elm_write,
dfs_elm_flush,
dfs_elm_lseek,
dfs_elm_getdents,
RT_NULL, /* poll interface */
.open = dfs_elm_open,
.close = dfs_elm_close,
.ioctl = dfs_elm_ioctl,
.read = dfs_elm_read,
.write = dfs_elm_write,
.flush = dfs_elm_flush,
.lseek = dfs_elm_lseek,
.getdents = dfs_elm_getdents,
};
static const struct dfs_filesystem_ops dfs_elm =
{
"elm",
DFS_FS_FLAG_DEFAULT,
FS_NEED_DEVICE,
&dfs_elm_fops,
dfs_elm_mount,
dfs_elm_unmount,
dfs_elm_mkfs,
dfs_elm_statfs,
.mount = dfs_elm_mount,
.umount = dfs_elm_unmount,
.mkfs = dfs_elm_mkfs,
.statfs = dfs_elm_statfs,
dfs_elm_unlink,
dfs_elm_stat,
dfs_elm_rename,
.unlink = dfs_elm_unlink,
.stat = dfs_elm_stat,
.rename = dfs_elm_rename,
.lookup = dfs_elm_lookup,
.create_vnode = dfs_elm_create_vnode,
.free_vnode = dfs_elm_free_vnode
};
static struct dfs_filesystem_type _elmfs =
{
.fs_ops = &dfs_elm,
};
int elm_init(void)
{
/* register fatfs file system */
dfs_register(&dfs_elm);
dfs_register(&_elmfs);
return 0;
}

View File

@ -4077,7 +4077,6 @@ FRESULT f_sync (
DWORD tm;
BYTE *dir;
res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res == FR_OK) {
if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */
@ -4201,7 +4200,6 @@ FRESULT f_chdrive (
}
FRESULT f_chdir (
const TCHAR* path /* Pointer to the directory path */
)
@ -4746,7 +4744,7 @@ FRESULT f_stat (
res = follow_path(&dj, path); /* Follow the file path */
if (res == FR_OK) { /* Follow completed */
if (dj.fn[NSFLAG] & NS_NONAME) { /* It is origin directory */
res = FR_INVALID_NAME;
fno->fattrib = AM_DIR;
} else { /* Found an object */
if (fno) get_fileinfo(&dj, fno);
}

View File

@ -1,13 +0,0 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('rpc/*.c')
CPPPATH = [cwd]
SrcRemove(src, ['rpc/auth_none.c'])
group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_NFS'], CPPPATH = CPPPATH)
Return('group')

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __NFS_H__
#define __NFS_H__
int nfs_init(void);
#endif

View File

@ -1,131 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#ifndef _MOUNT_H_RPCGEN
#define _MOUNT_H_RPCGEN
#include <rpc/rpc.h>
#ifdef __cplusplus
extern "C" {
#endif
/* This file is copied from RFC1813
* Copyright 1995 Sun Micrososystems (I assume)
*/
#define MNTPATHLEN 1024
#define MNTNAMLEN 255
#define FHSIZE3 64
typedef struct {
unsigned int fhandle3_len;
char *fhandle3_val;
} fhandle3;
typedef char *dirpath;
typedef char *name;
typedef struct exportnode *exports;
typedef struct groupnode *groups;
typedef struct mountbody *mountlist;
enum mountstat3 {
MNT3_OK = 0,
MNT3ERR_PERM = 1,
MNT3ERR_NOENT = 2,
MNT3ERR_IO = 5,
MNT3ERR_ACCES = 13,
MNT3ERR_NOTDIR = 20,
MNT3ERR_INVAL = 22,
MNT3ERR_NAMETOOLONG = 63,
MNT3ERR_NOTSUPP = 10004,
MNT3ERR_SERVERFAULT = 10006
};
typedef enum mountstat3 mountstat3;
struct mountres3_ok {
fhandle3 fhandle;
struct {
unsigned int auth_flavors_len;
int *auth_flavors_val;
} auth_flavors;
};
typedef struct mountres3_ok mountres3_ok;
struct mountres3 {
mountstat3 fhs_status;
union {
mountres3_ok mountinfo;
} mountres3_u;
};
typedef struct mountres3 mountres3;
struct mountbody {
name ml_hostname;
dirpath ml_directory;
mountlist ml_next;
};
typedef struct mountbody mountbody;
struct groupnode {
name gr_name;
groups gr_next;
};
typedef struct groupnode groupnode;
struct exportnode {
dirpath ex_dir;
groups ex_groups;
exports ex_next;
};
typedef struct exportnode exportnode;
#define MOUNT_PROGRAM 100005
#define MOUNT_V3 3
#define MOUNTPROC3_NULL 0
extern enum clnt_stat mountproc3_null_3(void *, CLIENT *);
#define MOUNTPROC3_MNT 1
extern enum clnt_stat mountproc3_mnt_3(dirpath , mountres3 *, CLIENT *);
#define MOUNTPROC3_DUMP 2
extern enum clnt_stat mountproc3_dump_3(mountlist *, CLIENT *);
#define MOUNTPROC3_UMNT 3
extern enum clnt_stat mountproc3_umnt_3(dirpath , void *, CLIENT *);
#define MOUNTPROC3_UMNTALL 4
extern enum clnt_stat mountproc3_umntall_3(void *, CLIENT *);
#define MOUNTPROC3_EXPORT 5
extern enum clnt_stat mountproc3_export_3(exports *, CLIENT *);
/* the xdr functions */
extern bool_t xdr_fhandle3(XDR *, fhandle3*);
extern bool_t xdr_dirpath(XDR *, dirpath*);
extern bool_t xdr_name(XDR *, name*);
extern bool_t xdr_exports(XDR *, exports*);
extern bool_t xdr_groups(XDR *, groups*);
extern bool_t xdr_mountlist(XDR *, mountlist*);
extern bool_t xdr_mountstat3(XDR *, mountstat3*);
extern bool_t xdr_mountres3_ok(XDR *, mountres3_ok*);
extern bool_t xdr_mountres3(XDR *, mountres3*);
extern bool_t xdr_mountbody(XDR *, mountbody*);
extern bool_t xdr_groupnode(XDR *, groupnode*);
extern bool_t xdr_exportnode(XDR *, exportnode*);
#ifdef __cplusplus
}
#endif
#endif /* !_MOUNT_H_RPCGEN */

View File

@ -1,68 +0,0 @@
%/* This file is copied from RFC1813
% * Copyright 1995 Sun Micrososystems (I assume)
% */
const MNTPATHLEN = 1024; /* Maximum bytes in a path name */
const MNTNAMLEN = 255; /* Maximum bytes in a name */
const FHSIZE3 = 64; /* Maximum bytes in a V3 file handle */
typedef opaque fhandle3<FHSIZE3>;
typedef string dirpath<MNTPATHLEN>;
typedef string name<MNTNAMLEN>;
typedef struct exportnode *exports;
typedef struct groupnode *groups;
typedef struct mountbody *mountlist;
enum mountstat3 {
MNT3_OK = 0, /* no error */
MNT3ERR_PERM = 1, /* Not owner */
MNT3ERR_NOENT = 2, /* No such file or directory */
MNT3ERR_IO = 5, /* I/O error */
MNT3ERR_ACCES = 13, /* Permission denied */
MNT3ERR_NOTDIR = 20, /* Not a directory */
MNT3ERR_INVAL = 22, /* Invalid argument */
MNT3ERR_NAMETOOLONG = 63, /* Filename too long */
MNT3ERR_NOTSUPP = 10004, /* Operation not supported */
MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */
};
struct mountres3_ok {
fhandle3 fhandle;
int auth_flavors<>;
};
union mountres3 switch (mountstat3 fhs_status) {
case MNT3_OK:
mountres3_ok mountinfo;
default:
void;
};
struct mountbody {
name ml_hostname;
dirpath ml_directory;
mountlist ml_next;
};
struct groupnode {
name gr_name;
groups gr_next;
};
struct exportnode {
dirpath ex_dir;
groups ex_groups;
exports ex_next;
};
program MOUNT_PROGRAM {
version MOUNT_V3 {
void MOUNTPROC3_NULL(void) = 0;
mountres3 MOUNTPROC3_MNT(dirpath) = 1;
mountlist MOUNTPROC3_DUMP(void) = 2;
void MOUNTPROC3_UMNT(dirpath) = 3;
void MOUNTPROC3_UMNTALL(void) = 4;
exports MOUNTPROC3_EXPORT(void) = 5;
} = 3;
} = 100005;

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include <string.h> /* for memset */
#include "mount.h"
/* This file is copied from RFC1813
* Copyright 1995 Sun Micrososystems (I assume)
*/
typedef char* caddr_t;
/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 25, 0 };
enum clnt_stat
mountproc3_null_3(void *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, MOUNTPROC3_NULL,
(xdrproc_t) xdr_void, (caddr_t) NULL,
(xdrproc_t) xdr_void, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
mountproc3_mnt_3(dirpath arg1, mountres3 *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, MOUNTPROC3_MNT,
(xdrproc_t) xdr_dirpath, (caddr_t) &arg1,
(xdrproc_t) xdr_mountres3, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
mountproc3_dump_3(mountlist *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, MOUNTPROC3_DUMP,
(xdrproc_t) xdr_void, (caddr_t) NULL,
(xdrproc_t) xdr_mountlist, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
mountproc3_umnt_3(dirpath arg1, void *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, MOUNTPROC3_UMNT,
(xdrproc_t) xdr_dirpath, (caddr_t) &arg1,
(xdrproc_t) xdr_void, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
mountproc3_umntall_3(void *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, MOUNTPROC3_UMNTALL,
(xdrproc_t) xdr_void, (caddr_t) NULL,
(xdrproc_t) xdr_void, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
mountproc3_export_3(exports *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, MOUNTPROC3_EXPORT,
(xdrproc_t) xdr_void, (caddr_t) NULL,
(xdrproc_t) xdr_exports, (caddr_t) clnt_res,
TIMEOUT));
}

View File

@ -1,142 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include "mount.h"
/* This file is copied from RFC1813
* Copyright 1995 Sun Micrososystems (I assume)
*/
bool_t
xdr_fhandle3(register XDR *xdrs, fhandle3 *objp)
{
if (!xdr_bytes(xdrs, (char **)&objp->fhandle3_val, (unsigned int *) &objp->fhandle3_len, FHSIZE3))
return (FALSE);
return (TRUE);
}
bool_t
xdr_dirpath(register XDR *xdrs, dirpath *objp)
{
if (!xdr_string(xdrs, objp, MNTPATHLEN))
return (FALSE);
return (TRUE);
}
bool_t
xdr_name(register XDR *xdrs, name *objp)
{
if (!xdr_string(xdrs, objp, MNTNAMLEN))
return (FALSE);
return (TRUE);
}
bool_t
xdr_exports(register XDR *xdrs, exports *objp)
{
if (!xdr_pointer(xdrs, (char **)objp, sizeof (struct exportnode), (xdrproc_t) xdr_exportnode))
return (FALSE);
return (TRUE);
}
bool_t
xdr_groups(register XDR *xdrs, groups *objp)
{
if (!xdr_pointer(xdrs, (char **)objp, sizeof (struct groupnode), (xdrproc_t) xdr_groupnode))
return (FALSE);
return (TRUE);
}
bool_t
xdr_mountlist(register XDR *xdrs, mountlist *objp)
{
if (!xdr_pointer(xdrs, (char **)objp, sizeof (struct mountbody), (xdrproc_t) xdr_mountbody))
return (FALSE);
return (TRUE);
}
bool_t
xdr_mountstat3(register XDR *xdrs, mountstat3 *objp)
{
int enum_objp;
enum_objp = *objp;
if (!xdr_enum(xdrs, (enum_t *)&enum_objp))
{
*objp = (mountstat3)enum_objp;
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_mountres3_ok(register XDR *xdrs, mountres3_ok *objp)
{
if (!xdr_fhandle3(xdrs, &objp->fhandle))
return (FALSE);
if (!xdr_array(xdrs, (char **)&objp->auth_flavors.auth_flavors_val, (unsigned int *) &objp->auth_flavors.auth_flavors_len, ~0,
sizeof (int), (xdrproc_t) xdr_int))
return (FALSE);
return (TRUE);
}
bool_t
xdr_mountres3(register XDR *xdrs, mountres3 *objp)
{
if (!xdr_mountstat3(xdrs, &objp->fhs_status))
return (FALSE);
switch (objp->fhs_status) {
case MNT3_OK:
if (!xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo))
return (FALSE);
break;
default :
return (FALSE);
}
return (TRUE);
}
bool_t
xdr_mountbody(register XDR *xdrs, mountbody *objp)
{
if (!xdr_name(xdrs, &objp->ml_hostname))
return (FALSE);
if (!xdr_dirpath(xdrs, &objp->ml_directory))
return (FALSE);
if (!xdr_mountlist(xdrs, &objp->ml_next))
return (FALSE);
return (TRUE);
}
bool_t
xdr_groupnode(register XDR *xdrs, groupnode *objp)
{
if (!xdr_name(xdrs, &objp->gr_name))
return (FALSE);
if (!xdr_groups(xdrs, &objp->gr_next))
return (FALSE);
return (TRUE);
}
bool_t
xdr_exportnode(register XDR *xdrs, exportnode *objp)
{
if (!xdr_dirpath(xdrs, &objp->ex_dir))
return (FALSE);
if (!xdr_groups(xdrs, &objp->ex_groups))
return (FALSE);
if (!xdr_exports(xdrs, &objp->ex_next))
return (FALSE);
return (TRUE);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,774 +0,0 @@
%/* This file is copied from RFC1813
% * Copyright 1995 Sun Micrososystems (I assume)
% */
const NFS3_FHSIZE = 64;
const NFS3_COOKIEVERFSIZE = 8;
const NFS3_CREATEVERFSIZE = 8;
const NFS3_WRITEVERFSIZE = 8;
const ACCESS3_READ = 0x0001;
const ACCESS3_LOOKUP = 0x0002;
const ACCESS3_MODIFY = 0x0004;
const ACCESS3_EXTEND = 0x0008;
const ACCESS3_DELETE = 0x0010;
const ACCESS3_EXECUTE = 0x0020;
const FSF3_LINK = 0x0001;
const FSF3_SYMLINK = 0x0002;
const FSF3_HOMOGENEOUS = 0x0008;
const FSF3_CANSETTIME = 0x0010;
typedef unsigned hyper uint64;
typedef hyper int64;
typedef unsigned long uint32;
typedef long int32;
typedef string filename3<>;
typedef string nfspath3<>;
typedef uint64 fileid3;
typedef uint64 cookie3;
typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
typedef opaque createverf3[NFS3_CREATEVERFSIZE];
typedef opaque writeverf3[NFS3_WRITEVERFSIZE];
typedef uint32 uid3;
typedef uint32 gid3;
typedef uint64 size3;
typedef uint64 offset3;
typedef uint32 mode3;
typedef uint32 count3;
enum nfsstat3 {
NFS3_OK = 0,
NFS3ERR_PERM = 1,
NFS3ERR_NOENT = 2,
NFS3ERR_IO = 5,
NFS3ERR_NXIO = 6,
NFS3ERR_ACCES = 13,
NFS3ERR_EXIST = 17,
NFS3ERR_XDEV = 18,
NFS3ERR_NODEV = 19,
NFS3ERR_NOTDIR = 20,
NFS3ERR_ISDIR = 21,
NFS3ERR_INVAL = 22,
NFS3ERR_FBIG = 27,
NFS3ERR_NOSPC = 28,
NFS3ERR_ROFS = 30,
NFS3ERR_MLINK = 31,
NFS3ERR_NAMETOOLONG = 63,
NFS3ERR_NOTEMPTY = 66,
NFS3ERR_DQUOT = 69,
NFS3ERR_STALE = 70,
NFS3ERR_REMOTE = 71,
NFS3ERR_BADHANDLE = 10001,
NFS3ERR_NOT_SYNC = 10002,
NFS3ERR_BAD_COOKIE = 10003,
NFS3ERR_NOTSUPP = 10004,
NFS3ERR_TOOSMALL = 10005,
NFS3ERR_SERVERFAULT = 10006,
NFS3ERR_BADTYPE = 10007,
NFS3ERR_JUKEBOX = 10008
};
enum ftype3 {
NFS3REG = 1,
NFS3DIR = 2,
NFS3BLK = 3,
NFS3CHR = 4,
NFS3LNK = 5,
NFS3SOCK = 6,
NFS3FIFO = 7
};
enum stable_how {
UNSTABLE = 0,
DATA_SYNC = 1,
FILE_SYNC = 2
};
enum createmode3 {
UNCHECKED = 0,
GUARDED = 1,
EXCLUSIVE = 2
};
struct specdata3 {
uint32 specdata1;
uint32 specdata2;
};
struct nfs_fh3 {
opaque data<NFS3_FHSIZE>;
};
struct nfstime3 {
uint32 seconds;
uint32 nseconds;
};
struct fattr3 {
ftype3 type;
mode3 mode;
uint32 nlink;
uid3 uid;
gid3 gid;
size3 size;
size3 used;
specdata3 rdev;
uint64 fsid;
fileid3 fileid;
nfstime3 atime;
nfstime3 mtime;
nfstime3 ctime;
};
union post_op_attr switch (bool attributes_follow) {
case TRUE:
fattr3 attributes;
case FALSE:
void;
};
struct wcc_attr {
size3 size;
nfstime3 mtime;
nfstime3 ctime;
};
union pre_op_attr switch (bool attributes_follow) {
case TRUE:
wcc_attr attributes;
case FALSE:
void;
};
struct wcc_data {
pre_op_attr before;
post_op_attr after;
};
union post_op_fh3 switch (bool handle_follows) {
case TRUE:
nfs_fh3 handle;
case FALSE:
void;
};
enum time_how {
DONT_CHANGE = 0,
SET_TO_SERVER_TIME = 1,
SET_TO_CLIENT_TIME = 2
};
union set_mode3 switch (bool set_it) {
case TRUE:
mode3 mode;
default:
void;
};
union set_uid3 switch (bool set_it) {
case TRUE:
uid3 uid;
default:
void;
};
union set_gid3 switch (bool set_it) {
case TRUE:
gid3 gid;
default:
void;
};
union set_size3 switch (bool set_it) {
case TRUE:
size3 size;
default:
void;
};
union set_atime switch (time_how set_it) {
case SET_TO_CLIENT_TIME:
nfstime3 atime;
default:
void;
};
union set_mtime switch (time_how set_it) {
case SET_TO_CLIENT_TIME:
nfstime3 mtime;
default:
void;
};
struct sattr3 {
set_mode3 mode;
set_uid3 uid;
set_gid3 gid;
set_size3 size;
set_atime atime;
set_mtime mtime;
};
struct diropargs3 {
nfs_fh3 dir;
filename3 name;
};
struct GETATTR3args {
nfs_fh3 object;
};
struct GETATTR3resok {
fattr3 obj_attributes;
};
union GETATTR3res switch (nfsstat3 status) {
case NFS3_OK:
GETATTR3resok resok;
default:
void;
};
union sattrguard3 switch (bool check) {
case TRUE:
nfstime3 obj_ctime;
case FALSE:
void;
};
struct SETATTR3args {
nfs_fh3 object;
sattr3 new_attributes;
sattrguard3 guard;
};
struct SETATTR3resok {
wcc_data obj_wcc;
};
struct SETATTR3resfail {
wcc_data obj_wcc;
};
union SETATTR3res switch (nfsstat3 status) {
case NFS3_OK:
SETATTR3resok resok;
default:
SETATTR3resfail resfail;
};
struct LOOKUP3args {
diropargs3 what;
};
struct LOOKUP3resok {
nfs_fh3 object;
post_op_attr obj_attributes;
post_op_attr dir_attributes;
};
struct LOOKUP3resfail {
post_op_attr dir_attributes;
};
union LOOKUP3res switch (nfsstat3 status) {
case NFS3_OK:
LOOKUP3resok resok;
default:
LOOKUP3resfail resfail;
};
struct ACCESS3args {
nfs_fh3 object;
uint32 access;
};
struct ACCESS3resok {
post_op_attr obj_attributes;
uint32 access;
};
struct ACCESS3resfail {
post_op_attr obj_attributes;
};
union ACCESS3res switch (nfsstat3 status) {
case NFS3_OK:
ACCESS3resok resok;
default:
ACCESS3resfail resfail;
};
struct READLINK3args {
nfs_fh3 symlink;
};
struct READLINK3resok {
post_op_attr symlink_attributes;
nfspath3 data;
};
struct READLINK3resfail {
post_op_attr symlink_attributes;
};
union READLINK3res switch (nfsstat3 status) {
case NFS3_OK:
READLINK3resok resok;
default:
READLINK3resfail resfail;
};
struct READ3args {
nfs_fh3 file;
offset3 offset;
count3 count;
};
struct READ3resok {
post_op_attr file_attributes;
count3 count;
bool eof;
opaque data<>;
};
struct READ3resfail {
post_op_attr file_attributes;
};
union READ3res switch (nfsstat3 status) {
case NFS3_OK:
READ3resok resok;
default:
READ3resfail resfail;
};
struct WRITE3args {
nfs_fh3 file;
offset3 offset;
count3 count;
stable_how stable;
opaque data<>;
};
struct WRITE3resok {
wcc_data file_wcc;
count3 count;
stable_how committed;
writeverf3 verf;
};
struct WRITE3resfail {
wcc_data file_wcc;
};
union WRITE3res switch (nfsstat3 status) {
case NFS3_OK:
WRITE3resok resok;
default:
WRITE3resfail resfail;
};
union createhow3 switch (createmode3 mode) {
case UNCHECKED:
case GUARDED:
sattr3 obj_attributes;
case EXCLUSIVE:
createverf3 verf;
};
struct CREATE3args {
diropargs3 where;
createhow3 how;
};
struct CREATE3resok {
post_op_fh3 obj;
post_op_attr obj_attributes;
wcc_data dir_wcc;
};
struct CREATE3resfail {
wcc_data dir_wcc;
};
union CREATE3res switch (nfsstat3 status) {
case NFS3_OK:
CREATE3resok resok;
default:
CREATE3resfail resfail;
};
struct MKDIR3args {
diropargs3 where;
sattr3 attributes;
};
struct MKDIR3resok {
post_op_fh3 obj;
post_op_attr obj_attributes;
wcc_data dir_wcc;
};
struct MKDIR3resfail {
wcc_data dir_wcc;
};
union MKDIR3res switch (nfsstat3 status) {
case NFS3_OK:
MKDIR3resok resok;
default:
MKDIR3resfail resfail;
};
struct symlinkdata3 {
sattr3 symlink_attributes;
nfspath3 symlink_data;
};
struct SYMLINK3args {
diropargs3 where;
symlinkdata3 symlink;
};
struct SYMLINK3resok {
post_op_fh3 obj;
post_op_attr obj_attributes;
wcc_data dir_wcc;
};
struct SYMLINK3resfail {
wcc_data dir_wcc;
};
union SYMLINK3res switch (nfsstat3 status) {
case NFS3_OK:
SYMLINK3resok resok;
default:
SYMLINK3resfail resfail;
};
struct devicedata3 {
sattr3 dev_attributes;
specdata3 spec;
};
union mknoddata3 switch (ftype3 type) {
case NFS3CHR:
case NFS3BLK:
devicedata3 device;
case NFS3SOCK:
case NFS3FIFO:
sattr3 pipe_attributes;
default:
void;
};
struct MKNOD3args {
diropargs3 where;
mknoddata3 what;
};
struct MKNOD3resok {
post_op_fh3 obj;
post_op_attr obj_attributes;
wcc_data dir_wcc;
};
struct MKNOD3resfail {
wcc_data dir_wcc;
};
union MKNOD3res switch (nfsstat3 status) {
case NFS3_OK:
MKNOD3resok resok;
default:
MKNOD3resfail resfail;
};
struct REMOVE3args {
diropargs3 object;
};
struct REMOVE3resok {
wcc_data dir_wcc;
};
struct REMOVE3resfail {
wcc_data dir_wcc;
};
union REMOVE3res switch (nfsstat3 status) {
case NFS3_OK:
REMOVE3resok resok;
default:
REMOVE3resfail resfail;
};
struct RMDIR3args {
diropargs3 object;
};
struct RMDIR3resok {
wcc_data dir_wcc;
};
struct RMDIR3resfail {
wcc_data dir_wcc;
};
union RMDIR3res switch (nfsstat3 status) {
case NFS3_OK:
RMDIR3resok resok;
default:
RMDIR3resfail resfail;
};
struct RENAME3args {
diropargs3 from;
diropargs3 to;
};
struct RENAME3resok {
wcc_data fromdir_wcc;
wcc_data todir_wcc;
};
struct RENAME3resfail {
wcc_data fromdir_wcc;
wcc_data todir_wcc;
};
union RENAME3res switch (nfsstat3 status) {
case NFS3_OK:
RENAME3resok resok;
default:
RENAME3resfail resfail;
};
struct LINK3args {
nfs_fh3 file;
diropargs3 link;
};
struct LINK3resok {
post_op_attr file_attributes;
wcc_data linkdir_wcc;
};
struct LINK3resfail {
post_op_attr file_attributes;
wcc_data linkdir_wcc;
};
union LINK3res switch (nfsstat3 status) {
case NFS3_OK:
LINK3resok resok;
default:
LINK3resfail resfail;
};
struct READDIR3args {
nfs_fh3 dir;
cookie3 cookie;
cookieverf3 cookieverf;
count3 count;
};
struct entry3 {
fileid3 fileid;
filename3 name;
cookie3 cookie;
entry3 *nextentry;
};
struct dirlist3 {
entry3 *entries;
bool eof;
};
struct READDIR3resok {
post_op_attr dir_attributes;
cookieverf3 cookieverf;
dirlist3 reply;
};
struct READDIR3resfail {
post_op_attr dir_attributes;
};
union READDIR3res switch (nfsstat3 status) {
case NFS3_OK:
READDIR3resok resok;
default:
READDIR3resfail resfail;
};
struct READDIRPLUS3args {
nfs_fh3 dir;
cookie3 cookie;
cookieverf3 cookieverf;
count3 dircount;
count3 maxcount;
};
struct entryplus3 {
fileid3 fileid;
filename3 name;
cookie3 cookie;
post_op_attr name_attributes;
post_op_fh3 name_handle;
entryplus3 *nextentry;
};
struct dirlistplus3 {
entryplus3 *entries;
bool eof;
};
struct READDIRPLUS3resok {
post_op_attr dir_attributes;
cookieverf3 cookieverf;
dirlistplus3 reply;
};
struct READDIRPLUS3resfail {
post_op_attr dir_attributes;
};
union READDIRPLUS3res switch (nfsstat3 status) {
case NFS3_OK:
READDIRPLUS3resok resok;
default:
READDIRPLUS3resfail resfail;
};
struct FSSTAT3args {
nfs_fh3 fsroot;
};
struct FSSTAT3resok {
post_op_attr obj_attributes;
size3 tbytes;
size3 fbytes;
size3 abytes;
size3 tfiles;
size3 ffiles;
size3 afiles;
uint32 invarsec;
};
struct FSSTAT3resfail {
post_op_attr obj_attributes;
};
union FSSTAT3res switch (nfsstat3 status) {
case NFS3_OK:
FSSTAT3resok resok;
default:
FSSTAT3resfail resfail;
};
struct FSINFO3args {
nfs_fh3 fsroot;
};
struct FSINFO3resok {
post_op_attr obj_attributes;
uint32 rtmax;
uint32 rtpref;
uint32 rtmult;
uint32 wtmax;
uint32 wtpref;
uint32 wtmult;
uint32 dtpref;
size3 maxfilesize;
nfstime3 time_delta;
uint32 properties;
};
struct FSINFO3resfail {
post_op_attr obj_attributes;
};
union FSINFO3res switch (nfsstat3 status) {
case NFS3_OK:
FSINFO3resok resok;
default:
FSINFO3resfail resfail;
};
struct PATHCONF3args {
nfs_fh3 object;
};
struct PATHCONF3resok {
post_op_attr obj_attributes;
uint32 linkmax;
uint32 name_max;
bool no_trunc;
bool chown_restricted;
bool case_insensitive;
bool case_preserving;
};
struct PATHCONF3resfail {
post_op_attr obj_attributes;
};
union PATHCONF3res switch (nfsstat3 status) {
case NFS3_OK:
PATHCONF3resok resok;
default:
PATHCONF3resfail resfail;
};
struct COMMIT3args {
nfs_fh3 file;
offset3 offset;
count3 count;
};
struct COMMIT3resok {
wcc_data file_wcc;
writeverf3 verf;
};
struct COMMIT3resfail {
wcc_data file_wcc;
};
union COMMIT3res switch (nfsstat3 status) {
case NFS3_OK:
COMMIT3resok resok;
default:
COMMIT3resfail resfail;
};
program NFS_PROGRAM {
version NFS_V3 {
void NFSPROC3_NULL(void) = 0;
GETATTR3res NFSPROC3_GETATTR(GETATTR3args) = 1;
SETATTR3res NFSPROC3_SETATTR(SETATTR3args) = 2;
LOOKUP3res NFSPROC3_LOOKUP(LOOKUP3args) = 3;
ACCESS3res NFSPROC3_ACCESS(ACCESS3args) = 4;
READLINK3res NFSPROC3_READLINK(READLINK3args) = 5;
READ3res NFSPROC3_READ(READ3args) = 6;
WRITE3res NFSPROC3_WRITE(WRITE3args) = 7;
CREATE3res NFSPROC3_CREATE(CREATE3args) = 8;
MKDIR3res NFSPROC3_MKDIR(MKDIR3args) = 9;
SYMLINK3res NFSPROC3_SYMLINK(SYMLINK3args) = 10;
MKNOD3res NFSPROC3_MKNOD(MKNOD3args) = 11;
REMOVE3res NFSPROC3_REMOVE(REMOVE3args) = 12;
RMDIR3res NFSPROC3_RMDIR(RMDIR3args) = 13;
RENAME3res NFSPROC3_RENAME(RENAME3args) = 14;
LINK3res NFSPROC3_LINK(LINK3args) = 15;
READDIR3res NFSPROC3_READDIR(READDIR3args) = 16;
READDIRPLUS3res NFSPROC3_READDIRPLUS(READDIRPLUS3args) = 17;
FSSTAT3res NFSPROC3_FSSTAT(FSSTAT3args) = 18;
FSINFO3res NFSPROC3_FSINFO(FSINFO3args) = 19;
PATHCONF3res NFSPROC3_PATHCONF(PATHCONF3args) = 20;
COMMIT3res NFSPROC3_COMMIT(COMMIT3args) = 21;
} = 3;
} = 100003;

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#define MAX_MARSHEL_SIZE 64
struct nfs_credentia
{
rt_uint32_t stamp;
char *name;
rt_uint32_t uid;
rt_uint32_t gid;
rt_uint32_t *auxi;
rt_uint32_t auxi_count;
};
static void authnone_verf(AUTH *);
static bool_t authnone_validate(AUTH *, struct opaque_auth *);
static bool_t authnone_refresh(AUTH *);
static void authnone_destroy(AUTH *);
static bool_t authnone_marshal(AUTH *client, XDR *xdrs);
static struct nfs_credentia _credentia = {
.stamp = 0,
.name = "rt-thread",
.uid = 0,
.gid = 0,
.auxi = NULL,
.auxi_count = 0,
};
struct opaque_auth _null_auth;
static struct auth_ops ops =
{
authnone_verf,
authnone_marshal,
authnone_validate,
authnone_refresh,
authnone_destroy
};
static struct authnone_private
{
AUTH no_client;
char marshalled_client[MAX_MARSHEL_SIZE];
unsigned int mcnt;
} *authnone_private;
AUTH *authnone_create(void)
{
register struct authnone_private *ap = authnone_private;
XDR xdr_stream;
register XDR *xdrs;
extern bool_t xdr_opaque_auth(XDR * xdrs, struct opaque_auth * ap);
struct opaque_auth auth;
rt_uint32_t *auth_buf, *auth_base;
int buf_len = 0, str_len = 0;
if (_credentia.name)
{
str_len = strlen(_credentia.name);
}
if (str_len == 0)
{
_credentia.name = "unknown";
str_len = strlen(_credentia.name);
}
buf_len = ((str_len) + (sizeof(rt_uint32_t)) - 1) & ~((sizeof(rt_uint32_t)) - 1);
buf_len += sizeof(struct nfs_credentia);
if (_credentia.auxi && _credentia.auxi_count)
{
buf_len += sizeof(rt_uint32_t) * _credentia.auxi_count;
}
auth_buf = auth_base = rt_malloc(buf_len);
if (auth_buf == NULL)
{
return NULL;
}
memset(auth_buf, 0, buf_len);
*auth_buf++ = htonl(rt_tick_get());
*auth_buf++ = htonl(str_len);
memcpy(auth_buf, _credentia.name, str_len);
auth_buf += (str_len + sizeof(rt_uint32_t) - 1) >> 2;
*auth_buf++ = htonl(_credentia.uid);
*auth_buf++ = htonl(_credentia.gid);
if (_credentia.auxi && _credentia.auxi_count)
{
rt_uint32_t tmp_cnt = 0;
*auth_buf++ = htonl(_credentia.auxi_count);
while (tmp_cnt < _credentia.auxi_count)
{
*auth_buf++ = htonl(_credentia.auxi[tmp_cnt]);
}
}
else
{
*auth_buf++ = htonl(0);
}
if (ap == 0)
{
ap = (struct authnone_private *) rt_malloc(sizeof(*ap));
if (ap == 0)
{
rt_free(auth_base);
return NULL;
}
memset(ap, 0, sizeof(*ap));
authnone_private = ap;
}
if (!ap->mcnt)
{
memset(&auth, 0, sizeof(auth));
auth.oa_flavor = 1;
auth.oa_base = (char *)auth_base;
auth.oa_length = (auth_buf - auth_base) * sizeof(rt_uint32_t);
ap->no_client.ah_cred = auth;
ap->no_client.ah_verf = _null_auth;
ap->no_client.ah_ops = &ops;
xdrs = &xdr_stream;
xdrmem_create(xdrs, ap->marshalled_client,
(unsigned int) MAX_MARSHEL_SIZE, XDR_ENCODE);
(void) xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
(void) xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
ap->mcnt = XDR_GETPOS(xdrs);
XDR_DESTROY(xdrs);
}
rt_free(auth_base);
return (&ap->no_client);
}
/*ARGSUSED*/
static bool_t authnone_marshal(AUTH *client, XDR *xdrs)
{
register struct authnone_private *ap = authnone_private;
if (ap == 0)
return (0);
return ((*xdrs->x_ops->x_putbytes)(xdrs,
ap->marshalled_client, ap->mcnt));
}
static void authnone_verf(AUTH *x)
{
}
static bool_t authnone_validate(AUTH *x, struct opaque_auth *x1)
{
return (TRUE);
}
static bool_t authnone_refresh(AUTH *x)
{
return (FALSE);
}
static void authnone_destroy(AUTH *x)
{
}

View File

@ -1,222 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#include <string.h> /* for memset */
#include "nfs.h"
/* This file is copied from RFC1813
* Copyright 1995 Sun Micrososystems (I assume)
*/
typedef char* caddr_t;
/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 25, 0 };
enum clnt_stat
nfsproc3_null_3(void *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_NULL,
(xdrproc_t) xdr_void, (caddr_t) NULL,
(xdrproc_t) xdr_void, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_getattr_3(GETATTR3args arg1, GETATTR3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_GETATTR,
(xdrproc_t) xdr_GETATTR3args, (caddr_t) &arg1,
(xdrproc_t) xdr_GETATTR3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_setattr_3(SETATTR3args arg1, SETATTR3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_SETATTR,
(xdrproc_t) xdr_SETATTR3args, (caddr_t) &arg1,
(xdrproc_t) xdr_SETATTR3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_lookup_3(LOOKUP3args arg1, LOOKUP3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_LOOKUP,
(xdrproc_t) xdr_LOOKUP3args, (caddr_t) &arg1,
(xdrproc_t) xdr_LOOKUP3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_access_3(ACCESS3args arg1, ACCESS3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_ACCESS,
(xdrproc_t) xdr_ACCESS3args, (caddr_t) &arg1,
(xdrproc_t) xdr_ACCESS3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_readlink_3(READLINK3args arg1, READLINK3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_READLINK,
(xdrproc_t) xdr_READLINK3args, (caddr_t) &arg1,
(xdrproc_t) xdr_READLINK3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_read_3(READ3args arg1, READ3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_READ,
(xdrproc_t) xdr_READ3args, (caddr_t) &arg1,
(xdrproc_t) xdr_READ3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_write_3(WRITE3args arg1, WRITE3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_WRITE,
(xdrproc_t) xdr_WRITE3args, (caddr_t) &arg1,
(xdrproc_t) xdr_WRITE3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_create_3(CREATE3args arg1, CREATE3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_CREATE,
(xdrproc_t) xdr_CREATE3args, (caddr_t) &arg1,
(xdrproc_t) xdr_CREATE3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_mkdir_3(MKDIR3args arg1, MKDIR3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_MKDIR,
(xdrproc_t) xdr_MKDIR3args, (caddr_t) &arg1,
(xdrproc_t) xdr_MKDIR3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_symlink_3(SYMLINK3args arg1, SYMLINK3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_SYMLINK,
(xdrproc_t) xdr_SYMLINK3args, (caddr_t) &arg1,
(xdrproc_t) xdr_SYMLINK3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_mknod_3(MKNOD3args arg1, MKNOD3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_MKNOD,
(xdrproc_t) xdr_MKNOD3args, (caddr_t) &arg1,
(xdrproc_t) xdr_MKNOD3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_remove_3(REMOVE3args arg1, REMOVE3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_REMOVE,
(xdrproc_t) xdr_REMOVE3args, (caddr_t) &arg1,
(xdrproc_t) xdr_REMOVE3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_rmdir_3(RMDIR3args arg1, RMDIR3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_RMDIR,
(xdrproc_t) xdr_RMDIR3args, (caddr_t) &arg1,
(xdrproc_t) xdr_RMDIR3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_rename_3(RENAME3args arg1, RENAME3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_RENAME,
(xdrproc_t) xdr_RENAME3args, (caddr_t) &arg1,
(xdrproc_t) xdr_RENAME3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_link_3(LINK3args arg1, LINK3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_LINK,
(xdrproc_t) xdr_LINK3args, (caddr_t) &arg1,
(xdrproc_t) xdr_LINK3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_readdir_3(READDIR3args arg1, READDIR3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_READDIR,
(xdrproc_t) xdr_READDIR3args, (caddr_t) &arg1,
(xdrproc_t) xdr_READDIR3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_readdirplus_3(READDIRPLUS3args arg1, READDIRPLUS3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_READDIRPLUS,
(xdrproc_t) xdr_READDIRPLUS3args, (caddr_t) &arg1,
(xdrproc_t) xdr_READDIRPLUS3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_fsstat_3(FSSTAT3args arg1, FSSTAT3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_FSSTAT,
(xdrproc_t) xdr_FSSTAT3args, (caddr_t) &arg1,
(xdrproc_t) xdr_FSSTAT3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_fsinfo_3(FSINFO3args arg1, FSINFO3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_FSINFO,
(xdrproc_t) xdr_FSINFO3args, (caddr_t) &arg1,
(xdrproc_t) xdr_FSINFO3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_pathconf_3(PATHCONF3args arg1, PATHCONF3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_PATHCONF,
(xdrproc_t) xdr_PATHCONF3args, (caddr_t) &arg1,
(xdrproc_t) xdr_PATHCONF3res, (caddr_t) clnt_res,
TIMEOUT));
}
enum clnt_stat
nfsproc3_commit_3(COMMIT3args arg1, COMMIT3res *clnt_res, CLIENT *clnt)
{
return (clnt_call(clnt, NFSPROC3_COMMIT,
(xdrproc_t) xdr_COMMIT3args, (caddr_t) &arg1,
(xdrproc_t) xdr_COMMIT3res, (caddr_t) clnt_res,
TIMEOUT));
}

File diff suppressed because it is too large Load Diff

View File

@ -1,112 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __AUTH_H__
#define __AUTH_H__
#include <rpc/xdr.h>
/*
* Status returned from authentication check
*/
enum auth_stat {
AUTH_OK=0,
/*
* failed at remote end
*/
AUTH_BADCRED=1, /* bogus credentials (seal broken) */
AUTH_REJECTEDCRED=2, /* client should begin new session */
AUTH_BADVERF=3, /* bogus verifier (seal broken) */
AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */
AUTH_TOOWEAK=5, /* rejected due to security reasons */
/*
* failed locally
*/
AUTH_INVALIDRESP=6, /* bogus response verifier */
AUTH_FAILED=7 /* some unknown reason */
};
union des_block {
struct {
uint32_t high;
uint32_t low;
} key;
char c[8];
};
typedef union des_block des_block;
/*
* Authentication info. Opaque to client.
*/
struct opaque_auth {
enum_t oa_flavor; /* flavor of auth */
char* oa_base; /* address of more auth stuff */
unsigned int oa_length; /* not to exceed MAX_AUTH_BYTES */
};
/*
* Auth handle, interface to client side authenticators.
*/
typedef struct AUTH AUTH;
struct AUTH {
struct opaque_auth ah_cred;
struct opaque_auth ah_verf;
union des_block ah_key;
struct auth_ops {
void (*ah_nextverf) (AUTH *);
int (*ah_marshal) (AUTH *, XDR *); /* nextverf & serialize */
int (*ah_validate) (AUTH *, struct opaque_auth *);
/* validate verifier */
int (*ah_refresh) (AUTH *); /* refresh credentials */
void (*ah_destroy) (AUTH *); /* destroy this structure */
} *ah_ops;
char* ah_private;
};
extern struct opaque_auth _null_auth;
/*
* Authentication ops.
* The ops and the auth handle provide the interface to the authenticators.
*
* AUTH *auth;
* XDR *xdrs;
* struct opaque_auth verf;
*/
#define AUTH_NEXTVERF(auth) \
((*((auth)->ah_ops->ah_nextverf))(auth))
#define auth_nextverf(auth) \
((*((auth)->ah_ops->ah_nextverf))(auth))
#define AUTH_MARSHALL(auth, xdrs) \
((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
#define auth_marshall(auth, xdrs) \
((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
#define AUTH_VALIDATE(auth, verfp) \
((*((auth)->ah_ops->ah_validate))((auth), verfp))
#define auth_validate(auth, verfp) \
((*((auth)->ah_ops->ah_validate))((auth), verfp))
#define AUTH_REFRESH(auth) \
((*((auth)->ah_ops->ah_refresh))(auth))
#define auth_refresh(auth) \
((*((auth)->ah_ops->ah_refresh))(auth))
#define AUTH_DESTROY(auth) \
((*((auth)->ah_ops->ah_destroy))(auth))
#define auth_destroy(auth) \
((*((auth)->ah_ops->ah_destroy))(auth))
#define MAX_AUTH_BYTES 400
#define MAXNETNAMELEN 255 /* maximum length of network user's name */
AUTH *authnone_create(void);
#endif

View File

@ -1,135 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] =
"@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
#endif
/*
* auth_none.c
* Creates a client authentication handle for passing "null"
* credentials and verifiers to remote systems.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#define MAX_MARSHEL_SIZE 20
static void authnone_verf(AUTH *);
static bool_t authnone_validate(AUTH *, struct opaque_auth *);
static bool_t authnone_refresh(AUTH *);
static void authnone_destroy(AUTH *);
static bool_t authnone_marshal(AUTH *client, XDR *xdrs);
struct opaque_auth _null_auth;
static struct auth_ops ops = {
authnone_verf,
authnone_marshal,
authnone_validate,
authnone_refresh,
authnone_destroy
};
static struct authnone_private {
AUTH no_client;
char marshalled_client[MAX_MARSHEL_SIZE];
unsigned int mcnt;
} *authnone_private;
AUTH *authnone_create()
{
register struct authnone_private *ap = authnone_private;
XDR xdr_stream;
register XDR *xdrs;
extern bool_t xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap);
if (ap == 0) {
ap = (struct authnone_private *) rt_malloc (sizeof(*ap));
if (ap == 0) return NULL;
memset(ap, 0, sizeof(*ap));
authnone_private = ap;
}
if (!ap->mcnt) {
ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
ap->no_client.ah_ops = &ops;
xdrs = &xdr_stream;
xdrmem_create(xdrs, ap->marshalled_client,
(unsigned int) MAX_MARSHEL_SIZE, XDR_ENCODE);
(void) xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
(void) xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
ap->mcnt = XDR_GETPOS(xdrs);
XDR_DESTROY(xdrs);
}
return (&ap->no_client);
}
/*ARGSUSED*/
static bool_t authnone_marshal(AUTH *client, XDR *xdrs)
{
register struct authnone_private *ap = authnone_private;
if (ap == 0)
return (0);
return ((*xdrs->x_ops->x_putbytes) (xdrs,
ap->marshalled_client, ap->mcnt));
}
static void authnone_verf(AUTH *x)
{
}
static bool_t authnone_validate(AUTH *x, struct opaque_auth *x1)
{
return (TRUE);
}
static bool_t authnone_refresh(AUTH *x)
{
return (FALSE);
}
static void authnone_destroy(AUTH *x)
{
}

View File

@ -1,330 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* clnt.h - Client side remote procedure call interface.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#ifndef _RPC_CLNT_H
#define _RPC_CLNT_H 1
#include <rpc/types.h>
#include <rpc/auth.h>
#include <lwip/sockets.h>
/*
* Rpc calls return an enum clnt_stat. This should be looked at more,
* since each implementation is required to live with this (implementation
* independent) list of errors.
*/
enum clnt_stat {
RPC_SUCCESS=0, /* call succeeded */
/*
* local errors
*/
RPC_CANTENCODEARGS=1, /* can't encode arguments */
RPC_CANTDECODERES=2, /* can't decode results */
RPC_CANTSEND=3, /* failure in sending call */
RPC_CANTRECV=4, /* failure in receiving result */
RPC_TIMEDOUT=5, /* call timed out */
/*
* remote errors
*/
RPC_VERSMISMATCH=6, /* rpc versions not compatible */
RPC_AUTHERROR=7, /* authentication error */
RPC_PROGUNAVAIL=8, /* program not available */
RPC_PROGVERSMISMATCH=9, /* program version mismatched */
RPC_PROCUNAVAIL=10, /* procedure unavailable */
RPC_CANTDECODEARGS=11, /* decode arguments error */
RPC_SYSTEMERROR=12, /* generic "other problem" */
RPC_NOBROADCAST = 21, /* Broadcasting not supported */
/*
* callrpc & clnt_create errors
*/
RPC_UNKNOWNHOST=13, /* unknown host name */
RPC_UNKNOWNPROTO=17, /* unknown protocol */
RPC_UNKNOWNADDR = 19, /* Remote address unknown */
/*
* rpcbind errors
*/
RPC_RPCBFAILURE=14, /* portmapper failed in its call */
#define RPC_PMAPFAILURE RPC_RPCBFAILURE
RPC_PROGNOTREGISTERED=15, /* remote program is not registered */
RPC_N2AXLATEFAILURE = 22, /* Name to addr translation failed */
/*
* unspecified error
*/
RPC_FAILED=16,
RPC_INTR=18,
RPC_TLIERROR=20,
RPC_UDERROR=23,
/*
* asynchronous errors
*/
RPC_INPROGRESS = 24,
RPC_STALERACHANDLE = 25
};
/*
* Error info.
*/
struct rpc_err {
int re_status;
union {
int RE_errno; /* related system error */
int RE_why; /* why the auth error occurred */
struct {
unsigned long low; /* lowest verion supported */
unsigned long high; /* highest verion supported */
} RE_vers;
struct { /* maybe meaningful if RPC_FAILED */
long s1;
long s2;
} RE_lb; /* life boot & debugging only */
} ru;
#define re_errno ru.RE_errno
#define re_why ru.RE_why
#define re_vers ru.RE_vers
#define re_lb ru.RE_lb
};
/*
* Client rpc handle.
* Created by individual implementations, see e.g. rpc_udp.c.
* Client is responsible for initializing auth, see e.g. auth_none.c.
*/
typedef struct CLIENT CLIENT;
struct CLIENT {
AUTH *cl_auth; /* authenticator */
struct clnt_ops {
enum clnt_stat (*cl_call) (CLIENT *, unsigned long, xdrproc_t, char*, xdrproc_t,
char*, struct timeval);
/* call remote procedure */
void (*cl_abort) (void); /* abort a call */
void (*cl_geterr) (CLIENT *, struct rpc_err *);
/* get specific error code */
bool_t (*cl_freeres) (CLIENT *, xdrproc_t, char*);
/* frees results */
void (*cl_destroy) (CLIENT *); /* destroy this structure */
bool_t (*cl_control) (CLIENT *, int, char *);
/* the ioctl() of rpc */
} *cl_ops;
char* cl_private; /* private stuff */
};
/*
* client side rpc interface ops
*
* Parameter types are:
*
*/
/*
* enum clnt_stat
* CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
* CLIENT *rh;
* unsigned long proc;
* xdrproc_t xargs;
* char* argsp;
* xdrproc_t xres;
* char* resp;
* struct timeval timeout;
*/
#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \
((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \
((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
/*
* void
* CLNT_ABORT(rh);
* CLIENT *rh;
*/
#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh))
#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh))
/*
* struct rpc_err
* CLNT_GETERR(rh);
* CLIENT *rh;
*/
#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
/*
* bool_t
* CLNT_FREERES(rh, xres, resp);
* CLIENT *rh;
* xdrproc_t xres;
* char* resp;
*/
#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
/*
* bool_t
* CLNT_CONTROL(cl, request, info)
* CLIENT *cl;
* unsigned int request;
* char *info;
*/
#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
/*
* control operations that apply to all transports
*
* Note: options marked XXX are no-ops in this implementation of RPC.
* The are present in TI-RPC but can't be implemented here since they
* depend on the presence of STREAMS/TLI, which we don't have.
*/
#define CLSET_TIMEOUT 1 /* set timeout (timeval) */
#define CLGET_TIMEOUT 2 /* get timeout (timeval) */
#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */
#define CLGET_FD 6 /* get connections file descriptor */
#define CLGET_SVC_ADDR 7 /* get server's address (netbuf) XXX */
#define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */
#define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy*/
#define CLGET_XID 10 /* Get xid */
#define CLSET_XID 11 /* Set xid */
#define CLGET_VERS 12 /* Get version number */
#define CLSET_VERS 13 /* Set version number */
#define CLGET_PROG 14 /* Get program number */
#define CLSET_PROG 15 /* Set program number */
#define CLSET_SVC_ADDR 16 /* get server's address (netbuf) XXX */
#define CLSET_PUSH_TIMOD 17 /* push timod if not already present XXX */
#define CLSET_POP_TIMOD 18 /* pop timod XXX */
/*
* Connectionless only control operations
*/
#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */
#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */
/*
* void
* CLNT_DESTROY(rh);
* CLIENT *rh;
*/
#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
/*
* RPCTEST is a test program which is accessible on every rpc
* transport/port. It is used for testing, performance evaluation,
* and network administration.
*/
#define RPCTEST_PROGRAM ((unsigned long)1)
#define RPCTEST_VERSION ((unsigned long)1)
#define RPCTEST_NULL_PROC ((unsigned long)2)
#define RPCTEST_NULL_BATCH_PROC ((unsigned long)3)
/*
* By convention, procedure 0 takes null arguments and returns them
*/
#define NULLPROC ((unsigned long)0)
/*
* Below are the client handle creation routines for the various
* implementations of client side rpc. They can return NULL if a
* creation failure occurs.
*/
/*
* Generic client creation routine. Supported protocols are "udp", "tcp" and
* "unix"
* CLIENT *
* clnt_create(host, prog, vers, prot)
* char *host; -- hostname
* unsigned long prog; -- program number
* u_ong vers; -- version number
* char *prot; -- protocol
*/
extern CLIENT *clnt_create (const char *__host, const unsigned long __prog,
const unsigned long __vers, const char *__prot)
;
/*
* UDP based rpc.
* CLIENT *
* clntudp_create(raddr, program, version, wait, sockp)
* struct sockaddr_in *raddr;
* unsigned long program;
* unsigned long version;
* struct timeval wait_resend;
* int *sockp;
*
* Same as above, but you specify max packet sizes.
* CLIENT *
* clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
* struct sockaddr_in *raddr;
* unsigned long program;
* unsigned long version;
* struct timeval wait_resend;
* int *sockp;
* unsigned int sendsz;
* unsigned int recvsz;
*/
extern CLIENT *clntudp_create (struct sockaddr_in *__raddr, unsigned long __program,
unsigned long __version, struct timeval __wait_resend,
int *__sockp);
extern CLIENT *clntudp_bufcreate (struct sockaddr_in *__raddr,
unsigned long __program, unsigned long __version,
struct timeval __wait_resend, int *__sockp,
unsigned int __sendsz, unsigned int __recvsz);
extern int callrpc (const char *__host, const unsigned long __prognum,
const unsigned long __versnum, const unsigned long __procnum,
const xdrproc_t __inproc, const char *__in,
const xdrproc_t __outproc, char *__out);
#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
void clnt_perror(CLIENT *rpch, const char *s);
#endif /* rpc/clnt.h */

View File

@ -1,95 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";
#endif
/*
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
#include <rpc/rpc.h>
#include <string.h>
/*
* Generic client creation: takes (hostname, program-number, protocol) and
* returns client handle. Default options are set, which the user can
* change using the rpc equivalent of ioctl()'s.
*/
CLIENT *clnt_create(const char *hostname, const unsigned long prog,
const unsigned long vers, const char *proto)
{
int sock;
struct sockaddr_in server;
struct addrinfo hint, *res = NULL;
struct timeval tv;
CLIENT *client;
int ret;
memset(&hint, 0, sizeof(hint));
ret = getaddrinfo(hostname, NULL, &hint, &res);
if (ret != 0)
{
rt_kprintf("getaddrinfo err: %d '%s'\n", ret, hostname);
return NULL;
}
memcpy(&server, res->ai_addr, sizeof(struct sockaddr_in));
freeaddrinfo(res);
sock = -1;
if (strcmp(proto, "udp") == 0)
{
tv.tv_sec = 5;
tv.tv_usec = 0;
client = clntudp_create(&server, prog, vers, tv, &sock);
if (client == NULL) return NULL;
tv.tv_sec = 1;
clnt_control(client, CLSET_TIMEOUT, (char *)&tv);
}
else
{
rt_kprintf("unknow protocol\n");
return NULL;
}
return (client);
}
void clnt_perror(CLIENT *rpch, const char *s)
{
rt_kprintf("rpc client error:%s\n", s);
}

View File

@ -1,406 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
#endif
/*
* clnt_udp.c, Implements a UDP/IP based, client side RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <rtthread.h>
/*
* UDP bases client side rpc operations
*/
static enum clnt_stat clntudp_call(register CLIENT *cl, /* client handle */
unsigned long proc, /* procedure number */
xdrproc_t xargs, /* xdr routine for args */
char* argsp, /* pointer to args */
xdrproc_t xresults, /* xdr routine for results */
char* resultsp, /* pointer to results */
struct timeval utimeout);
static void clntudp_abort(void);
static void clntudp_geterr(CLIENT *, struct rpc_err *);
static bool_t clntudp_freeres(CLIENT *, xdrproc_t, char*);
static bool_t clntudp_control(CLIENT *, int, char *);
static void clntudp_destroy(CLIENT *);
static struct clnt_ops udp_ops =
{
clntudp_call,
clntudp_abort,
clntudp_geterr,
clntudp_freeres,
clntudp_destroy,
clntudp_control
};
/*
* Private data kept per client handle
*/
struct cu_data
{
int cu_sock;
bool_t cu_closeit;
struct sockaddr_in cu_raddr;
int cu_rlen;
struct timeval cu_wait;
struct timeval cu_total;
struct rpc_err cu_error;
XDR cu_outxdrs;
unsigned int cu_xdrpos;
unsigned int cu_sendsz;
char *cu_outbuf;
unsigned int cu_recvsz;
char cu_inbuf[1];
};
/*
* Create a UDP based client handle.
* If *sockp<0, *sockp is set to a newly created UPD socket.
* If raddr->sin_port is 0 a binder on the remote machine
* is consulted for the correct port number.
* NB: It is the clients responsibility to close *sockp.
* NB: The rpch->cl_auth is initialized to null authentication.
* Caller may wish to set this something more useful.
*
* wait is the amount of time used between retransmitting a call if
* no response has been heard; retransmition occurs until the actual
* rpc call times out.
*
* sendsz and recvsz are the maximum allowable packet sizes that can be
* sent and received.
*/
CLIENT *clntudp_bufcreate(struct sockaddr_in *raddr,
unsigned long program,
unsigned long version,
struct timeval wait,
int *sockp,
unsigned int sendsz,
unsigned int recvsz)
{
CLIENT *cl;
register struct cu_data *cu = NULL;
struct rpc_msg call_msg;
static int xid_count = 0;
cl = (CLIENT *) rt_malloc (sizeof(CLIENT));
if (cl == NULL)
{
rt_kprintf("clntudp_create: out of memory\n");
goto fooy;
}
sendsz = ((sendsz + 3) / 4) * 4;
recvsz = ((recvsz + 3) / 4) * 4;
cu = (struct cu_data *) rt_malloc (sizeof(*cu) + sendsz + recvsz);
if (cu == NULL)
{
rt_kprintf("clntudp_create: out of memory\n");
goto fooy;
}
cu->cu_outbuf = &cu->cu_inbuf[recvsz];
if (raddr->sin_port == 0) {
unsigned short port;
extern unsigned short pmap_getport(struct sockaddr_in *address,
unsigned long program,
unsigned long version,
unsigned int protocol);
if ((port =
pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
rt_kprintf("pmap_getport failure\n");
goto fooy;
}
raddr->sin_port = htons(port);
}
cl->cl_ops = &udp_ops;
cl->cl_private = (char*) cu;
cu->cu_raddr = *raddr;
cu->cu_rlen = sizeof(cu->cu_raddr);
cu->cu_wait = wait;
cu->cu_total.tv_sec = -1;
cu->cu_total.tv_usec = -1;
cu->cu_sendsz = sendsz;
cu->cu_recvsz = recvsz;
call_msg.rm_xid = (uint32_t)(((unsigned long)rt_thread_self()) ^ ((unsigned long)rt_tick_get()) ^ (xid_count++));
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = program;
call_msg.rm_call.cb_vers = version;
xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE);
if (!xdr_callhdr(&(cu->cu_outxdrs), &call_msg))
{
rt_kprintf("xdr_callhdr failure\n");
goto fooy;
}
cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
if (*sockp < 0)
{
*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (*sockp < 0)
{
rt_kprintf("create socket error\n");
goto fooy;
}
cu->cu_closeit = TRUE;
}
else
{
cu->cu_closeit = FALSE;
}
cu->cu_sock = *sockp;
cl->cl_auth = authnone_create();
return (cl);
fooy:
if (cu) rt_free(cu);
if (cl) rt_free(cl);
return ((CLIENT *) NULL);
}
CLIENT *clntudp_create(struct sockaddr_in *raddr,
unsigned long program,
unsigned long version,
struct timeval wait,
int *sockp)
{
return (clntudp_bufcreate(raddr, program, version, wait, sockp,
UDPMSGSIZE, UDPMSGSIZE));
}
static enum clnt_stat clntudp_call(CLIENT *cl, unsigned long proc,
xdrproc_t xargs, char* argsp,
xdrproc_t xresults, char* resultsp,
struct timeval utimeout)
{
register struct cu_data *cu = (struct cu_data *) cl->cl_private;
register XDR *xdrs;
register int outlen;
register int inlen;
socklen_t fromlen;
struct sockaddr_in from;
struct rpc_msg reply_msg;
XDR reply_xdrs;
bool_t ok;
int nrefreshes = 2; /* number of times to refresh cred */
call_again:
xdrs = &(cu->cu_outxdrs);
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, cu->cu_xdrpos);
/*
* the transaction is the first thing in the out buffer
*/
(*(unsigned long *) (cu->cu_outbuf))++;
if ((!XDR_PUTLONG(xdrs, (long *) &proc)) ||
(!AUTH_MARSHALL(cl->cl_auth, xdrs)) || (!(*xargs) (xdrs, argsp)))
{
cu->cu_error.re_status = RPC_CANTENCODEARGS;
return RPC_CANTENCODEARGS;
}
outlen = (int) XDR_GETPOS(xdrs);
send_again:
if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
(struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen)
!= outlen)
{
cu->cu_error.re_errno = errno;
cu->cu_error.re_status = RPC_CANTSEND;
return RPC_CANTSEND;
}
/*
* sub-optimal code appears here because we have
* some clock time to spare while the packets are in flight.
* (We assume that this is actually only executed once.)
*/
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = resultsp;
reply_msg.acpted_rply.ar_results.proc = xresults;
/* do recv */
do
{
fromlen = sizeof(struct sockaddr);
inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
(int) cu->cu_recvsz, 0,
(struct sockaddr *) &from, &fromlen);
}while (inlen < 0 && errno == EINTR);
if (inlen < 4)
{
rt_kprintf("recv error, len %d\n", inlen);
cu->cu_error.re_errno = errno;
cu->cu_error.re_status = RPC_CANTRECV;
return RPC_CANTRECV;
}
/* see if reply transaction id matches sent id */
if (*((uint32_t *) (cu->cu_inbuf)) != *((uint32_t *) (cu->cu_outbuf)))
goto send_again;
/* we now assume we have the proper reply */
/*
* now decode and validate the response
*/
xdrmem_create(&reply_xdrs, cu->cu_inbuf, (unsigned int) inlen, XDR_DECODE);
ok = xdr_replymsg(&reply_xdrs, &reply_msg);
/* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
if (ok)
{
_seterr_reply(&reply_msg, &(cu->cu_error));
if (cu->cu_error.re_status == RPC_SUCCESS)
{
if (!AUTH_VALIDATE(cl->cl_auth,
&reply_msg.acpted_rply.ar_verf))
{
cu->cu_error.re_status = RPC_AUTHERROR;
cu->cu_error.re_why = AUTH_INVALIDRESP;
}
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
{
extern bool_t xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap);
xdrs->x_op = XDR_FREE;
(void) xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
else
{
/* maybe our credentials need to be refreshed ... */
if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth))
{
nrefreshes--;
goto call_again;
}
} /* end of unsuccessful completion */
} /* end of valid reply message */
else
{
cu->cu_error.re_status = RPC_CANTDECODERES;
}
return (enum clnt_stat)(cu->cu_error.re_status);
}
static void clntudp_geterr(CLIENT *cl, struct rpc_err *errp)
{
register struct cu_data *cu = (struct cu_data *) cl->cl_private;
*errp = cu->cu_error;
}
static bool_t clntudp_freeres(CLIENT *cl, xdrproc_t xdr_res, char* res_ptr)
{
register struct cu_data *cu = (struct cu_data *) cl->cl_private;
register XDR *xdrs = &(cu->cu_outxdrs);
xdrs->x_op = XDR_FREE;
return ((*xdr_res) (xdrs, res_ptr));
}
static void clntudp_abort()
{
}
static bool_t clntudp_control(CLIENT *cl, int request, char *info)
{
register struct cu_data *cu = (struct cu_data *) cl->cl_private;
switch (request)
{
case CLSET_TIMEOUT:
{
int mtimeout;
cu->cu_total = *(struct timeval *) info;
mtimeout = ((cu->cu_total.tv_sec * 1000) + ((cu->cu_total.tv_usec + 500)/1000));
/* set socket option, note: lwip only support msecond timeout */
setsockopt(cu->cu_sock, SOL_SOCKET, SO_RCVTIMEO,
&mtimeout, sizeof(mtimeout));
}
break;
case CLGET_TIMEOUT:
*(struct timeval *) info = cu->cu_total;
break;
case CLSET_RETRY_TIMEOUT:
cu->cu_wait = *(struct timeval *) info;
break;
case CLGET_RETRY_TIMEOUT:
*(struct timeval *) info = cu->cu_wait;
break;
case CLGET_SERVER_ADDR:
*(struct sockaddr_in *) info = cu->cu_raddr;
break;
default:
return (FALSE);
}
return (TRUE);
}
static void clntudp_destroy(CLIENT *cl)
{
register struct cu_data *cu = (struct cu_data *) cl->cl_private;
if (cu->cu_closeit)
{
lwip_close(cu->cu_sock);
}
XDR_DESTROY(&(cu->cu_outxdrs));
rt_free(cu);
rt_free(cl);
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include "pmap.h"
#include "clnt.h"
#include <rpc/rpc.h>
static struct timeval timeout = { 5, 0 };
static struct timeval tottimeout = { 60, 0 };
bool_t xdr_pmap(XDR *xdrs, struct pmap *regs)
{
if (xdr_u_long(xdrs, &regs->pm_prog) &&
xdr_u_long(xdrs, &regs->pm_vers) &&
xdr_u_long(xdrs, &regs->pm_prot))
return (xdr_u_long(xdrs, &regs->pm_port));
return (FALSE);
}
/*
* Find the mapped port for program,version.
* Calls the pmap service remotely to do the lookup.
* Returns 0 if no map exists.
*/
unsigned short pmap_getport(struct sockaddr_in *address, unsigned long program, unsigned long version, unsigned int protocol)
{
unsigned short port = 0;
int socket = -1;
register CLIENT *client = RT_NULL;
struct pmap parms;
address->sin_port = htons((unsigned short)PMAPPORT);
if (protocol == IPPROTO_UDP)
client = clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout,
&socket, RPCSMALLMSGSIZE,
RPCSMALLMSGSIZE);
if (client != (CLIENT *) NULL)
{
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_prot = protocol;
parms.pm_port = 0; /* not needed or used */
if (CLNT_CALL(client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, (char*)&parms,
(xdrproc_t)xdr_u_short, (char*)&port, tottimeout) != RPC_SUCCESS)
{
rt_kprintf("pmap failure\n");
}
CLNT_DESTROY(client);
}
(void) lwip_close(socket);
address->sin_port = 0;
return (port);
}

View File

@ -1,66 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef __RPC_PMAP_PROT_H__
#define __RPC_PMAP_PROT_H__
#include <rpc/xdr.h>
/* The following procedures are supported by the protocol:
*
* PMAPPROC_NULL() returns ()
* takes nothing, returns nothing
*
* PMAPPROC_SET(struct pmap) returns (bool_t)
* TRUE is success, FALSE is failure. Registers the tuple
* [prog, vers, prot, port].
*
* PMAPPROC_UNSET(struct pmap) returns (bool_t)
* TRUE is success, FALSE is failure. Un-registers pair
* [prog, vers]. prot and port are ignored.
*
* PMAPPROC_GETPORT(struct pmap) returns (long unsigned).
* 0 is failure. Otherwise returns the port number where the pair
* [prog, vers] is registered. It may lie!
*
* PMAPPROC_DUMP() RETURNS (struct pmaplist *)
*
* PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
* RETURNS (port, string<>);
* usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
* Calls the procedure on the local machine. If it is not registered,
* this procedure is quite; ie it does not return error information!!!
* This procedure only is supported on rpc/udp and calls via
* rpc/udp. This routine only passes null authentication parameters.
* This file has no interface to xdr routines for PMAPPROC_CALLIT.
*
* The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
*/
#define PMAPPORT ((unsigned short)111)
#define PMAPPROG ((unsigned long)100000)
#define PMAPVERS ((unsigned long)2)
#define PMAPVERS_PROTO ((unsigned long)2)
#define PMAPVERS_ORIG ((unsigned long)1)
#define PMAPPROC_NULL ((unsigned long)0)
#define PMAPPROC_SET ((unsigned long)1)
#define PMAPPROC_UNSET ((unsigned long)2)
#define PMAPPROC_GETPORT ((unsigned long)3)
#define PMAPPROC_DUMP ((unsigned long)4)
#define PMAPPROC_CALLIT ((unsigned long)5)
struct pmap {
long unsigned pm_prog;
long unsigned pm_vers;
long unsigned pm_prot;
long unsigned pm_port;
};
extern bool_t xdr_pmap (XDR *__xdrs, struct pmap *__regs);
#endif

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)rpc.h 2.3 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* rpc.h, Just includes the billions of rpc header files necessary to
* do remote procedure calling.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#ifndef _RPC_RPC_H
#define _RPC_RPC_H 1
#include <rpc/types.h> /* some typedefs */
/* external data representation interfaces */
#include <rpc/xdr.h> /* generic (de)serializer */
#include <rpc/auth.h>
/* Client side (mostly) remote procedure call */
#include <rpc/clnt.h> /* generic rpc stuff */
/* semi-private protocol headers */
#include <rpc/rpc_msg.h> /* protocol for rpc messages */
#endif

View File

@ -1,203 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/* @(#)rpc_msg.h 1.7 86/07/16 SMI */
#ifndef _RPC_MSG_H
#define _RPC_MSG_H 1
#include <rpc/xdr.h>
#include <rpc/clnt.h>
/*
* rpc_msg.h
* rpc message definition
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#define RPC_MSG_VERSION ((unsigned long) 2)
#define RPC_SERVICE_PORT ((unsigned short) 2048)
/*
* Bottom up definition of an rpc message.
* NOTE: call and reply use the same overall struct but
* different parts of unions within it.
*/
enum msg_type {
CALL=0,
REPLY=1
};
enum reply_stat {
MSG_ACCEPTED=0,
MSG_DENIED=1
};
enum accept_stat {
SUCCESS=0,
PROG_UNAVAIL=1,
PROG_MISMATCH=2,
PROC_UNAVAIL=3,
GARBAGE_ARGS=4,
SYSTEM_ERR=5
};
enum reject_stat {
RPC_MISMATCH=0,
AUTH_ERROR=1
};
/*
* Reply part of an rpc exchange
*/
/*
* Reply to an rpc request that was accepted by the server.
* Note: there could be an error even though the request was
* accepted.
*/
struct accepted_reply {
struct opaque_auth ar_verf;
int ar_stat;
union {
struct {
unsigned long low;
unsigned long high;
} AR_versions;
struct {
char* where;
xdrproc_t proc;
} AR_results;
/* and many other null cases */
} ru;
#define ar_results ru.AR_results
#define ar_vers ru.AR_versions
};
/*
* Reply to an rpc request that was rejected by the server.
*/
struct rejected_reply {
int rj_stat;
union {
struct {
unsigned long low;
unsigned long high;
} RJ_versions;
int RJ_why; /* why authentication did not work */
} ru;
#define rj_vers ru.RJ_versions
#define rj_why ru.RJ_why
};
/*
* Body of a reply to an rpc request.
*/
struct reply_body {
int rp_stat;
union {
struct accepted_reply RP_ar;
struct rejected_reply RP_dr;
} ru;
#define rp_acpt ru.RP_ar
#define rp_rjct ru.RP_dr
};
/*
* Body of an rpc request call.
*/
struct call_body {
unsigned long cb_rpcvers; /* must be equal to two */
unsigned long cb_prog;
unsigned long cb_vers;
unsigned long cb_proc;
struct opaque_auth cb_cred;
struct opaque_auth cb_verf; /* protocol specific - provided by client */
};
/*
* The rpc message
*/
struct rpc_msg {
unsigned long rm_xid;
int rm_direction;
union {
struct call_body RM_cmb;
struct reply_body RM_rmb;
} ru;
#define rm_call ru.RM_cmb
#define rm_reply ru.RM_rmb
};
#define acpted_rply ru.RM_rmb.ru.RP_ar
#define rjcted_rply ru.RM_rmb.ru.RP_dr
/*
* XDR routine to handle a rpc message.
* xdr_callmsg(xdrs, cmsg)
* XDR *xdrs;
* struct rpc_msg *cmsg;
*/
extern bool_t xdr_callmsg (XDR *__xdrs, struct rpc_msg *__cmsg);
/*
* XDR routine to pre-serialize the static part of a rpc message.
* xdr_callhdr(xdrs, cmsg)
* XDR *xdrs;
* struct rpc_msg *cmsg;
*/
extern bool_t xdr_callhdr (XDR *__xdrs, struct rpc_msg *__cmsg);
/*
* XDR routine to handle a rpc reply.
* xdr_replymsg(xdrs, rmsg)
* XDR *xdrs;
* struct rpc_msg *rmsg;
*/
extern bool_t xdr_replymsg (XDR *__xdrs, struct rpc_msg *__rmsg);
/*
* Fills in the error part of a reply message.
* _seterr_reply(msg, error)
* struct rpc_msg *msg;
* struct rpc_err *error;
*/
extern void _seterr_reply (struct rpc_msg *__msg, struct rpc_err *__error);
#endif /* rpc/rpc_msg.h */

View File

@ -1,267 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
#endif
/*
* rpc_prot.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* This set of routines implements the rpc message definition,
* its serializer and some common rpc utility routines.
* The routines are meant for various implementations of rpc -
* they are NOT for the rpc client or rpc service implementations!
* Because authentication stuff is easy and is part of rpc, the opaque
* routines are also in this program.
*/
#include <rpc/rpc.h>
/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
/*
* XDR an opaque authentication struct
* (see auth.h)
*/
bool_t xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap)
{
if (xdr_enum(xdrs, &(ap->oa_flavor)))
return (xdr_bytes(xdrs, &ap->oa_base,
&ap->oa_length, MAX_AUTH_BYTES));
return (FALSE);
}
/*
* XDR a DES block
*/
bool_t xdr_des_block(XDR *xdrs, des_block *blkp)
{
return (xdr_opaque(xdrs, (char*) blkp, sizeof(des_block)));
}
/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
/*
* XDR the MSG_ACCEPTED part of a reply message union
*/
static bool_t xdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar)
{
/* personalized union, rather than calling xdr_union */
if (!xdr_opaque_auth(xdrs, &(ar->ar_verf)))
return (FALSE);
if (!xdr_enum(xdrs, (enum_t *) & (ar->ar_stat)))
return (FALSE);
switch (ar->ar_stat) {
case SUCCESS:
return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));
case PROG_MISMATCH:
if (!xdr_u_long(xdrs, &(ar->ar_vers.low)))
return (FALSE);
return (xdr_u_long(xdrs, &(ar->ar_vers.high)));
}
return (TRUE); /* TRUE => open ended set of problems */
}
/*
* XDR the MSG_DENIED part of a reply message union
*/
static bool_t xdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr)
{
/* personalized union, rather than calling xdr_union */
if (!xdr_enum(xdrs, (enum_t *) & (rr->rj_stat)))
return (FALSE);
switch (rr->rj_stat) {
case RPC_MISMATCH:
if (!xdr_u_long(xdrs, &(rr->rj_vers.low)))
return (FALSE);
return (xdr_u_long(xdrs, &(rr->rj_vers.high)));
case AUTH_ERROR:
return (xdr_enum(xdrs, (enum_t *) & (rr->rj_why)));
}
return (FALSE);
}
static struct xdr_discrim reply_dscrm[3] = {
{(int) MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply},
{(int) MSG_DENIED, (xdrproc_t)xdr_rejected_reply},
{__dontcare__, NULL_xdrproc_t}
};
/*
* XDR a reply message
*/
bool_t xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
{
if (xdr_u_long(xdrs, &(rmsg->rm_xid)) &&
xdr_enum(xdrs, (enum_t *) & (rmsg->rm_direction)) &&
(rmsg->rm_direction == REPLY))
return (xdr_union(xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat),
(char*) & (rmsg->rm_reply.ru), reply_dscrm,
NULL_xdrproc_t));
return (FALSE);
}
/*
* Serializes the "static part" of a call message header.
* The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
* The rm_xid is not really static, but the user can easily munge on the fly.
*/
bool_t xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg)
{
cmsg->rm_direction = CALL;
cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
if (
(xdrs->x_op == XDR_ENCODE) &&
xdr_u_long(xdrs, &(cmsg->rm_xid)) &&
xdr_enum(xdrs, (enum_t *) & (cmsg->rm_direction)) &&
xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)))
return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)));
return (FALSE);
}
/* ************************** Client utility routine ************* */
static void accepted(enum accept_stat acpt_stat, struct rpc_err *error)
{
switch (acpt_stat) {
case PROG_UNAVAIL:
error->re_status = RPC_PROGUNAVAIL;
return;
case PROG_MISMATCH:
error->re_status = RPC_PROGVERSMISMATCH;
return;
case PROC_UNAVAIL:
error->re_status = RPC_PROCUNAVAIL;
return;
case GARBAGE_ARGS:
error->re_status = RPC_CANTDECODEARGS;
return;
case SYSTEM_ERR:
error->re_status = RPC_SYSTEMERROR;
return;
case SUCCESS:
error->re_status = RPC_SUCCESS;
return;
}
/* something's wrong, but we don't know what ... */
error->re_status = RPC_FAILED;
error->re_lb.s1 = (long) MSG_ACCEPTED;
error->re_lb.s2 = (long) acpt_stat;
}
static void rejected(enum reject_stat rjct_stat, struct rpc_err *error)
{
switch (rjct_stat) {
case RPC_VERSMISMATCH:
error->re_status = RPC_VERSMISMATCH;
return;
case AUTH_ERROR:
error->re_status = RPC_AUTHERROR;
return;
}
/* something's wrong, but we don't know what ... */
error->re_status = RPC_FAILED;
error->re_lb.s1 = (long) MSG_DENIED;
error->re_lb.s2 = (long) rjct_stat;
}
/*
* given a reply message, fills in the error
*/
void _seterr_reply(struct rpc_msg *msg, struct rpc_err *error)
{
/* optimized for normal, SUCCESSful case */
switch (msg->rm_reply.rp_stat) {
case MSG_ACCEPTED:
if (msg->acpted_rply.ar_stat == SUCCESS) {
error->re_status = RPC_SUCCESS;
return;
};
accepted((enum accept_stat)msg->acpted_rply.ar_stat, error);
break;
case MSG_DENIED:
rejected((enum reject_stat)msg->rjcted_rply.rj_stat, error);
break;
default:
error->re_status = RPC_FAILED;
error->re_lb.s1 = (long) (msg->rm_reply.rp_stat);
break;
}
switch (error->re_status) {
case RPC_VERSMISMATCH:
error->re_vers.low = msg->rjcted_rply.rj_vers.low;
error->re_vers.high = msg->rjcted_rply.rj_vers.high;
break;
case RPC_AUTHERROR:
error->re_why = msg->rjcted_rply.rj_why;
break;
case RPC_PROGVERSMISMATCH:
error->re_vers.low = msg->acpted_rply.ar_vers.low;
error->re_vers.high = msg->acpted_rply.ar_vers.high;
break;
}
}

View File

@ -1,89 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/* fixincludes should not add extern "C" to this file */
/*
* Rpc additions to <sys/types.h>
*/
#ifndef _RPC_TYPES_H
#define _RPC_TYPES_H 1
#include <rtthread.h>
#include <lwip/netdb.h>
#include <lwip/sockets.h>
#include <string.h>
#include <stdint.h>
#ifndef RT_USING_MINILIBC
typedef unsigned int u_int;
typedef unsigned char u_char;
typedef unsigned long u_long;
#else
#include <sys/types.h>
#include <stdint.h>
#endif
typedef int bool_t;
typedef int enum_t;
#if !defined(RT_USING_NEWLIB) && !defined(RT_USING_MUSL)
typedef unsigned long dev_t;
#endif
/* This needs to be changed to uint32_t in the future */
typedef unsigned long rpcprog_t;
typedef unsigned long rpcvers_t;
typedef unsigned long rpcproc_t;
typedef unsigned long rpcprot_t;
typedef unsigned long rpcport_t;
#define __dontcare__ -1
#ifndef FALSE
# define FALSE (0)
#endif
#ifndef TRUE
# define TRUE (1)
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#endif /* rpc/types.h */

View File

@ -1,784 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
#endif
/*
* xdr.c, Generic XDR routines implementation.
*
* Copyright (C) 1986, Sun Microsystems, Inc.
*
* These are the "generic" xdr routines used to serialize and de-serialize
* most common data items. See xdr.h for more info on the interface to
* xdr.
*/
#include <stdio.h>
#include <stdlib.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <string.h>
/*
* constants specific to the xdr "protocol"
*/
#define XDR_FALSE ((long) 0)
#define XDR_TRUE ((long) 1)
#define LASTUNSIGNED ((unsigned int) 0-1)
/*
* for unit alignment
*/
static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
/*
* Free a data structure using XDR
* Not a filter, but a convenient utility nonetheless
*/
void xdr_free(xdrproc_t proc, char* objp)
{
XDR x;
x.x_op = XDR_FREE;
(*proc) (&x, objp);
}
/*
* XDR nothing
*/
bool_t xdr_void( /* xdrs, addr */ )
/* XDR *xdrs; */
/* char* addr; */
{
return (TRUE);
}
/*
* XDR integers
*/
bool_t xdr_int(XDR* xdrs, int* ip)
{
if (sizeof(int) == sizeof(long)) {
return (xdr_long(xdrs, (long *) ip));
} else if (sizeof(int) < sizeof(long)) {
long l;
switch (xdrs->x_op) {
case XDR_ENCODE:
l = (long) *ip;
return XDR_PUTLONG(xdrs, &l);
case XDR_DECODE:
if (!XDR_GETLONG(xdrs, &l))
return FALSE;
*ip = (int) l;
case XDR_FREE:
return TRUE;
}
return FALSE;
} else {
return (xdr_short(xdrs, (short *) ip));
}
}
/*
* XDR unsigned integers
*/
bool_t xdr_u_int(XDR* xdrs, unsigned int* up)
{
if (sizeof(unsigned int) == sizeof(unsigned long)) {
return (xdr_u_long(xdrs, (unsigned long *) up));
} else if (sizeof(unsigned int) < sizeof(unsigned long)) {
unsigned long l;
switch (xdrs->x_op) {
case XDR_ENCODE:
l = (unsigned long) *up;
return XDR_PUTLONG(xdrs, (long*)&l);
case XDR_DECODE:
if (!XDR_GETLONG(xdrs, (long*)&l))
return FALSE;
*up = (unsigned int) l;
case XDR_FREE:
return TRUE;
}
return FALSE;
} else {
return (xdr_short(xdrs, (short *) up));
}
}
/*
* XDR long integers
* same as xdr_u_long - open coded to save a proc call!
*/
bool_t xdr_long(XDR* xdrs, long* lp)
{
if (xdrs->x_op == XDR_ENCODE
&& (sizeof(int32_t) == sizeof(long)
|| (int32_t) *lp == *lp))
return (XDR_PUTLONG(xdrs, lp));
if (xdrs->x_op == XDR_DECODE)
return (XDR_GETLONG(xdrs, lp));
if (xdrs->x_op == XDR_FREE)
return (TRUE);
return (FALSE);
}
/*
* XDR unsigned long integers
* same as xdr_long - open coded to save a proc call!
*/
bool_t xdr_u_long(XDR* xdrs, unsigned long* ulp)
{
if (xdrs->x_op == XDR_DECODE) {
long l;
if (XDR_GETLONG(xdrs, &l) == FALSE)
return FALSE;
*ulp = (uint32_t) l;
return TRUE;
}
if (xdrs->x_op == XDR_ENCODE) {
if (sizeof(uint32_t) != sizeof(unsigned long)
&& (uint32_t) *ulp != *ulp)
return FALSE;
return (XDR_PUTLONG(xdrs, (long *) ulp));
}
if (xdrs->x_op == XDR_FREE)
return (TRUE);
return (FALSE);
}
/*
* XDR long long integers
*/
bool_t xdr_longlong_t (XDR * xdrs, int64_t* llp)
{
int32_t t1, t2;
switch (xdrs->x_op)
{
case XDR_ENCODE:
t1 = (int32_t) ((*llp) >> 32);
t2 = (int32_t) (*llp);
return (XDR_PUTLONG (xdrs, &t1) && XDR_PUTLONG (xdrs, &t2));
case XDR_DECODE:
if (!XDR_GETLONG (xdrs, &t1) || !XDR_GETLONG (xdrs, &t2))
return FALSE;
*llp = ((int64_t) t1) << 32;
*llp |= (uint32_t) t2;
return TRUE;
case XDR_FREE:
return TRUE;
}
return FALSE;
}
/*
* XDR unsigned long long integers
*/
bool_t xdr_u_longlong_t (XDR * xdrs, uint64_t* ullp)
{
uint32_t t1, t2;
switch (xdrs->x_op)
{
case XDR_ENCODE:
t1 = (uint32_t) ((*ullp) >> 32);
t2 = (uint32_t) (*ullp);
return (XDR_PUTLONG (xdrs, (int32_t *)&t1) &&
XDR_PUTLONG (xdrs, (int32_t *)&t2));
case XDR_DECODE:
if (!XDR_GETLONG (xdrs, (int32_t *)&t1) ||
!XDR_GETLONG (xdrs, (int32_t *)&t2))
return FALSE;
*ullp = ((uint64_t) t1) << 32;
*ullp |= t2;
return TRUE;
case XDR_FREE:
return TRUE;
}
return FALSE;
}
/*
* XDR short integers
*/
bool_t xdr_short(XDR* xdrs, short* sp)
{
long l;
switch (xdrs->x_op) {
case XDR_ENCODE:
l = (long) *sp;
return (XDR_PUTLONG(xdrs, &l));
case XDR_DECODE:
if (!XDR_GETLONG(xdrs, &l)) {
return (FALSE);
}
*sp = (short) l;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
/*
* XDR unsigned short integers
*/
bool_t xdr_u_short(XDR* xdrs, unsigned short* usp)
{
unsigned long l;
switch (xdrs->x_op) {
case XDR_ENCODE:
l = (unsigned long) * usp;
return (XDR_PUTLONG(xdrs, (long*)&l));
case XDR_DECODE:
if (!XDR_GETLONG(xdrs, (long*)&l)) {
return (FALSE);
}
*usp = (unsigned short) l;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
/*
* XDR a char
*/
bool_t xdr_char(XDR* xdrs, char* cp)
{
int i;
i = (*cp);
if (!xdr_int(xdrs, &i)) {
return (FALSE);
}
*cp = i;
return (TRUE);
}
/*
* XDR an unsigned char
*/
bool_t xdr_u_char(XDR* xdrs, unsigned char* cp)
{
unsigned int u;
u = (*cp);
if (!xdr_u_int(xdrs, &u)) {
return (FALSE);
}
*cp = u;
return (TRUE);
}
/*
* XDR booleans
*/
bool_t xdr_bool(XDR *xdrs, bool_t *bp)
{
long lb;
switch (xdrs->x_op) {
case XDR_ENCODE:
lb = *bp ? XDR_TRUE : XDR_FALSE;
return (XDR_PUTLONG(xdrs, &lb));
case XDR_DECODE:
if (!XDR_GETLONG(xdrs, &lb)) {
return (FALSE);
}
*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
return (TRUE);
case XDR_FREE:
return (TRUE);
}
return (FALSE);
}
/*
* XDR enumerations
*/
bool_t xdr_enum(XDR *xdrs, enum_t *ep)
{
enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
/*
* enums are treated as ints
*/
/* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) {
return (xdr_long(xdrs, (long *)(void *)ep));
} else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) {
return (xdr_int(xdrs, (int *)(void *)ep));
} else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) {
return (xdr_short(xdrs, (short *)(void *)ep));
} else {
return (FALSE);
}
}
/*
* XDR opaque data
* Allows the specification of a fixed size sequence of opaque bytes.
* cp points to the opaque object and cnt gives the byte length.
*/
bool_t xdr_opaque(XDR *xdrs, char* cp, unsigned int cnt)
{
register unsigned int rndup;
static char crud[BYTES_PER_XDR_UNIT];
/*
* if no data we are done
*/
if (cnt == 0)
return (TRUE);
/*
* round byte count to full xdr units
*/
rndup = cnt % BYTES_PER_XDR_UNIT;
if (rndup > 0)
rndup = BYTES_PER_XDR_UNIT - rndup;
if (xdrs->x_op == XDR_DECODE) {
if (!XDR_GETBYTES(xdrs, cp, cnt)) {
return (FALSE);
}
if (rndup == 0)
return (TRUE);
return (XDR_GETBYTES(xdrs, crud, rndup));
}
if (xdrs->x_op == XDR_ENCODE) {
if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
return (FALSE);
}
if (rndup == 0)
return (TRUE);
return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
}
if (xdrs->x_op == XDR_FREE) {
return (TRUE);
}
return (FALSE);
}
/*
* XDR counted bytes
* *cpp is a pointer to the bytes, *sizep is the count.
* If *cpp is NULL maxsize bytes are allocated
*/
bool_t xdr_bytes(XDR *xdrs, char** cpp, unsigned int *sizep, unsigned int maxsize)
{
register char *sp = *cpp; /* sp is the actual string pointer */
register unsigned int nodesize;
/*
* first deal with the length since xdr bytes are counted
*/
if (!xdr_u_int(xdrs, sizep)) {
return (FALSE);
}
nodesize = *sizep;
if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
return (FALSE);
}
/*
* now deal with the actual bytes
*/
switch (xdrs->x_op) {
case XDR_DECODE:
if (nodesize == 0) {
return (TRUE);
}
if (sp == NULL) {
*cpp = sp = (char *) rt_malloc(nodesize);
}
if (sp == NULL) {
rt_kprintf("xdr_bytes: out of memory\n");
return (FALSE);
}
/* fall into ... */
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, nodesize));
case XDR_FREE:
if (sp != NULL) {
rt_free(sp);
*cpp = NULL;
}
return (TRUE);
}
return (FALSE);
}
/*
* Implemented here due to commonality of the object.
*/
bool_t xdr_netobj(XDR *xdrs, struct netobj *np)
{
return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
}
/*
* XDR a descriminated union
* Support routine for discriminated unions.
* You create an array of xdrdiscrim structures, terminated with
* an entry with a null procedure pointer. The routine gets
* the discriminant value and then searches the array of xdrdiscrims
* looking for that value. It calls the procedure given in the xdrdiscrim
* to handle the discriminant. If there is no specific routine a default
* routine may be called.
* If there is no specific or default routine an error is returned.
*/
bool_t xdr_union(XDR* xdrs, enum_t* dscmp, char* unp, const struct xdr_discrim* choices, xdrproc_t dfault)
{
register enum_t dscm;
/*
* we deal with the discriminator; it's an enum
*/
if (!xdr_enum(xdrs, dscmp)) {
return (FALSE);
}
dscm = *dscmp;
/*
* search choices for a value that matches the discriminator.
* if we find one, execute the xdr routine for that value.
*/
for (; choices->proc != NULL_xdrproc_t; choices++) {
if (choices->value == dscm)
return ((*(choices->proc)) (xdrs, unp, LASTUNSIGNED));
}
/*
* no match - execute the default xdr routine if there is one
*/
return ((dfault == NULL_xdrproc_t) ? FALSE :
(*dfault) (xdrs, unp, LASTUNSIGNED));
}
/*
* Non-portable xdr primitives.
* Care should be taken when moving these routines to new architectures.
*/
/*
* XDR null terminated ASCII strings
* xdr_string deals with "C strings" - arrays of bytes that are
* terminated by a NULL character. The parameter cpp references a
* pointer to storage; If the pointer is null, then the necessary
* storage is allocated. The last parameter is the max allowed length
* of the string as specified by a protocol.
*/
bool_t xdr_string(XDR *xdrs, char **cpp, unsigned int maxsize)
{
register char *sp = *cpp; /* sp is the actual string pointer */
unsigned int size;
unsigned int nodesize;
/*
* first deal with the length since xdr strings are counted-strings
*/
switch (xdrs->x_op) {
case XDR_FREE:
if (sp == NULL) {
return (TRUE); /* already free */
}
/* fall through... */
case XDR_ENCODE:
size = strlen(sp);
break;
}
if (!xdr_u_int(xdrs, &size)) {
return (FALSE);
}
if (size > maxsize) {
return (FALSE);
}
nodesize = size + 1;
/*
* now deal with the actual bytes
*/
switch (xdrs->x_op) {
case XDR_DECODE:
if (nodesize == 0) {
return (TRUE);
}
if (sp == NULL)
*cpp = sp = (char *) rt_malloc(nodesize);
if (sp == NULL) {
rt_kprintf("xdr_string: out of memory\n");
return (FALSE);
}
sp[size] = 0;
/* fall into ... */
case XDR_ENCODE:
return (xdr_opaque(xdrs, sp, size));
case XDR_FREE:
rt_free(sp);
*cpp = NULL;
return (TRUE);
}
return (FALSE);
}
/*
* Wrapper for xdr_string that can be called directly from
* routines like clnt_call
*/
bool_t xdr_wrapstring(XDR *xdrs, char **cpp)
{
if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
return (TRUE);
}
return (FALSE);
}
/*
* XDR an array of arbitrary elements
* *addrp is a pointer to the array, *sizep is the number of elements.
* If addrp is NULL (*sizep * elsize) bytes are allocated.
* elsize is the size (in bytes) of each element, and elproc is the
* xdr procedure to call to handle each element of the array.
*/
bool_t xdr_array(XDR *xdrs, char **addrp, unsigned int *sizep, unsigned int maxsize, unsigned int elsize, xdrproc_t elproc)
{
register unsigned int i;
register char* target = *addrp;
register unsigned int c; /* the actual element count */
register bool_t stat = TRUE;
register unsigned int nodesize;
/* like strings, arrays are really counted arrays */
if (!xdr_u_int(xdrs, sizep)) {
return (FALSE);
}
c = *sizep;
if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
return (FALSE);
}
/* duh, look for integer overflow (fefe) */
{
unsigned int i;
nodesize = 0;
for (i=c; i; --i) {
unsigned int tmp=nodesize+elsize;
if (tmp<nodesize) /* overflow */
return FALSE;
nodesize=tmp;
}
}
/*
* if we are deserializing, we may need to allocate an array.
* We also save time by checking for a null array if we are freeing.
*/
if (target == NULL)
switch (xdrs->x_op) {
case XDR_DECODE:
if (c == 0)
return (TRUE);
*addrp = target = rt_malloc(nodesize);
if (target == NULL) {
rt_kprintf("xdr_array: out of memory\n");
return (FALSE);
}
memset(target, 0, nodesize);
break;
case XDR_FREE:
return (TRUE);
}
/*
* now we xdr each element of array
*/
for (i = 0; (i < c) && stat; i++) {
stat = (*elproc) (xdrs, target, LASTUNSIGNED);
target += elsize;
}
/*
* the array may need freeing
*/
if (xdrs->x_op == XDR_FREE) {
rt_free(*addrp);
*addrp = NULL;
}
return (stat);
}
/*
* xdr_vector():
*
* XDR a fixed length array. Unlike variable-length arrays,
* the storage of fixed length arrays is static and unfreeable.
* > basep: base of the array
* > size: size of the array
* > elemsize: size of each element
* > xdr_elem: routine to XDR each element
*/
bool_t xdr_vector(XDR *xdrs, char *basep, unsigned int nelem, unsigned int elemsize, xdrproc_t xdr_elem)
{
register unsigned int i;
register char *elptr;
elptr = basep;
for (i = 0; i < nelem; i++) {
if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) {
return (FALSE);
}
elptr += elemsize;
}
return (TRUE);
}
/*
* XDR an indirect pointer
* xdr_reference is for recursively translating a structure that is
* referenced by a pointer inside the structure that is currently being
* translated. pp references a pointer to storage. If *pp is null
* the necessary storage is allocated.
* size is the sizeof the referneced structure.
* proc is the routine to handle the referenced structure.
*/
bool_t xdr_reference(XDR *xdrs, char **pp, unsigned int size, xdrproc_t proc)
{
register char* loc = *pp;
register bool_t stat;
if (loc == NULL)
switch (xdrs->x_op) {
case XDR_FREE:
return (TRUE);
case XDR_DECODE:
*pp = loc = (char*) rt_malloc(size);
if (loc == NULL) {
rt_kprintf("xdr_reference: out of memory\n");
return (FALSE);
}
memset(loc, 0, (int) size);
break;
}
stat = (*proc) (xdrs, loc, LASTUNSIGNED);
if (xdrs->x_op == XDR_FREE) {
rt_free(loc);
*pp = NULL;
}
return (stat);
}
/*
* xdr_pointer():
*
* XDR a pointer to a possibly recursive data structure. This
* differs with xdr_reference in that it can serialize/deserialiaze
* trees correctly.
*
* What's sent is actually a union:
*
* union object_pointer switch (boolean b) {
* case TRUE: object_data data;
* case FALSE: void nothing;
* }
*
* > objpp: Pointer to the pointer to the object.
* > obj_size: size of the object.
* > xdr_obj: routine to XDR an object.
*
*/
bool_t xdr_pointer(XDR *xdrs, char **objpp, unsigned int obj_size, xdrproc_t xdr_obj)
{
bool_t more_data;
more_data = (*objpp != NULL);
if (!xdr_bool(xdrs, &more_data)) {
return (FALSE);
}
if (!more_data) {
*objpp = NULL;
return (TRUE);
}
return (xdr_reference(xdrs, objpp, obj_size, xdr_obj));
}

View File

@ -1,369 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* xdr.h, External Data Representation Serialization Routines.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#ifndef _RPC_XDR_H
#define _RPC_XDR_H
#include <rpc/types.h>
/* We need FILE. */
#include <stdio.h>
/*
* XDR provides a conventional way for converting between C data
* types and an external bit-string representation. Library supplied
* routines provide for the conversion on built-in C data types. These
* routines and utility routines defined here are used to help implement
* a type encode/decode routine for each user-defined type.
*
* Each data type provides a single procedure which takes two arguments:
*
* bool_t
* xdrproc(xdrs, argresp)
* XDR *xdrs;
* <type> *argresp;
*
* xdrs is an instance of a XDR handle, to which or from which the data
* type is to be converted. argresp is a pointer to the structure to be
* converted. The XDR handle contains an operation field which indicates
* which of the operations (ENCODE, DECODE * or FREE) is to be performed.
*
* XDR_DECODE may allocate space if the pointer argresp is null. This
* data can be freed with the XDR_FREE operation.
*
* We write only one procedure per data type to make it easy
* to keep the encode and decode procedures for a data type consistent.
* In many cases the same code performs all operations on a user defined type,
* because all the hard work is done in the component type routines.
* decode as a series of calls on the nested data types.
*/
/*
* Xdr operations. XDR_ENCODE causes the type to be encoded into the
* stream. XDR_DECODE causes the type to be extracted from the stream.
* XDR_FREE can be used to release the space allocated by an XDR_DECODE
* request.
*/
enum xdr_op {
XDR_ENCODE = 0,
XDR_DECODE = 1,
XDR_FREE = 2
};
/*
* This is the number of bytes per unit of external data.
*/
#define BYTES_PER_XDR_UNIT (4)
/*
* This only works if the above is a power of 2. But it's defined to be
* 4 by the appropriate RFCs. So it will work. And it's normally quicker
* than the old routine.
*/
#define RNDUP(x) (((x) + BYTES_PER_XDR_UNIT - 1) & ~(BYTES_PER_XDR_UNIT - 1))
/*
* The XDR handle.
* Contains operation which is being applied to the stream,
* an operations vector for the particular implementation (e.g. see xdr_mem.c),
* and two private fields for the use of the particular implementation.
*/
typedef struct XDR XDR;
struct XDR
{
enum xdr_op x_op; /* operation; fast additional param */
struct xdr_ops
{
bool_t (*x_getlong) (XDR *__xdrs, long *__lp);
/* get a long from underlying stream */
bool_t (*x_putlong) (XDR *__xdrs, const long *__lp);
/* put a long to " */
bool_t (*x_getbytes) (XDR *__xdrs, char* __addr, unsigned int __len);
/* get some bytes from " */
bool_t (*x_putbytes) (XDR *__xdrs, const char *__addr, unsigned int __len);
/* put some bytes to " */
unsigned int (*x_getpostn) (const XDR *__xdrs);
/* returns bytes off from beginning */
bool_t (*x_setpostn) (XDR *__xdrs, unsigned int __pos);
/* lets you reposition the stream */
int32_t *(*x_inline) (XDR *__xdrs, unsigned int __len);
/* buf quick ptr to buffered data */
void (*x_destroy) (XDR *__xdrs);
/* free privates of this xdr_stream */
bool_t (*x_getint32) (XDR *__xdrs, int32_t *__ip);
/* get a int from underlying stream */
bool_t (*x_putint32) (XDR *__xdrs, const int32_t *__ip);
/* put a int to " */
}
*x_ops;
char* x_public; /* users' data */
char* x_private; /* pointer to private data */
char* x_base; /* private used for position info */
unsigned int x_handy; /* extra private word */
};
/*
* A xdrproc_t exists for each data type which is to be encoded or decoded.
*
* The second argument to the xdrproc_t is a pointer to an opaque pointer.
* The opaque pointer generally points to a structure of the data type
* to be decoded. If this pointer is 0, then the type routines should
* allocate dynamic storage of the appropriate size and return it.
* bool_t (*xdrproc_t)(XDR *, char* *);
*/
typedef bool_t (*xdrproc_t) (XDR *, void *,...);
/*
* Operations defined on a XDR handle
*
* XDR *xdrs;
* int32_t *int32p;
* long *longp;
* char* addr;
* unsigned int len;
* unsigned int pos;
*/
#define XDR_GETINT32(xdrs, int32p) \
(*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
#define xdr_getint32(xdrs, int32p) \
(*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
#define XDR_PUTINT32(xdrs, int32p) \
(*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
#define xdr_putint32(xdrs, int32p) \
(*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
#define XDR_GETLONG(xdrs, longp) \
(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
#define xdr_getlong(xdrs, longp) \
(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
#define XDR_PUTLONG(xdrs, longp) \
(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
#define xdr_putlong(xdrs, longp) \
(*(xdrs)->x_ops->x_putlong)(xdrs, longp)
#define XDR_GETBYTES(xdrs, addr, len) \
(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
#define xdr_getbytes(xdrs, addr, len) \
(*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
#define XDR_PUTBYTES(xdrs, addr, len) \
(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
#define xdr_putbytes(xdrs, addr, len) \
(*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
#define XDR_GETPOS(xdrs) \
(*(xdrs)->x_ops->x_getpostn)(xdrs)
#define xdr_getpos(xdrs) \
(*(xdrs)->x_ops->x_getpostn)(xdrs)
#define XDR_SETPOS(xdrs, pos) \
(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
#define xdr_setpos(xdrs, pos) \
(*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
#define XDR_INLINE(xdrs, len) \
(*(xdrs)->x_ops->x_inline)(xdrs, len)
#define xdr_inline(xdrs, len) \
(*(xdrs)->x_ops->x_inline)(xdrs, len)
#define XDR_DESTROY(xdrs) \
do { \
if ((xdrs)->x_ops->x_destroy) \
(*(xdrs)->x_ops->x_destroy)(xdrs); \
} while (0)
#define xdr_destroy(xdrs) \
do { \
if ((xdrs)->x_ops->x_destroy) \
(*(xdrs)->x_ops->x_destroy)(xdrs); \
} while (0)
/*
* Support struct for discriminated unions.
* You create an array of xdrdiscrim structures, terminated with
* a entry with a null procedure pointer. The xdr_union routine gets
* the discriminant value and then searches the array of structures
* for a matching value. If a match is found the associated xdr routine
* is called to handle that part of the union. If there is
* no match, then a default routine may be called.
* If there is no match and no default routine it is an error.
*/
#define NULL_xdrproc_t ((xdrproc_t)0)
struct xdr_discrim
{
int value;
xdrproc_t proc;
};
/*
* Inline routines for fast encode/decode of primitive data types.
* Caveat emptor: these use single memory cycles to get the
* data from the underlying buffer, and will fail to operate
* properly if the data is not aligned. The standard way to use these
* is to say:
* if ((buf = XDR_INLINE(xdrs, count)) == NULL)
* return (FALSE);
* <<< macro calls >>>
* where ``count'' is the number of bytes of data occupied
* by the primitive data types.
*
* N.B. and frozen for all time: each data type here uses 4 bytes
* of external representation.
*/
#define IXDR_GET_INT32(buf) ((int32_t)ntohl((uint32_t)*(buf)++))
#define IXDR_PUT_INT32(buf, v) (*(buf)++ = (int32_t)htonl((uint32_t)(v)))
#define IXDR_GET_U_INT32(buf) ((uint32_t)IXDR_GET_INT32(buf))
#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32(buf, (int32_t)(v))
/* WARNING: The IXDR_*_LONG defines are removed by Sun for new platforms
* and shouldn't be used any longer. Code which use this defines or longs
* in the RPC code will not work on 64bit Solaris platforms !
*/
#define IXDR_GET_LONG(buf) ((long)IXDR_GET_U_INT32(buf))
#define IXDR_PUT_LONG(buf, v) ((long)IXDR_PUT_INT32(buf, (long)(v)))
#define IXDR_GET_U_LONG(buf) ((unsigned long)IXDR_GET_LONG(buf))
#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG(buf, (long)(v))
#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))
#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf))
#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))
#define IXDR_GET_U_SHORT(buf) ((unsigned short)IXDR_GET_LONG(buf))
#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG(buf, (long)(v))
#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG(buf, (long)(v))
#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG(buf, (long)(v))
#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG(buf, (long)(v))
/*
* These are the "generic" xdr routines.
* None of these can have const applied because it's not possible to
* know whether the call is a read or a write to the passed parameter
* also, the XDR structure is always updated by some of these calls.
*/
extern bool_t xdr_void (void);
extern bool_t xdr_short (XDR *__xdrs, short *__sp);
extern bool_t xdr_u_short (XDR *__xdrs, unsigned short *__usp);
extern bool_t xdr_int (XDR *__xdrs, int *__ip);
extern bool_t xdr_u_int (XDR *__xdrs, unsigned int *__up);
extern bool_t xdr_long (XDR *__xdrs, long *__lp);
extern bool_t xdr_u_long (XDR *__xdrs, unsigned long *__ulp);
extern bool_t xdr_hyper (XDR *__xdrs, int64_t *__llp);
extern bool_t xdr_u_hyper (XDR *__xdrs, uint64_t *__ullp);
extern bool_t xdr_longlong_t (XDR *__xdrs, int64_t *__llp);
extern bool_t xdr_u_longlong_t (XDR *__xdrs, uint64_t *__ullp);
extern bool_t xdr_int8_t (XDR *__xdrs, int8_t *__ip);
extern bool_t xdr_uint8_t (XDR *__xdrs, uint8_t *__up);
extern bool_t xdr_int16_t (XDR *__xdrs, int16_t *__ip);
extern bool_t xdr_uint16_t (XDR *__xdrs, uint16_t *__up);
extern bool_t xdr_int32_t (XDR *__xdrs, int32_t *__ip);
extern bool_t xdr_uint32_t (XDR *__xdrs, uint32_t *__up);
extern bool_t xdr_int64_t (XDR *__xdrs, int64_t *__ip);
extern bool_t xdr_uint64_t (XDR *__xdrs, uint64_t *__up);
extern bool_t xdr_bool (XDR *__xdrs, bool_t *__bp);
extern bool_t xdr_enum (XDR *__xdrs, enum_t *__ep);
extern bool_t xdr_array (XDR * _xdrs, char* *__addrp, unsigned int *__sizep,
unsigned int __maxsize, unsigned int __elsize, xdrproc_t __elproc);
extern bool_t xdr_bytes (XDR *xdrs, char **cpp, unsigned int *sizep,
unsigned int maxsize);
extern bool_t xdr_opaque (XDR *__xdrs, char* __cp, unsigned int __cnt);
extern bool_t xdr_string (XDR *xdrs, char **cpp, unsigned int maxsize);
extern bool_t xdr_union (XDR *__xdrs, enum_t *__dscmp, char *__unp,
const struct xdr_discrim *__choices,
xdrproc_t dfault);
extern bool_t xdr_char (XDR *__xdrs, char *__cp);
extern bool_t xdr_u_char (XDR *__xdrs, unsigned char *__cp);
extern bool_t xdr_vector (XDR *__xdrs, char *__basep, unsigned int __nelem,
unsigned int __elemsize, xdrproc_t __xdr_elem);
extern bool_t xdr_float (XDR *__xdrs, float *__fp);
extern bool_t xdr_double (XDR *__xdrs, double *__dp);
extern bool_t xdr_reference (XDR *__xdrs, char* *__xpp, unsigned int __size,
xdrproc_t __proc);
extern bool_t xdr_pointer (XDR *__xdrs, char **__objpp,
unsigned int __obj_size, xdrproc_t __xdr_obj);
extern bool_t xdr_wrapstring (XDR *__xdrs, char **cpp);
extern unsigned long xdr_sizeof (xdrproc_t, void *);
/*
* Common opaque bytes objects used by many rpc protocols;
* declared here due to commonality.
*/
#define MAX_NETOBJ_SZ 1024
struct netobj
{
unsigned int n_len;
char *n_bytes;
};
typedef struct netobj netobj;
extern bool_t xdr_netobj (XDR *__xdrs, struct netobj *__np);
/*
* These are the public routines for the various implementations of
* xdr streams.
*/
/* XDR using memory buffers */
extern void xdrmem_create (XDR *__xdrs, const char* __addr,
unsigned int __size, enum xdr_op __xop);
/* XDR pseudo records for tcp */
extern void xdrrec_create (XDR *__xdrs, unsigned int __sendsize,
unsigned int __recvsize, char* __tcp_handle,
int (*__readit) (char *, char *, int),
int (*__writeit) (char *, char *, int));
/* make end of xdr record */
extern bool_t xdrrec_endofrecord (XDR *__xdrs, bool_t __sendnow);
/* move to beginning of next record */
extern bool_t xdrrec_skiprecord (XDR *__xdrs);
/* true if no more input */
extern bool_t xdrrec_eof (XDR *__xdrs);
/* free memory buffers for xdr */
extern void xdr_free (xdrproc_t __proc, char *__objp);
#endif /* rpc/xdr.h */

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
#endif
/*
* xdr_mem.h, XDR implementation using memory buffers.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* If you have some data to be interpreted as external data representation
* or to be converted to external data representation in a memory buffer,
* then this is the package for you.
*
*/
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <string.h>
#include <limits.h>
static bool_t xdrmem_getlong (XDR *, long *);
static bool_t xdrmem_putlong (XDR *, const long *);
static bool_t xdrmem_getbytes (XDR *, char *, unsigned int);
static bool_t xdrmem_putbytes (XDR *, const char *, unsigned int);
static unsigned int xdrmem_getpos (const XDR *);
static bool_t xdrmem_setpos (XDR *, unsigned int);
static int32_t *xdrmem_inline (XDR *, unsigned int);
static void xdrmem_destroy (XDR *);
static struct xdr_ops xdrmem_ops = {
xdrmem_getlong,
xdrmem_putlong,
xdrmem_getbytes,
xdrmem_putbytes,
xdrmem_getpos,
xdrmem_setpos,
xdrmem_inline,
xdrmem_destroy,
NULL,
NULL
};
/*
* The procedure xdrmem_create initializes a stream descriptor for a
* memory buffer.
*/
void
xdrmem_create (XDR *xdrs, const char* addr, unsigned int size, enum xdr_op op)
{
xdrs->x_op = op;
xdrs->x_ops = &xdrmem_ops;
xdrs->x_private = xdrs->x_base = (char*)addr;
xdrs->x_handy = size;
}
static void
xdrmem_destroy (XDR *xdrs)
{
}
static bool_t
xdrmem_getlong (XDR *xdrs, long *lp)
{
if (xdrs->x_handy < 4) return FALSE;
xdrs->x_handy -= 4;
*lp = (int32_t) ntohl((*((int32_t *) (xdrs->x_private))));
xdrs->x_private += 4;
return TRUE;
}
static bool_t
xdrmem_putlong (XDR *xdrs, const long *lp)
{
if (xdrs->x_handy < 4) return FALSE;
xdrs->x_handy -= 4;
*(int32_t *) xdrs->x_private = htonl(*lp);
xdrs->x_private += 4;
return (TRUE);
}
static bool_t
xdrmem_getbytes (XDR *xdrs, char *addr, unsigned int len)
{
if (xdrs->x_handy < len) return FALSE;
xdrs->x_handy -= len;
memmove(addr, xdrs->x_private, len);
xdrs->x_private += len;
return TRUE;
}
static bool_t
xdrmem_putbytes (XDR *xdrs, const char *addr, unsigned int len)
{
if (xdrs->x_handy < len) return FALSE;
xdrs->x_handy -= len;
memmove(xdrs->x_private, addr, len);
xdrs->x_private += len;
return (TRUE);
}
static unsigned int xdrmem_getpos (const XDR *xdrs)
{
return ((unsigned long) xdrs->x_private - (unsigned long) xdrs->x_base);
}
static bool_t xdrmem_setpos(XDR *xdrs, unsigned int pos)
{
register char* newaddr = xdrs->x_base + pos;
register char* lastaddr = xdrs->x_private + xdrs->x_handy;
if ((long) newaddr > (long) lastaddr
|| (UINT_MAX < LONG_MAX
&& (long) UINT_MAX < (long) lastaddr - (long) newaddr))
return (FALSE);
xdrs->x_private = newaddr;
xdrs->x_handy = (long) lastaddr - (long) newaddr;
return (TRUE);
}
static int32_t *
xdrmem_inline (XDR *xdrs, unsigned int len)
{
int32_t *buf = 0;
if (xdrs->x_handy >= len) {
xdrs->x_handy -= len;
buf = (int32_t *) xdrs->x_private;
xdrs->x_private += len;
}
return (buf);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -10,24 +10,44 @@
#include <rtthread.h>
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_dentry.h>
#include <dfs_file.h>
#include <dfs_mnt.h>
#include "dfs_romfs.h"
#include <errno.h>
#include <fcntl.h>
int dfs_romfs_mount(struct dfs_filesystem *fs, unsigned long rwflag, const void *data)
#include <rtdbg.h>
static const struct dfs_file_ops _rom_fops;
static const mode_t romfs_modemap[] =
{
S_IFREG | 0644, /* regular file */
S_IFDIR | 0644, /* directory */
0, /* hard link */
S_IFLNK | 0777, /* symlink */
S_IFBLK | 0600, /* blockdev */
S_IFCHR | 0600, /* chardev */
S_IFSOCK | 0644, /* socket */
S_IFIFO | 0644 /* FIFO */
};
static int dfs_romfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data)
{
struct romfs_dirent *root_dirent;
if (data == NULL)
return -EIO;
return -1;
root_dirent = (struct romfs_dirent *)data;
fs->data = root_dirent;
mnt->data = root_dirent;
return RT_EOK;
return 0;
}
int dfs_romfs_unmount(struct dfs_filesystem *fs)
static int dfs_romfs_umount(struct dfs_mnt *fs)
{
return RT_EOK;
}
@ -37,7 +57,7 @@ int dfs_romfs_ioctl(struct dfs_file *file, int cmd, void *args)
int ret = RT_EOK;
struct romfs_dirent *dirent;
dirent = (struct romfs_dirent *)file->vnode->data;
dirent = (struct romfs_dirent *)file->data;
RT_ASSERT(dirent != NULL);
switch (cmd)
@ -60,13 +80,14 @@ int dfs_romfs_ioctl(struct dfs_file *file, int cmd, void *args)
rt_inline int check_dirent(struct romfs_dirent *dirent)
{
if ((dirent->type != ROMFS_DIRENT_FILE && dirent->type != ROMFS_DIRENT_DIR)
|| dirent->size == ~0U)
if (dirent == NULL
||(dirent->type != ROMFS_DIRENT_FILE && dirent->type != ROMFS_DIRENT_DIR)
|| dirent->size == ~0)
return -1;
return 0;
}
struct romfs_dirent *dfs_romfs_lookup(struct romfs_dirent *root_dirent, const char *path, rt_size_t *size)
struct romfs_dirent *__dfs_romfs_lookup(struct romfs_dirent *root_dirent, const char *path, rt_size_t *size)
{
rt_size_t index, found;
const char *subpath, *subpath_end;
@ -83,7 +104,7 @@ struct romfs_dirent *dfs_romfs_lookup(struct romfs_dirent *root_dirent, const ch
return root_dirent;
}
/* goto root directory entries */
/* goto root directy entries */
dirent = (struct romfs_dirent *)root_dirent->data;
dirent_size = root_dirent->size;
@ -105,7 +126,7 @@ struct romfs_dirent *dfs_romfs_lookup(struct romfs_dirent *root_dirent, const ch
{
if (check_dirent(&dirent[index]) != 0)
return NULL;
if (rt_strlen(dirent[index].name) == (rt_size_t)(subpath_end - subpath) &&
if (rt_strlen(dirent[index].name) == (subpath_end - subpath) &&
rt_strncmp(dirent[index].name, subpath, (subpath_end - subpath)) == 0)
{
dirent_size = dirent[index].size;
@ -146,7 +167,68 @@ struct romfs_dirent *dfs_romfs_lookup(struct romfs_dirent *root_dirent, const ch
return NULL;
}
int dfs_romfs_read(struct dfs_file *file, void *buf, size_t count)
static struct dfs_vnode *dfs_romfs_lookup (struct dfs_dentry *dentry)
{
rt_size_t size;
struct dfs_vnode *vnode = RT_NULL;
struct romfs_dirent *root_dirent = RT_NULL, *dirent = RT_NULL;
RT_ASSERT(dentry != RT_NULL);
RT_ASSERT(dentry->mnt != RT_NULL);
root_dirent = (struct romfs_dirent *)dentry->mnt->data;
if (check_dirent(root_dirent) == 0)
{
/* create a vnode */
DLOG(msg, "rom", "vnode", DLOG_MSG, "dfs_vnode_create()");
vnode = dfs_vnode_create();
if (vnode)
{
dirent = __dfs_romfs_lookup(root_dirent, dentry->pathname, &size);
if (dirent)
{
vnode->nlink = 1;
vnode->size = dirent->size;
if (dirent->type == ROMFS_DIRENT_DIR)
{
vnode->mode = romfs_modemap[ROMFS_DIRENT_DIR] | S_IRUSR;
vnode->type = FT_DIRECTORY;
}
else if (dirent->type == ROMFS_DIRENT_FILE)
{
vnode->mode = romfs_modemap[ROMFS_DIRENT_FILE] | S_IRUSR | S_IXUSR;
vnode->type = FT_REGULAR;
}
DLOG(msg, "rom", "rom", DLOG_MSG, "vnode->data = dirent");
vnode->data = dirent;
vnode->mnt = dentry->mnt;
}
else
{
/* no-entry */
DLOG(msg, "rom", "vnode", DLOG_MSG, "dfs_vnode_destroy, no-dentry");
dfs_vnode_destroy(vnode);
vnode = RT_NULL;
}
}
}
return vnode;
}
static int dfs_romfs_free_vnode(struct dfs_vnode *vnode)
{
/* nothing to be freed */
if (vnode->ref_count <= 1)
{
vnode->data = NULL;
}
return 0;
}
static int dfs_romfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{
rt_size_t length;
struct romfs_dirent *dirent;
@ -159,39 +241,22 @@ int dfs_romfs_read(struct dfs_file *file, void *buf, size_t count)
return -EIO;
}
if (count < file->vnode->size - file->pos)
if (count < file->vnode->size - *pos)
length = count;
else
length = file->vnode->size - file->pos;
length = file->vnode->size - *pos;
if (length > 0)
rt_memcpy(buf, &(dirent->data[file->pos]), length);
memcpy(buf, &(dirent->data[*pos]), length);
/* update file current position */
file->pos += length;
*pos += length;
return length;
}
int dfs_romfs_lseek(struct dfs_file *file, off_t offset)
static int dfs_romfs_close(struct dfs_file *file)
{
if (offset <= file->vnode->size)
{
file->pos = offset;
return file->pos;
}
return -EIO;
}
int dfs_romfs_close(struct dfs_file *file)
{
RT_ASSERT(file->vnode->ref_count > 0);
if (file->vnode->ref_count > 1)
{
return RT_EOK;
}
file->vnode->data = NULL;
return RT_EOK;
}
@ -200,104 +265,56 @@ int dfs_romfs_open(struct dfs_file *file)
rt_size_t size;
struct romfs_dirent *dirent;
struct romfs_dirent *root_dirent;
struct dfs_filesystem *fs;
struct dfs_mnt *mnt;
if (file->flags & (O_CREAT | O_WRONLY | O_APPEND | O_TRUNC | O_RDWR))
{
return -EINVAL;
}
RT_ASSERT(file->vnode->ref_count > 0);
if (file->vnode->ref_count > 1)
{
if (file->vnode->type == FT_DIRECTORY
&& !(file->flags & O_DIRECTORY))
{
return -ENOENT;
}
file->pos = 0;
return 0;
}
fs = file->vnode->fs;
root_dirent = (struct romfs_dirent *)fs->data;
mnt = file->dentry->mnt;
RT_ASSERT(mnt != RT_NULL);
root_dirent = (struct romfs_dirent *)mnt->data;
if (check_dirent(root_dirent) != 0)
{
return -EIO;
}
if (file->flags & (O_CREAT | O_WRONLY | O_APPEND | O_TRUNC | O_RDWR))
{
return -EINVAL;
}
dirent = dfs_romfs_lookup(root_dirent, file->vnode->path, &size);
/* get rom dirent */
dirent = __dfs_romfs_lookup(root_dirent, file->dentry->pathname, &size);
if (dirent == NULL)
{
return -ENOENT;
}
/* entry is a directory file type */
if (dirent->type == ROMFS_DIRENT_DIR)
{
if (!(file->flags & O_DIRECTORY))
{
return -ENOENT;
}
file->vnode->type = FT_DIRECTORY;
}
else
{
/* entry is a file, but open it as a directory */
if (file->flags & O_DIRECTORY)
{
return -ENOENT;
}
file->vnode->type = FT_REGULAR;
}
file->vnode->data = dirent;
file->vnode->size = size;
file->pos = 0;
file->data = dirent;
file->fops = &_rom_fops;
file->fpos = 0;
return RT_EOK;
}
int dfs_romfs_stat(struct dfs_filesystem *fs, const char *path, struct stat *st)
static int dfs_romfs_stat(struct dfs_dentry *dentry, struct stat *st)
{
rt_size_t size;
struct romfs_dirent *dirent;
struct romfs_dirent *root_dirent;
root_dirent = (struct romfs_dirent *)fs->data;
dirent = dfs_romfs_lookup(root_dirent, path, &size);
if (dirent == NULL)
rt_err_t ret = dfs_file_lock();
if (ret == RT_EOK)
{
return -ENOENT;
st->st_dev = 0;
st->st_mode = dentry->vnode->mode;
st->st_size = dentry->vnode->size;
st->st_nlink = dentry->vnode->nlink;
st->st_mtime = 0;
dfs_file_unlock();
}
st->st_dev = 0;
st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH;
if (dirent->type == ROMFS_DIRENT_DIR)
{
st->st_mode &= ~S_IFREG;
st->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
}
st->st_size = dirent->size;
st->st_mtime = 0;
return RT_EOK;
}
int dfs_romfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
static int dfs_romfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count)
{
rt_size_t index;
rt_size_t len;
const char *name;
struct dirent *d;
struct romfs_dirent *dirent, *sub_dirent;
@ -320,11 +337,11 @@ int dfs_romfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t coun
}
index = 0;
for (index = 0; index < count && file->pos < file->vnode->size; index++)
for (index = 0; index < count && file->fpos < file->vnode->size; index++)
{
d = dirp + index;
sub_dirent = &dirent[file->pos];
sub_dirent = &dirent[file->fpos];
name = sub_dirent->name;
/* fill dirent */
@ -333,14 +350,12 @@ int dfs_romfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t coun
else
d->d_type = DT_REG;
len = rt_strlen(name);
RT_ASSERT(len <= RT_UINT8_MAX);
d->d_namlen = (rt_uint8_t)len;
d->d_namlen = rt_strlen(name);
d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_strncpy(d->d_name, name, DFS_PATH_MAX);
rt_strncpy(d->d_name, name, rt_strlen(name) + 1);
/* move to next position */
++ file->pos;
++ file->fpos;
}
return index * sizeof(struct dirent);
@ -348,37 +363,35 @@ int dfs_romfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t coun
static const struct dfs_file_ops _rom_fops =
{
dfs_romfs_open,
dfs_romfs_close,
dfs_romfs_ioctl,
dfs_romfs_read,
NULL,
NULL,
dfs_romfs_lseek,
dfs_romfs_getdents,
NULL,
.open = dfs_romfs_open,
.close = dfs_romfs_close,
.lseek = generic_dfs_lseek,
.read = dfs_romfs_read,
.getdents = dfs_romfs_getdents,
};
static const struct dfs_filesystem_ops _romfs =
static const struct dfs_filesystem_ops _romfs_ops =
{
"rom",
DFS_FS_FLAG_DEFAULT,
&_rom_fops,
.name ="rom",
.flags = 0,
.default_fops = &_rom_fops,
.mount = dfs_romfs_mount,
.umount = dfs_romfs_umount,
.stat = dfs_romfs_stat,
.lookup = dfs_romfs_lookup,
.free_vnode = dfs_romfs_free_vnode
};
dfs_romfs_mount,
dfs_romfs_unmount,
NULL,
NULL,
NULL,
dfs_romfs_stat,
NULL,
static struct dfs_filesystem_type _romfs =
{
.fs_ops = &_romfs_ops,
};
int dfs_romfs_init(void)
{
/* register rom file system */
dfs_register(&_romfs);
return 0;
}
INIT_COMPONENT_EXPORT(dfs_romfs_init);

View File

@ -27,6 +27,8 @@ static const unsigned char _dummy_txt[] =
rt_weak const struct romfs_dirent _root_dirent[] =
{
{ROMFS_DIRENT_DIR, "dev", RT_NULL, 0},
{ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0},
{ROMFS_DIRENT_DIR, "dummy", (rt_uint8_t *)_dummy, sizeof(_dummy) / sizeof(_dummy[0])},
{ROMFS_DIRENT_FILE, "dummy.txt", _dummy_txt, sizeof(_dummy_txt)},
};
@ -35,4 +37,3 @@ rt_weak const struct romfs_dirent romfs_root =
{
ROMFS_DIRENT_DIR, "/", (rt_uint8_t *)_root_dirent, sizeof(_root_dirent) / sizeof(_root_dirent[0])
};

View File

@ -94,4 +94,3 @@ int dfs_skt_init(void)
return 0;
}
INIT_COMPONENT_EXPORT(dfs_skt_init);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -13,7 +13,9 @@
#include <rtthread.h>
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_dentry.h>
#include <dfs_file.h>
#include <dfs_mnt.h>
#ifdef RT_USING_SMART
#include <lwp.h>
@ -109,48 +111,55 @@ static int _free_subdir(struct tmpfs_file *dfile)
return 0;
}
int dfs_tmpfs_mount(struct dfs_filesystem *fs,
unsigned long rwflag,
const void *data)
static int dfs_tmpfs_mount(struct dfs_mnt *mnt,
unsigned long rwflag,
const void *data)
{
struct tmpfs_sb *superblock;
superblock = rt_calloc(1, sizeof(struct tmpfs_sb));
superblock->df_size = sizeof(struct tmpfs_sb);
superblock->magic = TMPFS_MAGIC;
rt_list_init(&superblock->sibling);
if (superblock)
{
superblock->df_size = sizeof(struct tmpfs_sb);
superblock->magic = TMPFS_MAGIC;
rt_list_init(&superblock->sibling);
superblock->root.name[0] = '/';
superblock->root.sb = superblock;
superblock->root.type = TMPFS_TYPE_DIR;
rt_list_init(&superblock->root.sibling);
rt_list_init(&superblock->root.subdirs);
superblock->root.name[0] = '/';
superblock->root.sb = superblock;
superblock->root.type = TMPFS_TYPE_DIR;
rt_list_init(&superblock->root.sibling);
rt_list_init(&superblock->root.subdirs);
fs->data = superblock;
mnt->data = superblock;
}
else
{
return -1;
}
return RT_EOK;
return 0;
}
int dfs_tmpfs_unmount(struct dfs_filesystem *fs)
static int dfs_tmpfs_unmount(struct dfs_mnt *mnt)
{
struct tmpfs_sb *superblock;
superblock = (struct tmpfs_sb *)fs->data;
superblock = (struct tmpfs_sb *)mnt->data;
RT_ASSERT(superblock != NULL);
_free_subdir(&(superblock->root));
rt_free(superblock);
fs->data = NULL;
mnt->data = NULL;
return RT_EOK;
}
int dfs_tmpfs_statfs(struct dfs_filesystem *fs, struct statfs *buf)
int dfs_tmpfs_statfs(struct dfs_mnt *mnt, struct statfs *buf)
{
struct tmpfs_sb *superblock;
superblock = (struct tmpfs_sb *)fs->data;
superblock = (struct tmpfs_sb *)mnt->data;
RT_ASSERT(superblock != NULL);
RT_ASSERT(buf != NULL);
@ -263,7 +272,7 @@ find_subpath:
return NULL;
}
int dfs_tmpfs_read(struct dfs_file *file, void *buf, size_t count)
static int dfs_tmpfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
{
rt_size_t length;
struct tmpfs_file *d_file;
@ -271,66 +280,68 @@ int dfs_tmpfs_read(struct dfs_file *file, void *buf, size_t count)
d_file = (struct tmpfs_file *)file->vnode->data;
RT_ASSERT(d_file != NULL);
if (count < file->vnode->size - file->pos)
if (count < file->vnode->size - file->fpos)
length = count;
else
length = file->vnode->size - file->pos;
length = file->vnode->size - file->fpos;
if (length > 0)
memcpy(buf, &(d_file->data[file->pos]), length);
memcpy(buf, &(d_file->data[file->fpos]), length);
/* update file current position */
file->pos += length;
file->fpos += length;
*pos = file->fpos;
return length;
}
int dfs_tmpfs_write(struct dfs_file *fd, const void *buf, size_t count)
static int dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
{
struct tmpfs_file *d_file;
struct tmpfs_sb *superblock;
d_file = (struct tmpfs_file *)fd->vnode->data;
d_file = (struct tmpfs_file *)file->vnode->data;
RT_ASSERT(d_file != NULL);
superblock = d_file->sb;
RT_ASSERT(superblock != NULL);
if (count + fd->pos > fd->vnode->size)
if (count + file->fpos > file->vnode->size)
{
rt_uint8_t *ptr;
ptr = rt_realloc(d_file->data, fd->pos + count);
ptr = rt_realloc(d_file->data, file->fpos + count);
if (ptr == NULL)
{
rt_set_errno(-ENOMEM);
return 0;
}
superblock->df_size += (fd->pos - d_file->size + count);
superblock->df_size += (file->fpos - d_file->size + count);
/* update d_file and file size */
d_file->data = ptr;
d_file->size = fd->pos + count;
fd->vnode->size = d_file->size;
d_file->size = file->fpos + count;
file->vnode->size = d_file->size;
LOG_D("tmpfile ptr:%x, size:%d", ptr, d_file->size);
}
if (count > 0)
memcpy(d_file->data + fd->pos, buf, count);
memcpy(d_file->data + file->fpos, buf, count);
/* update file current position */
fd->pos += count;
file->fpos += count;
*pos = file->fpos;
return count;
}
int dfs_tmpfs_lseek(struct dfs_file *file, off_t offset)
static int dfs_tmpfs_lseek(struct dfs_file *file, off_t offset, int wherece)
{
if (offset <= (off_t)file->vnode->size)
{
file->pos = offset;
file->fpos = offset;
return file->pos;
return file->fpos;
}
return -EIO;
@ -339,97 +350,23 @@ int dfs_tmpfs_lseek(struct dfs_file *file, off_t offset)
int dfs_tmpfs_close(struct dfs_file *file)
{
RT_ASSERT(file->vnode->ref_count > 0);
if (file->vnode->ref_count > 1)
{
return 0;
}
file->vnode->data = NULL;
return RT_EOK;
}
int dfs_tmpfs_open(struct dfs_file *file)
{
rt_size_t size;
struct tmpfs_sb *superblock;
struct tmpfs_file *d_file, *p_file;
struct dfs_filesystem *fs;
char parent_path[DFS_PATH_MAX],file_name[TMPFS_NAME_MAX];
struct tmpfs_file *d_file;
RT_DEFINE_SPINLOCK(lock);
RT_ASSERT(file->vnode->ref_count > 0);
if (file->vnode->ref_count > 1)
{
if (file->vnode->type == FT_DIRECTORY
&& !(file->flags & O_DIRECTORY))
{
return -ENOENT;
}
file->pos = 0;
return 0;
}
fs = file->vnode->fs;
superblock = (struct tmpfs_sb *)fs->data;
RT_ASSERT(superblock != NULL);
/* find file */
d_file = dfs_tmpfs_lookup(superblock, file->vnode->path, &size);
if (d_file == NULL && !(file->flags & O_CREAT))
return -ENOENT;
/* Creates a new file. */
if (file->flags & O_CREAT)
{
if (d_file == NULL)
{
/* find parent file */
_path_separate(file->vnode->path, parent_path, file_name);
if (file_name[0] == '\0') /* it's root dir */
return -ENOENT;
/* open parent directory */
p_file = dfs_tmpfs_lookup(superblock, parent_path, &size);
if (p_file == NULL)
return -ENOENT;
/* create a file entry */
d_file = (struct tmpfs_file *)rt_calloc(1, sizeof(struct tmpfs_file));
if (d_file == NULL)
{
return -ENOMEM;
}
superblock->df_size += sizeof(struct tmpfs_file);
strncpy(d_file->name, file_name, TMPFS_NAME_MAX);
rt_list_init(&(d_file->subdirs));
rt_list_init(&(d_file->sibling));
d_file->data = NULL;
d_file->size = 0;
d_file->sb = superblock;
if (file->flags & O_DIRECTORY)
{
d_file->type = TMPFS_TYPE_DIR;
}
else
{
d_file->type = TMPFS_TYPE_FILE;
}
rt_hw_spin_lock(&lock);
rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling));
rt_hw_spin_unlock(&lock);
}
}
d_file = (struct tmpfs_file *)file->vnode->data;
RT_ASSERT(d_file != RT_NULL);
/* Creates a new file.
* If the file is existing, it is truncated and overwritten.
*/
* If the file is existing, it is truncated and overwritten.
*/
if (file->flags & O_TRUNC)
{
d_file->size = 0;
file->vnode->size = d_file->size;
file->fpos = file->vnode->size;
if (d_file->data != NULL)
{
/* ToDo: fix for rt-smart. */
@ -438,52 +375,33 @@ int dfs_tmpfs_open(struct dfs_file *file)
}
}
/* fill file */
if (d_file->type == TMPFS_TYPE_DIR)
{
if (file->flags & O_DIRECTORY)
file->vnode->type = FT_DIRECTORY;
else
return -ENOMEM;
}
else
{
if (file->flags & O_DIRECTORY)
{
return -ENOMEM;
}
file->vnode->type = FT_DEVICE;
}
file->vnode->data = d_file;
file->vnode->size = d_file->size;
if (file->flags & O_APPEND)
{
file->pos = file->vnode->size;
file->fpos = file->vnode->size;
}
else
{
file->pos = 0;
file->fpos = 0;
}
return 0;
}
int dfs_tmpfs_stat(struct dfs_filesystem *fs,
const char *path,
struct stat *st)
static int dfs_tmpfs_stat(struct dfs_dentry *dentry, struct stat *st)
{
rt_size_t size;
struct tmpfs_file *d_file;
struct tmpfs_sb *superblock;
superblock = (struct tmpfs_sb *)fs->data;
d_file = dfs_tmpfs_lookup(superblock, path, &size);
superblock = (struct tmpfs_sb *)dentry->mnt->data;
d_file = dfs_tmpfs_lookup(superblock, dentry->pathname, &size);
if (d_file == NULL)
return -ENOENT;
st->st_dev = 0;
st->st_dev = (dev_t)(size_t)(dentry->mnt->dev_id);
st->st_ino = (ino_t)dfs_dentry_full_path_crc32(dentry);
st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH;
if (d_file->type == TMPFS_TYPE_DIR)
@ -518,14 +436,14 @@ int dfs_tmpfs_getdents(struct dfs_file *file,
if (count == 0)
return -EINVAL;
end = file->pos + count;
end = file->fpos + count;
index = 0;
count = 0;
rt_list_for_each(list, &d_file->subdirs)
{
n_file = rt_list_entry(list, struct tmpfs_file, sibling);
if (index >= (rt_size_t)file->pos)
if (index >= (rt_size_t)file->fpos)
{
d = dirp + count;
if (d_file->type == TMPFS_TYPE_FILE)
@ -541,7 +459,7 @@ int dfs_tmpfs_getdents(struct dfs_file *file,
rt_strncpy(d->d_name, n_file->name, TMPFS_NAME_MAX);
count += 1;
file->pos += 1;
file->fpos += 1;
}
index += 1;
if (index >= end)
@ -553,7 +471,7 @@ int dfs_tmpfs_getdents(struct dfs_file *file,
return count * sizeof(struct dirent);
}
int dfs_tmpfs_unlink(struct dfs_filesystem *fs, const char *path)
int dfs_tmpfs_unlink(struct dfs_dentry *dentry)
{
rt_size_t size;
struct tmpfs_sb *superblock;
@ -561,10 +479,10 @@ int dfs_tmpfs_unlink(struct dfs_filesystem *fs, const char *path)
RT_DEFINE_SPINLOCK(lock);
superblock = (struct tmpfs_sb *)fs->data;
superblock = (struct tmpfs_sb *)dentry->mnt->data;
RT_ASSERT(superblock != NULL);
d_file = dfs_tmpfs_lookup(superblock, path, &size);
d_file = dfs_tmpfs_lookup(superblock, dentry->pathname, &size);
if (d_file == NULL)
return -ENOENT;
@ -579,30 +497,28 @@ int dfs_tmpfs_unlink(struct dfs_filesystem *fs, const char *path)
return RT_EOK;
}
int dfs_tmpfs_rename(struct dfs_filesystem *fs,
const char *oldpath,
const char *newpath)
int dfs_tmpfs_rename(struct dfs_dentry *old_dentry, struct dfs_dentry *new_dentry)
{
struct tmpfs_file *d_file, *p_file;
struct tmpfs_sb *superblock;
rt_size_t size;
char parent_path[DFS_PATH_MAX],file_name[TMPFS_NAME_MAX];
char parent_path[DFS_PATH_MAX], file_name[TMPFS_NAME_MAX];
RT_DEFINE_SPINLOCK(lock);
superblock = (struct tmpfs_sb *)fs->data;
superblock = (struct tmpfs_sb *)old_dentry->mnt->data;
RT_ASSERT(superblock != NULL);
d_file = dfs_tmpfs_lookup(superblock, newpath, &size);
d_file = dfs_tmpfs_lookup(superblock, new_dentry->pathname, &size);
if (d_file != NULL)
return -EEXIST;
d_file = dfs_tmpfs_lookup(superblock, oldpath, &size);
d_file = dfs_tmpfs_lookup(superblock, old_dentry->pathname, &size);
if (d_file == NULL)
return -ENOENT;
/* find parent file */
_path_separate(newpath, parent_path, file_name);
_path_separate(new_dentry->pathname, parent_path, file_name);
if (file_name[0] == '\0') /* it's root dir */
return -ENOENT;
/* open parent directory */
@ -622,32 +538,167 @@ int dfs_tmpfs_rename(struct dfs_filesystem *fs,
return RT_EOK;
}
static struct dfs_vnode *_dfs_tmpfs_lookup(struct dfs_dentry *dentry)
{
struct dfs_vnode *vnode = RT_NULL;
rt_size_t size;
struct tmpfs_sb *superblock;
struct tmpfs_file *d_file;
if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
{
return NULL;
}
superblock = (struct tmpfs_sb *)dentry->mnt->data;
d_file = dfs_tmpfs_lookup(superblock, dentry->pathname, &size);
if (d_file)
{
vnode = dfs_vnode_create();
if (vnode)
{
if (d_file->type == TMPFS_TYPE_DIR)
{
vnode->mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR;
vnode->type = FT_DIRECTORY;
}
else
{
vnode->mode = S_IFREG | S_IRUSR | S_IWUSR | S_IXUSR;
vnode->type = FT_REGULAR;
}
vnode->mnt = dentry->mnt;
vnode->data = d_file;
vnode->size = d_file->size;
}
}
return vnode;
}
static struct dfs_vnode *dfs_tmpfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode)
{
struct dfs_vnode *vnode = RT_NULL;
rt_size_t size;
struct tmpfs_sb *superblock;
struct tmpfs_file *d_file, *p_file;
char parent_path[DFS_PATH_MAX], file_name[TMPFS_NAME_MAX];
RT_DEFINE_SPINLOCK(lock);
if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL)
{
return NULL;
}
superblock = (struct tmpfs_sb *)dentry->mnt->data;
vnode = dfs_vnode_create();
if (vnode)
{
/* find parent file */
_path_separate(dentry->pathname, parent_path, file_name);
if (file_name[0] == '\0') /* it's root dir */
{
dfs_vnode_destroy(vnode);
return NULL;
}
/* open parent directory */
p_file = dfs_tmpfs_lookup(superblock, parent_path, &size);
if (p_file == NULL)
{
dfs_vnode_destroy(vnode);
return NULL;
}
/* create a file entry */
d_file = (struct tmpfs_file *)rt_calloc(1, sizeof(struct tmpfs_file));
if (d_file == NULL)
{
dfs_vnode_destroy(vnode);
return NULL;
}
superblock->df_size += sizeof(struct tmpfs_file);
strncpy(d_file->name, file_name, TMPFS_NAME_MAX);
rt_list_init(&(d_file->subdirs));
rt_list_init(&(d_file->sibling));
d_file->data = NULL;
d_file->size = 0;
d_file->sb = superblock;
if (type == FT_DIRECTORY)
{
d_file->type = TMPFS_TYPE_DIR;
vnode->mode = S_IFDIR | mode;
vnode->type = FT_DIRECTORY;
}
else
{
d_file->type = TMPFS_TYPE_FILE;
vnode->mode = S_IFREG | mode;
vnode->type = FT_REGULAR;
}
rt_hw_spin_lock(&lock);
rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling));
rt_hw_spin_unlock(&lock);
vnode->mnt = dentry->mnt;
vnode->data = d_file;
vnode->size = d_file->size;
}
return vnode;
}
static int dfs_tmpfs_free_vnode(struct dfs_vnode *vnode)
{
/* nothing to be freed */
if (vnode && vnode->ref_count <= 1)
{
vnode->data = NULL;
}
return 0;
}
static const struct dfs_file_ops _tmp_fops =
{
dfs_tmpfs_open,
dfs_tmpfs_close,
dfs_tmpfs_ioctl,
dfs_tmpfs_read,
dfs_tmpfs_write,
NULL, /* flush */
dfs_tmpfs_lseek,
dfs_tmpfs_getdents,
.open = dfs_tmpfs_open,
.close = dfs_tmpfs_close,
.ioctl = dfs_tmpfs_ioctl,
.read = dfs_tmpfs_read,
.write = dfs_tmpfs_write,
.lseek = dfs_tmpfs_lseek,
.getdents = dfs_tmpfs_getdents,
};
static const struct dfs_filesystem_ops _tmpfs =
static const struct dfs_filesystem_ops _tmpfs_ops =
{
"tmp",
DFS_FS_FLAG_DEFAULT,
&_tmp_fops,
.name = "tmp",
.flags = DFS_FS_FLAG_DEFAULT,
.default_fops = &_tmp_fops,
dfs_tmpfs_mount,
dfs_tmpfs_unmount,
NULL, /* mkfs */
dfs_tmpfs_statfs,
.mount = dfs_tmpfs_mount,
.umount = dfs_tmpfs_unmount,
.statfs = dfs_tmpfs_statfs,
dfs_tmpfs_unlink,
dfs_tmpfs_stat,
dfs_tmpfs_rename,
.unlink = dfs_tmpfs_unlink,
.stat = dfs_tmpfs_stat,
.rename = dfs_tmpfs_rename,
.lookup = _dfs_tmpfs_lookup,
.create_vnode = dfs_tmpfs_create_vnode,
.free_vnode = dfs_tmpfs_free_vnode
};
static struct dfs_filesystem_type _tmpfs =
{
.fs_ops = &_tmpfs_ops,
};
int dfs_tmpfs_init(void)
@ -657,3 +708,4 @@ int dfs_tmpfs_init(void)
return 0;
}
INIT_COMPONENT_EXPORT(dfs_tmpfs_init);

View File

@ -1,11 +1,12 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2005-02-22 Bernard The first version.
* 2023-05-05 Bernard change to dfs v2.0
*/
#ifndef __DFS_H__
@ -15,21 +16,15 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include "../../libc/compilers/common/include/dirent.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <rtatomic.h>
#include <rtdevice.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DFS_FILESYSTEMS_MAX
#define DFS_FILESYSTEMS_MAX 4
#endif
#ifndef DFS_FD_MAX
#define DFS_FD_MAX 16
#endif
@ -49,25 +44,32 @@ extern "C" {
#define SECTOR_SIZE 512
#endif
#ifndef DFS_FILESYSTEM_TYPES_MAX
#define DFS_FILESYSTEM_TYPES_MAX 2
#endif
#define DFS_FS_FLAG_DEFAULT 0x00 /* default flag */
#define DFS_FS_FLAG_FULLPATH 0x01 /* set full path to underlaying file system */
/* File types */
#define FT_REGULAR 0 /* regular file */
#define FT_SOCKET 1 /* socket file */
#define FT_DIRECTORY 2 /* directory */
#define FT_USER 3 /* user defined */
#define FT_DEVICE 4 /* device */
/* File flags */
#define DFS_F_OPEN 0x01000000
#define DFS_F_DIRECTORY 0x02000000
#define DFS_F_EOF 0x04000000
#define DFS_F_ERR 0x08000000
#define DFS_F_FREAD 0x01
#define DFS_F_FWRITE 0x02
#ifdef __cplusplus
extern "C" {
#endif
rt_inline int dfs_fflags(int oflags)
{
int rw = oflags & O_ACCMODE;
oflags &= ~O_ACCMODE;
return (rw + 1) | oflags;
}
rt_inline int dfs_oflags(int fflags)
{
int rw = fflags & (DFS_F_FREAD | DFS_F_FWRITE);
fflags &= ~(DFS_F_FREAD | DFS_F_FWRITE);
return (rw - 1) | fflags;
}
struct dfs_fdtable
{
@ -81,18 +83,12 @@ int dfs_init(void);
char *dfs_normalize_path(const char *directory, const char *filename);
const char *dfs_subdir(const char *directory, const char *filename);
int fd_is_open(const char *pathname);
struct dfs_fdtable *dfs_fdtable_get(void);
void dfs_lock(void);
rt_err_t dfs_lock(void);
void dfs_unlock(void);
void dfs_file_lock(void);
rt_err_t dfs_file_lock(void);
void dfs_file_unlock(void);
void dfs_fm_lock(void);
void dfs_fm_unlock(void);
#ifdef DFS_USING_POSIX
/* FD APIs */
int fdt_fd_new(struct dfs_fdtable *fdt);
@ -108,6 +104,7 @@ void fd_init(struct dfs_file *fd);
struct dfs_fdtable *dfs_fdtable_get(void);
struct dfs_fdtable *dfs_fdtable_get_global(void);
int dfs_dup(int oldfd, int startfd);
#endif /* DFS_USING_POSIX */
#ifdef __cplusplus

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-05-05 Bernard Implement dentry in dfs v2.0
*/
#ifndef __DFS_DENTRY_H__
#define __DFS_DENTRY_H__
#include "dfs_file.h"
#include "dfs_fs.h"
#ifdef __cplusplus
extern "C"
{
#endif
struct dfs_mnt;
struct dfs_vnode;
struct dfs_dentry
{
rt_list_t hashlist;
uint32_t flags;
#define DENTRY_IS_MOUNTED 0x1 /* dentry is mounted */
#define DENTRY_IS_ALLOCED 0x2 /* dentry is allocated */
#define DENTRY_IS_ADDHASH 0x4 /* dentry was added into hash table */
#define DENTRY_IS_OPENED 0x8 /* dentry was opened. */
char *pathname; /* the pathname under mounted file sytem */
struct dfs_vnode *vnode; /* the vnode of this dentry */
struct dfs_mnt *mnt; /* which mounted file system does this dentry belong to */
rt_atomic_t ref_count; /* the reference count */
};
struct dfs_dentry *dfs_dentry_create(struct dfs_mnt *mnt, char *fullpath);
struct dfs_dentry *dfs_dentry_unref(struct dfs_dentry *dentry);
struct dfs_dentry *dfs_dentry_ref(struct dfs_dentry *dentry);
void dfs_dentry_insert(struct dfs_dentry *dentry);
struct dfs_dentry *dfs_dentry_lookup(struct dfs_mnt *mnt, const char *path, uint32_t flags);
/* get full path of a dentry */
char* dfs_dentry_full_path(struct dfs_dentry* dentry);
/* get pathname (with mnt path) of a dentry */
char* dfs_dentry_pathname(struct dfs_dentry* dentry);
/* get full path crc32 */
uint32_t dfs_dentry_full_path_crc32(struct dfs_dentry* dentry);
int dfs_dentry_init(void);
#ifdef __cplusplus
}
#endif
#endif /*__DFS_DENTRY_H__*/

View File

@ -1,11 +1,12 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2005-01-26 Bernard The first version.
* 2023-05-05 Bernard Change to dfs v2.0
*/
#ifndef __DFS_FILE_H__
@ -15,55 +16,113 @@
#include <dfs_fs.h>
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#define STDIN_FILENO 0 /* standard input file descriptor */
#define STDOUT_FILENO 1 /* standard output file descriptor */
#define STDERR_FILENO 2 /* standard error file descriptor */
struct dfs_file;
struct dfs_vnode;
struct dfs_dentry;
struct dfs_attr;
struct rt_pollreq;
struct dirent;
struct lwp_avl_struct;
struct file_lock;
struct dfs_file_ops
{
int (*open) (struct dfs_file *fd);
int (*close) (struct dfs_file *fd);
int (*ioctl) (struct dfs_file *fd, int cmd, void *args);
int (*read) (struct dfs_file *fd, void *buf, size_t count);
int (*write) (struct dfs_file *fd, const void *buf, size_t count);
int (*flush) (struct dfs_file *fd);
int (*lseek) (struct dfs_file *fd, off_t offset);
int (*getdents) (struct dfs_file *fd, struct dirent *dirp, uint32_t count);
int (*open)(struct dfs_file *file);
int (*close)(struct dfs_file *file);
int (*ioctl)(struct dfs_file *file, int cmd, void *arg);
int (*read)(struct dfs_file *file, void *buf, size_t count, off_t *pos);
int (*write)(struct dfs_file *file, const void *buf, size_t count, off_t *pos);
int (*flush)(struct dfs_file *file);
int (*lseek)(struct dfs_file *file, off_t offset, int wherece);
int (*truncate)(struct dfs_file *file, off_t offset);
int (*getdents)(struct dfs_file *file, struct dirent *dirp, uint32_t count);
int (*poll)(struct dfs_file *file, struct rt_pollreq *req);
int (*poll) (struct dfs_file *fd, struct rt_pollreq *req);
int (*mmap)(struct dfs_file *file, struct lwp_avl_struct *mmap);
int (*lock)(struct dfs_file *file, struct file_lock *flock);
int (*flock)(struct dfs_file *file, int, struct file_lock *flock);
};
/* file descriptor */
#define DFS_FD_MAGIC 0xfdfd
struct dfs_vnode
{
uint16_t type; /* Type (regular or socket) */
uint32_t flags;
uint32_t mode;
int type; /* node type */
char *path; /* Name (below mount point) */
char *fullpath; /* Full path is hash key */
int ref_count; /* Descriptor reference count */
rt_list_t list; /* The node of vnode hash table */
rt_atomic_t ref_count; /* reference count */
struct dfs_mnt *mnt; /* which mounted file system does this vnode belong to */
size_t size;
uint32_t nlink;
struct dfs_filesystem *fs;
const struct dfs_file_ops *fops;
uint32_t flags; /* self flags, is dir etc.. */
size_t size; /* Size in bytes */
void *data; /* Specific file system data */
unsigned int uid;
unsigned int gid;
struct timespec atime;
struct timespec mtime;
struct timespec ctime;
void *data; /* private data of this file system */
};
/* file descriptor */
#define DFS_FD_MAGIC 0xfdfd
struct dfs_file
{
uint16_t magic; /* file descriptor magic number */
uint32_t flags; /* Descriptor flags */
int ref_count; /* Descriptor reference count */
off_t pos; /* Current file position */
struct dfs_vnode *vnode; /* file node struct */
void *data; /* Specific fd data */
uint16_t magic;
uint16_t mode;
uint32_t flags;
rt_atomic_t ref_count;
off_t fpos;
struct rt_mutex pos_lock;
const struct dfs_file_ops *fops;
struct dfs_dentry *dentry; /* dentry of this file */
struct dfs_vnode *vnode; /* vnode of this file */
void *data;
};
/* file is open for reading */
#define FMODE_READ 0x1
/* file is open for writing */
#define FMODE_WRITE 0x2
/* file is seekable */
#define FMODE_LSEEK 0x4
/* file can be accessed using pread */
#define FMODE_PREAD 0x8
/* file can be accessed using pwrite */
#define FMODE_PWRITE 0x10
/* File is opened for execution with sys_execve / sys_uselib */
#define FMODE_EXEC 0x20
/* File is opened with O_NDELAY (only set for block devices) */
#define FMODE_NDELAY 0x40
/* File is opened with O_EXCL (only set for block devices) */
#define FMODE_EXCL 0x80
/* dfs_vnode.c */
int dfs_vnode_init(struct dfs_vnode *vnode, int type, const struct dfs_file_ops *fops);
struct dfs_vnode *dfs_vnode_create(void);
int dfs_vnode_destroy(struct dfs_vnode* vnode);
struct dfs_vnode *dfs_vnode_ref(struct dfs_vnode *vnode);
void dfs_vnode_unref(struct dfs_vnode *vnode);
/*dfs_file.c*/
struct dfs_mmap2_args
{
void *addr;
@ -75,22 +134,37 @@ struct dfs_mmap2_args
void *ret;
};
void dfs_vnode_mgr_init(void);
int dfs_file_is_open(const char *pathname);
int dfs_file_open(struct dfs_file *fd, const char *path, int flags);
int dfs_file_close(struct dfs_file *fd);
int dfs_file_ioctl(struct dfs_file *fd, int cmd, void *args);
int dfs_file_read(struct dfs_file *fd, void *buf, size_t len);
int dfs_file_getdents(struct dfs_file *fd, struct dirent *dirp, size_t nbytes);
int dfs_file_unlink(const char *path);
int dfs_file_write(struct dfs_file *fd, const void *buf, size_t len);
int dfs_file_flush(struct dfs_file *fd);
int dfs_file_lseek(struct dfs_file *fd, off_t offset);
void dfs_file_init(struct dfs_file *file);
void dfs_file_deinit(struct dfs_file *file);
int dfs_file_open(struct dfs_file *file, const char *path, int flags, mode_t mode);
int dfs_file_close(struct dfs_file *file);
ssize_t dfs_file_read(struct dfs_file *file, void *buf, size_t len);
ssize_t dfs_file_write(struct dfs_file *file, const void *buf, size_t len);
int generic_dfs_lseek(struct dfs_file *file, off_t offset, int whence);
off_t dfs_file_lseek(struct dfs_file *file, off_t offset, int wherece);
int dfs_file_stat(const char *path, struct stat *buf);
int dfs_file_rename(const char *oldpath, const char *newpath);
int dfs_file_ftruncate(struct dfs_file *fd, off_t length);
int dfs_file_mmap2(struct dfs_file *fd, struct dfs_mmap2_args *mmap2);
int dfs_file_lstat(const char *path, struct stat *buf);
int dfs_file_setattr(const char *path, struct dfs_attr *attr);
int dfs_file_fstat(struct dfs_file *file, struct stat *buf);
int dfs_file_ioctl(struct dfs_file *file, int cmd, void *args);
int dfs_file_fcntl(int fd, int cmd, unsigned long arg);
int dfs_file_fsync(struct dfs_file *file);
int dfs_file_unlink(const char *path);
int dfs_file_link(const char *oldname, const char *newname);
int dfs_file_symlink(const char *oldname, const char *name);
int dfs_file_readlink(const char *path, char *buf, int bufsize);
int dfs_file_rename(const char *old_file, const char *new_file);
int dfs_file_ftruncate(struct dfs_file *file, off_t length);
int dfs_file_getdents(struct dfs_file *file, struct dirent *dirp, size_t nbytes);
int dfs_file_mkdir(const char *path, mode_t mode);
int dfs_file_rmdir(const char *pathname);
int dfs_file_isdir(const char *path);
int dfs_file_access(const char *path, mode_t mode);
int dfs_file_chdir(const char *path);
char *dfs_file_getcwd(char *buf, size_t size);
int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2);
/* 0x5254 is just a magic number to make these relatively unique ("RT") */
#define RT_FIOFTRUNCATE 0x52540000U

View File

@ -1,99 +1,98 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2005-02-22 Bernard The first version.
* 2023-05-05 Bernard Change to dfs v2.0
*/
#ifndef __DFS_FS_H__
#define __DFS_FS_H__
#include <dfs.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <dfs_file.h>
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
/* Pre-declaration */
struct dfs_filesystem;
struct dfs_file;
/* File system operations */
struct dfs_filesystem_ops
{
char *name;
uint32_t flags; /* flags for file system operations */
/* operations for file */
const struct dfs_file_ops *fops;
/* mount and unmount file system */
int (*mount) (struct dfs_filesystem *fs, unsigned long rwflag, const void *data);
int (*unmount) (struct dfs_filesystem *fs);
/* make a file system */
int (*mkfs) (rt_device_t dev_id, const char *fs_name);
int (*statfs) (struct dfs_filesystem *fs, struct statfs *buf);
int (*unlink) (struct dfs_filesystem *fs, const char *pathname);
int (*stat) (struct dfs_filesystem *fs, const char *filename, struct stat *buf);
int (*rename) (struct dfs_filesystem *fs, const char *oldpath, const char *newpath);
};
/* Mounted file system */
struct dfs_filesystem
{
rt_device_t dev_id; /* Attached device */
char *path; /* File system mount point */
const struct dfs_filesystem_ops *ops; /* Operations for file system type */
void *data; /* Specific file system data */
};
/* file system partition table */
struct dfs_partition
{
uint8_t type; /* file system type */
off_t offset; /* partition start offset */
size_t size; /* partition size */
uint8_t type; /* file system type */
off_t offset; /* partition start offset */
size_t size; /* partition size */
rt_sem_t lock;
};
/* mount table */
struct dfs_mount_tbl
struct dfs_attr
{
const char *device_name;
const char *path;
const char *filesystemtype;
unsigned long rwflag;
const void *data;
mode_t st_mode;
};
int dfs_register(const struct dfs_filesystem_ops *ops);
struct dfs_filesystem *dfs_filesystem_lookup(const char *path);
struct dfs_mnt;
struct dfs_dentry;
struct dfs_vnode;
struct statfs;
struct dfs_filesystem_ops
{
const char *name;
uint32_t flags;
#define FS_NEED_DEVICE 0x1
const struct dfs_file_ops *default_fops;
int (*mount)(struct dfs_mnt *mnt, unsigned long rwflag, const void *data);
int (*umount)(struct dfs_mnt *mnt);
int (*mkfs)(rt_device_t devid, const char *fs_name);
int (*readlink)(struct dfs_dentry *dentry, char *buf, int len);
int (*link)(struct dfs_dentry *src_dentry, struct dfs_dentry *dst_dentry); /*hard link interface */
int (*unlink)(struct dfs_dentry *dentry);
int (*symlink)(struct dfs_dentry *parent_dentry, const char *target, const char *newpath); /*soft link interface*/
int (*rename)(struct dfs_dentry *old_dentry, struct dfs_dentry *new_dentry);
int (*stat)(struct dfs_dentry *dentry, struct stat *buf);
int (*statfs)(struct dfs_mnt *mnt, struct statfs *buf);
int (*setattr) (struct dfs_dentry *dentry, struct dfs_attr *attr);
struct dfs_vnode* (*lookup)(struct dfs_dentry *dentry);
struct dfs_vnode* (*create_vnode)(struct dfs_dentry *dentry, int type, mode_t mode);
int (*free_vnode)(struct dfs_vnode* vnode);
};
struct dfs_filesystem_type
{
const struct dfs_filesystem_ops *fs_ops;
struct dfs_filesystem_type *next;
};
int dfs_unregister(struct dfs_filesystem_type *fs);
int dfs_register(struct dfs_filesystem_type *fs);
const char *dfs_filesystem_get_mounted_path(struct rt_device *device);
int dfs_filesystem_get_partition(struct dfs_partition *part,
uint8_t *buf,
uint32_t pindex);
int dfs_mount(const char *device_name,
const char *path,
const char *filesystemtype,
unsigned long rwflag,
const void *data);
const char *path,
const char *filesystemtype,
unsigned long rwflag,
const void *data);
int dfs_umount(const char *specialfile);
int dfs_unmount(const char *specialfile);
int dfs_mkfs(const char *fs_name, const char *device_name);
int dfs_statfs(const char *path, struct statfs *buffer);
int dfs_mount_device(rt_device_t dev);
int dfs_unmount_device(rt_device_t dev);
int dfs_filesystem_get_partition(struct dfs_partition *part,
uint8_t *buf,
uint32_t pindex);
#ifdef __cplusplus
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-05-05 Bernard Implement dentry in dfs v2.0
*/
#ifndef DFS_MNT_H__
#define DFS_MNT_H__
#include <rtservice.h>
#include <rtthread.h>
#ifdef __cplusplus
extern "C"
{
#endif
struct dfs_mnt;
struct dfs_dentry;
struct dfs_filesystem_ops;
struct dfs_mnt
{
struct dfs_mnt *parent; /* the parent mounted file system */
rt_list_t sibling; /* the sibling node for mounted list */
rt_list_t child; /* the child node for mounted list */
char *fullpath; /* the fullpath of this mounted file system */
int flags; /* the falgs of this mounted file system */
#define MNT_IS_ALLOCED 0x1 /* the mnt struct is allocated */
#define MNT_IS_ADDLIST 0x2 /* the mnt struct is added into list */
#define MNT_IS_MOUNTED 0x4 /* the mnt struct is mounted */
rt_atomic_t ref_count; /* reference count */
rt_device_t dev_id; /* the mounted device id */
const struct dfs_filesystem_ops *fs_ops;
void *data;
};
struct dfs_mnt *dfs_mnt_create(const char *path);
int dfs_mnt_destroy(struct dfs_mnt* mnt);
int dfs_mnt_list(struct dfs_mnt* mnt);
int dfs_mnt_insert(struct dfs_mnt* mnt, struct dfs_mnt* child);
struct dfs_mnt *dfs_mnt_lookup(const char *path);
const char *dfs_mnt_get_mounted_path(struct rt_device *device);
struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt);
int dfs_mnt_unref(struct dfs_mnt* mnt);
rt_bool_t dfs_mnt_has_child_mnt(struct dfs_mnt *mnt, const char* fullpath);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2009-05-27 Yi.qiu The first version.
* 2010-07-18 Bernard add stat and statfs structure definitions.
* 2011-05-16 Yi.qiu Change parameter name of rename, "new" is C++ key word.
* 2017-12-27 Bernard Add fcntl API.
* 2018-02-07 Bernard Change the 3rd parameter of open/fcntl/ioctl to '...'
*/
#ifndef __DFS_POSIX_H__
#define __DFS_POSIX_H__
#include <fcntl.h>
#include <errno.h>
#include <dfs.h>
#include <dfs_file.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef DFS_PRIVATE_H__
#define DFS_PRIVATE_H__
#include <dfs.h>
#define DBG_TAG "DFS"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#define NO_WORKING_DIR "system does not support working directory\n"
/* extern variable */
extern const struct dfs_filesystem_ops *filesystem_operation_table[];
extern struct dfs_filesystem filesystem_table[];
extern const struct dfs_mount_tbl mount_table[];
extern char working_directory[];
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -12,106 +12,38 @@
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_dentry.h>
#include <dfs_file.h>
#include <dfs_mnt.h>
#include <rtservice.h>
#include "dfs_private.h"
#define DBG_TAG "DFS"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#ifdef RT_USING_SMART
#include <lwp.h>
#endif
#ifdef RT_USING_POSIX_STDIO
#include <libc.h>
#endif /* RT_USING_POSIX_STDIO */
/* Global variables */
const struct dfs_filesystem_ops *filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX];
struct dfs_filesystem filesystem_table[DFS_FILESYSTEMS_MAX];
/* device filesystem lock */
static struct rt_mutex fslock;
static struct rt_mutex fdlock;
#ifdef DFS_USING_WORKDIR
char working_directory[DFS_PATH_MAX] = {"/"};
#endif
static struct dfs_fdtable _fdtab;
static int fd_alloc(struct dfs_fdtable *fdt, int startfd);
/**
* @addtogroup DFS
* @{
*/
/**
* this function will initialize device file system.
*/
int dfs_init(void)
{
static rt_bool_t init_ok = RT_FALSE;
if (init_ok)
{
rt_kprintf("dfs already init.\n");
return 0;
}
/* init vnode hash table */
dfs_vnode_mgr_init();
/* clear filesystem operations table */
rt_memset((void *)filesystem_operation_table, 0, sizeof(filesystem_operation_table));
/* clear filesystem table */
rt_memset(filesystem_table, 0, sizeof(filesystem_table));
/* clean fd table */
rt_memset(&_fdtab, 0, sizeof(_fdtab));
/* create device filesystem lock */
rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_PRIO);
rt_mutex_init(&fdlock, "fdlock", RT_IPC_FLAG_PRIO);
#ifdef DFS_USING_WORKDIR
/* set current working directory */
rt_memset(working_directory, 0, sizeof(working_directory));
working_directory[0] = '/';
#endif
#ifdef RT_USING_DFS_TMPFS
{
extern int dfs_tmpfs_init(void);
dfs_tmpfs_init();
}
#endif
#ifdef RT_USING_DFS_DEVFS
{
extern int devfs_init(void);
/* if enable devfs, initialize and mount it as soon as possible */
devfs_init();
dfs_mount(NULL, "/dev", "devfs", 0, 0);
}
#if defined(RT_USING_DEV_BUS) && defined(RT_USING_DFS_TMPFS)
mkdir("/dev/shm", 0x777);
if (dfs_mount(RT_NULL, "/dev/shm", "tmp", 0, 0) != 0)
{
rt_kprintf("Dir /dev/shm mount failed!\n");
}
#endif
#endif
init_ok = RT_TRUE;
return 0;
}
INIT_PREV_EXPORT(dfs_init);
/* device filesystem lock */
static struct rt_mutex fslock;
static struct rt_mutex fdlock;
static struct dfs_fdtable _fdtab = {0};
static int fd_alloc(struct dfs_fdtable *fdt, int startfd);
/**
* this function will lock device file system.
*
* @note please don't invoke it on ISR.
*/
void dfs_lock(void)
rt_err_t dfs_lock(void)
{
rt_err_t result = -RT_EBUSY;
@ -120,25 +52,7 @@ void dfs_lock(void)
result = rt_mutex_take(&fslock, RT_WAITING_FOREVER);
}
if (result != RT_EOK)
{
RT_ASSERT(0);
}
}
void dfs_file_lock(void)
{
rt_err_t result = -RT_EBUSY;
while (result == -RT_EBUSY)
{
result = rt_mutex_take(&fdlock, RT_WAITING_FOREVER);
}
if (result != RT_EOK)
{
RT_ASSERT(0);
}
return result;
}
/**
@ -151,13 +65,54 @@ void dfs_unlock(void)
rt_mutex_release(&fslock);
}
#ifdef DFS_USING_POSIX
/**
* @addtogroup DFS
*/
/*@{*/
rt_err_t dfs_file_lock(void)
{
rt_err_t result = -RT_EBUSY;
while (result == -RT_EBUSY)
{
result = rt_mutex_take(&fdlock, RT_WAITING_FOREVER);
}
return result;
}
void dfs_file_unlock(void)
{
rt_mutex_release(&fdlock);
}
/**
* this function will initialize device file system.
*/
int dfs_init(void)
{
static rt_bool_t init_ok = RT_FALSE;
if (init_ok)
{
LOG_E("DFS was already initialized.\n");
return 0;
}
/* create device filesystem lock */
rt_mutex_init(&fslock, "fslock", RT_IPC_FLAG_FIFO);
rt_mutex_init(&fdlock, "fdlock", RT_IPC_FLAG_FIFO);
/* clean fd table */
dfs_dentry_init();
init_ok = RT_TRUE;
return 0;
}
INIT_PREV_EXPORT(dfs_init);
static int fd_slot_expand(struct dfs_fdtable *fdt, int fd)
{
int nr;
@ -189,7 +144,7 @@ static int fd_slot_expand(struct dfs_fdtable *fdt, int fd)
{
fds[index] = NULL;
}
fdt->fds = fds;
fdt->fds = fds;
fdt->maxfd = nr;
return fd;
@ -219,28 +174,12 @@ static int fd_slot_alloc(struct dfs_fdtable *fdt, int startfd)
}
return idx;
}
static int fd_alloc(struct dfs_fdtable *fdt, int startfd)
{
int idx;
struct dfs_file *fd = NULL;
idx = fd_slot_alloc(fdt, startfd);
/* allocate 'struct dfs_file' */
if (idx < 0)
{
return -1;
}
fd = (struct dfs_file *)rt_calloc(1, sizeof(struct dfs_file));
if (!fd)
{
return -1;
}
fd->ref_count = 1;
fd->magic = DFS_FD_MAGIC;
fd->vnode = NULL;
fdt->fds[idx] = fd;
return idx;
}
@ -259,14 +198,34 @@ int fdt_fd_new(struct dfs_fdtable *fdt)
/* find an empty fd entry */
idx = fd_alloc(fdt, DFS_STDIO_OFFSET);
/* can't find an empty fd entry */
if (idx < 0)
{
LOG_E("DFS fd new is failed! Could not found an empty fd entry.");
}
else
{
struct dfs_file *file;
file = (struct dfs_file *)rt_calloc(1, sizeof(struct dfs_file));
if (file)
{
file->magic = DFS_FD_MAGIC;
file->ref_count = 1;
rt_mutex_init(&file->pos_lock, "fpos", RT_IPC_FLAG_PRIO);
RT_ASSERT(fdt->fds[idx] == NULL);
fdt->fds[idx] = file;
LOG_D("allocate a new fd @ %d", idx);
}
else
{
fdt->fds[idx] = RT_NULL;
idx = -1;
}
}
dfs_file_unlock();
return idx;
}
@ -288,28 +247,24 @@ int fd_new(void)
* pointer.
*/
struct dfs_file *fdt_fd_get(struct dfs_fdtable* fdt, int fd)
struct dfs_file *fdt_fd_get(struct dfs_fdtable *fdt, int fd)
{
struct dfs_file *d;
struct dfs_file *f;
if (fd < 0 || fd >= (int)fdt->maxfd)
{
return NULL;
}
dfs_file_lock();
d = fdt->fds[fd];
f = fdt->fds[fd];
/* check dfs_file valid or not */
if ((d == NULL) || (d->magic != DFS_FD_MAGIC))
/* check file valid or not */
if ((f == NULL) || (f->magic != DFS_FD_MAGIC))
{
dfs_file_unlock();
return NULL;
}
dfs_file_unlock();
return d;
return f;
}
struct dfs_file *fd_get(int fd)
@ -325,51 +280,6 @@ struct dfs_file *fd_get(int fd)
*
* This function will put the file descriptor.
*/
void fdt_fd_release(struct dfs_fdtable* fdt, int fd)
{
struct dfs_file *fd_slot = NULL;
RT_ASSERT(fdt != NULL);
dfs_file_lock();
if ((fd < 0) || (fd >= fdt->maxfd))
{
dfs_file_unlock();
return;
}
fd_slot = fdt->fds[fd];
if (fd_slot == NULL)
{
dfs_file_unlock();
return;
}
fdt->fds[fd] = NULL;
/* check fd */
RT_ASSERT(fd_slot->magic == DFS_FD_MAGIC);
fd_slot->ref_count--;
/* clear this fd entry */
if (fd_slot->ref_count == 0)
{
struct dfs_vnode *vnode = fd_slot->vnode;
if (vnode)
{
vnode->ref_count--;
if(vnode->ref_count == 0)
{
rt_free(vnode);
fd_slot->vnode = RT_NULL;
}
}
rt_free(fd_slot);
}
dfs_file_unlock();
}
void fd_release(int fd)
{
struct dfs_fdtable *fdt;
@ -378,7 +288,135 @@ void fd_release(int fd)
fdt_fd_release(fdt, fd);
}
rt_err_t sys_dup(int oldfd)
void fdt_fd_release(struct dfs_fdtable *fdt, int fd)
{
if (fd < fdt->maxfd)
{
struct dfs_file *file = fdt_fd_get(fdt, fd);
if (file && file->ref_count == 1)
{
rt_mutex_detach(&file->pos_lock);
rt_free(file);
}
else
{
rt_atomic_sub(&(file->ref_count), 1);
}
fdt->fds[fd] = RT_NULL;
}
}
static int fd_get_fd_index_form_fdt(struct dfs_fdtable *fdt, struct dfs_file *file)
{
int fd = -1;
if (file == RT_NULL)
{
return -1;
}
dfs_file_lock();
for (int index = 0; index < (int)fdt->maxfd; index++)
{
if (fdt->fds[index] == file)
{
fd = index;
break;
}
}
dfs_file_unlock();
return fd;
}
int fd_get_fd_index(struct dfs_file *file)
{
struct dfs_fdtable *fdt;
fdt = dfs_fdtable_get();
return fd_get_fd_index_form_fdt(fdt, file);
}
int fd_associate(struct dfs_fdtable *fdt, int fd, struct dfs_file *file)
{
int retfd = -1;
if (!file)
{
return retfd;
}
if (!fdt)
{
return retfd;
}
dfs_file_lock();
/* check old fd */
if ((fd < 0) || (fd >= fdt->maxfd))
{
goto exit;
}
if (fdt->fds[fd])
{
goto exit;
}
/* inc ref_count */
rt_atomic_add(&(file->ref_count), 1);
fdt->fds[fd] = file;
retfd = fd;
exit:
dfs_file_unlock();
return retfd;
}
/**
* This function will get the file descriptor table of current process.
*/
struct dfs_fdtable *dfs_fdtable_get(void)
{
struct dfs_fdtable *fdt;
#ifdef RT_USING_SMART
struct rt_lwp *lwp;
lwp = (struct rt_lwp *)rt_thread_self()->lwp;
if (lwp)
fdt = &lwp->fdt;
else
fdt = &_fdtab;
#else
fdt = &_fdtab;
#endif
return fdt;
}
#ifdef RT_USING_SMART
struct dfs_fdtable *dfs_fdtable_get_pid(int pid)
{
struct rt_lwp *lwp = RT_NULL;
struct dfs_fdtable *fdt = RT_NULL;
lwp = lwp_from_pid(pid);
if (lwp)
{
fdt = &lwp->fdt;
}
return fdt;
}
#endif
struct dfs_fdtable *dfs_fdtable_get_global(void)
{
return &_fdtab;
}
int dfs_dup(int oldfd, int startfd)
{
int newfd = -1;
struct dfs_fdtable *fdt = NULL;
@ -395,79 +433,32 @@ rt_err_t sys_dup(int oldfd)
goto exit;
}
/* get a new fd */
newfd = fd_slot_alloc(fdt, DFS_STDIO_OFFSET);
newfd = fd_slot_alloc(fdt, startfd);
if (newfd >= 0)
{
fdt->fds[newfd] = fdt->fds[oldfd];
/* inc ref_count */
fdt->fds[newfd]->ref_count++;
rt_atomic_add(&(fdt->fds[newfd]->ref_count), 1);
}
exit:
dfs_file_unlock();
return newfd;
}
#endif /* DFS_USING_POSIX */
/**
* @ingroup Fd
*
* This function will return whether this file has been opend.
*
* @param pathname the file path name.
*
* @return 0 on file has been open successfully, -1 on open failed.
*/
int fd_is_open(const char *pathname)
#ifdef RT_USING_SMART
sysret_t sys_dup(int oldfd)
#else
int sys_dup(int oldfd)
#endif
{
char *fullpath;
unsigned int index;
struct dfs_filesystem *fs;
struct dfs_file *fd;
struct dfs_fdtable *fdt;
int newfd = dfs_dup(oldfd, DFS_STDIO_OFFSET);
fdt = dfs_fdtable_get();
fullpath = dfs_normalize_path(NULL, pathname);
if (fullpath != NULL)
{
char *mountpath;
fs = dfs_filesystem_lookup(fullpath);
if (fs == NULL)
{
/* can't find mounted file system */
rt_free(fullpath);
return -1;
}
/* get file path name under mounted file system */
if (fs->path[0] == '/' && fs->path[1] == '\0')
mountpath = fullpath;
else
mountpath = fullpath + strlen(fs->path);
dfs_lock();
for (index = 0; index < fdt->maxfd; index++)
{
fd = fdt->fds[index];
if (fd == NULL || fd->vnode->fops == NULL || fd->vnode->path == NULL) continue;
if (fd->vnode->fs == fs && strcmp(fd->vnode->path, mountpath) == 0)
{
/* found file in file descriptor table */
rt_free(fullpath);
dfs_unlock();
return 0;
}
}
dfs_unlock();
rt_free(fullpath);
}
return -1;
#ifdef RT_USING_SMART
return (sysret_t)newfd;
#else
return newfd;
#endif
}
rt_err_t sys_dup2(int oldfd, int newfd)
@ -518,91 +509,13 @@ rt_err_t sys_dup2(int oldfd, int newfd)
fdt->fds[newfd] = fdt->fds[oldfd];
/* inc ref_count */
fdt->fds[newfd]->ref_count++;
rt_atomic_add(&(fdt->fds[newfd]->ref_count), 1);
retfd = newfd;
exit:
dfs_file_unlock();
return retfd;
}
static int fd_get_fd_index_form_fdt(struct dfs_fdtable *fdt, struct dfs_file *file)
{
int fd = -1;
if (file == RT_NULL)
{
return -1;
}
dfs_file_lock();
for(int index = 0; index < (int)fdt->maxfd; index++)
{
if(fdt->fds[index] == file)
{
fd = index;
break;
}
}
dfs_file_unlock();
return fd;
}
int fd_get_fd_index(struct dfs_file *file)
{
struct dfs_fdtable *fdt;
fdt = dfs_fdtable_get();
return fd_get_fd_index_form_fdt(fdt, file);
}
int fd_associate(struct dfs_fdtable *fdt, int fd, struct dfs_file *file)
{
int retfd = -1;
if (!file)
{
return retfd;
}
if (!fdt)
{
return retfd;
}
dfs_file_lock();
/* check old fd */
if ((fd < 0) || (fd >= fdt->maxfd))
{
goto exit;
}
if (fdt->fds[fd])
{
goto exit;
}
/* inc ref_count */
file->ref_count++;
fdt->fds[fd] = file;
retfd = fd;
exit:
dfs_file_unlock();
return retfd;
}
void fd_init(struct dfs_file *fd)
{
if (fd)
{
fd->magic = DFS_FD_MAGIC;
fd->ref_count = 1;
fd->pos = 0;
fd->vnode = NULL;
fd->data = NULL;
}
}
/**
* this function will return a sub-path name under directory.
*
@ -621,7 +534,7 @@ const char *dfs_subdir(const char *directory, const char *filename)
dir = filename + strlen(directory);
if ((*dir != '/') && (dir != filename))
{
dir --;
dir--;
}
return dir;
@ -692,7 +605,8 @@ char *dfs_normalize_path(const char *directory, const char *filename)
if (c == '.')
{
if (!src[1]) src++; /* '.' and ends */
if (!src[1])
src++; /* '.' and ends */
else if (src[1] == '/')
{
/* './' case */
@ -739,17 +653,12 @@ char *dfs_normalize_path(const char *directory, const char *filename)
continue;
up_one:
/* keep the topmost root directory */
if (dst - dst0 != 1 || dst[-1] != '/')
up_one:
dst--;
if (dst < dst0)
{
dst--;
if (dst < dst0)
{
rt_free(fullpath);
return NULL;
}
rt_free(fullpath);
return NULL;
}
while (dst0 < dst && dst[-1] != '/')
dst--;
@ -773,49 +682,8 @@ up_one:
}
RTM_EXPORT(dfs_normalize_path);
/**
* This function will get the file descriptor table of current process.
*/
struct dfs_fdtable *dfs_fdtable_get(void)
{
struct dfs_fdtable *fdt;
#ifdef RT_USING_SMART
struct rt_lwp *lwp;
lwp = (struct rt_lwp *)rt_thread_self()->lwp;
if (lwp)
fdt = &lwp->fdt;
else
fdt = &_fdtab;
#else
fdt = &_fdtab;
#endif
return fdt;
}
#ifdef RT_USING_SMART
struct dfs_fdtable *dfs_fdtable_get_pid(int pid)
{
struct rt_lwp *lwp = RT_NULL;
struct dfs_fdtable *fdt = RT_NULL;
lwp = lwp_from_pid(pid);
if (lwp)
{
fdt = &lwp->fdt;
}
return fdt;
}
#endif
struct dfs_fdtable *dfs_fdtable_get_global(void)
{
return &_fdtab;
}
#ifdef RT_USING_FINSH
#include <finsh.h>
int list_fd(void)
{
int index;
@ -824,101 +692,29 @@ int list_fd(void)
fd_table = dfs_fdtable_get();
if (!fd_table) return -1;
dfs_lock();
rt_enter_critical();
rt_kprintf("fd type ref magic path\n");
rt_kprintf("-- ------ --- ----- ------\n");
for (index = 0; index < (int)fd_table->maxfd; index++)
{
struct dfs_file *fd = fd_table->fds[index];
struct dfs_file *file = fd_table->fds[index];
if (fd && fd->vnode->fops)
if (file && file->vnode)
{
rt_kprintf("%2d ", index);
if (fd->vnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir");
else if (fd->vnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file");
else if (fd->vnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket");
else if (fd->vnode->type == FT_USER) rt_kprintf("%-7.7s ", "user");
else if (fd->vnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device");
if (file->vnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir");
else if (file->vnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file");
else if (file->vnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket");
else if (file->vnode->type == FT_USER) rt_kprintf("%-7.7s ", "user");
else if (file->vnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device");
else rt_kprintf("%-8.8s ", "unknown");
rt_kprintf("%3d ", fd->vnode->ref_count);
rt_kprintf("%04x ", fd->magic);
if (fd->vnode->path)
rt_kprintf("%3d ", file->ref_count);
rt_kprintf("%04x ", file->magic);
if (file->dentry)
{
rt_kprintf("%s\n", fd->vnode->path);
}
else
{
rt_kprintf("\n");
}
}
}
dfs_unlock();
return 0;
}
#ifdef RT_USING_SMART
static int lsofp(int pid)
{
int index;
struct dfs_fdtable *fd_table = RT_NULL;
if (pid == (-1))
{
fd_table = dfs_fdtable_get();
if (!fd_table) return -1;
}
else
{
fd_table = dfs_fdtable_get_pid(pid);
if (!fd_table)
{
rt_kprintf("PID %s is not a applet(lwp)\n", pid);
return -1;
}
}
rt_kprintf("--- -- ------ ------ ----- ---------- ---------- ---------- ------\n");
rt_enter_critical();
for (index = 0; index < (int)fd_table->maxfd; index++)
{
struct dfs_file *fd = fd_table->fds[index];
if (fd && fd->vnode->fops)
{
if(pid == (-1))
{
rt_kprintf(" K ");
}
else
{
rt_kprintf("%3d ", pid);
}
rt_kprintf("%2d ", index);
if (fd->vnode->type == FT_DIRECTORY) rt_kprintf("%-7.7s ", "dir");
else if (fd->vnode->type == FT_REGULAR) rt_kprintf("%-7.7s ", "file");
else if (fd->vnode->type == FT_SOCKET) rt_kprintf("%-7.7s ", "socket");
else if (fd->vnode->type == FT_USER) rt_kprintf("%-7.7s ", "user");
else if (fd->vnode->type == FT_DEVICE) rt_kprintf("%-7.7s ", "device");
else rt_kprintf("%-8.8s ", "unknown");
rt_kprintf("%6d ", fd->vnode->ref_count);
rt_kprintf("%04x 0x%.8x ", fd->magic, (int)(size_t)fd->vnode);
if(fd->vnode == RT_NULL)
{
rt_kprintf("0x%.8x 0x%.8x ", (int)0x00000000, (int)(size_t)fd);
}
else
{
rt_kprintf("0x%.8x 0x%.8x ", (int)(size_t)(fd->vnode->data), (int)(size_t)fd);
}
if (fd->vnode->path)
{
rt_kprintf("%s \n", fd->vnode->path);
rt_kprintf("%s%s\n", file->dentry->mnt->fullpath, file->dentry->pathname);
}
else
{
@ -930,45 +726,66 @@ static int lsofp(int pid)
return 0;
}
MSH_CMD_EXPORT(list_fd, list file descriptor);
int lsof(int argc, char *argv[])
int dfs_fd_dump(int argc, char** argv)
{
rt_kprintf("PID fd type fd-ref magic vnode vnode/data addr path \n");
int index;
if (argc == 1)
dfs_file_lock();
for (index = 0; index < _fdtab.maxfd; index++)
{
struct rt_list_node *node, *list;
struct lwp_avl_struct *pids = lwp_get_pid_ary();
lsofp(-1);
for (int index = 0; index < RT_LWP_MAX_NR; index++)
struct dfs_file *file = _fdtab.fds[index];
if (file)
{
struct rt_lwp *lwp = (struct rt_lwp *)pids[index].data;
if (lwp)
char* fullpath = dfs_dentry_full_path(file->dentry);
if (fullpath)
{
list = &lwp->t_grp;
for (node = list->next; node != list; node = node->next)
{
lsofp(lwp_to_pid(lwp));
}
printf("[%d] - %s, ref_count %zd\n", index,
fullpath, (size_t)rt_atomic_load(&(file->ref_count)));
rt_free(fullpath);
}
else
{
printf("[%d] - %s, ref_count %zd\n", index,
file->dentry->pathname, (size_t)rt_atomic_load(&(file->ref_count)));
}
}
}
else if (argc == 3)
dfs_file_unlock();
return 0;
}
MSH_CMD_EXPORT_ALIAS(dfs_fd_dump, fd_dump, fd dump);
#ifdef PKG_USING_DLOG
int dfs_dlog(int argc, char** argv)
{
if (argc == 2)
{
if (argv[1][0] == '-' && argv[1][1] == 'p')
if (strcmp(argv[1], "on") == 0)
{
int pid = atoi(argv[2]);
lsofp(pid);
dlog_session_start();
dlog_participant("dfs");
dlog_participant("dfs_file");
dlog_participant("dentry");
dlog_participant("vnode");
dlog_participant("mnt");
dlog_participant("rom");
dlog_participant("devfs");
}
else if (strcmp(argv[1], "off") == 0)
{
dlog_session_stop();
}
}
return 0;
}
MSH_CMD_EXPORT(lsof, list open files);
#endif /* RT_USING_SMART */
MSH_CMD_EXPORT(dfs_dlog, dfs dlog on|off);
#endif
#endif
/**@}*/

View File

@ -0,0 +1,368 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-10-10 Bernard The first version of rewrite dfs
*/
#include <rtthread.h>
#include "dfs.h"
#include "dfs_file.h"
#include "dfs_private.h"
#include "dfs_dentry.h"
#include "dfs_mnt.h"
#define DBG_TAG "DFS.dentry"
#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
#define DFS_DENTRY_HASH_NR 32
struct dentry_hash_head
{
rt_list_t head[DFS_DENTRY_HASH_NR];
};
static struct dentry_hash_head hash_head;
static uint32_t _dentry_hash(struct dfs_mnt *mnt, const char *path)
{
uint32_t val = 0;
if (path)
{
while (*path)
{
val = ((val << 5) + val) + *path++;
}
}
return (val ^ (unsigned long) mnt) & (DFS_DENTRY_HASH_NR - 1);
}
struct dfs_dentry *dfs_dentry_create(struct dfs_mnt *mnt, char *fullpath)
{
struct dfs_dentry *dentry = RT_NULL;
if (mnt == RT_NULL || fullpath == RT_NULL)
{
return dentry;
}
dentry = (struct dfs_dentry *)rt_calloc(1, sizeof(struct dfs_dentry));
if (dentry)
{
char *dentry_path = fullpath;
int mntpoint_len = strlen(mnt->fullpath);
if (rt_strncmp(mnt->fullpath, dentry_path, mntpoint_len) == 0)
{
dentry_path += mntpoint_len;
}
dentry->pathname = strlen(dentry_path) ? rt_strdup(dentry_path) : rt_strdup(fullpath);
dentry->mnt = dfs_mnt_ref(mnt);
rt_atomic_store(&(dentry->ref_count), 1);
dentry->flags |= DENTRY_IS_ALLOCED;
LOG_I("create a dentry:%p for %s", dentry, fullpath);
}
return dentry;
}
struct dfs_dentry * dfs_dentry_ref(struct dfs_dentry *dentry)
{
if (dentry)
{
int ret = dfs_file_lock();
if (ret == RT_EOK)
{
rt_atomic_add(&(dentry->ref_count), 1);
if (dentry->vnode)
{
rt_atomic_add(&(dentry->vnode->ref_count), 1);
}
dfs_file_unlock();
}
}
return dentry;
}
struct dfs_dentry *dfs_dentry_unref(struct dfs_dentry *dentry)
{
rt_err_t ret = RT_EOK;
if (dentry)
{
ret = dfs_file_lock();
if (ret == RT_EOK)
{
if (dentry->flags & DENTRY_IS_ALLOCED)
{
rt_atomic_sub(&(dentry->ref_count), 1);
}
if (rt_atomic_load(&(dentry->ref_count)) == 0)
{
DLOG(msg, "dentry", "dentry", DLOG_MSG, "free dentry, ref_count=0");
if (dentry->flags & DENTRY_IS_ADDHASH)
{
rt_list_remove(&dentry->hashlist);
}
/* release vnode */
if (dentry->vnode)
{
dfs_vnode_unref(dentry->vnode);
}
/* release mnt */
DLOG(msg, "dentry", "mnt", DLOG_MSG, "dfs_mnt_unref(dentry->mnt)");
if (dentry->mnt)
{
dfs_mnt_unref(dentry->mnt);
}
dfs_file_unlock();
LOG_I("free a dentry: %p", dentry);
rt_free(dentry->pathname);
rt_free(dentry);
}
else
{
if (dentry->vnode)
{
rt_atomic_sub(&(dentry->vnode->ref_count), 1);
}
dfs_file_unlock();
DLOG(note, "dentry", "dentry ref_count=%d", rt_atomic_load(&(dentry->ref_count)));
}
}
}
return dentry;
}
static struct dfs_dentry *_dentry_hash_lookup(struct dfs_mnt *mnt, const char *path)
{
rt_err_t ret = RT_EOK;
struct dfs_dentry *entry = RT_NULL;
int path_len = strlen(path);
ret = dfs_file_lock();
if (ret == RT_EOK)
{
rt_list_for_each_entry(entry, &hash_head.head[_dentry_hash(mnt, path)], hashlist)
{
if (entry->mnt == mnt && !strncmp(entry->pathname, path, path_len))
{
dfs_dentry_ref(entry);
dfs_file_unlock();
return entry;
}
}
dfs_file_unlock();
}
return RT_NULL;
}
void dfs_dentry_insert(struct dfs_dentry *dentry)
{
dfs_file_lock();
rt_list_insert_after(&hash_head.head[_dentry_hash(dentry->mnt, dentry->pathname)], &dentry->hashlist);
dentry->flags |= DENTRY_IS_ADDHASH;
dfs_file_unlock();
}
/*
* lookup a dentry, return this dentry and increase refcount if exist, otherwise return NULL
*/
struct dfs_dentry *dfs_dentry_lookup(struct dfs_mnt *mnt, const char *path, uint32_t flags)
{
struct dfs_dentry *dentry;
struct dfs_vnode *vnode;
int mntpoint_len = strlen(mnt->fullpath);
if (rt_strncmp(mnt->fullpath, path, mntpoint_len) == 0)
{
path += mntpoint_len;
if ((*path) == '\0')
{
/* root */
path = "/";
}
}
dentry = _dentry_hash_lookup(mnt, path);
if (!dentry)
{
if (mnt->fs_ops->lookup)
{
DLOG(activate, "dentry");
/* not in hash table, create it */
DLOG(msg, "dentry", "dentry", DLOG_MSG, "dfs_dentry_create(%s)", path);
dentry = dfs_dentry_create(mnt, (char*)path);
if (dentry)
{
DLOG(msg, "dentry", mnt->fs_ops->name, DLOG_MSG, "vnode=fs_ops->lookup(dentry)");
vnode = mnt->fs_ops->lookup(dentry);
if (vnode)
{
DLOG(msg, mnt->fs_ops->name, "dentry", DLOG_MSG_RET, "return vnode");
dentry->vnode = vnode; /* the refcount of created vnode is 1. no need to reference */
dfs_file_lock();
rt_list_insert_after(&hash_head.head[_dentry_hash(mnt, path)], &dentry->hashlist);
dentry->flags |= DENTRY_IS_ADDHASH;
dfs_file_unlock();
if (dentry->flags & (DENTRY_IS_ALLOCED | DENTRY_IS_ADDHASH)
&& !(dentry->flags & DENTRY_IS_OPENED))
{
rt_err_t ret = dfs_file_lock();
if (ret == RT_EOK)
{
dentry->flags |= DENTRY_IS_OPENED;
dfs_file_unlock();
}
}
}
else
{
DLOG(msg, mnt->fs_ops->name, "dentry", DLOG_MSG_RET, "no dentry");
DLOG(msg, "dentry", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
dfs_dentry_unref(dentry);
dentry = RT_NULL;
}
}
DLOG(deactivate, "dentry");
}
}
else
{
DLOG(note, "dentry", "found dentry");
}
return dentry;
}
char* dfs_dentry_full_path(struct dfs_dentry* dentry)
{
char *path = NULL;
if (dentry && dentry->mnt)
{
int mnt_len = strlen(dentry->mnt->fullpath);
int path_len = strlen(dentry->pathname);
path = (char *) rt_malloc(mnt_len + path_len + 3);
if (path)
{
if (dentry->pathname[0] == '/')
{
rt_snprintf(path, mnt_len + path_len + 2, "%s%s", dentry->mnt->fullpath,
dentry->pathname);
}
else
{
rt_snprintf(path, mnt_len + path_len + 2, "%s/%s", dentry->mnt->fullpath,
dentry->pathname);
}
}
}
return path;
}
char* dfs_dentry_pathname(struct dfs_dentry* dentry)
{
char *pathname = RT_NULL;
char *index = RT_NULL;
index = strrchr(dentry->pathname, '/');
if (index)
{
int length = index - dentry->pathname;
int path_length = strlen(dentry->mnt->fullpath) + length + 3;
pathname = (char*) rt_malloc(path_length);
if (pathname)
{
if (dentry->pathname[0] == '/')
{
rt_snprintf(pathname, path_length - 1, "%s%.*s", dentry->mnt->fullpath,
length, dentry->pathname);
}
else
{
rt_snprintf(pathname, path_length - 1, "%s/%.*s", dentry->mnt->fullpath,
length, dentry->pathname);
}
}
}
else
{
pathname = rt_strdup(dentry->mnt->fullpath);
}
return pathname;
}
uint32_t dfs_dentry_full_path_crc32(struct dfs_dentry* dentry)
{
uint32_t crc32 = 0xFFFFFFFF;
char *fullpath = dfs_dentry_full_path(dentry);
if (fullpath)
{
int i = 0;
while(fullpath[i] != '\0')
{
for (uint8_t b = 1; b; b <<= 1)
{
crc32 ^= (fullpath[i] & b) ? 1 : 0;
crc32 = (crc32 & 1) ? crc32 >> 1 ^ 0xEDB88320 : crc32 >> 1;
}
i ++;
}
rt_free(fullpath);
}
return crc32;
}
int dfs_dentry_init(void)
{
int i = 0;
for(i = 0; i < DFS_DENTRY_HASH_NR; i++)
{
rt_list_init(&hash_head.head[i]);
}
return 0;
}
int dfs_dentry_dump(int argc, char** argv)
{
int index = 0;
struct dfs_dentry *entry = RT_NULL;
dfs_lock();
for (index = 0; index < DFS_DENTRY_HASH_NR; index ++)
{
rt_list_for_each_entry(entry, &hash_head.head[index], hashlist)
{
printf("dentry:%s @ %p, ref_count = %zd\n", entry->pathname, entry, (size_t)rt_atomic_load(&entry->ref_count));
}
}
dfs_unlock();
return 0;
}
MSH_CMD_EXPORT_ALIAS(dfs_dentry_dump, dentry_dump, dump dentry in the system);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -10,107 +10,408 @@
* 2011-03-12 Bernard fix the filesystem lookup issue.
* 2017-11-30 Bernard fix the filesystem_operation_table issue.
* 2017-12-05 Bernard fix the fs type search issue in mkfs.
* 2023-05-05 Bernard change to dfs v2.0
*/
#include <dfs_fs.h>
#include <dfs_file.h>
#include <dfs_dentry.h>
#include <dfs_mnt.h>
#include "dfs_private.h"
#define DBG_TAG "DFS.fs"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
static struct dfs_filesystem_type *file_systems = NULL;
extern rt_list_t _mnt_list;
/**
* @addtogroup FsApi
* @{
*/
/*@{*/
/**
* this function will register a file system instance to device file system.
*
* @param ops the file system instance to be registered.
*
* @return 0 on successful, -1 on failed.
*/
int dfs_register(const struct dfs_filesystem_ops *ops)
static struct dfs_filesystem_type **_find_filesystem(const char *name)
{
int ret = RT_EOK;
const struct dfs_filesystem_ops **empty = NULL;
const struct dfs_filesystem_ops **iter;
/* lock filesystem */
dfs_lock();
/* check if this filesystem was already registered */
for (iter = &filesystem_operation_table[0];
iter < &filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]; iter ++)
struct dfs_filesystem_type **type;
for (type = &file_systems; *type; type = &(*type)->next)
{
/* find out an empty filesystem type entry */
if (*iter == NULL)
(empty == NULL) ? (empty = iter) : 0;
else if (strcmp((*iter)->name, ops->name) == 0)
{
rt_set_errno(-EEXIST);
ret = -1;
if (strcmp((*type)->fs_ops->name, name) == 0)
break;
}
}
/* save the filesystem's operations */
if (empty == NULL)
return type;
}
int dfs_register(struct dfs_filesystem_type *fs)
{
int ret = 0;
struct dfs_filesystem_type **type = _find_filesystem(fs->fs_ops->name);
LOG_D("register %s file system.", fs->fs_ops->name);
if (*type)
{
rt_set_errno(-ENOSPC);
LOG_E("There is no space to register this file system (%s).", ops->name);
ret = -1;
ret = -EBUSY;
}
else if (ret == RT_EOK)
else
{
*empty = ops;
*type = fs;
}
dfs_unlock();
return ret;
}
/**
* this function will return the file system mounted on specified path.
*
* @param path the specified path string.
*
* @return the found file system or NULL if no file system mounted on
* specified path
*/
struct dfs_filesystem *dfs_filesystem_lookup(const char *path)
int dfs_unregister(struct dfs_filesystem_type *fs)
{
struct dfs_filesystem *iter;
struct dfs_filesystem *fs = NULL;
uint32_t fspath, prefixlen;
int ret = 0;
struct dfs_filesystem_type **type;
prefixlen = 0;
RT_ASSERT(path);
/* lock filesystem */
dfs_lock();
/* lookup it in the filesystem table */
for (iter = &filesystem_table[0];
iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++)
if (fs)
{
if ((iter->path == NULL) || (iter->ops == NULL))
continue;
LOG_D("unregister %s file system.", fs->fs_ops->name);
fspath = strlen(iter->path);
if ((fspath < prefixlen)
|| (strncmp(iter->path, path, fspath) != 0))
continue;
for (type = &file_systems; *type; type = &(*type)->next)
{
if (strcmp((*type)->fs_ops->name, fs->fs_ops->name) == 0)
{
*type = (*type)->next;
break;
}
}
/* check next path separator */
if (fspath > 1 && (strlen(path) > fspath) && (path[fspath] != '/'))
continue;
fs = iter;
prefixlen = fspath;
if (!*type) ret = -EINVAL;
}
dfs_unlock();
return ret;
}
return fs;
/*
* parent(mount path)
* mnt_parent <- - - - - - - +
* | |
* |- mnt_child <- - - - - -+ (1 refcount)
* | |
* |- parent - - + (1 refcount)
*/
int dfs_mount(const char *device_name,
const char *path,
const char *filesystemtype,
unsigned long rwflag,
const void *data)
{
int ret = RT_EOK;
char *fullpath = RT_NULL;
rt_device_t dev_id = RT_NULL;
struct dfs_mnt *mnt_parent = RT_NULL, *mnt_child = RT_NULL;
struct dfs_dentry *mntpoint_dentry = RT_NULL;
struct dfs_filesystem_type *type = *_find_filesystem(filesystemtype);
if (type)
{
fullpath = dfs_normalize_path(RT_NULL, path);
if (!fullpath)
{
rt_set_errno(EPERM);
ret = -1;
}
}
else
{
rt_set_errno(ENOENT);
ret = -1;
}
if (fullpath)
{
DLOG(note, "mnt", "mount %s(%s) on path: %s", device_name, filesystemtype, fullpath);
/* open specific device */
if (device_name) dev_id = rt_device_find(device_name);
if (!(type->fs_ops->flags & FS_NEED_DEVICE) ||
((type->fs_ops->flags & FS_NEED_DEVICE) && dev_id))
{
DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt_parent = dfs_mnt_lookup(%s)", fullpath);
mnt_parent = dfs_mnt_lookup(fullpath);
if ((!mnt_parent && (strcmp(fullpath, "/") == 0 || strcmp(fullpath, "/dev") == 0))
|| (mnt_parent && strcmp(fullpath, "/") == 0 && strcmp(mnt_parent->fullpath, fullpath) != 0))
{
LOG_D("no mnt found @ mount point %s, should be root.", fullpath);
DLOG(msg, "mnt", "dfs", DLOG_MSG_RET, "no mnt");
/* it's the root file system */
/* the mount point dentry is the same as root dentry. */
DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt_parent = dfs_mnt_create(path)");
mnt_parent = dfs_mnt_create(fullpath); /* mnt->ref_count should be 1. */
if (mnt_parent)
{
DLOG(msg, "mnt", "dfs", DLOG_MSG_RET, "return mnt, ref_count=1");
mnt_parent->fs_ops = type->fs_ops;
mnt_parent->dev_id = dev_id;
if (mnt_parent->fs_ops->mount)
{
DLOG(msg, "dfs", type->fs_ops->name, DLOG_MSG, "fs_ops->mount(mnt_parent, rwflag, data)");
ret = mnt_parent->fs_ops->mount(mnt_parent, rwflag, data);
if (ret == RT_EOK)
{
DLOG(msg, type->fs_ops->name, "dfs", DLOG_MSG_RET, "mount OK, ret root_dentry");
mnt_child = mnt_parent;
DLOG(note_right, "mnt", "mount sucessfully");
DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_insert(, mnt_child)");
dfs_mnt_insert(RT_NULL, mnt_child);
/* unref it, because the ref_count = 1 when create */
DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_unref(mnt_parent)");
dfs_mnt_unref(mnt_parent);
/*
* About root mnt:
* There are two ref_count:
* 1. the gobal root reference.
* 1. the mnt->parent reference.
*/
}
else
{
LOG_W("mount %s failed with file system type: %s", fullpath, type->fs_ops->name);
DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_destroy(mnt_parent)");
dfs_mnt_destroy(mnt_parent);
mnt_parent = RT_NULL;
rt_set_errno(EPERM);
ret = -1;
}
}
else
{
LOG_W("no mount method on file system type: %s", type->fs_ops->name);
DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_destroy(mnt_parent), no mount method");
dfs_mnt_destroy(mnt_parent);
mnt_parent = RT_NULL;
rt_set_errno(EIO);
ret = -1;
}
}
else
{
LOG_E("create a mnt point failed.");
rt_set_errno(ENOMEM);
ret = -1;
}
}
else if (strcmp(mnt_parent->fullpath, fullpath) != 0)
{
DLOG(msg, "dfs", "dentry", DLOG_MSG, "mntpoint_dentry = dfs_dentry_lookup(mnt_parent, %s, 0)", fullpath);
mntpoint_dentry = dfs_dentry_lookup(mnt_parent, fullpath, 0);
if (mntpoint_dentry)
{
DLOG(msg, "dentry", "dfs", DLOG_MSG_RET, "dentry exist");
DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt_child = dfs_mnt_create(path)");
mnt_child = dfs_mnt_create(fullpath);
if (mnt_child)
{
LOG_D("create mnt point %p", mnt_child);
mnt_child->fs_ops = type->fs_ops;
mnt_child->dev_id = dev_id;
if (mnt_child->fs_ops->mount)
{
DLOG(msg, "dfs", type->fs_ops->name, DLOG_MSG, "root_dentry = fs_ops->mount(mnt_child, rwflag, data)");
ret = mnt_child->fs_ops->mount(mnt_child, rwflag, data);
if (ret == RT_EOK)
{
LOG_D("mount %s sucessfully", fullpath);
DLOG(msg, mnt_child->fs_ops->name, "dfs", DLOG_MSG_RET, "mount OK");
DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_insert(mnt_parent, mnt_child)");
dfs_mnt_insert(mnt_parent, mnt_child);
/* unref it, because the ref_count = 1 when create */
DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_unref(mnt_child)");
dfs_mnt_unref(mnt_child);
}
else
{
LOG_W("mount %s failed with file system type: %s", fullpath, type->fs_ops->name);
DLOG(msg, mnt_child->fs_ops->name, "dfs", DLOG_MSG_RET, "mount failed");
dfs_mnt_destroy(mnt_child);
rt_set_errno(EPERM);
ret = -1;
}
}
else
{
LOG_W("no mount method on file system type: %s", type->fs_ops->name);
dfs_mnt_destroy(mnt_child);
rt_set_errno(EIO);
ret = -1;
}
}
else
{
LOG_E("create a mnt point failed.");
rt_set_errno(ENOMEM);
ret = -1;
}
dfs_dentry_unref(mntpoint_dentry);
}
else
{
LOG_W("no mount point (%s) in file system: %s", fullpath, mnt_parent->fullpath);
rt_set_errno(ENOTDIR);
ret = -1;
}
}
else
{
LOG_E("mount point (%s) already mounted!", fullpath);
rt_set_errno(EEXIST);
ret = -1;
}
}
else
{
LOG_E("No device found for this file system.");
rt_set_errno(ENODEV);
ret = -1;
}
rt_free(fullpath);
}
return ret;
}
int dfs_umount(const char *specialfile)
{
int ret = -RT_ERROR;
char *fullpath = RT_NULL;
struct dfs_mnt *mnt = RT_NULL;
fullpath = dfs_normalize_path(NULL, specialfile);
if (fullpath)
{
DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt = dfs_mnt_lookup(%s)", fullpath);
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
if (strcmp(mnt->fullpath, fullpath) == 0)
{
/* is the mount point */
if (rt_atomic_load(&(mnt->ref_count)) == 1 && rt_list_isempty(&mnt->child))
{
DLOG(msg, "dfs", mnt->fs_ops->name, DLOG_MSG, "fs_ops->umount(mnt)");
ret = mnt->fs_ops->umount(mnt);
if (ret == 0)
{
DLOG(msg, mnt->fs_ops->name, "dfs", DLOG_MSG_RET, "return OK");
/* destroy this mount point */
DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_destroy(mnt)");
dfs_mnt_destroy(mnt);
}
else
{
LOG_E("umount file system: %s failed.", fullpath);
}
}
else
{
LOG_E("the file system is busy!");
}
}
else
{
LOG_E("the path:%s is not a mountpoint!", fullpath);
}
}
else
{
LOG_E("no filesystem found.");
}
rt_free(fullpath);
}
else
{
rt_set_errno(-ENOTDIR);
}
return ret;
}
/* for compatibility */
int dfs_unmount(const char *specialfile)
{
return dfs_umount(specialfile);
}
int dfs_mkfs(const char *fs_name, const char *device_name)
{
rt_device_t dev_id = NULL;
struct dfs_filesystem_type *type;
int ret = -RT_ERROR;
type = *_find_filesystem(fs_name);
if (!type)
{
rt_kprintf("no file system: %s found!\n", fs_name);
return ret;
}
else
{
if (type->fs_ops->flags & FS_NEED_DEVICE)
{
/* check device name, and it should not be NULL */
if (device_name != NULL)
dev_id = rt_device_find(device_name);
if (dev_id == NULL)
{
rt_set_errno(-ENODEV);
rt_kprintf("Device (%s) was not found", device_name);
return ret;
}
}
else
{
dev_id = RT_NULL;
}
}
if (type->fs_ops->mkfs)
{
ret = type->fs_ops->mkfs(dev_id, type->fs_ops->name);
}
return ret;
}
int dfs_statfs(const char *path, struct statfs *buffer)
{
struct dfs_mnt *mnt;
char *fullpath;
int ret = -RT_ERROR;
fullpath = dfs_normalize_path(NULL, path);
if (!fullpath)
{
return ret;
}
DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
mnt = dfs_mnt_lookup(fullpath);
if (mnt)
{
if (mnt->fs_ops->statfs)
{
ret = mnt->fs_ops->statfs(mnt, buffer);
}
}
return ret;
}
/**
@ -123,23 +424,6 @@ struct dfs_filesystem *dfs_filesystem_lookup(const char *path)
const char *dfs_filesystem_get_mounted_path(struct rt_device *device)
{
const char *path = NULL;
struct dfs_filesystem *iter;
dfs_lock();
for (iter = &filesystem_table[0];
iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++)
{
/* find the mounted device */
if (iter->ops == NULL) continue;
else if (iter->dev_id == device)
{
path = iter->path;
break;
}
}
/* release filesystem_table lock */
dfs_unlock();
return path;
}
@ -154,8 +438,8 @@ const char *dfs_filesystem_get_mounted_path(struct rt_device *device)
* @return RT_EOK on successful or -RT_ERROR on failed.
*/
int dfs_filesystem_get_partition(struct dfs_partition *part,
uint8_t *buf,
uint32_t pindex)
uint8_t *buf,
uint32_t pindex)
{
#define DPT_ADDRESS 0x1be /* device partition offset in Boot Sector */
#define DPT_ITEM_SIZE 16 /* partition item size */
@ -183,16 +467,16 @@ int dfs_filesystem_get_partition(struct dfs_partition *part,
part->offset = *(dpt + 8) | *(dpt + 9) << 8 | *(dpt + 10) << 16 | *(dpt + 11) << 24;
part->size = *(dpt + 12) | *(dpt + 13) << 8 | *(dpt + 14) << 16 | *(dpt + 15) << 24;
rt_kprintf("found part[%d], begin: %d, size: ",
rt_kprintf("found part[%d], begin: %ld, size: ",
pindex, part->offset * 512);
if ((part->size >> 11) == 0)
rt_kprintf("%d%s", part->size >> 1, "KB\n"); /* KB */
rt_kprintf("%ld%s", part->size >> 1, "KB\n"); /* KB */
else
{
unsigned int part_size;
part_size = part->size >> 11; /* MB */
if ((part_size >> 10) == 0)
rt_kprintf("%d.%d%s", part_size, (part->size >> 1) & 0x3FF, "MB\n");
rt_kprintf("%d.%ld%s", part_size, (part->size >> 1) & 0x3FF, "MB\n");
else
rt_kprintf("%d.%d%s", part_size >> 10, part_size & 0x3FF, "GB\n");
}
@ -200,458 +484,4 @@ int dfs_filesystem_get_partition(struct dfs_partition *part,
return RT_EOK;
}
/**
* this function will mount a file system on a specified path.
*
* @param device_name the name of device which includes a file system.
* @param path the path to mount a file system
* @param filesystemtype the file system type
* @param rwflag the read/write etc. flag.
* @param data the private data(parameter) for this file system.
*
* @return 0 on successful or -1 on failed.
*/
int dfs_mount(const char *device_name,
const char *path,
const char *filesystemtype,
unsigned long rwflag,
const void *data)
{
const struct dfs_filesystem_ops **ops;
struct dfs_filesystem *iter;
struct dfs_filesystem *fs = NULL;
char *fullpath = NULL;
rt_device_t dev_id;
/* open specific device */
if (device_name == NULL)
{
/* which is a non-device filesystem mount */
dev_id = NULL;
}
else if ((dev_id = rt_device_find(device_name)) == NULL)
{
/* no this device */
rt_set_errno(-ENODEV);
return -1;
}
/* find out the specific filesystem */
dfs_lock();
for (ops = &filesystem_operation_table[0];
ops < &filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX]; ops++)
if ((*ops != NULL) && (strncmp((*ops)->name, filesystemtype, strlen((*ops)->name)) == 0))
break;
dfs_unlock();
if (ops == &filesystem_operation_table[DFS_FILESYSTEM_TYPES_MAX])
{
/* can't find filesystem */
rt_set_errno(-ENODEV);
return -1;
}
/* check if there is mount implementation */
if ((*ops == NULL) || ((*ops)->mount == NULL))
{
rt_set_errno(-ENOSYS);
return -1;
}
/* make full path for special file */
fullpath = dfs_normalize_path(NULL, path);
if (fullpath == NULL) /* not an abstract path */
{
rt_set_errno(-ENOTDIR);
return -1;
}
/* Check if the path exists or not, raw APIs call, fixme */
if ((strcmp(fullpath, "/") != 0) && (strcmp(fullpath, "/dev") != 0))
{
struct dfs_file fd;
fd_init(&fd);
if (dfs_file_open(&fd, fullpath, O_RDONLY | O_DIRECTORY) < 0)
{
rt_free(fullpath);
rt_set_errno(-ENOTDIR);
return -1;
}
dfs_file_close(&fd);
}
/* check whether the file system mounted or not in the filesystem table
* if it is unmounted yet, find out an empty entry */
dfs_lock();
for (iter = &filesystem_table[0];
iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++)
{
/* check if it is an empty filesystem table entry? if it is, save fs */
if (iter->ops == NULL)
(fs == NULL) ? (fs = iter) : 0;
/* check if the PATH is mounted */
else if (strcmp(iter->path, path) == 0)
{
rt_set_errno(-EINVAL);
goto err1;
}
}
if ((fs == NULL) && (iter == &filesystem_table[DFS_FILESYSTEMS_MAX]))
{
rt_set_errno(-ENOSPC);
LOG_E("There is no space to mount this file system (%s).", filesystemtype);
goto err1;
}
/* register file system */
fs->path = fullpath;
fs->ops = *ops;
fs->dev_id = dev_id;
/* For UFS, record the real filesystem name */
fs->data = (void *) filesystemtype;
/* release filesystem_table lock */
dfs_unlock();
/* open device, but do not check the status of device */
if (dev_id != NULL)
{
if (rt_device_open(fs->dev_id,
RT_DEVICE_OFLAG_RDWR) != RT_EOK)
{
/* The underlying device has error, clear the entry. */
dfs_lock();
rt_memset(fs, 0, sizeof(struct dfs_filesystem));
goto err1;
}
}
/* call mount of this filesystem */
if ((*ops)->mount(fs, rwflag, data) < 0)
{
/* close device */
if (dev_id != NULL)
rt_device_close(fs->dev_id);
/* mount failed */
dfs_lock();
/* clear filesystem table entry */
rt_memset(fs, 0, sizeof(struct dfs_filesystem));
goto err1;
}
return 0;
err1:
dfs_unlock();
rt_free(fullpath);
return -1;
}
/**
* this function will unmount a file system on specified path.
*
* @param specialfile the specified path which mounted a file system.
*
* @return 0 on successful or -1 on failed.
*/
int dfs_unmount(const char *specialfile)
{
char *fullpath;
struct dfs_filesystem *iter;
struct dfs_filesystem *fs = NULL;
fullpath = dfs_normalize_path(NULL, specialfile);
if (fullpath == NULL)
{
rt_set_errno(-ENOTDIR);
return -1;
}
/* lock filesystem */
dfs_lock();
for (iter = &filesystem_table[0];
iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++)
{
/* check if the PATH is mounted */
if ((iter->path != NULL) && (strcmp(iter->path, fullpath) == 0))
{
fs = iter;
break;
}
}
if (fs == NULL ||
fs->ops->unmount == NULL ||
fs->ops->unmount(fs) < 0)
{
goto err1;
}
/* close device, but do not check the status of device */
if (fs->dev_id != NULL)
rt_device_close(fs->dev_id);
if (fs->path != NULL)
rt_free(fs->path);
/* clear this filesystem table entry */
rt_memset(fs, 0, sizeof(struct dfs_filesystem));
dfs_unlock();
rt_free(fullpath);
return 0;
err1:
dfs_unlock();
rt_free(fullpath);
return -1;
}
/**
* make a file system on the special device
*
* @param fs_name the file system name
* @param device_name the special device name
*
* @return 0 on successful, otherwise failed.
*/
int dfs_mkfs(const char *fs_name, const char *device_name)
{
int index;
rt_device_t dev_id = NULL;
/* check device name, and it should not be NULL */
if (device_name != NULL)
dev_id = rt_device_find(device_name);
if (dev_id == NULL)
{
rt_set_errno(-ENODEV);
LOG_E("Device (%s) was not found", device_name);
return -1;
}
/* lock file system */
dfs_lock();
/* find the file system operations */
for (index = 0; index < DFS_FILESYSTEM_TYPES_MAX; index ++)
{
if (filesystem_operation_table[index] != NULL &&
strncmp(filesystem_operation_table[index]->name, fs_name,
strlen(filesystem_operation_table[index]->name)) == 0)
break;
}
dfs_unlock();
if (index < DFS_FILESYSTEM_TYPES_MAX)
{
/* find file system operation */
const struct dfs_filesystem_ops *ops = filesystem_operation_table[index];
if (ops->mkfs == NULL)
{
LOG_E("The file system (%s) mkfs function was not implement", fs_name);
rt_set_errno(-ENOSYS);
return -1;
}
return ops->mkfs(dev_id, fs_name);
}
LOG_E("File system (%s) was not found.", fs_name);
return -1;
}
/**
* this function will return the information about a mounted file system.
*
* @param path the path which mounted file system.
* @param buffer the buffer to save the returned information.
*
* @return 0 on successful, others on failed.
*/
int dfs_statfs(const char *path, struct statfs *buffer)
{
struct dfs_filesystem *fs;
fs = dfs_filesystem_lookup(path);
if (fs != NULL)
{
if (fs->ops->statfs != NULL)
return fs->ops->statfs(fs, buffer);
}
rt_set_errno(-ENOSYS);
return -1;
}
#ifdef RT_USING_DFS_MNTTABLE
int dfs_mount_table(void)
{
int index = 0;
while (1)
{
if (mount_table[index].path == NULL) break;
if (dfs_mount(mount_table[index].device_name,
mount_table[index].path,
mount_table[index].filesystemtype,
mount_table[index].rwflag,
mount_table[index].data) != 0)
{
LOG_E("mount fs[%s] on %s failed.\n", mount_table[index].filesystemtype,
mount_table[index].path);
return -RT_ERROR;
}
index ++;
}
return 0;
}
INIT_ENV_EXPORT(dfs_mount_table);
int dfs_mount_device(rt_device_t dev)
{
int index = 0;
if(dev == RT_NULL) {
rt_kprintf("the device is NULL to be mounted.\n");
return -RT_ERROR;
}
while (1)
{
if (mount_table[index].path == NULL) break;
if(strcmp(mount_table[index].device_name, dev->parent.name) == 0) {
if (dfs_mount(mount_table[index].device_name,
mount_table[index].path,
mount_table[index].filesystemtype,
mount_table[index].rwflag,
mount_table[index].data) != 0)
{
LOG_E("mount fs[%s] device[%s] to %s failed.\n", mount_table[index].filesystemtype, dev->parent.name,
mount_table[index].path);
return -RT_ERROR;
} else {
LOG_D("mount fs[%s] device[%s] to %s ok.\n", mount_table[index].filesystemtype, dev->parent.name,
mount_table[index].path);
return RT_EOK;
}
}
index ++;
}
rt_kprintf("can't find device:%s to be mounted.\n", dev->parent.name);
return -RT_ERROR;
}
int dfs_unmount_device(rt_device_t dev)
{
struct dfs_filesystem *iter;
struct dfs_filesystem *fs = NULL;
/* lock filesystem */
dfs_lock();
for (iter = &filesystem_table[0];
iter < &filesystem_table[DFS_FILESYSTEMS_MAX]; iter++)
{
/* check if the PATH is mounted */
if (strcmp(iter->dev_id->parent.name, dev->parent.name) == 0)
{
fs = iter;
break;
}
}
if (fs == NULL ||
fs->ops->unmount == NULL ||
fs->ops->unmount(fs) < 0)
{
goto err1;
}
/* close device, but do not check the status of device */
if (fs->dev_id != NULL)
rt_device_close(fs->dev_id);
if (fs->path != NULL)
rt_free(fs->path);
/* clear this filesystem table entry */
rt_memset(fs, 0, sizeof(struct dfs_filesystem));
dfs_unlock();
return 0;
err1:
dfs_unlock();
return -1;
}
#endif
#ifdef RT_USING_FINSH
#include <finsh.h>
void mkfs(const char *fs_name, const char *device_name)
{
dfs_mkfs(fs_name, device_name);
}
FINSH_FUNCTION_EXPORT(mkfs, make a file system);
int df(const char *path)
{
int result;
int minor = 0;
long long cap;
struct statfs buffer;
int unit_index = 0;
char *unit_str[] = {"KB", "MB", "GB"};
result = dfs_statfs(path ? path : NULL, &buffer);
if (result != 0)
{
if (rt_get_errno() == -ENOSYS)
rt_kprintf("The function is not implemented.\n");
else
rt_kprintf("statfs failed: errno=%d.\n", rt_get_errno());
return -1;
}
cap = ((long long)buffer.f_bsize) * ((long long)buffer.f_bfree) / 1024LL;
for (unit_index = 0; unit_index < 2; unit_index ++)
{
if (cap < 1024) break;
minor = (cap % 1024) * 10 / 1024; /* only one decimal point */
cap = cap / 1024;
}
rt_kprintf("disk free: %d.%d %s [ %d block, %d bytes per block ]\n",
(unsigned long)cap, minor, unit_str[unit_index], buffer.f_bfree, buffer.f_bsize);
return 0;
}
FINSH_FUNCTION_EXPORT(df, get disk free);
#endif
/**@}*/
/* @} */

View File

@ -0,0 +1,386 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-05-05 Bernard Implement mnt in dfs v2.0
*/
#include <rtthread.h>
#include "dfs.h"
#include "dfs_mnt.h"
#include "dfs_dentry.h"
#include "dfs_private.h"
#define DBG_TAG "DFS.mnt"
#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
static struct dfs_mnt *_root_mnt = RT_NULL;
/*
* mnt tree structure
*
* mnt_root <----------------------------------------+
* | (child) +----------+ |
* v (sibling) v | |
* mnt_child0 -> mnt_child1 | |
* | (child) | |
* v / (parent) | (root)
* mnt_child10 ---/
*
*/
struct dfs_mnt *dfs_mnt_create(const char *path)
{
struct dfs_mnt *mnt = rt_calloc(1, sizeof(struct dfs_mnt));
if (mnt)
{
LOG_I("create mnt at %s", path);
mnt->fullpath = rt_strdup(path);
rt_list_init(&mnt->sibling);
rt_list_init(&mnt->child);
mnt->flags |= MNT_IS_ALLOCED;
rt_atomic_store(&(mnt->ref_count), 1);
}
else
{
rt_set_errno(-ENOMEM);
}
return mnt;
}
int dfs_mnt_insert(struct dfs_mnt* mnt, struct dfs_mnt* child)
{
if (child)
{
if (mnt == RT_NULL)
{
/* insert into root */
mnt = dfs_mnt_lookup(child->fullpath);
if (mnt == RT_NULL || (strcmp(child->fullpath, "/") == 0))
{
/* it's root mnt */
mnt = child;
/* ref to gobal root */
if (_root_mnt)
{
child = _root_mnt;
rt_atomic_sub(&(_root_mnt->parent->ref_count), 1);
rt_atomic_sub(&(_root_mnt->ref_count), 1);
_root_mnt = dfs_mnt_ref(mnt);
mnt->parent = dfs_mnt_ref(mnt);
mnt->flags |= MNT_IS_ADDLIST;
mkdir("/dev", 0777);
}
else
{
_root_mnt = dfs_mnt_ref(mnt);
}
}
}
if (mnt)
{
child->flags |= MNT_IS_ADDLIST;
if (child != mnt)
{
/* not the root, insert into the child list */
rt_list_insert_before(&mnt->child, &child->sibling);
/* child ref self */
dfs_mnt_ref(child);
}
/* parent ref parent */
child->parent = dfs_mnt_ref(mnt);
}
}
return 0;
}
/* remove mnt from mnt_tree */
int dfs_mnt_remove(struct dfs_mnt* mnt)
{
int ret = -RT_ERROR;
if (rt_list_isempty(&mnt->child))
{
rt_list_remove(&mnt->sibling);
if (mnt->parent)
{
/* parent unref parent */
rt_atomic_sub(&(mnt->parent->ref_count), 1);
}
ret = RT_EOK;
}
else
{
LOG_W("remove a mnt point:%s with child.", mnt->fullpath);
}
return ret;
}
/**
* this function will return the file system mounted on specified path.
*
* @param path the specified path string.
*
* @return the found file system or NULL if no file system mounted on
* specified path
*/
struct dfs_mnt* dfs_mnt_lookup(const char* fullpath)
{
struct dfs_mnt *mnt = _root_mnt;
struct dfs_mnt *iter = RT_NULL;
if (mnt)
{
dfs_lock();
if (strncmp(mnt->fullpath, fullpath, strlen(fullpath))!= 0)
{
while (!rt_list_isempty(&mnt->child))
{
rt_list_for_each_entry(iter, &mnt->child, sibling)
{
int mnt_len = rt_strlen(iter->fullpath);
if ((strncmp(iter->fullpath, fullpath, mnt_len) == 0) &&
((fullpath[mnt_len] == '\0') ||
(fullpath[mnt_len] == '/')))
{
mnt = iter;
break;
}
}
if (mnt != iter) break;
}
}
dfs_unlock();
if (mnt)
{
LOG_D("mnt_lookup: %s path @ mount point %p", fullpath, mnt);
DLOG(note, "mnt", "found mnt(%s)", mnt->fs_ops->name);
}
}
return mnt;
}
struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt)
{
if (mnt)
{
rt_atomic_add(&(mnt->ref_count), 1);
DLOG(note, "mnt", "mnt(%s),ref_count=%d", mnt->fs_ops->name, rt_atomic_load(&(mnt->ref_count)));
}
return mnt;
}
int dfs_mnt_unref(struct dfs_mnt* mnt)
{
rt_err_t ret = RT_EOK;
if (mnt)
{
ret = dfs_lock();
if (ret == RT_EOK)
{
rt_atomic_sub(&(mnt->ref_count), 1);
if (rt_atomic_load(&(mnt->ref_count)) < 0)
{
LOG_W("bug on mnt(%s) release ref_count(%d).", mnt->fullpath, mnt->ref_count);
}
DLOG(note, "mnt", "mnt(%s),ref_count=%d", mnt->fs_ops->name, rt_atomic_load(&(mnt->ref_count)));
dfs_unlock();
}
}
return 0;
}
int dfs_mnt_destroy(struct dfs_mnt* mnt)
{
rt_err_t ret = RT_EOK;
if (mnt)
{
ret = dfs_lock();
if (ret == RT_EOK)
{
if (rt_atomic_load(&(mnt->ref_count)) != 1)
{
LOG_W("bug on mnt(%s) ref_count(%d).", mnt->fullpath, mnt->ref_count);
}
/* remote it from mnt list */
if (mnt->flags & MNT_IS_ADDLIST)
{
dfs_mnt_remove(mnt);
}
/* free full path */
rt_free(mnt->fullpath);
mnt->fullpath = RT_NULL;
dfs_unlock();
/* destroy self and the ref_count should be 0 */
DLOG(msg, "mnt", "mnt", DLOG_MSG, "free mnt(%s)", mnt->fs_ops->name);
rt_free(mnt);
}
}
return 0;
}
static struct dfs_mnt* _dfs_mnt_foreach(struct dfs_mnt *mnt, struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter), void *parameter)
{
struct dfs_mnt *iter, *ret = NULL;
if (mnt)
{
ret = func(mnt, parameter);
if (ret == RT_NULL)
{
if (!rt_list_isempty(&mnt->child))
{
/* for each in mount point list */
rt_list_for_each_entry(iter, &mnt->child, sibling)
{
ret = _dfs_mnt_foreach(iter, func, parameter);
if (ret != RT_NULL)
{
break;
}
}
}
}
}
else
{
ret = RT_NULL;
}
return ret;
}
static struct dfs_mnt* _mnt_cmp_devid(struct dfs_mnt *mnt, void *device)
{
struct dfs_mnt *ret = RT_NULL;
struct rt_device *dev = (struct rt_device*)device;
if (dev && mnt)
{
if (mnt->dev_id == dev)
{
ret = mnt;
}
}
return ret;
}
/**
* this function will return the mounted path for specified device.
*
* @param device the device object which is mounted.
*
* @return the mounted path or NULL if none device mounted.
*/
const char *dfs_mnt_get_mounted_path(struct rt_device *device)
{
const char* path = RT_NULL;
if (_root_mnt)
{
struct dfs_mnt* mnt;
dfs_lock();
mnt = _dfs_mnt_foreach(_root_mnt, _mnt_cmp_devid, device);
dfs_unlock();
if (mnt) path = mnt->fullpath;
}
return path;
}
static struct dfs_mnt* _mnt_dump(struct dfs_mnt *mnt, void *parameter)
{
if (mnt)
{
if (mnt->dev_id)
{
rt_kprintf("%-10s %-6s %-10s %d\n",
mnt->fs_ops->name, mnt->dev_id->parent.name, mnt->fullpath, rt_atomic_load(&(mnt->ref_count)));
}
else
{
rt_kprintf("%-10s (NULL) %-10s %d\n",
mnt->fs_ops->name, mnt->fullpath, rt_atomic_load(&(mnt->ref_count)));
}
}
return RT_NULL;
}
static struct dfs_mnt* _mnt_cmp_path(struct dfs_mnt* mnt, void *parameter)
{
const char* fullpath = (const char*)parameter;
struct dfs_mnt *ret = RT_NULL;
if (strncmp(mnt->fullpath, fullpath, rt_strlen(fullpath)) == 0)
{
ret = mnt;
}
return ret;
}
rt_bool_t dfs_mnt_has_child_mnt(struct dfs_mnt *mnt, const char* fullpath)
{
int ret = RT_FALSE;
if (mnt && fullpath)
{
struct dfs_mnt *m = RT_NULL;
dfs_lock();
m = _dfs_mnt_foreach(mnt, _mnt_cmp_path, (void*)fullpath);
dfs_unlock();
if (m)
{
ret = RT_TRUE;
}
}
return ret;
}
int dfs_mnt_list(struct dfs_mnt *mnt)
{
if (!mnt) mnt = _root_mnt;
/* lock file system */
dfs_lock();
_dfs_mnt_foreach(mnt, _mnt_dump, RT_NULL);
/* unlock file system */
dfs_unlock();
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -7,12 +7,15 @@
* Date Author Notes
* 2009-05-27 Yi.qiu The first version
* 2018-02-07 Bernard Change the 3rd parameter of open/fcntl/ioctl to '...'
* 2022-01-19 Meco Man add creat()
* 2021-08-26 linzhenxing add setcwd and modify getcwd\chdir
*/
#include <dfs_file.h>
#include <dfs_private.h>
#include <sys/errno.h>
#include <dfs.h>
#include <unistd.h>
#include <dfs_dentry.h>
#include <dfs_mnt.h>
#include "dfs_private.h"
#ifdef RT_USING_SMART
#include <lwp.h>
@ -35,26 +38,39 @@
int open(const char *file, int flags, ...)
{
int fd, result;
struct dfs_file *d;
struct dfs_file *df = RT_NULL;
mode_t mode = 0;
/* allocate a fd */
fd = fd_new();
if (fd < 0)
if (file == NULL)
{
rt_set_errno(-ENOMEM);
rt_set_errno(-EBADF);
return -1;
}
d = fd_get(fd);
result = dfs_file_open(d, file, flags);
if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE)
{
va_list ap;
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
}
fd = fd_new();
if (fd >= 0)
{
df = fd_get(fd);
}
else
{
rt_set_errno(-RT_ERROR);
return RT_NULL;
}
result = dfs_file_open(df, file, flags, mode);
if (result < 0)
{
/* release the ref-count of fd */
fd_release(fd);
rt_set_errno(result);
return -1;
}
@ -135,18 +151,17 @@ RTM_EXPORT(creat);
int close(int fd)
{
int result;
struct dfs_file *d;
struct dfs_file *file;
d = fd_get(fd);
if (d == NULL)
file = fd_get(fd);
if (file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
result = dfs_file_close(d);
result = dfs_file_close(file);
if (result < 0)
{
rt_set_errno(result);
@ -171,25 +186,30 @@ RTM_EXPORT(close);
* @return the actual read data buffer length. If the returned value is 0, it
* may be reach the end of file, please check errno.
*/
#ifdef _READ_WRITE_RETURN_TYPE
_READ_WRITE_RETURN_TYPE read(int fd, void *buf, size_t len) /* some gcc tool chains will use different data structure */
#if defined(RT_USING_NEWLIB) && defined(_EXFUN)
_READ_WRITE_RETURN_TYPE _EXFUN(read, (int fd, void *buf, size_t len))
#else
ssize_t read(int fd, void *buf, size_t len)
#endif
{
int result;
struct dfs_file *d;
ssize_t result;
struct dfs_file *file;
/* get the fd */
d = fd_get(fd);
if (d == NULL)
if (buf == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
file = fd_get(fd);
if (file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
result = dfs_file_read(d, buf, len);
result = dfs_file_read(file, buf, len);
if (result < 0)
{
rt_set_errno(result);
@ -211,25 +231,30 @@ RTM_EXPORT(read);
*
* @return the actual written data buffer length.
*/
#ifdef _READ_WRITE_RETURN_TYPE
_READ_WRITE_RETURN_TYPE write(int fd, const void *buf, size_t len) /* some gcc tool chains will use different data structure */
#if defined(RT_USING_NEWLIB) && defined(_EXFUN)
_READ_WRITE_RETURN_TYPE _EXFUN(write, (int fd, const void *buf, size_t len))
#else
ssize_t write(int fd, const void *buf, size_t len)
#endif
{
int result;
struct dfs_file *d;
ssize_t result;
struct dfs_file *file;
/* get the fd */
d = fd_get(fd);
if (d == NULL)
if (buf == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
file = fd_get(fd);
if (file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
result = dfs_file_write(d, buf, len);
result = dfs_file_write(file, buf, len);
if (result < 0)
{
rt_set_errno(result);
@ -253,43 +278,18 @@ RTM_EXPORT(write);
*/
off_t lseek(int fd, off_t offset, int whence)
{
int result;
struct dfs_file *d;
off_t result;
struct dfs_file *file;
d = fd_get(fd);
if (d == NULL)
file = fd_get(fd);
if (file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
switch (whence)
{
case SEEK_SET:
break;
case SEEK_CUR:
offset += d->pos;
break;
case SEEK_END:
offset += d->vnode->size;
break;
default:
rt_set_errno(-EINVAL);
return -1;
}
if (offset < 0)
{
rt_set_errno(-EINVAL);
return -1;
}
result = dfs_file_lseek(d, offset);
result = dfs_file_lseek(file, offset, whence);
if (result < 0)
{
rt_set_errno(result);
@ -297,11 +297,10 @@ off_t lseek(int fd, off_t offset, int whence)
return -1;
}
return offset;
return result;
}
RTM_EXPORT(lseek);
#ifndef _WIN32
/**
* this function is a POSIX compliant version, which will rename old file name
* to new file name.
@ -317,6 +316,12 @@ int rename(const char *old_file, const char *new_file)
{
int result;
if (old_file == NULL || new_file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
result = dfs_file_rename(old_file, new_file);
if (result < 0)
{
@ -328,7 +333,6 @@ int rename(const char *old_file, const char *new_file)
return 0;
}
RTM_EXPORT(rename);
#endif
/**
* this function is a POSIX compliant version, which will unlink (remove) a
@ -341,6 +345,21 @@ RTM_EXPORT(rename);
int unlink(const char *pathname)
{
int result;
struct stat stat;
if (pathname == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
result = dfs_file_lstat(pathname, &stat);
if (result == 0 && S_ISDIR(stat.st_mode))
{
rt_set_errno(-RT_ERROR);
return -1;
}
result = dfs_file_unlink(pathname);
if (result < 0)
@ -354,6 +373,7 @@ int unlink(const char *pathname)
}
RTM_EXPORT(unlink);
#ifndef _WIN32 /* we can not implement these functions */
/**
* this function is a POSIX compliant version, which will get file information.
*
@ -366,12 +386,16 @@ int stat(const char *file, struct stat *buf)
{
int result;
if (file == NULL || buf == NULL)
{
rt_set_errno(EBADF);
return -1;
}
result = dfs_file_stat(file, buf);
if (result < 0)
{
rt_set_errno(result);
return -1;
rt_set_errno(-result);
}
return result;
@ -388,20 +412,30 @@ RTM_EXPORT(stat);
*/
int fstat(int fildes, struct stat *buf)
{
struct dfs_file *d;
int ret = 0;
struct dfs_file *file;
if (buf == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
/* get the fd */
d = fd_get(fildes);
if (d == NULL)
file = fd_get(fildes);
if (file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
return stat(d->vnode->fullpath, buf);
ret = file->dentry->mnt->fs_ops->stat(file->dentry, buf);
return ret;
}
RTM_EXPORT(fstat);
#endif
/**
* this function is a POSIX compliant version, which shall request that all data
@ -416,17 +450,17 @@ RTM_EXPORT(fstat);
int fsync(int fildes)
{
int ret;
struct dfs_file *d;
struct dfs_file *file;
/* get the fd */
d = fd_get(fildes);
if (d == NULL)
file = fd_get(fildes);
if (file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
ret = dfs_file_flush(d);
ret = dfs_file_fsync(file);
return ret;
}
@ -447,11 +481,10 @@ RTM_EXPORT(fsync);
int fcntl(int fildes, int cmd, ...)
{
int ret = -1;
struct dfs_file *d;
struct dfs_file *file;
/* get the fd */
d = fd_get(fildes);
if (d)
file = fd_get(fildes);
if (file)
{
void *arg;
va_list ap;
@ -460,9 +493,16 @@ int fcntl(int fildes, int cmd, ...)
arg = va_arg(ap, void *);
va_end(ap);
ret = dfs_file_ioctl(d, cmd, arg);
ret = dfs_file_ioctl(file, cmd, arg);
if (ret < 0)
{
ret = dfs_file_fcntl(fildes, cmd, (unsigned long)arg);
}
}
else
{
ret = -EBADF;
}
else ret = -EBADF;
if (ret < 0)
{
@ -513,10 +553,10 @@ RTM_EXPORT(ioctl);
int ftruncate(int fd, off_t length)
{
int result;
struct dfs_file *d;
struct dfs_file *file;
d = fd_get(fd);
if (d == NULL)
file = fd_get(fd);
if (file == NULL)
{
rt_set_errno(-EBADF);
@ -529,7 +569,8 @@ int ftruncate(int fd, off_t length)
return -1;
}
result = dfs_file_ftruncate(d, length);
result = dfs_file_ftruncate(file, length);
if (result < 0)
{
rt_set_errno(result);
@ -554,6 +595,12 @@ int statfs(const char *path, struct statfs *buf)
{
int result;
if (path == NULL || buf == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
result = dfs_statfs(path, buf);
if (result < 0)
{
@ -577,18 +624,27 @@ RTM_EXPORT(statfs);
*/
int fstatfs(int fildes, struct statfs *buf)
{
struct dfs_file *d;
int ret = 0;
struct dfs_file *file;
if (buf == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
/* get the fd */
d = fd_get(fildes);
if (d == NULL)
file = fd_get(fildes);
if (file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
return statfs(d->vnode->fullpath, buf);
ret = file->dentry->mnt->fs_ops->statfs(file->dentry->mnt, buf);
return ret;
}
RTM_EXPORT(fstatfs);
@ -602,37 +658,47 @@ RTM_EXPORT(fstatfs);
*/
int mkdir(const char *path, mode_t mode)
{
int fd;
struct dfs_file *d;
int result;
struct stat stat;
struct dfs_file file;
fd = fd_new();
if (fd == -1)
if (path == NULL)
{
rt_set_errno(-ENOMEM);
rt_set_errno(-EBADF);
return -1;
}
d = fd_get(fd);
result = dfs_file_open(d, path, O_DIRECTORY | O_CREAT);
if (result < 0)
if (path && dfs_file_lstat(path, &stat) == 0)
{
rt_set_errno(-RT_ERROR);
return -1;
}
dfs_file_init(&file);
result = dfs_file_open(&file, path, O_DIRECTORY | O_CREAT, mode);
if (result >= 0)
{
dfs_file_close(&file);
result = 0;
}
else
{
fd_release(fd);
rt_set_errno(result);
return -1;
result = -1;
}
dfs_file_close(d);
fd_release(fd);
dfs_file_deinit(&file);
return 0;
return result;
}
RTM_EXPORT(mkdir);
#ifdef RT_USING_FINSH
#include <finsh.h>
FINSH_FUNCTION_EXPORT(mkdir, create a directory);
#endif
/**
* this function is a POSIX compliant version, which will remove a directory.
*
@ -643,6 +709,49 @@ RTM_EXPORT(mkdir);
int rmdir(const char *pathname)
{
int result;
DIR *dir = RT_NULL;
struct stat stat;
if (!pathname)
{
rt_set_errno(-RT_ERROR);
return -1;
}
dir = opendir(pathname);
if (dir)
{
struct dirent *dirent;
while (1)
{
dirent = readdir(dir);
if (dirent == RT_NULL)
break;
if (rt_strcmp(".", dirent->d_name) != 0 &&
rt_strcmp("..", dirent->d_name) != 0)
{
break;
}
}
closedir(dir);
if (dirent)
{
rt_set_errno(-RT_ERROR);
return -1;
}
}
if (dfs_file_lstat(pathname, &stat) == 0)
{
if (S_ISLNK(stat.st_mode))
{
rt_set_errno(-RT_ERROR);
return -1;
}
}
result = dfs_file_unlink(pathname);
if (result < 0)
@ -665,30 +774,35 @@ RTM_EXPORT(rmdir);
*/
DIR *opendir(const char *name)
{
struct dfs_file *d;
DIR *t = RT_NULL;
int fd, result;
DIR *t;
struct dfs_file *file = RT_NULL;
t = NULL;
/* allocate a fd */
fd = fd_new();
if (fd == -1)
if (!name || dfs_file_isdir(name) != 0)
{
rt_set_errno(-ENOMEM);
return NULL;
rt_set_errno(-RT_ERROR);
return RT_NULL;
}
d = fd_get(fd);
result = dfs_file_open(d, name, O_RDONLY | O_DIRECTORY);
fd = fd_new();
if (fd >= 0)
{
file = fd_get(fd);
}
else
{
rt_set_errno(-RT_ERROR);
return RT_NULL;
}
result = dfs_file_open(file, name, O_RDONLY | O_DIRECTORY, 0);
if (result >= 0)
{
/* open successfully */
t = (DIR *) rt_malloc(sizeof(DIR));
if (t == NULL)
{
dfs_file_close(d);
dfs_file_close(file);
fd_release(fd);
}
else
@ -701,7 +815,6 @@ DIR *opendir(const char *name)
return t;
}
/* open failed */
fd_release(fd);
rt_set_errno(result);
@ -721,40 +834,49 @@ RTM_EXPORT(opendir);
struct dirent *readdir(DIR *d)
{
int result;
struct dfs_file *fd;
struct dirent *dirent = NULL;
fd = fd_get(d->fd);
if (fd == NULL)
if (d == NULL)
{
rt_set_errno(-EBADF);
return NULL;
}
if (d->num)
do
{
struct dirent *dirent_ptr;
dirent_ptr = (struct dirent *)&d->buf[d->cur];
d->cur += dirent_ptr->d_reclen;
}
if (!d->num || d->cur >= d->num)
{
/* get a new entry */
result = dfs_file_getdents(fd,
(struct dirent *)d->buf,
sizeof(d->buf) - 1);
if (result <= 0)
if (d->num)
{
rt_set_errno(result);
return NULL;
struct dirent *dirent_ptr;
dirent_ptr = (struct dirent *)&d->buf[d->cur];
d->cur += dirent_ptr->d_reclen;
}
d->num = result;
d->cur = 0; /* current entry index */
}
if (!d->num || d->cur >= d->num)
{
/* get a new entry */
result = dfs_file_getdents(fd_get(d->fd),
(struct dirent *)d->buf,
sizeof(d->buf) - 1);
if (result <= 0)
{
rt_set_errno(result);
return (struct dirent *)(d->buf + d->cur);
return NULL;
}
d->num = result;
d->cur = 0; /* current entry index */
}
dirent = (struct dirent *)(d->buf + d->cur);
if (rt_strcmp(".", dirent->d_name) != 0 &&
rt_strcmp("..", dirent->d_name) != 0)
{
break;
}
} while (dirent);
return dirent;
}
RTM_EXPORT(readdir);
@ -768,18 +890,24 @@ RTM_EXPORT(readdir);
*/
long telldir(DIR *d)
{
struct dfs_file *fd;
struct dfs_file *file;
long result;
fd = fd_get(d->fd);
if (fd == NULL)
if (d == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
file = fd_get(d->fd);
if (file == NULL)
{
rt_set_errno(-EBADF);
return 0;
}
result = fd->pos - d->num + d->cur;
result = file->fpos - d->num + d->cur;
return result;
}
@ -794,19 +922,39 @@ RTM_EXPORT(telldir);
*/
void seekdir(DIR *d, long offset)
{
struct dfs_file *fd;
struct dfs_file *file;
fd = fd_get(d->fd);
if (fd == NULL)
if (d == NULL)
{
rt_set_errno(-EBADF);
return;
}
file = fd_get(d->fd);
if (file == NULL)
{
rt_set_errno(-EBADF);
return ;
return;
}
/* seek to the offset position of directory */
if (dfs_file_lseek(fd, offset) >= 0)
d->num = d->cur = 0;
if (d && d->fd > 0)
{
if (file->fpos > offset)
{
/* seek to the offset position of directory */
if (dfs_file_lseek(fd_get(d->fd), 0, SEEK_SET) >= 0)
d->num = d->cur = 0;
}
while(file->fpos < offset)
{
if (!readdir(d))
{
break;
}
}
}
}
RTM_EXPORT(seekdir);
@ -818,19 +966,12 @@ RTM_EXPORT(seekdir);
*/
void rewinddir(DIR *d)
{
struct dfs_file *fd;
fd = fd_get(d->fd);
if (fd == NULL)
if (d && d->fd > 0)
{
rt_set_errno(-EBADF);
return ;
/* seek to the beginning of directory */
if (dfs_file_lseek(fd_get(d->fd), 0, SEEK_SET) >= 0)
d->num = d->cur = 0;
}
/* seek to the beginning of directory */
if (dfs_file_lseek(fd, 0) >= 0)
d->num = d->cur = 0;
}
RTM_EXPORT(rewinddir);
@ -845,21 +986,22 @@ RTM_EXPORT(rewinddir);
int closedir(DIR *d)
{
int result;
struct dfs_file *fd;
struct dfs_file *file;
fd = fd_get(d->fd);
if (fd == NULL)
if (d == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
result = dfs_file_close(fd);
fd_release(d->fd);
rt_free(d);
file = fd_get(d->fd);
if (file == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
result = dfs_file_close(file);
if (result < 0)
{
rt_set_errno(result);
@ -867,7 +1009,12 @@ int closedir(DIR *d)
return -1;
}
else
return 0;
{
fd_release(d->fd);
rt_free(d);
}
return 0;
}
RTM_EXPORT(closedir);
@ -893,7 +1040,8 @@ int chdir(const char *path)
#endif
dfs_unlock();
return 0;
rt_set_errno(-ENOTDIR);
return -1;
}
if (strlen(path) > DFS_PATH_MAX)
@ -955,12 +1103,52 @@ FINSH_FUNCTION_EXPORT_ALIAS(chdir, cd, change current working directory);
*/
int access(const char *path, int amode)
{
int fd, ret = -1, flags = 0;
struct stat sb;
if (stat(path, &sb) < 0)
return -1; /* already sets errno */
if (path == NULL)
{
rt_set_errno(-EBADF);
return -1;
}
if (amode == F_OK)
{
if (stat(path, &sb) < 0)
return -1; /* already sets errno */
else
return 0;
}
/* ignore R_OK,W_OK,X_OK condition */
return 0;
if (dfs_file_isdir(path) == 0)
{
flags |= O_DIRECTORY;
}
if (amode & R_OK)
{
flags |= O_RDONLY;
}
if (amode & W_OK)
{
flags |= O_WRONLY;
}
if (amode & X_OK)
{
flags |= O_EXEC;
}
fd = open(path, flags, 0);
if (fd >= 0)
{
ret = 0;
close(fd);
}
return ret;
}
/**
* this function is a POSIX compliant version, which will set current
@ -970,6 +1158,12 @@ int access(const char *path, int amode)
*/
void setcwd(char *buf)
{
if (buf == NULL)
{
rt_set_errno(-EBADF);
return;
}
#ifdef DFS_USING_WORKDIR
dfs_lock();
#ifdef RT_USING_SMART
@ -997,6 +1191,12 @@ RTM_EXPORT(setcwd);
*/
char *getcwd(char *buf, size_t size)
{
if (buf == NULL)
{
rt_set_errno(-EBADF);
return NULL;
}
#ifdef DFS_USING_WORKDIR
char *dir_buf = RT_NULL;

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#ifndef DFS_PRIVATE_H__
#define DFS_PRIVATE_H__
#include <dfs.h>
#define NO_WORKING_DIR "system does not support working directory\n"
extern char working_directory[];
#endif

View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-05-05 Bernard Implement vnode in dfs v2.0
*/
#include <dfs_file.h>
#include <dfs_mnt.h>
#define DBG_TAG "DFS.vnode"
#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
int dfs_vnode_init(struct dfs_vnode *vnode, int type, const struct dfs_file_ops *fops)
{
if (vnode)
{
rt_memset(vnode, 0, sizeof(struct dfs_vnode));
vnode->type = type;
rt_atomic_store(&(vnode->ref_count), 1);
vnode->mnt = RT_NULL;
vnode->fops = fops;
}
return 0;
}
struct dfs_vnode *dfs_vnode_create(void)
{
struct dfs_vnode *vnode = rt_calloc(1, sizeof(struct dfs_vnode));
if (!vnode)
{
LOG_E("create a vnode failed.");
return RT_NULL;
}
rt_atomic_store(&(vnode->ref_count), 1);
LOG_I("create a vnode: %p", vnode);
return vnode;
}
int dfs_vnode_destroy(struct dfs_vnode* vnode)
{
rt_err_t ret = RT_EOK;
if (vnode)
{
ret = dfs_file_lock();
if (ret == RT_EOK)
{
if (rt_atomic_load(&(vnode->ref_count)) == 1)
{
LOG_I("free a vnode: %p", vnode);
if (vnode->mnt)
{
DLOG(msg, "vnode", vnode->mnt->fs_ops->name, DLOG_MSG, "fs_ops->free_vnode");
vnode->mnt->fs_ops->free_vnode(vnode);
}
else
{
DLOG(msg, "vnode", "vnode", DLOG_MSG, "destroy vnode(mnt=NULL)");
}
dfs_file_unlock();
rt_free(vnode);
}
else
{
dfs_file_unlock();
}
}
}
return 0;
}
struct dfs_vnode *dfs_vnode_ref(struct dfs_vnode *vnode)
{
if (vnode)
{
rt_atomic_add(&(vnode->ref_count), 1);
DLOG(note, "vnode", "vnode ref_count=%d", rt_atomic_load(&(vnode->ref_count)));
}
return vnode;
}
void dfs_vnode_unref(struct dfs_vnode *vnode)
{
rt_err_t ret = RT_EOK;
if (vnode)
{
ret = dfs_file_lock();
if (ret == RT_EOK)
{
rt_atomic_sub(&(vnode->ref_count), 1);
DLOG(note, "vnode", "vnode ref_count=%d", rt_atomic_load(&(vnode->ref_count)));
if (rt_atomic_load(&(vnode->ref_count)) == 0)
{
LOG_I("free a vnode: %p", vnode);
DLOG(msg, "vnode", "vnode", DLOG_MSG, "free vnode, ref_count=0");
if (vnode->mnt)
{
DLOG(msg, "vnode", vnode->mnt->fs_ops->name, DLOG_MSG, "fs_ops->free_vnode");
vnode->mnt->fs_ops->free_vnode(vnode);
}
dfs_file_unlock();
rt_free(vnode);
}
else
{
dfs_file_unlock();
DLOG(note, "vnode", "vnode ref_count=%d", rt_atomic_load(&(vnode->ref_count)));
}
}
}
return;
}

View File

@ -200,7 +200,11 @@ static int pipe_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
* When the return value is 0, it means O_NONBLOCK is enabled and there is no thread that has the pipe open for writing.
* When the return value is -EAGAIN, it means there are no data to be read.
*/
#ifdef RT_USING_DFS_V2
static int pipe_fops_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
#else
static int pipe_fops_read(struct dfs_file *fd, void *buf, size_t count)
#endif
{
int len = 0;
rt_pipe_t *pipe;
@ -254,7 +258,11 @@ out:
* When the return value is -EAGAIN, it means O_NONBLOCK is enabled and there are no space to be written.
* When the return value is -EPIPE, it means there is no thread that has the pipe open for reading.
*/
#ifdef RT_USING_DFS_V2
static int pipe_fops_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos)
#else
static int pipe_fops_write(struct dfs_file *fd, const void *buf, size_t count)
#endif
{
int len;
rt_pipe_t *pipe;
@ -369,15 +377,12 @@ static int pipe_fops_poll(struct dfs_file *fd, rt_pollreq_t *req)
static const struct dfs_file_ops pipe_fops =
{
pipe_fops_open,
pipe_fops_close,
pipe_fops_ioctl,
pipe_fops_read,
pipe_fops_write,
RT_NULL,
RT_NULL,
RT_NULL,
pipe_fops_poll,
.open = pipe_fops_open,
.close = pipe_fops_close,
.ioctl = pipe_fops_ioctl,
.read = pipe_fops_read,
.write = pipe_fops_write,
.poll = pipe_fops_poll,
};
#endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */

View File

@ -135,7 +135,11 @@ static int serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
return rt_device_control(device, cmd, args);
}
#ifdef RT_USING_DFS_V2
static int serial_fops_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
#else
static int serial_fops_read(struct dfs_file *fd, void *buf, size_t count)
#endif
{
int size = 0;
rt_device_t device;
@ -169,7 +173,11 @@ static int serial_fops_read(struct dfs_file *fd, void *buf, size_t count)
return size;
}
#ifdef RT_USING_DFS_V2
static int serial_fops_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos)
#else
static int serial_fops_write(struct dfs_file *fd, const void *buf, size_t count)
#endif
{
rt_device_t device;
@ -211,15 +219,12 @@ static int serial_fops_poll(struct dfs_file *fd, struct rt_pollreq *req)
static const struct dfs_file_ops _serial_fops =
{
serial_fops_open,
serial_fops_close,
serial_fops_ioctl,
serial_fops_read,
serial_fops_write,
RT_NULL, /* flush */
RT_NULL, /* lseek */
RT_NULL, /* getdents */
serial_fops_poll,
.open = serial_fops_open,
.close = serial_fops_close,
.ioctl = serial_fops_ioctl,
.read = serial_fops_read,
.write = serial_fops_write,
.poll = serial_fops_poll,
};
#endif /* RT_USING_POSIX_STDIO */

View File

@ -338,7 +338,11 @@ static int tty_ioctl(struct dfs_file *fd, int cmd, void *args)
return ret;
}
#ifdef RT_USING_DFS_V2
static int tty_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
#else
static int tty_read(struct dfs_file *fd, void *buf, size_t count)
#endif
{
int ret = 0;
struct tty_struct *tty = RT_NULL;
@ -355,7 +359,11 @@ static int tty_read(struct dfs_file *fd, void *buf, size_t count)
return ret;
}
static int tty_write(struct dfs_file *fd, const void *buf, size_t count)
#ifdef RT_USING_DFS_V2
static int tty_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos)
#else
static int tty_write(struct dfs_file *fd, const void *buf, size_t count )
#endif
{
int ret = 0;
struct tty_struct *tty = RT_NULL;
@ -391,15 +399,12 @@ static int tty_poll(struct dfs_file *fd, struct rt_pollreq *req)
static const struct dfs_file_ops tty_fops =
{
tty_open,
tty_close,
tty_ioctl,
tty_read,
tty_write,
RT_NULL, /* flush */
RT_NULL, /* lseek */
RT_NULL, /* getdents */
tty_poll,
.open = tty_open,
.close = tty_close,
.ioctl = tty_ioctl,
.read = tty_read,
.write = tty_write,
.poll = tty_poll,
};
const struct dfs_file_ops *tty_get_fops(void)

View File

@ -677,9 +677,21 @@ void msh_auto_complete_path(char *path)
if (multi == 1)
{
struct stat buffer = {0};
if ((stat(path, &buffer) == 0) && (S_ISDIR(buffer.st_mode)))
if ((stat(path, &buffer) == 0))
{
strcat(path, "/");
if (S_ISDIR(buffer.st_mode))
{
strcat(path, "/");
}
else if (S_ISLNK(buffer.st_mode))
{
DIR *dir = opendir(path);
if (dir)
{
closedir(dir);
strcat(path, "/");
}
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -18,6 +18,9 @@
#include <dfs_file.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef RT_USING_DFS_V2
#include <dfs_mnt.h>
#endif
static int msh_readline(int fd, char *line_buf, int size)
{
@ -170,6 +173,46 @@ static int cmd_ls(int argc, char **argv)
}
MSH_CMD_EXPORT_ALIAS(cmd_ls, ls, List information about the FILEs.);
#ifdef RT_USING_DFS_V2
static int cmd_ln(int argc, char **argv)
{
if (argc < 3)
{
rt_kprintf("Usage: ln target link_name\n");
rt_kprintf("Make symbolic link between files.\n");
}
else
{
for(int i = 0; i + 3 <= argc; i ++)
{
dfs_file_symlink(argv[1], argv[2 + i]);
}
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(cmd_ln, ln, Make symbolic link between files);
static int cmd_link(int argc, char **argv)
{
if (argc < 3)
{
rt_kprintf("Usage: link target link_name\n");
rt_kprintf("Make link between files.\n");
}
else
{
for(int i = 0; i + 3 <= argc; i ++)
{
dfs_file_link(argv[1], argv[2 + i]);
}
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(cmd_link, link, Make link between files);
#endif
static int cmd_cp(int argc, char **argv)
{
void copy(const char *src, const char *dst);
@ -301,7 +344,7 @@ static void directory_delete_for_msh(const char *pathname, char f, char v)
rt_strcmp("..", dirent->d_name) != 0)
{
rt_sprintf(full_path, "%s/%s", pathname, dirent->d_name);
if (dirent->d_type == DT_REG)
if (dirent->d_type != DT_DIR)
{
if (unlink(full_path) != 0)
{
@ -313,7 +356,7 @@ static void directory_delete_for_msh(const char *pathname, char f, char v)
rt_kprintf("removed '%s'\n", full_path);
}
}
else if (dirent->d_type == DT_DIR)
else
{
directory_delete_for_msh(full_path, f, v);
}
@ -321,7 +364,7 @@ static void directory_delete_for_msh(const char *pathname, char f, char v)
}
closedir(dir);
rt_free(full_path);
if (unlink(pathname) != 0)
if (rmdir(pathname) != 0)
{
if (f == 0)
rt_kprintf("cannot remove '%s'\n", pathname);
@ -373,7 +416,11 @@ static int cmd_rm(int argc, char **argv)
for (index = 1; index < argc; index ++)
{
struct stat s;
#ifdef RT_USING_DFS_V2
if (dfs_file_lstat(argv[index], &s) == 0)
#else
if (stat(argv[index], &s) == 0)
#endif
{
if (s.st_mode & S_IFDIR)
{
@ -479,8 +526,6 @@ static int cmd_mkfs(int argc, char **argv)
}
MSH_CMD_EXPORT_ALIAS(cmd_mkfs, mkfs, format disk with file system);
extern struct dfs_filesystem filesystem_table[];
/*
* If no argument is specified, display the mount history;
* If there are 3 arguments, mount the filesystem.
@ -493,6 +538,14 @@ static int cmd_mount(int argc, char **argv)
{
if (argc == 1)
{
#ifdef RT_USING_DFS_V2
/* display the mount history */
rt_kprintf("filesystem device mountpoint refcount\n");
rt_kprintf("---------- ------ ---------- --------\n");
dfs_mnt_list(RT_NULL);
#else
extern struct dfs_filesystem filesystem_table[];
struct dfs_filesystem *iter;
/* display the mount history */
@ -507,6 +560,7 @@ static int cmd_mount(int argc, char **argv)
iter->ops->name, iter->dev_id->parent.name, iter->path);
}
}
#endif
return 0;
}
else if (argc == 4)
@ -586,9 +640,11 @@ static int cmd_umount(int argc, char **argv)
}
MSH_CMD_EXPORT_ALIAS(cmd_umount, umount, Unmount the mountpoint);
extern int df(const char *path);
static int cmd_df(int argc, char **argv)
{
#ifndef RT_USING_DFS_V2
extern int df(const char *path);
if (argc != 2)
{
df("/");
@ -604,6 +660,7 @@ static int cmd_df(int argc, char **argv)
df(argv[1]);
}
}
#endif
return 0;
}
@ -742,4 +799,299 @@ static int cmd_tail(int argc, char **argv)
}
MSH_CMD_EXPORT_ALIAS(cmd_tail, tail, print the last N - lines data of the given file);
#ifdef RT_USING_DFS_V2
static void directory_setattr(const char *pathname, struct dfs_attr *attr, char f, char v)
{
DIR *dir = NULL;
struct dirent *dirent = NULL;
char *full_path;
if (pathname == RT_NULL)
return;
full_path = (char *)rt_malloc(DFS_PATH_MAX);
if (full_path == RT_NULL)
return;
dir = opendir(pathname);
if (dir == RT_NULL)
{
if (f == 0)
{
rt_kprintf("cannot open '%s'\n", pathname);
}
rt_free(full_path);
return;
}
while (1)
{
dirent = readdir(dir);
if (dirent == RT_NULL)
break;
if (rt_strcmp(".", dirent->d_name) != 0 &&
rt_strcmp("..", dirent->d_name) != 0)
{
rt_sprintf(full_path, "%s/%s", pathname, dirent->d_name);
if (dirent->d_type == DT_REG)
{
if (dfs_file_setattr(full_path, attr) != 0)
{
if (f == 0)
{
rt_kprintf("'%s' setattr failed, no such file or directory\n", full_path);
}
}
else if (v)
{
rt_kprintf("'%s' setattr 0x%X\n", full_path, attr->st_mode);
}
}
else if (dirent->d_type == DT_DIR)
{
directory_setattr(full_path, attr, f, v);
}
}
}
closedir(dir);
rt_free(full_path);
if (dfs_file_setattr(pathname, attr) != 0)
{
if (f == 0)
{
rt_kprintf("'%s' setattr failed, no such file or directory\n", pathname);
}
}
else if (v)
{
rt_kprintf("'%s' setattr 0x%X\n", pathname, attr->st_mode);
}
}
static int cmd_chmod(int argc, char **argv)
{
if (argc < 3)
{
rt_kprintf("Usage: chmod [OPTION]... MODE[,MODE]... FILE...\n");
rt_kprintf(" chmod [-f|v|r] [u|g|o|a][+/-/=][r|w|x] file...\n");
rt_kprintf(" -f suppress most error messages\n");
rt_kprintf(" -v output a diagnostic for every file processed\n");
rt_kprintf(" -r change files and directories recursively\n");
rt_kprintf("Change the mode of each FILE to MODE.\n");
}
else
{
int argv_c = 1;
char f = 0, r = 0, v = 0;
if (argv[argv_c][0] == '-')
{
for (int i = 1; argv[argv_c][i]; i++)
{
switch (argv[argv_c][i])
{
case 'f':
f = 1;
break;
case 'r':
r = 1;
break;
case 'v':
v = 1;
break;
default:
rt_kprintf("Error: Bad option: %c\n", argv[argv_c][i]);
return 0;
}
}
argv_c++;
}
if (argc - argv_c > 1)
{
int U = 1, G = 2, O = 4, ALL = 7;
int off[5] = {0, 6, 3, 0, 0};
int ADD = 1, SUB = 2, SET = 4;
int R = 4, W = 2, X = 1;
int user[3] = {0}, change[3] = {0}, mode[3] = {0};
struct dfs_attr attr;
char *cmd = argv[argv_c];
int index = 0, num = 0;
while (cmd[index] != '\0')
{
switch (cmd[index])
{
case 'u':
user[num] |= U;
break;
case 'g':
user[num] |= G;
break;
case 'o':
user[num] |= O;
break;
case 'a':
user[num] |= ALL;
break;
case ',':
if (num < 2)
num++;
break;
}
index++;
}
index = 0;
num = 0;
while (cmd[index] != '\0')
{
switch (cmd[index])
{
case '+':
change[num] = ADD;
break;
case '-':
change[num] = SUB;
break;
case '=':
change[num] = SET;
break;
case ',':
if (num < 2)
num++;
break;
}
index++;
}
index = 0;
num = 0;
while (cmd[index] != '\0')
{
switch (cmd[index])
{
case 'r':
mode[num] |= R;
break;
case 'w':
mode[num] |= W;
break;
case 'x':
mode[num] |= X;
break;
case ',':
if (num < 2)
num++;
break;
}
index++;
}
attr.st_mode = 0;
for (int i = 0; i <= num; i++)
{
if (change[i] == ADD)
{
if (user[i] & U)
{
attr.st_mode |= mode[i] << off[user[i] & U];
}
if (user[i] & G)
{
attr.st_mode |= mode[i] << off[user[i] & G];
}
if (user[i] & O)
{
attr.st_mode |= mode[i] << off[user[i] & O];
}
}
else if (change[i] == SUB)
{
if (user[i] & U)
{
attr.st_mode &= ~(mode[i] << off[user[i] & U]);
}
if (user[i] & G)
{
attr.st_mode &= ~(mode[i] << off[user[i] & G]);
}
if (user[i] & O)
{
attr.st_mode &= ~(mode[i] << off[user[i] & O]);
}
}
else if (change[i] == SET)
{
if (user[i] & U)
{
attr.st_mode &= ~(7 << off[user[i] & U]);
attr.st_mode |= mode[i] << off[user[i] & U];
}
if (user[i] & G)
{
attr.st_mode &= ~(7 << off[user[i] & G]);
attr.st_mode |= mode[i] << off[user[i] & G];
}
if (user[i] & O)
{
attr.st_mode &= ~(7 << off[user[i] & O]);
attr.st_mode |= mode[i] << off[user[i] & O];
}
}
}
argv_c++;
for (int i = argv_c; i < argc; i++)
{
if (r)
{
struct stat s;
if (stat(argv[i], &s) == 0)
{
if (s.st_mode & S_IFDIR)
{
directory_setattr(argv[i], &attr, f, v);
}
else if (f == 0)
{
rt_kprintf("'%s' is not a directory\n", argv[i]);
}
}
}
else
{
if (dfs_file_setattr(argv[i], &attr) != 0)
{
if (f == 0)
{
rt_kprintf("'%s' setattr failed, no such file or directory\n", argv[i]);
}
}
else if (v)
{
rt_kprintf("'%s' setattr 0x%X\n", argv[i], attr.st_mode);
}
}
}
}
}
return 0;
}
MSH_CMD_EXPORT_ALIAS(cmd_chmod, chmod, Change the file attr.);
#endif
#endif /* defined(RT_USING_FINSH) && defined(DFS_USING_POSIX) */

View File

@ -26,10 +26,14 @@ extern "C" {
#define FT_SOCKET 1 /* socket file */
#define FT_DIRECTORY 2 /* directory */
#define FT_USER 3 /* user defined */
#define FT_DEVICE 4 /* device */
#define FT_SYMLINK 5 /* symbol link */
#define DT_UNKNOWN 0x00
#define DT_REG 0x01
#define DT_DIR 0x02
#define DT_FIFO 0x01
#define DT_SYMLINK 0x03
#define DT_DIR 0x04
#define DT_REG 0x08
#ifndef HAVE_DIR_STRUCTURE
#define HAVE_DIR_STRUCTURE
@ -61,7 +65,7 @@ DIR *opendir(const char *);
struct dirent *readdir(DIR *);
int readdir_r(DIR *, struct dirent *, struct dirent **);
void rewinddir(DIR *);
void seekdir(DIR *, long int);
void seekdir(DIR *, long);
long telldir(DIR *);
#ifdef __cplusplus

View File

@ -1,10 +1,32 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023/06/08 Bernard Add macro definition for `#pragma once`
*/
#ifndef UNISTD_H__
#define UNISTD_H__
#include "sys/unistd.h"
#ifndef F_OK
#define F_OK 0
#endif
#ifndef R_OK
#define R_OK 4
#endif
#ifndef W_OK
#define W_OK 2
#endif
#ifndef X_OK
#define X_OK 1
#endif
#endif /* UNISTD_H__ */

View File

@ -13,12 +13,24 @@
#include <sys/_default_fcntl.h>
#ifndef O_DIRECTORY
#define O_DIRECTORY 0x200000
#ifndef O_EXEC
#define O_EXEC 0x400000
#endif
#ifndef O_TMPFILE
#define O_TMPFILE 0x800000
#endif
#ifndef O_BINARY
#define O_BINARY 0x10000
#endif
#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0x100000
#endif
#ifndef O_DIRECTORY
#define O_DIRECTORY 0x200000
#endif
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -31,7 +31,7 @@ int libc_system_init(void)
if (dev_console)
{
int fd = libc_stdio_set_console(dev_console->parent.name, O_RDWR);
if (fd < 0)
if (fd < 0)
{
return -1;
}
@ -43,7 +43,7 @@ int libc_system_init(void)
#endif /* RT_USING_POSIX_STDIO */
return 0;
}
INIT_COMPONENT_EXPORT(libc_system_init);
INIT_APP_EXPORT(libc_system_init);
#if defined(RT_USING_POSIX_STDIO) && defined(RT_USING_NEWLIBC)

View File

@ -381,6 +381,7 @@ static int _ipc_msg_fd_new(void *file)
{
int fd;
struct dfs_file *d;
struct dfs_vnode *vnode = (struct dfs_vnode *)file;
fd = fd_new();
if (fd < 0)
@ -395,7 +396,11 @@ static int _ipc_msg_fd_new(void *file)
return -1;
}
d->vnode = (struct dfs_vnode *)file;
#ifdef RT_USING_DFS_V2
d->fops = vnode->fops;
#endif
d->vnode = vnode;
d->flags = O_RDWR; /* set flags as read and write */
return fd;
@ -946,15 +951,8 @@ static int channel_fops_close(struct dfs_file *file)
static const struct dfs_file_ops channel_fops =
{
NULL, /* open */
channel_fops_close,
NULL,
NULL,
NULL,
NULL,
NULL, /* lseek */
NULL, /* getdents */
channel_fops_poll,
.close = channel_fops_close, /* close */
.poll = channel_fops_poll, /* poll */
};
int lwp_channel_open(int fdt_type, const char *name, int flags)
@ -980,18 +978,8 @@ int lwp_channel_open(int fdt_type, const char *name, int flags)
ch = rt_raw_channel_open(name, flags);
if (ch)
{
rt_memset(d->vnode, 0, sizeof(struct dfs_vnode));
rt_list_init(&d->vnode->list);
d->vnode->type = FT_USER;
d->vnode->path = NULL;
d->vnode->fullpath = NULL;
d->vnode->fops = &channel_fops;
d->flags = O_RDWR; /* set flags as read and write */
d->vnode->size = 0;
d->pos = 0;
d->vnode->ref_count = 1;
/* initialize vnode */
dfs_vnode_init(d->vnode, FT_USER, &channel_fops);
/* set socket to the data of dfs_file */
d->vnode->data = (void *)ch;

View File

@ -40,6 +40,9 @@
#include <poll.h>
#include <sys/select.h>
#include <dfs_file.h>
#ifdef RT_USING_DFS_V2
#include <dfs_dentry.h>
#endif
#include <unistd.h>
#include <stdio.h> /* rename() */
#include <sys/stat.h>
@ -482,6 +485,7 @@ sysret_t sys_open(const char *name, int flag, ...)
int ret = -1;
rt_size_t len = 0;
char *kname = RT_NULL;
mode_t mode = 0;
if (!lwp_user_accessable((void *)name, 1))
{
@ -500,8 +504,16 @@ sysret_t sys_open(const char *name, int flag, ...)
return -ENOMEM;
}
if ((flag & O_CREAT) || (flag & O_TMPFILE) == O_TMPFILE)
{
va_list ap;
va_start(ap, flag);
mode = va_arg(ap, mode_t);
va_end(ap);
}
lwp_get_from_user(kname, (void *)name, len + 1);
ret = open(kname, flag, 0);
ret = open(kname, flag, mode);
if (ret < 0)
{
ret = GET_ERRNO();
@ -511,11 +523,23 @@ sysret_t sys_open(const char *name, int flag, ...)
return ret;
#else
int ret;
mode_t mode = 0;
if (!lwp_user_accessable((void *)name, 1))
{
return -EFAULT;
}
int ret = open(name, flag, 0);
if ((flag & O_CREAT) || (flag & O_TMPFILE) == O_TMPFILE)
{
va_list ap;
va_start(ap, flag);
mode = va_arg(ap, mode_t);
va_end(ap);
}
ret = open(name, flag, mode);
return (ret < 0 ? GET_ERRNO() : ret);
#endif
}
@ -3803,10 +3827,10 @@ sysret_t sys_rmdir(const char *path)
{
return -EFAULT;
}
err = unlink(path);
err = rmdir(path);
return (err < 0 ? GET_ERRNO() : err);
#else
int ret = unlink(path);
int ret = rmdir(path);
return (ret < 0 ? GET_ERRNO() : ret);
#endif
}
@ -4294,7 +4318,28 @@ ssize_t sys_readlink(char* path, char *buf, size_t bufsz)
}
else
{
#ifdef RT_USING_DFS_V2
char *link_fn = (char *)rt_malloc(DFS_PATH_MAX);
if (link_fn)
{
err = dfs_file_readlink(copy_path, link_fn, DFS_PATH_MAX);
if (err > 0)
{
rtn = lwp_put_to_user(buf, link_fn, bufsz > err ? err : bufsz - 1);
}
else
{
rtn = -EIO;
}
rt_free(link_fn);
}
else
{
rtn = -ENOMEM;
}
#else
rtn = lwp_put_to_user(buf, copy_path, copy_len);
#endif
}
rt_free(copy_path);
return rtn;
@ -4315,6 +4360,26 @@ ssize_t sys_readlink(char* path, char *buf, size_t bufsz)
return -EBADF;
}
#ifdef RT_USING_DFS_V2
{
char *fullpath = dfs_dentry_full_path(d->dentry);
if (fullpath)
{
copy_len = strlen(fullpath);
if (copy_len > bufsz)
{
copy_len = bufsz;
}
bufsz = lwp_put_to_user(buf, fullpath, copy_len);
rt_free(fullpath);
}
else
{
bufsz = 0;
}
}
#else
copy_len = strlen(d->vnode->fullpath);
if (copy_len > bufsz)
{
@ -4322,6 +4387,7 @@ ssize_t sys_readlink(char* path, char *buf, size_t bufsz)
}
bufsz = lwp_put_to_user(buf, d->vnode->fullpath, copy_len);
#endif
return bufsz;
}

View File

@ -46,7 +46,11 @@ static int dfs_net_ioctl(struct dfs_file* file, int cmd, void* args)
return ret;
}
#ifdef RT_USING_DFS_V2
static int dfs_net_read(struct dfs_file* file, void *buf, size_t count, off_t *pos)
#else
static int dfs_net_read(struct dfs_file* file, void *buf, size_t count)
#endif
{
int ret;
int socket = (int)(size_t)file->vnode->data;
@ -57,10 +61,15 @@ static int dfs_net_read(struct dfs_file* file, void *buf, size_t count)
ret = rt_get_errno();
return (ret > 0) ? (-ret) : ret;
}
return ret;
}
#ifdef RT_USING_DFS_V2
static int dfs_net_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
#else
static int dfs_net_write(struct dfs_file *file, const void *buf, size_t count)
#endif
{
int ret;
int socket = (int)(size_t)file->vnode->data;
@ -71,8 +80,10 @@ static int dfs_net_write(struct dfs_file *file, const void *buf, size_t count)
ret = rt_get_errno();
return (ret > 0) ? (-ret) : ret;
}
return ret;
}
static int dfs_net_close(struct dfs_file* file)
{
int socket;
@ -95,15 +106,11 @@ static int dfs_net_poll(struct dfs_file *file, struct rt_pollreq *req)
const struct dfs_file_ops _net_fops =
{
NULL, /* open */
dfs_net_close,
dfs_net_ioctl,
dfs_net_read,
dfs_net_write,
NULL,
NULL, /* lseek */
NULL, /* getdents */
dfs_net_poll,
.close = dfs_net_close,
.ioctl = dfs_net_ioctl,
.read = dfs_net_read,
.write = dfs_net_write,
.poll = dfs_net_poll,
};
const struct dfs_file_ops *dfs_net_get_fops(void)

View File

@ -40,6 +40,9 @@ int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
d = fd_get(fd);
if(d)
{
#ifdef RT_USING_DFS_V2
d->fops = dfs_net_get_fops();
#endif
/* this is a socket fd */
d->vnode = (struct dfs_vnode *)rt_malloc(sizeof(struct dfs_vnode));
if (!d->vnode)
@ -50,16 +53,7 @@ int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
return -1;
}
rt_memset(d->vnode, 0, sizeof(struct dfs_vnode));
rt_list_init(&d->vnode->list);
d->vnode->type = FT_SOCKET;
d->vnode->path = NULL;
d->vnode->fullpath = NULL;
d->vnode->ref_count = 1;
d->vnode->fops = dfs_net_get_fops();
d->flags = O_RDWR; /* set flags as read and write */
d->vnode->size = 0;
d->pos = 0;
dfs_vnode_init(d->vnode, FT_SOCKET, dfs_net_get_fops());
/* set socket to the data of dfs_file */
d->vnode->data = (void *)(size_t)new_socket;
@ -238,6 +232,11 @@ int socket(int domain, int type, int protocol)
return -1;
}
d = fd_get(fd);
#ifdef RT_USING_DFS_V2
d->fops = dfs_net_get_fops();
#endif
d->vnode = (struct dfs_vnode *)rt_malloc(sizeof(struct dfs_vnode));
if (!d->vnode)
{
@ -258,18 +257,7 @@ int socket(int domain, int type, int protocol)
socket = sal_socket(domain, type, protocol);
if (socket >= 0)
{
rt_memset(d->vnode, 0, sizeof(struct dfs_vnode));
rt_list_init(&d->vnode->list);
/* this is a socket fd */
d->vnode->type = FT_SOCKET;
d->vnode->path = NULL;
d->vnode->fullpath = NULL;
d->vnode->ref_count = 1;
d->vnode->fops = dfs_net_get_fops();
d->flags = O_RDWR; /* set flags as read and write */
d->vnode->size = 0;
d->pos = 0;
dfs_vnode_init(d->vnode, FT_SOCKET, dfs_net_get_fops());
/* set socket to the data of dfs_file */
d->vnode->data = (void *)(size_t)socket;