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:
parent
c33a21509a
commit
99e80f8d33
@ -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
|
||||
|
||||
|
@ -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
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
@ -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
|
@ -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 */
|
@ -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;
|
@ -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));
|
||||
}
|
@ -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
@ -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;
|
@ -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)
|
||||
{
|
||||
}
|
@ -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
@ -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
|
@ -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)
|
||||
{
|
||||
}
|
@ -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 */
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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, ®s->pm_prog) &&
|
||||
xdr_u_long(xdrs, ®s->pm_vers) &&
|
||||
xdr_u_long(xdrs, ®s->pm_prot))
|
||||
return (xdr_u_long(xdrs, ®s->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);
|
||||
}
|
@ -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
|
@ -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
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 */
|
@ -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));
|
||||
}
|
@ -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 */
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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])
|
||||
};
|
||||
|
||||
|
@ -94,4 +94,3 @@ int dfs_skt_init(void)
|
||||
return 0;
|
||||
}
|
||||
INIT_COMPONENT_EXPORT(dfs_skt_init);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
64
components/dfs/dfs_v2/include/dfs_dentry.h
Normal file
64
components/dfs/dfs_v2/include/dfs_dentry.h
Normal 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__*/
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
65
components/dfs/dfs_v2/include/dfs_mnt.h
Normal file
65
components/dfs/dfs_v2/include/dfs_mnt.h
Normal 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
|
32
components/dfs/dfs_v2/include/dfs_posix.h
Normal file
32
components/dfs/dfs_v2/include/dfs_posix.h
Normal 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
|
@ -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
|
@ -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
|
||||
/**@}*/
|
||||
|
368
components/dfs/dfs_v2/src/dfs_dentry.c
Normal file
368
components/dfs/dfs_v2/src/dfs_dentry.c
Normal 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
@ -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
|
||||
|
||||
/**@}*/
|
||||
/* @} */
|
||||
|
386
components/dfs/dfs_v2/src/dfs_mnt.c
Normal file
386
components/dfs/dfs_v2/src/dfs_mnt.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
||||
|
19
components/dfs/dfs_v2/src/dfs_private.h
Normal file
19
components/dfs/dfs_v2/src/dfs_private.h
Normal 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
|
134
components/dfs/dfs_v2/src/dfs_vnode.c
Normal file
134
components/dfs/dfs_v2/src/dfs_vnode.c
Normal 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;
|
||||
}
|
@ -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) */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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, "/");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) */
|
||||
|
@ -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
|
||||
|
@ -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__ */
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user