mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-20 11:07:58 +08:00
Filesystem: Reference counting for locations
o A new data structure rtems_filesystem_global_location_t was
introduced to be used for
o the mount point location in the mount table entry,
o the file system root location in the mount table entry,
o the root directory location in the user environment, and
o the current directory location in the user environment.
During the path evaluation global start locations are obtained to
ensure that the current file system instance will be not unmounted in
the meantime.
o The user environment uses now reference counting and is protected
from concurrent access.
o The path evaluation process was completely rewritten and simplified.
The IMFS, RFS, NFS, and DOSFS use now a generic path evaluation
method. Recursive calls in the path evaluation have been replaced
with iteration to avoid stack overflows. Only the evaluation of
symbolic links is recursive. No dynamic memory allocations and
intermediate buffers are used in the high level path evaluation. No
global locks are held during the file system instance specific path
evaluation process.
o Recursive symbolic link evaluation is now limited by
RTEMS_FILESYSTEM_SYMLOOP_MAX. Applications can retrieve this value
via sysconf().
o The device file system (devFS) uses now no global variables and
allocation from the workspace. Node names are allocated from the
heap.
o The upper layer lseek() performs now some parameter checks.
o The upper layer ftruncate() performs now some parameter checks.
o unmask() is now restricted to the RWX flags and protected from
concurrent access.
o The fchmod_h and rmnod_h file system node handlers are now a file
system operation.
o The unlink_h operation has been removed. All nodes are now destroyed
with the rmnod_h operation.
o New lock_h, unlock_h, clonenod_h, and are_nodes_equal_h file system
operations.
o The path evaluation and file system operations are now protected by
per file system instance lock and unlock operations.
o Fix and test file descriptor duplicate in fcntl().
o New test fstests/fsnofs01.
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
*
|
||||
* Initial release: Oct 1, 2004 by Ed Sutter
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* This code was derived from the tftpDriver.c code written by
|
||||
* W. Eric Norum, which was apparently derived from the IMFS driver.
|
||||
*
|
||||
@@ -69,79 +72,31 @@ struct tfdinfo {
|
||||
*/
|
||||
char TFS_PATHNAME_PREFIX[128];
|
||||
|
||||
/*
|
||||
* Root node_access value
|
||||
* By using the address of a local static variable
|
||||
* we ensure a unique value for this identifier.
|
||||
*/
|
||||
#define ROOT_NODE_ACCESS (&tfs_mutex)
|
||||
static const rtems_filesystem_operations_table rtems_tfs_ops;
|
||||
static const rtems_filesystem_file_handlers_r rtems_tfs_handlers;
|
||||
|
||||
/* Number of streams open at the same time
|
||||
*/
|
||||
static rtems_id tfs_mutex;
|
||||
|
||||
extern rtems_filesystem_operations_table rtems_tfs_ops;
|
||||
extern rtems_filesystem_file_handlers_r rtems_tfs_handlers;
|
||||
|
||||
/* Direct copy from the IMFS. Look at this.
|
||||
*/
|
||||
|
||||
rtems_filesystem_limits_and_options_t rtems_tfs_limits_and_options = {
|
||||
5, /* link_max */
|
||||
6, /* max_canon */
|
||||
7, /* max_input */
|
||||
255, /* name_max */
|
||||
255, /* path_max */
|
||||
2, /* pipe_buf */
|
||||
1, /* posix_async_io */
|
||||
2, /* posix_chown_restrictions */
|
||||
3, /* posix_no_trunc */
|
||||
4, /* posix_prio_io */
|
||||
5, /* posix_sync_io */
|
||||
6 /* posix_vdisable */
|
||||
};
|
||||
static bool rtems_tfs_is_directory(
|
||||
const char *path,
|
||||
size_t pathlen
|
||||
)
|
||||
{
|
||||
return path [pathlen - 1] == '/';
|
||||
}
|
||||
|
||||
static int rtems_tfs_mount_me(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
const void *data
|
||||
)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
char *root_path = strdup("/");
|
||||
|
||||
mt_entry->mt_fs_root.handlers = &rtems_tfs_handlers;
|
||||
mt_entry->mt_fs_root.ops = &rtems_tfs_ops;
|
||||
if (root_path == NULL) {
|
||||
rtems_set_errno_and_return_minus_one(ENOMEM);
|
||||
}
|
||||
|
||||
/* We have no TFS specific data to maintain. This filesystem
|
||||
* may only be mounted once. And we maintain no real filesystem
|
||||
* nodes, so there is no real root.
|
||||
*/
|
||||
|
||||
mt_entry->fs_info = NULL;
|
||||
mt_entry->mt_fs_root.node_access = ROOT_NODE_ACCESS;
|
||||
|
||||
/* These need to be looked at for full POSIX semantics.
|
||||
*/
|
||||
|
||||
mt_entry->pathconf_limits_and_options = rtems_tfs_limits_and_options;
|
||||
|
||||
|
||||
/* Now allocate a semaphore for mutual exclusion.
|
||||
* NOTE: This could be in an fsinfo for this filesystem type.
|
||||
*/
|
||||
|
||||
sc = rtems_semaphore_create (
|
||||
rtems_build_name('U', 'M', 'O', 'N'),
|
||||
1,
|
||||
RTEMS_FIFO |
|
||||
RTEMS_BINARY_SEMAPHORE |
|
||||
RTEMS_NO_INHERIT_PRIORITY |
|
||||
RTEMS_NO_PRIORITY_CEILING |
|
||||
RTEMS_LOCAL,
|
||||
0,
|
||||
&tfs_mutex);
|
||||
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
rtems_set_errno_and_return_minus_one( ENOMEM );
|
||||
mt_entry->mt_fs_root->location.handlers = &rtems_tfs_handlers;
|
||||
mt_entry->mt_fs_root->location.ops = &rtems_tfs_ops;
|
||||
mt_entry->mt_fs_root->location.node_access = root_path;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -180,16 +135,6 @@ int rtems_initialize_tfs_filesystem(
|
||||
return(status);
|
||||
}
|
||||
|
||||
static int rtems_tfs_evaluate_for_make(
|
||||
const char *path,
|
||||
rtems_filesystem_location_info_t *pathloc,
|
||||
const char **name
|
||||
)
|
||||
{
|
||||
pathloc->node_access = NULL;
|
||||
rtems_set_errno_and_return_minus_one( EIO );
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a path to canonical form
|
||||
*/
|
||||
@@ -242,53 +187,41 @@ static void fixPath(char *path)
|
||||
*outp = '\0';
|
||||
}
|
||||
|
||||
static int rtems_tfs_eval_path(
|
||||
const char *pathname,
|
||||
size_t pathnamelen,
|
||||
int flags,
|
||||
rtems_filesystem_location_info_t *pathloc
|
||||
)
|
||||
static void rtems_tfs_eval_path(rtems_filesystem_eval_path_context_t *self)
|
||||
{
|
||||
pathloc->handlers = &rtems_tfs_handlers;
|
||||
int eval_flags = rtems_filesystem_eval_path_get_flags(self);
|
||||
|
||||
/*
|
||||
* Hack to provide the illusion of directories inside the TFS file system.
|
||||
* Paths ending in a / are assumed to be directories.
|
||||
*/
|
||||
if (pathname[strlen(pathname)-1] == '/') {
|
||||
int isRelative = (pathloc->node_access != ROOT_NODE_ACCESS);
|
||||
char *cp;
|
||||
if ((eval_flags & RTEMS_LIBIO_MAKE) == 0) {
|
||||
int rw = RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE;
|
||||
|
||||
/*
|
||||
* Reject attempts to open() directories
|
||||
*/
|
||||
if (flags & RTEMS_LIBIO_PERMS_RDWR)
|
||||
rtems_set_errno_and_return_minus_one( EISDIR );
|
||||
if (isRelative) {
|
||||
cp = malloc (strlen(pathloc->node_access)+strlen(pathname)+1);
|
||||
if (cp == NULL)
|
||||
rtems_set_errno_and_return_minus_one( ENOMEM );
|
||||
strcpy (cp, pathloc->node_access);
|
||||
strcat (cp, pathname);
|
||||
if ((eval_flags & rw) != rw) {
|
||||
rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_get_currentloc(self);
|
||||
char *current = currentloc->node_access;
|
||||
size_t currentlen = strlen(current);
|
||||
const char *path = rtems_filesystem_eval_path_get_path(self);
|
||||
size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self);
|
||||
size_t len = currentlen + pathlen;
|
||||
|
||||
rtems_filesystem_eval_path_clear_path(self);
|
||||
|
||||
current = realloc(current, len + 1);
|
||||
if (current != NULL) {
|
||||
memcpy(current + currentlen, path, pathlen);
|
||||
current [len] = '\0';
|
||||
if (!rtems_tfs_is_directory(current, len)) {
|
||||
fixPath (current);
|
||||
}
|
||||
currentloc->node_access = current;
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(self, ENOMEM);
|
||||
}
|
||||
} else {
|
||||
cp = strdup (pathname);
|
||||
if (cp == NULL)
|
||||
rtems_set_errno_and_return_minus_one( ENOMEM );
|
||||
rtems_filesystem_eval_path_error(self, EINVAL);
|
||||
}
|
||||
fixPath (cp);
|
||||
pathloc->node_access = cp;
|
||||
return 0;
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(self, EIO);
|
||||
}
|
||||
if (pathloc->node_access != ROOT_NODE_ACCESS)
|
||||
pathloc->node_access = 0;
|
||||
|
||||
/*
|
||||
* Reject it if it's not read-only or write-only.
|
||||
*/
|
||||
flags &= RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE;
|
||||
if ((flags != RTEMS_LIBIO_PERMS_READ) && (flags != RTEMS_LIBIO_PERMS_WRITE) )
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -310,8 +243,8 @@ static int rtems_tfs_eval_path(
|
||||
static int rtems_tfs_open_worker(
|
||||
rtems_libio_t *iop,
|
||||
char *path,
|
||||
uint32_t flags,
|
||||
uint32_t mode
|
||||
int oflag,
|
||||
mode_t mode
|
||||
)
|
||||
{
|
||||
static int beenhere = 0;
|
||||
@@ -321,7 +254,7 @@ static int rtems_tfs_open_worker(
|
||||
char *buf, *fstr, *istr, *bstr, pathcopy[TFSNAMESIZE*3+1];
|
||||
|
||||
if (RTEMS_TFS_DEBUG)
|
||||
printk("_open_r(%s,0x%" PRIx32 ",0x%" PRIx32 ")\n",path,flags,mode);
|
||||
printk("_open_r(%s,0x%" PRIx32 ",0x%" PRIx32 ")\n",path,oflag,mode);
|
||||
|
||||
if (!beenhere) {
|
||||
newlib_tfdlock();
|
||||
@@ -371,7 +304,7 @@ static int rtems_tfs_open_worker(
|
||||
|
||||
/* If O_EXCL and O_CREAT are set, then fail if the file exists...
|
||||
*/
|
||||
if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
|
||||
if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
|
||||
if (mon_tfsstat((char *)pathcopy)) {
|
||||
return(EEXIST);
|
||||
}
|
||||
@@ -384,7 +317,7 @@ static int rtems_tfs_open_worker(
|
||||
* O_WRONLY | O_CREAT Create if it doesn't exist
|
||||
* O_WRONLY | O_CREAT | O_EXCL Fail if file exists
|
||||
*/
|
||||
switch(flags & O_ACCMODE) {
|
||||
switch(oflag & O_ACCMODE) {
|
||||
case O_RDONLY:
|
||||
flagmode = TFS_RDONLY;
|
||||
break;
|
||||
@@ -405,7 +338,7 @@ static int rtems_tfs_open_worker(
|
||||
flagmode = TFS_CREATE|TFS_APPEND;
|
||||
break;
|
||||
default:
|
||||
printk("_open_r(): flag 0x%" PRIx32 " not supported\n",flags);
|
||||
printk("_open_r(): flag 0x%i not supported\n",oflag);
|
||||
return(ENOTSUP);
|
||||
}
|
||||
|
||||
@@ -489,41 +422,27 @@ static int rtems_tfs_open_worker(
|
||||
static int rtems_tfs_open(
|
||||
rtems_libio_t *iop,
|
||||
const char *new_name,
|
||||
uint32_t flags,
|
||||
uint32_t mode
|
||||
int oflag,
|
||||
mode_t mode
|
||||
)
|
||||
{
|
||||
char *full_path_name;
|
||||
char *s1;
|
||||
int err;
|
||||
|
||||
if (RTEMS_TFS_DEBUG)
|
||||
printk("rtems_tfs_open(%s)\n",new_name);
|
||||
full_path_name = iop->pathinfo.node_access;
|
||||
|
||||
/*
|
||||
* Tack the `current directory' on to relative paths.
|
||||
* We know that the current directory ends in a / character.
|
||||
*/
|
||||
if (*new_name == '/') {
|
||||
/*
|
||||
* Skip the TFS filesystem prefix.
|
||||
*/
|
||||
int len = strlen (TFS_PATHNAME_PREFIX);
|
||||
if (strncmp (new_name, TFS_PATHNAME_PREFIX, len))
|
||||
return ENOENT;
|
||||
new_name += len;
|
||||
s1 = "";
|
||||
} else {
|
||||
s1 = rtems_filesystem_current.node_access;
|
||||
if (RTEMS_TFS_DEBUG)
|
||||
printk("rtems_tfs_open(%s)\n",full_path_name);
|
||||
|
||||
if (rtems_tfs_is_directory(full_path_name, strlen(full_path_name))) {
|
||||
rtems_set_errno_and_return_minus_one (ENOTSUP);
|
||||
}
|
||||
full_path_name = malloc (strlen (s1) + strlen (new_name) + 1);
|
||||
if (full_path_name == NULL)
|
||||
return ENOMEM;
|
||||
strcpy (full_path_name, s1);
|
||||
strcat (full_path_name, new_name);
|
||||
fixPath (full_path_name);
|
||||
err = rtems_tfs_open_worker (iop, full_path_name, flags, mode);
|
||||
free (full_path_name);
|
||||
|
||||
err = rtems_tfs_open_worker (iop, full_path_name, oflag, mode);
|
||||
if (err != 0) {
|
||||
rtems_set_errno_and_return_minus_one (err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -671,68 +590,92 @@ static int rtems_tfs_ioctl(
|
||||
void *buf
|
||||
)
|
||||
{
|
||||
int fd, ret;
|
||||
int ret;
|
||||
|
||||
fd = (int) iop->data0;
|
||||
ret = mon_tfsctrl(cmd,(long)buf,0);
|
||||
return(-1);
|
||||
if (ret != TFS_OKAY)
|
||||
return(-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static rtems_filesystem_node_types_t rtems_tfs_node_type(
|
||||
rtems_filesystem_location_info_t *pathloc
|
||||
const rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
if ((pathloc->node_access == NULL) ||
|
||||
(pathloc->node_access == ROOT_NODE_ACCESS))
|
||||
return RTEMS_FILESYSTEM_MEMORY_FILE;
|
||||
return RTEMS_FILESYSTEM_DIRECTORY;
|
||||
const char *path = loc->node_access;
|
||||
size_t pathlen = strlen(path);
|
||||
|
||||
return rtems_tfs_is_directory(path, pathlen) ?
|
||||
RTEMS_FILESYSTEM_DIRECTORY
|
||||
: RTEMS_FILESYSTEM_MEMORY_FILE;
|
||||
}
|
||||
|
||||
static int rtems_tfs_free_node_info(
|
||||
|
||||
rtems_filesystem_location_info_t *pathloc)
|
||||
static int rtems_tfs_clone_node_info(
|
||||
rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
if (pathloc->node_access && (pathloc->node_access != ROOT_NODE_ACCESS)) {
|
||||
free (pathloc->node_access);
|
||||
pathloc->node_access = NULL;
|
||||
int rv = 0;
|
||||
|
||||
loc->node_access = strdup(loc->node_access);
|
||||
|
||||
if (loc->node_access == NULL) {
|
||||
errno = ENOMEM;
|
||||
rv = -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void rtems_tfs_free_node_info(
|
||||
const rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
free(loc->node_access);
|
||||
}
|
||||
|
||||
rtems_filesystem_operations_table rtems_tfs_ops = {
|
||||
rtems_tfs_eval_path, /* eval_path */
|
||||
rtems_tfs_evaluate_for_make, /* evaluate_for_make */
|
||||
rtems_filesystem_default_link, /* link */
|
||||
rtems_filesystem_default_unlink, /* unlink */
|
||||
rtems_tfs_node_type, /* node_type */
|
||||
rtems_filesystem_default_mknod, /* mknod */
|
||||
rtems_filesystem_default_chown, /* chown */
|
||||
rtems_tfs_free_node_info, /* freenodinfo */
|
||||
rtems_filesystem_default_mount, /* mount */
|
||||
rtems_tfs_mount_me, /* initialize */
|
||||
rtems_filesystem_default_unmount, /* unmount */
|
||||
rtems_filesystem_default_fsunmount, /* fsunmount */
|
||||
rtems_filesystem_default_utime, /* utime */
|
||||
rtems_filesystem_default_evaluate_link, /* evaluate_link */
|
||||
rtems_filesystem_default_symlink, /* symlink */
|
||||
rtems_filesystem_default_readlink, /* readlin */
|
||||
rtems_filesystem_default_rename, /* rename */
|
||||
rtems_filesystem_default_statvfs /* statvfs */
|
||||
static bool rtems_tfs_are_nodes_equal(
|
||||
const rtems_filesystem_location_info_t *a,
|
||||
const rtems_filesystem_location_info_t *b
|
||||
)
|
||||
{
|
||||
return strcmp(a->node_access, b->node_access) == 0;
|
||||
}
|
||||
|
||||
static const rtems_filesystem_operations_table rtems_tfs_ops = {
|
||||
.lock_h = rtems_filesystem_default_lock,
|
||||
.unlock_h = rtems_filesystem_default_unlock,
|
||||
.eval_path_h = rtems_tfs_eval_path,
|
||||
.link_h = rtems_filesystem_default_link,
|
||||
.are_nodes_equal_h = rtems_tfs_are_nodes_equal,
|
||||
.node_type_h = rtems_tfs_node_type,
|
||||
.mknod_h = rtems_filesystem_default_mknod,
|
||||
.rmnod_h = rtems_filesystem_default_rmnod,
|
||||
.fchmod_h = rtems_filesystem_default_fchmod,
|
||||
.chown_h = rtems_filesystem_default_chown,
|
||||
.clonenod_h = rtems_tfs_clone_node_info,
|
||||
.freenod_h = rtems_tfs_free_node_info,
|
||||
.mount_h = rtems_filesystem_default_mount,
|
||||
.fsmount_me_h = rtems_tfs_mount_me,
|
||||
.unmount_h = rtems_filesystem_default_unmount,
|
||||
.fsunmount_me_h = rtems_filesystem_default_fsunmount,
|
||||
.utime_h = rtems_filesystem_default_utime,
|
||||
.symlink_h = rtems_filesystem_default_symlink,
|
||||
.readlink_h = rtems_filesystem_default_readlink,
|
||||
.rename_h = rtems_filesystem_default_rename,
|
||||
.statvfs_h = rtems_filesystem_default_statvfs
|
||||
};
|
||||
|
||||
rtems_filesystem_file_handlers_r rtems_tfs_handlers = {
|
||||
rtems_tfs_open, /* open */
|
||||
rtems_tfs_close, /* close */
|
||||
rtems_tfs_read, /* read */
|
||||
rtems_tfs_write, /* write */
|
||||
rtems_tfs_ioctl, /* ioctl */
|
||||
rtems_tfs_lseek, /* lseek */
|
||||
rtems_filesystem_default_fstat, /* fstat */
|
||||
rtems_filesystem_default_fchmod, /* fchmod */
|
||||
rtems_tfs_ftruncate, /* ftruncate */
|
||||
rtems_filesystem_default_fsync, /* fsync */
|
||||
rtems_filesystem_default_fdatasync, /* fdatasync */
|
||||
rtems_filesystem_default_fcntl, /* fcntl */
|
||||
rtems_filesystem_default_rmnod /* rmnod */
|
||||
static const rtems_filesystem_file_handlers_r rtems_tfs_handlers = {
|
||||
.open_h = rtems_tfs_open,
|
||||
.close_h = rtems_tfs_close,
|
||||
.read_h = rtems_tfs_read,
|
||||
.write_h = rtems_tfs_write,
|
||||
.ioctl_h = rtems_tfs_ioctl,
|
||||
.lseek_h = rtems_tfs_lseek,
|
||||
.fstat_h = rtems_filesystem_default_fstat,
|
||||
.ftruncate_h = rtems_tfs_ftruncate,
|
||||
.fsync_h = rtems_filesystem_default_fsync,
|
||||
.fdatasync_h = rtems_filesystem_default_fdatasync,
|
||||
.fcntl_h = rtems_filesystem_default_fcntl
|
||||
};
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
* COPYRIGHT (c) 1989-2011.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -18,6 +21,8 @@
|
||||
#ifndef _RTEMS_FS_H
|
||||
#define _RTEMS_FS_H
|
||||
|
||||
#include <rtems/chain.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -31,9 +36,6 @@ extern "C" {
|
||||
/* FIXME: shouldn't this better not be here? */
|
||||
typedef struct rtems_libio_tt rtems_libio_t;
|
||||
|
||||
typedef struct rtems_filesystem_location_info_tt
|
||||
rtems_filesystem_location_info_t;
|
||||
|
||||
struct rtems_filesystem_mount_table_entry_tt;
|
||||
typedef struct rtems_filesystem_mount_table_entry_tt
|
||||
rtems_filesystem_mount_table_entry_t;
|
||||
@@ -43,18 +45,57 @@ typedef struct _rtems_filesystem_file_handlers_r
|
||||
typedef struct _rtems_filesystem_operations_table
|
||||
rtems_filesystem_operations_table;
|
||||
|
||||
/*
|
||||
* Structure used to determine a location/filesystem in the tree.
|
||||
/**
|
||||
* @brief File system location.
|
||||
*
|
||||
* @ingroup LibIO
|
||||
*/
|
||||
|
||||
struct rtems_filesystem_location_info_tt
|
||||
{
|
||||
typedef struct rtems_filesystem_location_info_tt {
|
||||
rtems_chain_node mt_entry_node;
|
||||
void *node_access;
|
||||
void *node_access_2;
|
||||
const rtems_filesystem_file_handlers_r *handlers;
|
||||
const rtems_filesystem_operations_table *ops;
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry;
|
||||
};
|
||||
} rtems_filesystem_location_info_t;
|
||||
|
||||
/**
|
||||
* @brief Global file system location.
|
||||
*
|
||||
* @ingroup LibIO
|
||||
*
|
||||
* The global file system locations are used for
|
||||
* - the mount point location in the mount table entry,
|
||||
* - the file system root location in the mount table entry,
|
||||
* - the root directory location in the user environment, and
|
||||
* - the current directory location in the user environment.
|
||||
*
|
||||
* During the path evaluation global start locations are obtained to ensure
|
||||
* that the current file system will be not unmounted in the meantime.
|
||||
*
|
||||
* To support a release within critical sections of the operating system a
|
||||
* deferred release is supported. This is similar to malloc() and free().
|
||||
*
|
||||
* @see rtems_filesystem_global_location_obtain() and
|
||||
* rtems_filesystem_global_location_release().
|
||||
*/
|
||||
typedef struct rtems_filesystem_global_location_t {
|
||||
rtems_filesystem_location_info_t location;
|
||||
int reference_count;
|
||||
|
||||
/**
|
||||
* A release within a critical section of the operating system will add this
|
||||
* location to a list of deferred released locations. This list is processed
|
||||
* in the next rtems_filesystem_global_location_obtain() in FIFO order.
|
||||
*/
|
||||
struct rtems_filesystem_global_location_t *deferred_released_next;
|
||||
|
||||
/**
|
||||
* A release within a critical section can happen multiple times. This field
|
||||
* counts the deferred releases.
|
||||
*/
|
||||
int deferred_released_count;
|
||||
} rtems_filesystem_global_location_t;
|
||||
|
||||
/*
|
||||
* Return the mount table entry for a path location.
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
/**
|
||||
* @file rtems/userenv.h
|
||||
* @file
|
||||
*
|
||||
* This file defines the interface for POSIX per-process environment.
|
||||
* @ingroup LibIOEnv
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPYRIGHT (c) 1989-2011.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -18,6 +21,13 @@
|
||||
#ifndef _RTEMS_USERENV_H
|
||||
#define _RTEMS_USERENV_H
|
||||
|
||||
/*
|
||||
* According to IEEE Std 1003.1-2001,
|
||||
* limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX
|
||||
* XXX: We do not rely on this.
|
||||
*/
|
||||
#include <limits.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/fs.h>
|
||||
|
||||
@@ -25,33 +35,30 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* External structures
|
||||
/**
|
||||
* @defgroup LibIOEnv User Environment
|
||||
*
|
||||
* @ingroup LibIO
|
||||
*
|
||||
* @brief Provides a POSIX like user environment for tasks.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* According to IEEE Std 1003.1-2001,
|
||||
* limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX
|
||||
* FIXME: We should not rely on this.
|
||||
*/
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef LOGIN_NAME_MAX
|
||||
#ifdef _POSIX_LOGIN_NAME_MAX
|
||||
#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
|
||||
#else
|
||||
/* Fallback */
|
||||
#define LOGIN_NAME_MAX 9
|
||||
#endif
|
||||
#ifdef _POSIX_LOGIN_NAME_MAX
|
||||
#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
|
||||
#else
|
||||
/* Fallback */
|
||||
#define LOGIN_NAME_MAX 9
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
rtems_id task_id;
|
||||
rtems_filesystem_location_info_t current_directory;
|
||||
rtems_filesystem_location_info_t root_directory;
|
||||
rtems_filesystem_global_location_t *current_directory;
|
||||
rtems_filesystem_global_location_t *root_directory;
|
||||
/* Default mode for all files. */
|
||||
mode_t umask;
|
||||
nlink_t link_counts;
|
||||
/* _POSIX_types */
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
@@ -59,6 +66,9 @@ typedef struct {
|
||||
gid_t egid;
|
||||
char login_buffer[LOGIN_NAME_MAX];
|
||||
pid_t pgrp; /* process group id */
|
||||
/* User environment maintenance */
|
||||
rtems_id task_id;
|
||||
int reference_count;
|
||||
} rtems_user_env_t;
|
||||
|
||||
extern rtems_user_env_t * rtems_current_user_env;
|
||||
@@ -66,7 +76,6 @@ extern rtems_user_env_t rtems_global_user_env;
|
||||
|
||||
#define rtems_filesystem_current (rtems_current_user_env->current_directory)
|
||||
#define rtems_filesystem_root (rtems_current_user_env->root_directory)
|
||||
#define rtems_filesystem_link_counts (rtems_current_user_env->link_counts)
|
||||
#define rtems_filesystem_umask (rtems_current_user_env->umask)
|
||||
|
||||
#define _POSIX_types_Uid (rtems_current_user_env->uid)
|
||||
@@ -75,14 +84,48 @@ extern rtems_user_env_t rtems_global_user_env;
|
||||
#define _POSIX_types_Egid (rtems_current_user_env->egid)
|
||||
#define _POSIX_types_Getlogin_buffer (rtems_current_user_env->login_buffer)
|
||||
|
||||
|
||||
/*
|
||||
* Instantiate a private copy of the per user information for the calling task.
|
||||
/**
|
||||
* @brief Creates a private environment.
|
||||
*
|
||||
* If the task has already a private environment nothing will be changed. This
|
||||
* function must be called from normal thread context and may block on a mutex.
|
||||
* Thread dispatching is disabled to protect some critical sections.
|
||||
*
|
||||
* @retval RTEMS_SUCCESSFUL Successful operation.
|
||||
* @retval RTEMS_NO_MEMORY Not enough memory.
|
||||
* @retval RTEMS_UNSATISFIED Cloning of the current environment failed.
|
||||
* @retval RTEMS_TOO_MANY Cannot register the private environment.
|
||||
*/
|
||||
|
||||
rtems_status_code rtems_libio_set_private_env(void);
|
||||
|
||||
/**
|
||||
* @brief Creates a private environment shared with another task.
|
||||
*
|
||||
* An attempt to share the environment with itself has no effect. This
|
||||
* function must be called from normal thread context and may block on a mutex.
|
||||
* Thread dispatching is disabled to protect some critical sections.
|
||||
*
|
||||
* @param[in] task_id The private environment is shared with the task specified
|
||||
* by this identifier.
|
||||
*
|
||||
* @retval RTEMS_SUCCESSFUL Successful operation.
|
||||
* @retval RTEMS_UNSATISFIED No shared environment is available for this task
|
||||
* @retval RTEMS_TOO_MANY Cannot register the shared environment.
|
||||
* identifier.
|
||||
*/
|
||||
rtems_status_code rtems_libio_share_private_env(rtems_id task_id) ;
|
||||
|
||||
/**
|
||||
* @brief Use the global environment.
|
||||
*
|
||||
* A private environment will be released. This function may be called from
|
||||
* every thread context. Thread dispatching is disabled to protect the
|
||||
* critical sections.
|
||||
*/
|
||||
void rtems_libio_use_global_env(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -57,7 +57,7 @@ ASSOCIATION_C_FILES = src/assoclocalbyname.c \
|
||||
|
||||
BASE_FS_C_FILES = src/base_fs.c src/mount.c src/unmount.c src/libio.c \
|
||||
src/mount-mgr.c src/mount-mktgt.c src/libio_init.c \
|
||||
src/eval.c src/privateenv.c \
|
||||
src/privateenv.c \
|
||||
src/open_dev_console.c src/__usrenv.c src/rtems_mkdir.c
|
||||
|
||||
if LIBNETWORKING
|
||||
@@ -99,7 +99,7 @@ ID_C_FILES = src/getegid.c src/geteuid.c src/getgid.c src/getgroups.c \
|
||||
|
||||
MALLOC_C_FILES = src/malloc_initialize.c src/calloc.c src/malloc.c \
|
||||
src/realloc.c src/_calloc_r.c src/_malloc_r.c \
|
||||
src/free.c src/freenode.c src/_free_r.c \
|
||||
src/free.c src/_free_r.c \
|
||||
src/_realloc_r.c src/mallocfreespace.c \
|
||||
src/mallocgetheapptr.c src/mallocsetheapptr.c \
|
||||
src/mallocinfo.c src/malloc_walk.c src/malloc_get_statistics.c \
|
||||
@@ -127,8 +127,16 @@ BSD_LIBC_C_FILES = src/strlcpy.c src/strlcat.c src/issetugid.c
|
||||
|
||||
libcsupport_a_SOURCES = src/gxx_wrappers.c src/getchark.c src/printk.c \
|
||||
src/printk_plugin.c src/putk.c src/vprintk.c \
|
||||
src/sup_fs_is_separator.c src/sup_fs_get_start_loc.c \
|
||||
src/sup_fs_get_sym_start_loc.c \
|
||||
src/sup_fs_location.c \
|
||||
src/sup_fs_eval_path.c \
|
||||
src/sup_fs_eval_path_generic.c \
|
||||
src/sup_fs_check_permissions.c \
|
||||
src/sup_fs_next_token.c \
|
||||
src/sup_fs_exist_in_same_instance.c \
|
||||
src/sup_fs_mount_iterate.c \
|
||||
src/sup_fs_node_type.c \
|
||||
src/clonenode.c \
|
||||
src/freenode.c \
|
||||
$(BSD_LIBC_C_FILES) $(BASE_FS_C_FILES) $(MALLOC_C_FILES) \
|
||||
$(ERROR_C_FILES) $(ASSOCIATION_C_FILES)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,9 @@
|
||||
* COPYRIGHT (c) 1989-2008.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -10,18 +13,246 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
/*
|
||||
* Global information for POSIX Process Environment Support
|
||||
*/
|
||||
static int null_handler_open(
|
||||
rtems_libio_t *iop,
|
||||
const char *path,
|
||||
int oflag,
|
||||
mode_t mode
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rtems_user_env_t rtems_global_user_env;
|
||||
rtems_user_env_t * rtems_current_user_env = &rtems_global_user_env;
|
||||
static int null_handler_fstat(
|
||||
const rtems_filesystem_location_info_t *pathloc,
|
||||
struct stat *buf
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers = {
|
||||
.open_h = null_handler_open,
|
||||
.close_h = rtems_filesystem_default_close,
|
||||
.read_h = rtems_filesystem_default_read,
|
||||
.write_h = rtems_filesystem_default_write,
|
||||
.ioctl_h = rtems_filesystem_default_ioctl,
|
||||
.lseek_h = rtems_filesystem_default_lseek,
|
||||
.fstat_h = null_handler_fstat,
|
||||
.ftruncate_h = rtems_filesystem_default_ftruncate,
|
||||
.fsync_h = rtems_filesystem_default_fsync,
|
||||
.fdatasync_h = rtems_filesystem_default_fdatasync,
|
||||
.fcntl_h = rtems_filesystem_default_fcntl
|
||||
};
|
||||
|
||||
static void null_op_lock_or_unlock(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry
|
||||
)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static int null_op_mknod(
|
||||
const rtems_filesystem_location_info_t *parentloc,
|
||||
const char *name,
|
||||
size_t namelen,
|
||||
mode_t mode,
|
||||
dev_t dev
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_rmnod(
|
||||
const rtems_filesystem_location_info_t *parentloc,
|
||||
const rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_link(
|
||||
const rtems_filesystem_location_info_t *parentloc,
|
||||
const rtems_filesystem_location_info_t *targetloc,
|
||||
const char *name,
|
||||
size_t namelen
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_fchmod(
|
||||
const rtems_filesystem_location_info_t *pathloc,
|
||||
mode_t mode
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_chown(
|
||||
const rtems_filesystem_location_info_t *loc,
|
||||
uid_t owner,
|
||||
gid_t group
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_clonenode(
|
||||
rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_mount(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_fsmount_me(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
const void *data
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_unmount(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void null_op_fsunmount_me(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry
|
||||
)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static int null_op_utime(
|
||||
const rtems_filesystem_location_info_t *loc,
|
||||
time_t actime,
|
||||
time_t modtime
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_symlink(
|
||||
const rtems_filesystem_location_info_t *parentloc,
|
||||
const char *name,
|
||||
size_t namelen,
|
||||
const char *target
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t null_op_readlink(
|
||||
const rtems_filesystem_location_info_t *loc,
|
||||
char *buf,
|
||||
size_t bufsize
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_rename(
|
||||
const rtems_filesystem_location_info_t *oldparentloc,
|
||||
const rtems_filesystem_location_info_t *oldloc,
|
||||
const rtems_filesystem_location_info_t *newparentloc,
|
||||
const char *name,
|
||||
size_t namelen
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int null_op_statvfs(
|
||||
const rtems_filesystem_location_info_t *loc,
|
||||
struct statvfs *buf
|
||||
)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const rtems_filesystem_operations_table null_ops = {
|
||||
.lock_h = null_op_lock_or_unlock,
|
||||
.unlock_h = null_op_lock_or_unlock,
|
||||
.eval_path_h = rtems_filesystem_default_eval_path,
|
||||
.link_h = null_op_link,
|
||||
.are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
|
||||
.node_type_h = rtems_filesystem_default_node_type,
|
||||
.mknod_h = null_op_mknod,
|
||||
.rmnod_h = null_op_rmnod,
|
||||
.fchmod_h = null_op_fchmod,
|
||||
.chown_h = null_op_chown,
|
||||
.clonenod_h = null_op_clonenode,
|
||||
.freenod_h = rtems_filesystem_default_freenode,
|
||||
.mount_h = null_op_mount,
|
||||
.fsmount_me_h = null_op_fsmount_me,
|
||||
.unmount_h = null_op_unmount,
|
||||
.fsunmount_me_h = null_op_fsunmount_me,
|
||||
.utime_h = null_op_utime,
|
||||
.symlink_h = null_op_symlink,
|
||||
.readlink_h = null_op_readlink,
|
||||
.rename_h = null_op_rename,
|
||||
.statvfs_h = null_op_statvfs
|
||||
};
|
||||
|
||||
rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry = {
|
||||
.location_chain = {
|
||||
.Head = {
|
||||
.Node = {
|
||||
.next = &rtems_filesystem_global_location_null.location.mt_entry_node,
|
||||
.previous = NULL
|
||||
},
|
||||
.fill = &rtems_filesystem_global_location_null.location.mt_entry_node,
|
||||
}
|
||||
},
|
||||
.mt_point_node = &rtems_filesystem_global_location_null,
|
||||
.mt_fs_root = &rtems_filesystem_global_location_null,
|
||||
.mounted = false,
|
||||
.writeable = false
|
||||
};
|
||||
|
||||
rtems_filesystem_global_location_t rtems_filesystem_global_location_null = {
|
||||
.location = {
|
||||
.mt_entry_node = {
|
||||
.next = &rtems_filesystem_null_mt_entry.location_chain.Tail.Node,
|
||||
.previous = &rtems_filesystem_null_mt_entry.location_chain.Head.Node
|
||||
},
|
||||
.handlers = &rtems_filesystem_null_handlers,
|
||||
.ops = &null_ops,
|
||||
.mt_entry = &rtems_filesystem_null_mt_entry
|
||||
},
|
||||
|
||||
/*
|
||||
* The initial reference count accounts for the following references
|
||||
* o the root directory of the user environment,
|
||||
* o the current directory of the user environment,
|
||||
* o the root node of the null file system instance, and
|
||||
* o the mount point node of the null file system instance.
|
||||
*/
|
||||
.reference_count = 4
|
||||
};
|
||||
|
||||
rtems_user_env_t rtems_global_user_env = {
|
||||
.current_directory = &rtems_filesystem_global_location_null,
|
||||
.root_directory = &rtems_filesystem_global_location_null,
|
||||
.umask = S_IWGRP | S_IWOTH
|
||||
};
|
||||
|
||||
rtems_user_env_t *rtems_current_user_env = &rtems_global_user_env;
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* COPYRIGHT (c) 1989-2007.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -16,12 +19,10 @@
|
||||
#endif
|
||||
|
||||
#if defined(RTEMS_NEWLIB) && !defined(HAVE__RENAME_R)
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int _rename_r(
|
||||
struct _reent *ptr __attribute__((unused)),
|
||||
@@ -29,85 +30,47 @@ int _rename_r(
|
||||
const char *new
|
||||
)
|
||||
{
|
||||
int old_parent_pathlen;
|
||||
rtems_filesystem_location_info_t old_loc;
|
||||
rtems_filesystem_location_info_t old_parent_loc;
|
||||
rtems_filesystem_location_info_t new_parent_loc;
|
||||
int i;
|
||||
int result;
|
||||
const char *name;
|
||||
bool free_old_parentloc = false;
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t old_ctx;
|
||||
int old_eval_flags = 0;
|
||||
rtems_filesystem_location_info_t old_parentloc;
|
||||
int old_parent_eval_flags = RTEMS_LIBIO_PERMS_WRITE
|
||||
| RTEMS_LIBIO_FOLLOW_HARD_LINK;
|
||||
const rtems_filesystem_location_info_t *old_currentloc =
|
||||
rtems_filesystem_eval_path_start_with_parent(
|
||||
&old_ctx,
|
||||
old,
|
||||
old_eval_flags,
|
||||
&old_parentloc,
|
||||
old_parent_eval_flags
|
||||
);
|
||||
rtems_filesystem_eval_path_context_t new_ctx;
|
||||
|
||||
/*
|
||||
* Get the parent node of the old path to be renamed. Find the parent path.
|
||||
*/
|
||||
/* FIXME: This is not POSIX conform */
|
||||
int new_eval_flags = RTEMS_LIBIO_FOLLOW_HARD_LINK
|
||||
| RTEMS_LIBIO_MAKE
|
||||
| RTEMS_LIBIO_EXCLUSIVE;
|
||||
|
||||
old_parent_pathlen = rtems_filesystem_dirname ( old );
|
||||
const rtems_filesystem_location_info_t *new_currentloc =
|
||||
rtems_filesystem_eval_path_start( &new_ctx, new, new_eval_flags );
|
||||
|
||||
if ( old_parent_pathlen == 0 )
|
||||
rtems_filesystem_get_start_loc( old, &i, &old_parent_loc );
|
||||
else {
|
||||
result = rtems_filesystem_evaluate_path( old, old_parent_pathlen,
|
||||
RTEMS_LIBIO_PERMS_WRITE,
|
||||
&old_parent_loc,
|
||||
false );
|
||||
if ( result != 0 )
|
||||
return -1;
|
||||
|
||||
free_old_parentloc = true;
|
||||
rv = rtems_filesystem_location_exists_in_same_fs_instance_as(
|
||||
old_currentloc,
|
||||
new_currentloc
|
||||
);
|
||||
if ( rv == 0 ) {
|
||||
rv = (*new_currentloc->ops->rename_h)(
|
||||
&old_parentloc,
|
||||
old_currentloc,
|
||||
new_currentloc,
|
||||
rtems_filesystem_eval_path_get_token( &new_ctx ),
|
||||
rtems_filesystem_eval_path_get_tokenlen( &new_ctx )
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start from the parent to find the node that should be under it.
|
||||
*/
|
||||
rtems_filesystem_eval_path_cleanup_with_parent( &old_ctx, &old_parentloc );
|
||||
rtems_filesystem_eval_path_cleanup( &new_ctx );
|
||||
|
||||
old_loc = old_parent_loc;
|
||||
name = old + old_parent_pathlen;
|
||||
name += rtems_filesystem_prefix_separators( name, strlen( name ) );
|
||||
|
||||
result = rtems_filesystem_evaluate_relative_path( name , strlen( name ),
|
||||
0, &old_loc, false );
|
||||
if ( result != 0 ) {
|
||||
if ( free_old_parentloc )
|
||||
rtems_filesystem_freenode( &old_parent_loc );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the parent of the new node we are renaming to.
|
||||
*/
|
||||
|
||||
rtems_filesystem_get_start_loc( new, &i, &new_parent_loc );
|
||||
|
||||
result = (*new_parent_loc.ops->evalformake_h)( &new[i], &new_parent_loc, &name );
|
||||
if ( result != 0 ) {
|
||||
rtems_filesystem_freenode( &new_parent_loc );
|
||||
if ( free_old_parentloc )
|
||||
rtems_filesystem_freenode( &old_parent_loc );
|
||||
rtems_filesystem_freenode( &old_loc );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the caller is trying to rename across file system
|
||||
* boundaries.
|
||||
*/
|
||||
|
||||
if ( old_parent_loc.mt_entry != new_parent_loc.mt_entry ) {
|
||||
rtems_filesystem_freenode( &new_parent_loc );
|
||||
if ( free_old_parentloc )
|
||||
rtems_filesystem_freenode( &old_parent_loc );
|
||||
rtems_filesystem_freenode( &old_loc );
|
||||
rtems_set_errno_and_return_minus_one( EXDEV );
|
||||
}
|
||||
|
||||
result = (*new_parent_loc.ops->rename_h)( &old_parent_loc, &old_loc, &new_parent_loc, name );
|
||||
|
||||
rtems_filesystem_freenode( &new_parent_loc );
|
||||
if ( free_old_parentloc )
|
||||
rtems_filesystem_freenode( &old_parent_loc );
|
||||
rtems_filesystem_freenode( &old_loc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* COPYRIGHT (c) 1989-2008.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -35,62 +38,20 @@
|
||||
|
||||
void rtems_filesystem_initialize( void )
|
||||
{
|
||||
int status;
|
||||
const rtems_filesystem_mount_table_t *mt;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int rv = 0;
|
||||
const rtems_filesystem_mount_configuration *root_config =
|
||||
&rtems_filesystem_root_configuration;
|
||||
|
||||
/*
|
||||
* Set the default umask to "022".
|
||||
*/
|
||||
|
||||
rtems_filesystem_umask = 022;
|
||||
|
||||
/*
|
||||
* mount the first filesystem.
|
||||
*/
|
||||
if ( rtems_filesystem_mount_table_size == 0 )
|
||||
rtems_fatal_error_occurred( 0xABCD0001 );
|
||||
|
||||
mt = &rtems_filesystem_mount_table[0];
|
||||
|
||||
status = mount( mt->device, mt->mount_point, mt->type, mt->fsoptions, NULL );
|
||||
if ( status == -1 )
|
||||
rv = mount(
|
||||
root_config->source,
|
||||
root_config->target,
|
||||
root_config->filesystemtype,
|
||||
root_config->options,
|
||||
root_config->data
|
||||
);
|
||||
if ( rv != 0 )
|
||||
rtems_fatal_error_occurred( 0xABCD0002 );
|
||||
|
||||
rtems_filesystem_link_counts = 0;
|
||||
|
||||
/* setup the 'current' and 'root' directories
|
||||
*
|
||||
* NOTE: cloning the pathlocs is not strictly
|
||||
* necessary. Since we implicitely let
|
||||
* all threads that don't call
|
||||
* libio_set_private_env() share the same
|
||||
* (initial) 'root' and 'current' locs,
|
||||
* we (also implicitely) assume that the
|
||||
* root filesystem doesn't care about
|
||||
* reference counts.
|
||||
* I just inserted the code snippet below
|
||||
* to remind everybody of the fact by
|
||||
* making it more explicit...
|
||||
* Ideally, every thread would have to
|
||||
* call either share_private_env() or
|
||||
* set_private_env() - but then: that's
|
||||
* gonna hit performance.
|
||||
*
|
||||
* Till Straumann, 10/25/2002
|
||||
*/
|
||||
/* Clone the root pathloc */
|
||||
rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
|
||||
rtems_filesystem_root = loc;
|
||||
/* One more clone for the current node */
|
||||
rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
|
||||
rtems_filesystem_current = loc;
|
||||
|
||||
/* Note: the global_env's refcnt doesn't matter
|
||||
* as the global env is never released
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Traditionally RTEMS devices are under "/dev" so install this directory.
|
||||
*
|
||||
@@ -100,8 +61,8 @@ void rtems_filesystem_initialize( void )
|
||||
* created that way by the IMFS.
|
||||
*/
|
||||
|
||||
status = mkdir( "/dev", 0777);
|
||||
if ( status != 0 )
|
||||
rv = mkdir( "/dev", 0777);
|
||||
if ( rv != 0 )
|
||||
rtems_fatal_error_occurred( 0xABCD0003 );
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* COPYRIGHT (c) 1989-2010.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -12,46 +15,47 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int chdir(
|
||||
const char *pathname
|
||||
)
|
||||
int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc )
|
||||
{
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int result;
|
||||
int rv = 0;
|
||||
rtems_filesystem_global_location_t *global_loc =
|
||||
rtems_filesystem_location_transform_to_global( loc );
|
||||
rtems_filesystem_node_types_t type =
|
||||
rtems_filesystem_node_type( &global_loc->location );
|
||||
|
||||
if ( !pathname )
|
||||
rtems_set_errno_and_return_minus_one( EFAULT );
|
||||
|
||||
/*
|
||||
* Get the node where we wish to go.
|
||||
*/
|
||||
result = rtems_filesystem_evaluate_path(
|
||||
pathname, strlen( pathname ), RTEMS_LIBIO_PERMS_SEARCH, &loc, true );
|
||||
if ( result != 0 )
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Verify you can change directory into this node.
|
||||
*/
|
||||
if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
|
||||
rtems_filesystem_freenode( &loc );
|
||||
rtems_set_errno_and_return_minus_one( ENOTDIR );
|
||||
if ( type == RTEMS_FILESYSTEM_DIRECTORY ) {
|
||||
rtems_filesystem_global_location_assign(
|
||||
&rtems_filesystem_current,
|
||||
global_loc
|
||||
);
|
||||
} else {
|
||||
rtems_filesystem_location_error( &global_loc->location, ENOTDIR );
|
||||
rtems_filesystem_global_location_release( global_loc );
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
rtems_filesystem_freenode( &rtems_filesystem_current );
|
||||
|
||||
rtems_filesystem_current = loc;
|
||||
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int chdir( const char *path )
|
||||
{
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_PERMS_EXEC
|
||||
| RTEMS_LIBIO_FOLLOW_LINK;
|
||||
rtems_filesystem_location_info_t pathloc;
|
||||
|
||||
rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
|
||||
rtems_filesystem_eval_path_extract_currentloc( &ctx, &pathloc );
|
||||
rv = rtems_filesystem_chdir( &pathloc );
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -12,35 +12,24 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int chmod(
|
||||
const char *path,
|
||||
mode_t mode
|
||||
)
|
||||
int chmod( const char *path, mode_t mode )
|
||||
{
|
||||
int status;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int result;
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_FOLLOW_LINK;
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
|
||||
|
||||
status = rtems_filesystem_evaluate_path( path, strlen( path ), 0, &loc, true );
|
||||
if ( status != 0 )
|
||||
return -1;
|
||||
rv = (*currentloc->ops->fchmod_h)( currentloc, mode );
|
||||
|
||||
result = (*loc.handlers->fchmod_h)( &loc, mode );
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
rtems_filesystem_freenode( &loc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* COPYRIGHT (c) 1989-1999.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -12,39 +15,38 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
int _chown_helper(
|
||||
int rtems_filesystem_chown(
|
||||
const char *path,
|
||||
uid_t owner,
|
||||
gid_t group,
|
||||
int follow_link
|
||||
uid_t owner,
|
||||
gid_t group,
|
||||
int eval_follow_link
|
||||
)
|
||||
{
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int result;
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = eval_follow_link;
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
|
||||
|
||||
if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x00, &loc, follow_link ) )
|
||||
return -1;
|
||||
rv = (*currentloc->ops->chown_h)(
|
||||
currentloc,
|
||||
owner,
|
||||
group
|
||||
);
|
||||
|
||||
result = (*loc.ops->chown_h)( &loc, owner, group );
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
rtems_filesystem_freenode( &loc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int chown(
|
||||
const char *path,
|
||||
uid_t owner,
|
||||
gid_t group
|
||||
)
|
||||
int chown( const char *path, uid_t owner, gid_t group )
|
||||
{
|
||||
return _chown_helper( path, owner, group, true );
|
||||
return rtems_filesystem_chown( path, owner, group, RTEMS_LIBIO_FOLLOW_LINK );
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
* COPYRIGHT (c) 1989-2008.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -13,43 +16,77 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int chroot(
|
||||
const char *pathname
|
||||
)
|
||||
int chroot( const char *path )
|
||||
{
|
||||
int result;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int rv = 0;
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_PERMS_SEARCH
|
||||
| RTEMS_LIBIO_FOLLOW_LINK;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
rtems_filesystem_global_location_t *new_current_loc;
|
||||
|
||||
/* an automatic call to new private env the first time */
|
||||
if (rtems_current_user_env == &rtems_global_user_env) {
|
||||
rtems_libio_set_private_env(); /* try to set a new private env*/
|
||||
if (rtems_current_user_env == &rtems_global_user_env) /* not ok */
|
||||
rtems_set_errno_and_return_minus_one( ENOTSUP );
|
||||
/*
|
||||
* We use the global environment for path evaluation. This makes it possible
|
||||
* to escape from a chroot environment referencing an unmounted file system.
|
||||
*/
|
||||
rtems_filesystem_eval_path_start_with_root_and_current(
|
||||
&ctx,
|
||||
path,
|
||||
eval_flags,
|
||||
&rtems_global_user_env.root_directory,
|
||||
&rtems_global_user_env.current_directory
|
||||
);
|
||||
|
||||
rtems_filesystem_eval_path_extract_currentloc( &ctx, &loc );
|
||||
new_current_loc = rtems_filesystem_location_transform_to_global( &loc );
|
||||
if ( !rtems_filesystem_global_location_is_null( new_current_loc ) ) {
|
||||
rtems_filesystem_global_location_t *new_root_loc =
|
||||
rtems_filesystem_global_location_obtain( &new_current_loc );
|
||||
rtems_filesystem_node_types_t type =
|
||||
(*new_root_loc->location.ops->node_type_h)( &new_root_loc->location );
|
||||
|
||||
if ( type == RTEMS_FILESYSTEM_DIRECTORY ) {
|
||||
sc = rtems_libio_set_private_env();
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
rtems_filesystem_global_location_assign(
|
||||
&rtems_filesystem_root,
|
||||
new_root_loc
|
||||
);
|
||||
rtems_filesystem_global_location_assign(
|
||||
&rtems_filesystem_current,
|
||||
new_current_loc
|
||||
);
|
||||
} else {
|
||||
if (sc != RTEMS_UNSATISFIED) {
|
||||
errno = ENOMEM;
|
||||
}
|
||||
rv = -1;
|
||||
}
|
||||
} else {
|
||||
rtems_filesystem_location_error( &new_root_loc->location, ENOTDIR );
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
if ( rv != 0 ) {
|
||||
rtems_filesystem_global_location_release( new_root_loc );
|
||||
}
|
||||
} else {
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
result = chdir(pathname);
|
||||
if (result) {
|
||||
rtems_set_errno_and_return_minus_one( errno );
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
if ( rv != 0 ) {
|
||||
rtems_filesystem_global_location_release( new_current_loc );
|
||||
}
|
||||
|
||||
/* clone the new root location */
|
||||
if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) {
|
||||
/* our cwd has changed, though - but there is no easy way of return :-( */
|
||||
rtems_set_errno_and_return_minus_one( errno );
|
||||
}
|
||||
rtems_filesystem_freenode(&rtems_filesystem_root);
|
||||
rtems_filesystem_root = loc;
|
||||
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
void rtems_filesystem_location_clone(
|
||||
rtems_filesystem_location_info_t *clone,
|
||||
const rtems_filesystem_location_info_t *master
|
||||
)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
clone = rtems_filesystem_location_copy( clone, master );
|
||||
rv = (*clone->ops->clonenod_h)( clone );
|
||||
if ( rv != 0 ) {
|
||||
rtems_filesystem_location_remove_from_mt_entry( clone );
|
||||
rtems_filesystem_location_initialize_to_null( clone );
|
||||
}
|
||||
}
|
||||
@@ -22,16 +22,14 @@ int close(
|
||||
)
|
||||
{
|
||||
rtems_libio_t *iop;
|
||||
rtems_status_code rc;
|
||||
int rc;
|
||||
|
||||
rtems_libio_check_fd(fd);
|
||||
iop = rtems_libio_iop(fd);
|
||||
rtems_libio_check_is_open(iop);
|
||||
|
||||
rc = RTEMS_SUCCESSFUL;
|
||||
rc = (*iop->pathinfo.handlers->close_h)( iop );
|
||||
|
||||
rtems_filesystem_freenode( &iop->pathinfo );
|
||||
rtems_libio_free( iop );
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* rtems_filesystem_evaluate_path()
|
||||
*
|
||||
* Routine to seed the evaluate path routine.
|
||||
*
|
||||
* COPYRIGHT (c) 1989-2010.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int rtems_filesystem_evaluate_relative_path(
|
||||
const char *pathname,
|
||||
size_t pathnamelen,
|
||||
int flags,
|
||||
rtems_filesystem_location_info_t *pathloc,
|
||||
int follow_link
|
||||
)
|
||||
{
|
||||
int result;
|
||||
rtems_filesystem_node_types_t type;
|
||||
|
||||
#if defined(RTEMS_DEBUG)
|
||||
/*
|
||||
* Verify Input parameters that should never be bad unless someone
|
||||
* is implementing a new filesystem and has bugs.
|
||||
*/
|
||||
if ( !pathname )
|
||||
rtems_set_errno_and_return_minus_one( EFAULT );
|
||||
|
||||
if ( !pathloc )
|
||||
rtems_set_errno_and_return_minus_one( EIO );
|
||||
#endif
|
||||
|
||||
result = (*pathloc->ops->evalpath_h)( pathname, pathnamelen, flags, pathloc );
|
||||
|
||||
/*
|
||||
* Get the Node type and determine if you need to follow the link or
|
||||
* not.
|
||||
*/
|
||||
|
||||
if ( (result == 0) && follow_link ) {
|
||||
|
||||
type = (*pathloc->ops->node_type_h)( pathloc );
|
||||
|
||||
if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
|
||||
( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
|
||||
|
||||
/* what to do with the valid node pathloc points to
|
||||
* if eval_link_h fails?
|
||||
* Let the FS implementation deal with this case. It
|
||||
* should probably free pathloc in either case:
|
||||
* - if the link evaluation fails, it must free the
|
||||
* original (valid) pathloc because we are going
|
||||
* to return -1 and hence the FS generics won't
|
||||
* cleanup pathloc.
|
||||
* - if the link evaluation is successful, the updated
|
||||
* pathloc will be passed up (and eventually released).
|
||||
* Hence, the (valid) originial node that we submit to
|
||||
* eval_link_h() should be released by the handler.
|
||||
*/
|
||||
|
||||
result = (*pathloc->ops->eval_link_h)( pathloc, flags );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int rtems_filesystem_evaluate_path(
|
||||
const char *pathname,
|
||||
size_t pathnamelen,
|
||||
int flags,
|
||||
rtems_filesystem_location_info_t *pathloc,
|
||||
int follow_link
|
||||
)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#if defined(RTEMS_DEBUG)
|
||||
/*
|
||||
* Verify Input parameters that should never be bad unless someone
|
||||
* is implementing a new filesystem and has bugs.
|
||||
*/
|
||||
if ( !pathname )
|
||||
rtems_set_errno_and_return_minus_one( EFAULT );
|
||||
|
||||
if ( !pathloc )
|
||||
rtems_set_errno_and_return_minus_one( EIO );
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Evaluate the path using the optable evalpath.
|
||||
*/
|
||||
|
||||
rtems_filesystem_get_start_loc( pathname, &i, pathloc );
|
||||
|
||||
/*
|
||||
* We evaluation the path relative to the start location we get got.
|
||||
*/
|
||||
return rtems_filesystem_evaluate_relative_path( &pathname[i],
|
||||
pathnamelen - i,
|
||||
flags,
|
||||
pathloc,
|
||||
follow_link );
|
||||
}
|
||||
|
||||
int rtems_filesystem_dirname(
|
||||
const char *pathname
|
||||
)
|
||||
{
|
||||
int len = strlen( pathname );
|
||||
|
||||
while ( len ) {
|
||||
len--;
|
||||
if ( rtems_filesystem_is_separator( pathname[len] ) )
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int rtems_filesystem_prefix_separators(
|
||||
const char *pathname,
|
||||
int pathnamelen
|
||||
)
|
||||
{
|
||||
/*
|
||||
* Eat any separators at start of the path.
|
||||
*/
|
||||
int stripped = 0;
|
||||
while ( *pathname && pathnamelen && rtems_filesystem_is_separator( *pathname ) )
|
||||
{
|
||||
pathname++;
|
||||
pathnamelen--;
|
||||
stripped++;
|
||||
}
|
||||
return stripped;
|
||||
}
|
||||
@@ -4,6 +4,9 @@
|
||||
* COPYRIGHT (c) 1989-2011.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -12,65 +15,50 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int fchdir(
|
||||
int fd
|
||||
)
|
||||
int fchdir( int fd )
|
||||
{
|
||||
int rv = 0;
|
||||
rtems_libio_t *iop;
|
||||
rtems_filesystem_location_info_t loc, saved;
|
||||
struct stat st;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
|
||||
st.st_mode = 0;
|
||||
st.st_uid = 0;
|
||||
st.st_gid = 0;
|
||||
|
||||
rtems_libio_check_fd( fd );
|
||||
iop = rtems_libio_iop( fd );
|
||||
rtems_libio_check_is_open(iop);
|
||||
rtems_libio_check_is_open( iop );
|
||||
|
||||
/*
|
||||
* Verify you can change directory into this node.
|
||||
*/
|
||||
rtems_filesystem_instance_lock( &iop->pathinfo );
|
||||
rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, &st );
|
||||
if ( rv == 0 ) {
|
||||
bool access_ok = rtems_filesystem_check_access(
|
||||
RTEMS_LIBIO_PERMS_EXEC,
|
||||
st.st_mode,
|
||||
st.st_uid,
|
||||
st.st_gid
|
||||
);
|
||||
|
||||
if ( (*iop->pathinfo.ops->node_type_h)( &iop->pathinfo ) !=
|
||||
RTEMS_FILESYSTEM_DIRECTORY ) {
|
||||
rtems_set_errno_and_return_minus_one( ENOTDIR );
|
||||
if ( access_ok ) {
|
||||
rtems_filesystem_location_clone( &loc, &iop->pathinfo );
|
||||
} else {
|
||||
errno = EACCES;
|
||||
rv = -1;
|
||||
}
|
||||
}
|
||||
rtems_filesystem_instance_unlock( &iop->pathinfo );
|
||||
|
||||
if ( rv == 0 ) {
|
||||
rv = rtems_filesystem_chdir( &loc );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FIXME : I feel there should be another call to
|
||||
* actually take into account the extra reference to
|
||||
* this node which we are making here. I can
|
||||
* see the freenode interface but do not see
|
||||
* allocnode node interface. It maybe node_type.
|
||||
*
|
||||
* FIXED: T.Straumann: it is evaluate_path()
|
||||
* but note the race condition. Threads who
|
||||
* share their rtems_filesystem_current better
|
||||
* be synchronized!
|
||||
*/
|
||||
|
||||
saved = rtems_filesystem_current;
|
||||
rtems_filesystem_current = iop->pathinfo;
|
||||
|
||||
/* clone the current node */
|
||||
if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) {
|
||||
/* cloning failed; restore original and bail out */
|
||||
rtems_filesystem_current = saved;
|
||||
return -1;
|
||||
}
|
||||
/* release the old one */
|
||||
rtems_filesystem_freenode( &saved );
|
||||
|
||||
rtems_filesystem_current = loc;
|
||||
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -12,31 +12,25 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int fchmod(
|
||||
int fd,
|
||||
mode_t mode
|
||||
)
|
||||
int fchmod( int fd, mode_t mode )
|
||||
{
|
||||
int rv;
|
||||
rtems_libio_t *iop;
|
||||
|
||||
rtems_libio_check_fd( fd );
|
||||
iop = rtems_libio_iop( fd );
|
||||
rtems_libio_check_is_open(iop);
|
||||
|
||||
/*
|
||||
* Now process the fchmod().
|
||||
*/
|
||||
return (*iop->pathinfo.handlers->fchmod_h)( &iop->pathinfo, mode );
|
||||
rtems_filesystem_instance_lock( &iop->pathinfo );
|
||||
rv = (*iop->pathinfo.ops->fchmod_h)( &iop->pathinfo, mode );
|
||||
rtems_filesystem_instance_unlock( &iop->pathinfo );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -12,24 +12,16 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int fchown(
|
||||
int fd,
|
||||
uid_t owner,
|
||||
gid_t group
|
||||
)
|
||||
int fchown( int fd, uid_t owner, gid_t group )
|
||||
{
|
||||
int rv = 0;
|
||||
rtems_libio_t *iop;
|
||||
|
||||
rtems_libio_check_fd( fd );
|
||||
@@ -38,5 +30,9 @@ int fchown(
|
||||
|
||||
rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
|
||||
|
||||
return (*iop->pathinfo.ops->chown_h)( &iop->pathinfo, owner, group );
|
||||
rtems_filesystem_instance_lock( &iop->pathinfo );
|
||||
rv = (*iop->pathinfo.ops->chown_h)( &iop->pathinfo, owner, group );
|
||||
rtems_filesystem_instance_unlock( &iop->pathinfo );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -12,17 +12,53 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
static int duplicate_iop( rtems_libio_t *iop, int fd2 )
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
/*
|
||||
* FIXME: We ignore the start value fd2 for the file descriptor search. This
|
||||
* is not POSIX conform.
|
||||
*/
|
||||
rtems_libio_t *diop = rtems_libio_allocate();
|
||||
|
||||
if (diop != NULL) {
|
||||
int oflag = rtems_libio_to_fcntl_flags( iop->flags );
|
||||
|
||||
oflag &= ~O_CREAT;
|
||||
diop->flags |= rtems_libio_fcntl_flags( oflag );
|
||||
|
||||
rtems_filesystem_instance_lock( &iop->pathinfo );
|
||||
rtems_filesystem_location_clone( &diop->pathinfo, &iop->pathinfo );
|
||||
rtems_filesystem_instance_unlock( &iop->pathinfo );
|
||||
|
||||
/*
|
||||
* XXX: We call the open handler here to have a proper open and close pair.
|
||||
*
|
||||
* FIXME: What to do with the path?
|
||||
*/
|
||||
rv = (*diop->pathinfo.handlers->open_h)( diop, NULL, oflag, 0 );
|
||||
if ( rv == 0 ) {
|
||||
rv = diop - rtems_libio_iops;
|
||||
} else {
|
||||
rtems_libio_free( diop );
|
||||
}
|
||||
} else {
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int vfcntl(
|
||||
int fd,
|
||||
int cmd,
|
||||
@@ -30,7 +66,6 @@ static int vfcntl(
|
||||
)
|
||||
{
|
||||
rtems_libio_t *iop;
|
||||
rtems_libio_t *diop;
|
||||
int fd2;
|
||||
int flags;
|
||||
int mask;
|
||||
@@ -51,20 +86,7 @@ static int vfcntl(
|
||||
switch ( cmd ) {
|
||||
case F_DUPFD: /* dup */
|
||||
fd2 = va_arg( ap, int );
|
||||
if ( fd2 )
|
||||
diop = rtems_libio_iop( fd2 );
|
||||
else {
|
||||
/* allocate a file control block */
|
||||
diop = rtems_libio_allocate();
|
||||
if ( diop == 0 ) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
diop->flags = iop->flags;
|
||||
diop->pathinfo = iop->pathinfo;
|
||||
ret = (int) (diop - rtems_libio_iops);
|
||||
ret = duplicate_iop( iop, fd2 );
|
||||
break;
|
||||
|
||||
case F_GETFD: /* get f_flags */
|
||||
@@ -138,7 +160,7 @@ static int vfcntl(
|
||||
*/
|
||||
|
||||
if (ret >= 0) {
|
||||
int err = (*iop->pathinfo.handlers->fcntl_h)( cmd, iop );
|
||||
int err = (*iop->pathinfo.handlers->fcntl_h)( iop, cmd );
|
||||
if (err) {
|
||||
errno = err;
|
||||
ret = -1;
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* COPYRIGHT (c) 1989-2010.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -11,10 +14,16 @@
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
void rtems_filesystem_freenode( rtems_filesystem_location_info_t *_node )
|
||||
void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc )
|
||||
{
|
||||
_node->ops->freenod_h(_node );
|
||||
rtems_filesystem_instance_lock( loc );
|
||||
(*loc->ops->freenod_h)( loc );
|
||||
rtems_filesystem_instance_unlock( loc );
|
||||
rtems_filesystem_location_remove_from_mt_entry( loc );
|
||||
}
|
||||
|
||||
@@ -12,39 +12,30 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int ftruncate(
|
||||
int fd,
|
||||
off_t length
|
||||
)
|
||||
int ftruncate( int fd, off_t length )
|
||||
{
|
||||
rtems_libio_t *iop;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int rv = 0;
|
||||
|
||||
rtems_libio_check_fd( fd );
|
||||
iop = rtems_libio_iop( fd );
|
||||
rtems_libio_check_is_open(iop);
|
||||
rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
|
||||
if ( length >= 0 ) {
|
||||
rtems_libio_t *iop;
|
||||
|
||||
/*
|
||||
* Now process the ftruncate() request.
|
||||
*/
|
||||
rtems_libio_check_fd( fd );
|
||||
iop = rtems_libio_iop( fd );
|
||||
rtems_libio_check_is_open( iop );
|
||||
rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
|
||||
|
||||
/*
|
||||
* Make sure we are not working on a directory
|
||||
*/
|
||||
rv = (*iop->pathinfo.handlers->ftruncate_h)( iop, length );
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
loc = iop->pathinfo;
|
||||
if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
|
||||
rtems_set_errno_and_return_minus_one( EISDIR );
|
||||
|
||||
return (*iop->pathinfo.handlers->ftruncate_h)( iop, length );
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ int getdents(
|
||||
int dd_len
|
||||
)
|
||||
{
|
||||
rtems_libio_t *iop;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
rtems_libio_t *iop;
|
||||
rtems_filesystem_node_types_t type;
|
||||
|
||||
/*
|
||||
* Get the file control block structure associated with the file descriptor
|
||||
@@ -43,8 +43,8 @@ int getdents(
|
||||
/*
|
||||
* Make sure we are working on a directory
|
||||
*/
|
||||
loc = iop->pathinfo;
|
||||
if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
|
||||
type = rtems_filesystem_node_type( &iop->pathinfo );
|
||||
if ( type != RTEMS_FILESYSTEM_DIRECTORY )
|
||||
rtems_set_errno_and_return_minus_one( ENOTDIR );
|
||||
|
||||
/*
|
||||
|
||||
@@ -12,20 +12,19 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
int _chown_helper( const char *path, uid_t owner, gid_t group, int follow_link);
|
||||
|
||||
int lchown(
|
||||
const char *path,
|
||||
uid_t owner,
|
||||
gid_t group
|
||||
)
|
||||
int lchown( const char *path, uid_t owner, gid_t group )
|
||||
{
|
||||
return _chown_helper( path, owner, group, false );
|
||||
return rtems_filesystem_chown(
|
||||
path,
|
||||
owner,
|
||||
group,
|
||||
RTEMS_LIBIO_FOLLOW_HARD_LINK
|
||||
);
|
||||
}
|
||||
|
||||
+13
-101
@@ -47,14 +47,14 @@
|
||||
* Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
|
||||
*/
|
||||
|
||||
const rtems_assoc_t access_modes_assoc[] = {
|
||||
static const rtems_assoc_t access_modes_assoc[] = {
|
||||
{ "READ", LIBIO_FLAGS_READ, O_RDONLY },
|
||||
{ "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
|
||||
{ "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
const rtems_assoc_t status_flags_assoc[] = {
|
||||
static const rtems_assoc_t status_flags_assoc[] = {
|
||||
#ifdef ACCEPT_O_NDELAY_ALIAS
|
||||
{ "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
|
||||
#endif
|
||||
@@ -64,9 +64,7 @@ const rtems_assoc_t status_flags_assoc[] = {
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
uint32_t rtems_libio_fcntl_flags(
|
||||
uint32_t fcntl_flags
|
||||
)
|
||||
uint32_t rtems_libio_fcntl_flags( int fcntl_flags )
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
uint32_t access_modes;
|
||||
@@ -75,7 +73,7 @@ uint32_t rtems_libio_fcntl_flags(
|
||||
* Access mode is a small integer
|
||||
*/
|
||||
|
||||
access_modes = fcntl_flags & O_ACCMODE;
|
||||
access_modes = (uint32_t) (fcntl_flags & O_ACCMODE);
|
||||
fcntl_flags &= ~O_ACCMODE;
|
||||
flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
|
||||
|
||||
@@ -83,8 +81,11 @@ uint32_t rtems_libio_fcntl_flags(
|
||||
* Everything else is single bits
|
||||
*/
|
||||
|
||||
flags |=
|
||||
rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
|
||||
flags |= rtems_assoc_local_by_remote_bitfield(
|
||||
status_flags_assoc,
|
||||
(uint32_t) fcntl_flags
|
||||
);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -94,11 +95,9 @@ uint32_t rtems_libio_fcntl_flags(
|
||||
* Convert RTEMS internal flags to UNIX fnctl(2) flags
|
||||
*/
|
||||
|
||||
uint32_t rtems_libio_to_fcntl_flags(
|
||||
uint32_t flags
|
||||
)
|
||||
int rtems_libio_to_fcntl_flags( uint32_t flags )
|
||||
{
|
||||
uint32_t fcntl_flags = 0;
|
||||
int fcntl_flags = 0;
|
||||
|
||||
if ( (flags & LIBIO_FLAGS_READ_WRITE) == LIBIO_FLAGS_READ_WRITE ) {
|
||||
fcntl_flags |= O_RDWR;
|
||||
@@ -176,6 +175,8 @@ void rtems_libio_free(
|
||||
rtems_libio_t *iop
|
||||
)
|
||||
{
|
||||
rtems_filesystem_location_free( &iop->pathinfo );
|
||||
|
||||
rtems_libio_lock();
|
||||
|
||||
if (iop->sem)
|
||||
@@ -187,92 +188,3 @@ void rtems_libio_free(
|
||||
|
||||
rtems_libio_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* rtems_libio_is_open_files_in_fs
|
||||
*
|
||||
* This routine scans the entire file descriptor table to determine if the
|
||||
* are any active file descriptors that refer to the at least one node in the
|
||||
* file system that we are trying to dismount.
|
||||
*
|
||||
* If there is at least one node in the file system referenced by the mount
|
||||
* table entry a 1 is returned, otherwise a 0 is returned.
|
||||
*/
|
||||
|
||||
int rtems_libio_is_open_files_in_fs(
|
||||
rtems_filesystem_mount_table_entry_t * fs_mt_entry
|
||||
)
|
||||
{
|
||||
rtems_libio_t *iop;
|
||||
int result = 0;
|
||||
uint32_t i;
|
||||
|
||||
rtems_libio_lock();
|
||||
|
||||
/*
|
||||
* Look for any active file descriptor entry.
|
||||
*/
|
||||
|
||||
for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
|
||||
|
||||
if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
|
||||
|
||||
/*
|
||||
* Check if this node is under the file system that we
|
||||
* are trying to dismount.
|
||||
*/
|
||||
|
||||
if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtems_libio_unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* rtems_libio_is_file_open
|
||||
*
|
||||
* This routine scans the entire file descriptor table to determine if the
|
||||
* given file refers to an active file descriptor.
|
||||
*
|
||||
* If the given file is open a 1 is returned, otherwise a 0 is returned.
|
||||
*/
|
||||
|
||||
int rtems_libio_is_file_open(
|
||||
void *node_access
|
||||
)
|
||||
{
|
||||
rtems_libio_t *iop;
|
||||
int result=0;
|
||||
uint32_t i;
|
||||
|
||||
rtems_libio_lock();
|
||||
|
||||
/*
|
||||
* Look for any active file descriptor entry.
|
||||
*/
|
||||
|
||||
for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
|
||||
if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
|
||||
|
||||
/*
|
||||
* Check if this node is under the file system that we
|
||||
* are trying to dismount.
|
||||
*/
|
||||
|
||||
if ( iop->pathinfo.node_access == node_access ) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtems_libio_unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
#include <rtems/rtems_bsdnet_internal.h>
|
||||
|
||||
/*
|
||||
* Convert an RTEMS file descriptor to a BSD socket pointer.
|
||||
@@ -69,5 +70,7 @@ int rtems_bsdnet_makeFdForSocket(
|
||||
iop->data1 = so;
|
||||
iop->pathinfo.handlers = h;
|
||||
iop->pathinfo.ops = &rtems_filesystem_operations_default;
|
||||
iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
|
||||
rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo);
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -12,65 +12,44 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int link(
|
||||
const char *existing,
|
||||
const char *new
|
||||
)
|
||||
int link( const char *path1, const char *path2 )
|
||||
{
|
||||
rtems_filesystem_location_info_t existing_loc;
|
||||
rtems_filesystem_location_info_t parent_loc;
|
||||
int i;
|
||||
int result;
|
||||
const char *name_start;
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx_1;
|
||||
rtems_filesystem_eval_path_context_t ctx_2;
|
||||
int eval_flags_1 = RTEMS_LIBIO_FOLLOW_LINK;
|
||||
int eval_flags_2 = RTEMS_LIBIO_FOLLOW_LINK
|
||||
| RTEMS_LIBIO_MAKE
|
||||
| RTEMS_LIBIO_EXCLUSIVE;
|
||||
const rtems_filesystem_location_info_t *currentloc_1 =
|
||||
rtems_filesystem_eval_path_start( &ctx_1, path1, eval_flags_1 );
|
||||
const rtems_filesystem_location_info_t *currentloc_2 =
|
||||
rtems_filesystem_eval_path_start( &ctx_2, path2, eval_flags_2 );
|
||||
|
||||
/*
|
||||
* Get the node we are linking to.
|
||||
*/
|
||||
|
||||
result = rtems_filesystem_evaluate_path( existing, strlen( existing ),
|
||||
0, &existing_loc, true );
|
||||
if ( result != 0 )
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Get the parent of the node we are creating.
|
||||
*/
|
||||
|
||||
rtems_filesystem_get_start_loc( new, &i, &parent_loc );
|
||||
|
||||
result = (*parent_loc.ops->evalformake_h)( &new[i], &parent_loc, &name_start );
|
||||
if ( result != 0 ) {
|
||||
rtems_filesystem_freenode( &existing_loc );
|
||||
return -1;
|
||||
rv = rtems_filesystem_location_exists_in_same_fs_instance_as(
|
||||
currentloc_1,
|
||||
currentloc_2
|
||||
);
|
||||
if ( rv == 0 ) {
|
||||
rv = (*currentloc_2->ops->link_h)(
|
||||
currentloc_2,
|
||||
currentloc_1,
|
||||
rtems_filesystem_eval_path_get_token( &ctx_2 ),
|
||||
rtems_filesystem_eval_path_get_tokenlen( &ctx_2 )
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the caller is trying to link across file system
|
||||
* boundaries.
|
||||
*/
|
||||
rtems_filesystem_eval_path_cleanup( &ctx_1 );
|
||||
rtems_filesystem_eval_path_cleanup( &ctx_2 );
|
||||
|
||||
if ( parent_loc.mt_entry != existing_loc.mt_entry ) {
|
||||
rtems_filesystem_freenode( &existing_loc );
|
||||
rtems_filesystem_freenode( &parent_loc );
|
||||
rtems_set_errno_and_return_minus_one( EXDEV );
|
||||
}
|
||||
|
||||
result = (*parent_loc.ops->link_h)( &existing_loc, &parent_loc, name_start );
|
||||
|
||||
rtems_filesystem_freenode( &existing_loc );
|
||||
rtems_filesystem_freenode( &parent_loc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -85,10 +64,10 @@ int link(
|
||||
|
||||
int _link_r(
|
||||
struct _reent *ptr __attribute__((unused)),
|
||||
const char *existing,
|
||||
const char *new
|
||||
const char *path1,
|
||||
const char *path2
|
||||
)
|
||||
{
|
||||
return link( existing, new );
|
||||
return link( path1, path2 );
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,64 +12,74 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
off_t lseek(
|
||||
int fd,
|
||||
off_t offset,
|
||||
int whence
|
||||
)
|
||||
off_t lseek( int fd, off_t offset, int whence )
|
||||
{
|
||||
off_t rv = 0;
|
||||
rtems_libio_t *iop;
|
||||
off_t old_offset;
|
||||
off_t status;
|
||||
off_t reference_offset;
|
||||
off_t old_offset;
|
||||
off_t new_offset;
|
||||
|
||||
rtems_libio_check_fd( fd );
|
||||
iop = rtems_libio_iop( fd );
|
||||
rtems_libio_check_is_open(iop);
|
||||
|
||||
/*
|
||||
* Now process the lseek().
|
||||
*/
|
||||
|
||||
old_offset = iop->offset;
|
||||
switch ( whence ) {
|
||||
case SEEK_SET:
|
||||
iop->offset = offset;
|
||||
reference_offset = 0;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
iop->offset += offset;
|
||||
reference_offset = old_offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
iop->offset = iop->size + offset;
|
||||
reference_offset = iop->size;
|
||||
break;
|
||||
|
||||
default:
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
errno = EINVAL;
|
||||
rv = (off_t) -1;
|
||||
break;
|
||||
}
|
||||
new_offset = reference_offset + offset;
|
||||
|
||||
if ( rv == 0 ) {
|
||||
if (
|
||||
(reference_offset >= 0 && new_offset >= offset)
|
||||
|| (reference_offset < 0 && new_offset <= offset)
|
||||
) {
|
||||
switch ( rtems_filesystem_node_type( &iop->pathinfo ) ) {
|
||||
case RTEMS_FILESYSTEM_DIRECTORY:
|
||||
case RTEMS_FILESYSTEM_MEMORY_FILE:
|
||||
if ( new_offset < 0 ) {
|
||||
errno = EINVAL;
|
||||
rv = (off_t) -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( rv == 0 ) {
|
||||
iop->offset = new_offset;
|
||||
rv = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
|
||||
if ( rv == (off_t) -1 ) {
|
||||
iop->offset = old_offset;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errno = EOVERFLOW;
|
||||
rv = (off_t) -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* At this time, handlers assume iop->offset has the desired
|
||||
* new offset.
|
||||
*/
|
||||
|
||||
status = (*iop->pathinfo.handlers->lseek_h)( iop, offset, whence );
|
||||
if ( status == (off_t) -1 )
|
||||
iop->offset = old_offset;
|
||||
|
||||
/*
|
||||
* So if the operation failed, we have to restore iop->offset.
|
||||
*/
|
||||
|
||||
return status;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
|
||||
#define _STAT_NAME lstat
|
||||
#define _STAT_R_NAME _lstat_r
|
||||
#define _STAT_FOLLOW_LINKS false
|
||||
#define _STAT_FOLLOW_LINKS RTEMS_LIBIO_FOLLOW_HARD_LINK
|
||||
|
||||
#include "stat.c"
|
||||
|
||||
@@ -16,58 +16,65 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int mknod(
|
||||
const char *pathname,
|
||||
mode_t mode,
|
||||
dev_t dev
|
||||
int rtems_filesystem_mknod(
|
||||
const rtems_filesystem_location_info_t *parentloc,
|
||||
const char *name,
|
||||
size_t namelen,
|
||||
mode_t mode,
|
||||
dev_t dev
|
||||
)
|
||||
{
|
||||
rtems_filesystem_location_info_t temp_loc;
|
||||
int i;
|
||||
const char *name_start;
|
||||
int result;
|
||||
int rv = 0;
|
||||
|
||||
/*
|
||||
* The file type is field within the mode. Check we have a sane mode set.
|
||||
*/
|
||||
switch (mode & S_IFMT)
|
||||
{
|
||||
case S_IFDIR:
|
||||
case S_IFCHR:
|
||||
mode &= ~rtems_filesystem_umask;
|
||||
|
||||
switch (mode & S_IFMT) {
|
||||
case S_IFBLK:
|
||||
case S_IFREG:
|
||||
case S_IFCHR:
|
||||
case S_IFDIR:
|
||||
case S_IFIFO:
|
||||
case S_IFREG:
|
||||
break;
|
||||
default:
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
errno = EINVAL;
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
|
||||
if ( rv == 0 ) {
|
||||
rv = (*parentloc->ops->mknod_h)( parentloc, name, namelen, mode, dev );
|
||||
}
|
||||
|
||||
result = (*temp_loc.ops->evalformake_h)(
|
||||
&pathname[i],
|
||||
&temp_loc,
|
||||
&name_start
|
||||
);
|
||||
if ( result != 0 )
|
||||
return -1;
|
||||
|
||||
result = (*temp_loc.ops->mknod_h)( name_start, mode, dev, &temp_loc );
|
||||
|
||||
rtems_filesystem_freenode( &temp_loc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int mknod( const char *path, mode_t mode, dev_t dev )
|
||||
{
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_FOLLOW_LINK
|
||||
| RTEMS_LIBIO_MAKE
|
||||
| RTEMS_LIBIO_EXCLUSIVE
|
||||
| (S_ISDIR(mode) ? RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS : 0);
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
|
||||
|
||||
rv = rtems_filesystem_mknod(
|
||||
currentloc,
|
||||
rtems_filesystem_eval_path_get_token( &ctx ),
|
||||
rtems_filesystem_eval_path_get_tokenlen( &ctx ),
|
||||
mode,
|
||||
dev
|
||||
);
|
||||
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
+142
-180
@@ -20,22 +20,15 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <rtems/chain.h>
|
||||
#include <rtems/seterr.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
static RTEMS_CHAIN_DEFINE_EMPTY(mount_chain);
|
||||
RTEMS_CHAIN_DEFINE_EMPTY(rtems_filesystem_mount_table);
|
||||
|
||||
/*
|
||||
* Default pathconfs.
|
||||
@@ -55,14 +48,6 @@ const rtems_filesystem_limits_and_options_t rtems_filesystem_default_pathconf =
|
||||
0 /* posix_vdisable: special char processing, 0=no, 1=yes */
|
||||
};
|
||||
|
||||
static bool is_node_fs_root(
|
||||
const rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return arg == mt_entry->mt_fs_root.node_access;
|
||||
}
|
||||
|
||||
static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
|
||||
const char *source_or_null,
|
||||
const char *target_or_null,
|
||||
@@ -76,11 +61,15 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
|
||||
strlen( source_or_null ) + 1 : 0;
|
||||
size_t target_size = strlen( target ) + 1;
|
||||
size_t size = sizeof( rtems_filesystem_mount_table_entry_t )
|
||||
+ filesystemtype_size + source_size + target_size;
|
||||
+ filesystemtype_size + source_size + target_size
|
||||
+ sizeof( rtems_filesystem_global_location_t );
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry = calloc( 1, size );
|
||||
|
||||
if ( mt_entry != NULL ) {
|
||||
char *str = (char *) mt_entry + sizeof( *mt_entry );
|
||||
rtems_filesystem_global_location_t *mt_fs_root =
|
||||
(rtems_filesystem_global_location_t *)
|
||||
((char *) mt_entry + sizeof( *mt_entry ));
|
||||
char *str = (char *) mt_fs_root + sizeof( *mt_fs_root );
|
||||
|
||||
memcpy( str, filesystemtype, filesystemtype_size );
|
||||
mt_entry->type = str;
|
||||
@@ -92,6 +81,23 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
|
||||
|
||||
memcpy( str, target, target_size );
|
||||
mt_entry->target = str;
|
||||
str += target_size;
|
||||
|
||||
mt_entry->mounted = true;
|
||||
mt_entry->mt_fs_root = mt_fs_root;
|
||||
mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf;
|
||||
|
||||
mt_fs_root->location.mt_entry = mt_entry;
|
||||
mt_fs_root->reference_count = 1;
|
||||
|
||||
rtems_chain_initialize(
|
||||
&mt_entry->location_chain,
|
||||
mt_fs_root,
|
||||
1,
|
||||
sizeof(*mt_fs_root)
|
||||
);
|
||||
} else {
|
||||
free( mt_entry );
|
||||
}
|
||||
|
||||
*target_length_ptr = target_size - 1;
|
||||
@@ -99,20 +105,82 @@ static rtems_filesystem_mount_table_entry_t *alloc_mount_table_entry(
|
||||
return mt_entry;
|
||||
}
|
||||
|
||||
/*
|
||||
* mount
|
||||
*
|
||||
* This routine will attempt to mount a new file system at the specified
|
||||
* mount point. A series of tests will be run to determine if any of the
|
||||
* following reasons exist to prevent the mount operation:
|
||||
*
|
||||
* 1) The file system type or options are not valid
|
||||
* 2) No new file system root node is specified
|
||||
* 3) The selected file system has already been mounted
|
||||
* 4) The mount point exists with the proper permissions to allow mounting
|
||||
* 5) The selected mount point already has a file system mounted to it
|
||||
*
|
||||
*/
|
||||
static int register_subordinate_file_system(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
const char *target
|
||||
)
|
||||
{
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_PERMS_RWX
|
||||
| RTEMS_LIBIO_FOLLOW_LINK;
|
||||
rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start( &ctx, target, eval_flags );
|
||||
|
||||
if ( !rtems_filesystem_location_is_root( currentloc ) ) {
|
||||
rtems_filesystem_location_info_t targetloc;
|
||||
rtems_filesystem_global_location_t *mt_point_node;
|
||||
|
||||
rtems_filesystem_eval_path_extract_currentloc( &ctx, &targetloc );
|
||||
mt_point_node = rtems_filesystem_location_transform_to_global( &targetloc );
|
||||
mt_entry->mt_point_node = mt_point_node;
|
||||
rv = (*mt_point_node->location.ops->mount_h)( mt_entry );
|
||||
if ( rv == 0 ) {
|
||||
rtems_filesystem_mt_lock();
|
||||
rtems_chain_append_unprotected(
|
||||
&rtems_filesystem_mount_table,
|
||||
&mt_entry->mt_node
|
||||
);
|
||||
rtems_filesystem_mt_unlock();
|
||||
} else {
|
||||
rtems_filesystem_global_location_release( mt_point_node );
|
||||
}
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error( &ctx, EBUSY );
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int register_root_file_system(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry
|
||||
)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
rtems_filesystem_mt_lock();
|
||||
if ( rtems_chain_is_empty( &rtems_filesystem_mount_table ) ) {
|
||||
rtems_chain_append_unprotected(
|
||||
&rtems_filesystem_mount_table,
|
||||
&mt_entry->mt_node
|
||||
);
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
rv = -1;
|
||||
}
|
||||
rtems_filesystem_mt_unlock();
|
||||
|
||||
if ( rv == 0 ) {
|
||||
rtems_filesystem_global_location_t *new_fs_root =
|
||||
rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root );
|
||||
rtems_filesystem_global_location_t *new_fs_current =
|
||||
rtems_filesystem_global_location_obtain( &mt_entry->mt_fs_root );
|
||||
|
||||
rtems_filesystem_global_location_assign(
|
||||
&rtems_filesystem_root,
|
||||
new_fs_root
|
||||
);
|
||||
rtems_filesystem_global_location_assign(
|
||||
&rtems_filesystem_current,
|
||||
new_fs_current
|
||||
);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int mount(
|
||||
const char *source,
|
||||
@@ -122,161 +190,55 @@ int mount(
|
||||
const void *data
|
||||
)
|
||||
{
|
||||
rtems_filesystem_fsmount_me_t mount_h = NULL;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry = NULL;
|
||||
rtems_filesystem_location_info_t *loc_to_free = NULL;
|
||||
bool has_target = target != NULL;
|
||||
size_t target_length = 0;
|
||||
int rv = 0;
|
||||
|
||||
/*
|
||||
* Are the file system options valid?
|
||||
*/
|
||||
if (
|
||||
options == RTEMS_FILESYSTEM_READ_ONLY
|
||||
|| options == RTEMS_FILESYSTEM_READ_WRITE
|
||||
) {
|
||||
rtems_filesystem_fsmount_me_t fsmount_me_h =
|
||||
rtems_filesystem_get_mount_handler( filesystemtype );
|
||||
|
||||
if ( options != RTEMS_FILESYSTEM_READ_ONLY &&
|
||||
options != RTEMS_FILESYSTEM_READ_WRITE )
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
if ( fsmount_me_h != NULL ) {
|
||||
size_t target_length = 0;
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry = alloc_mount_table_entry(
|
||||
source,
|
||||
target,
|
||||
filesystemtype,
|
||||
&target_length
|
||||
);
|
||||
|
||||
/*
|
||||
* Get mount handler
|
||||
*/
|
||||
mount_h = rtems_filesystem_get_mount_handler( filesystemtype );
|
||||
if ( !mount_h )
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
if ( mt_entry != NULL ) {
|
||||
mt_entry->writeable = options == RTEMS_FILESYSTEM_READ_WRITE;
|
||||
|
||||
/*
|
||||
* Allocate a mount table entry
|
||||
*/
|
||||
mt_entry = alloc_mount_table_entry(
|
||||
source,
|
||||
target,
|
||||
filesystemtype,
|
||||
&target_length
|
||||
);
|
||||
if ( !mt_entry )
|
||||
rtems_set_errno_and_return_minus_one( ENOMEM );
|
||||
rv = (*fsmount_me_h)( mt_entry, data );
|
||||
if ( rv == 0 ) {
|
||||
if ( target != NULL ) {
|
||||
rv = register_subordinate_file_system( mt_entry, target );
|
||||
} else {
|
||||
rv = register_root_file_system( mt_entry );
|
||||
}
|
||||
|
||||
mt_entry->mt_fs_root.mt_entry = mt_entry;
|
||||
mt_entry->options = options;
|
||||
mt_entry->pathconf_limits_and_options = rtems_filesystem_default_pathconf;
|
||||
if ( rv != 0 ) {
|
||||
(*mt_entry->mt_fs_root->location.ops->fsunmount_me_h)( mt_entry );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The mount_point should be a directory with read/write/execute
|
||||
* permissions in the existing tree.
|
||||
*/
|
||||
|
||||
if ( has_target ) {
|
||||
if ( rtems_filesystem_evaluate_path(
|
||||
target, target_length, RTEMS_LIBIO_PERMS_RWX, &loc, true ) == -1 )
|
||||
goto cleanup_and_bail;
|
||||
|
||||
loc_to_free = &loc;
|
||||
|
||||
/*
|
||||
* Test to see if it is a directory
|
||||
*/
|
||||
|
||||
if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
|
||||
errno = ENOTDIR;
|
||||
goto cleanup_and_bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* You can only mount one file system onto a single mount point.
|
||||
*/
|
||||
|
||||
if ( rtems_filesystem_mount_iterate( is_node_fs_root, loc.node_access ) ) {
|
||||
errno = EBUSY;
|
||||
goto cleanup_and_bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* This must be a good mount point, so move the location information
|
||||
* into the allocated mount entry. Note: the information that
|
||||
* may have been allocated in loc should not be sent to freenode
|
||||
* until the system is unmounted. It may be needed to correctly
|
||||
* traverse the tree.
|
||||
*/
|
||||
|
||||
mt_entry->mt_point_node.node_access = loc.node_access;
|
||||
mt_entry->mt_point_node.handlers = loc.handlers;
|
||||
mt_entry->mt_point_node.ops = loc.ops;
|
||||
mt_entry->mt_point_node.mt_entry = loc.mt_entry;
|
||||
|
||||
/*
|
||||
* This link to the parent is only done when we are dealing with system
|
||||
* below the base file system
|
||||
*/
|
||||
|
||||
if ( loc.ops->mount_h( mt_entry ) ) {
|
||||
goto cleanup_and_bail;
|
||||
if ( rv != 0 ) {
|
||||
free( mt_entry );
|
||||
}
|
||||
} else {
|
||||
errno = ENOMEM;
|
||||
rv = -1;
|
||||
}
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
rv = -1;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Do we already have a base file system ?
|
||||
*/
|
||||
if ( !rtems_chain_is_empty( &mount_chain ) ) {
|
||||
errno = EINVAL;
|
||||
goto cleanup_and_bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a mount of the base file system --> The
|
||||
* mt_point_node.node_access will be left to null to indicate that this
|
||||
* is the root of the entire file system.
|
||||
*/
|
||||
errno = EINVAL;
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
if ( (*mount_h)( mt_entry, data ) ) {
|
||||
/*
|
||||
* Try to undo the mount operation
|
||||
*/
|
||||
loc.ops->unmount_h( mt_entry );
|
||||
goto cleanup_and_bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the mount table entry to the mount table chain
|
||||
*/
|
||||
rtems_libio_lock();
|
||||
rtems_chain_append( &mount_chain, &mt_entry->Node );
|
||||
rtems_libio_unlock();
|
||||
|
||||
if ( !has_target )
|
||||
rtems_filesystem_root = mt_entry->mt_fs_root;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_and_bail:
|
||||
|
||||
free( mt_entry );
|
||||
|
||||
if ( loc_to_free )
|
||||
rtems_filesystem_freenode( loc_to_free );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool rtems_filesystem_mount_iterate(
|
||||
rtems_per_filesystem_mount_routine routine,
|
||||
void *routine_arg
|
||||
)
|
||||
{
|
||||
rtems_chain_node *node = NULL;
|
||||
bool stop = false;
|
||||
|
||||
rtems_libio_lock();
|
||||
for (
|
||||
node = rtems_chain_first( &mount_chain );
|
||||
!rtems_chain_is_tail( &mount_chain, node ) && !stop;
|
||||
node = rtems_chain_next( node )
|
||||
) {
|
||||
const rtems_filesystem_mount_table_entry_t *mt_entry =
|
||||
(rtems_filesystem_mount_table_entry_t *) node;
|
||||
|
||||
stop = (*routine)( mt_entry, routine_arg );
|
||||
}
|
||||
rtems_libio_unlock();
|
||||
|
||||
return stop;
|
||||
return rv;
|
||||
}
|
||||
|
||||
+117
-164
@@ -4,6 +4,9 @@
|
||||
* COPYRIGHT (c) 1989-2010.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (c) 2012 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
@@ -12,185 +15,135 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Returns file descriptor on success or -1 and errno set to one of the
|
||||
* following:
|
||||
*
|
||||
* EACCESS - Seach permission is denied on a component of the path prefix,
|
||||
* or the file exists and the permissions specified by the
|
||||
* flags are denied, or the file does not exist and write
|
||||
* permission is denied for the parent directory of the file
|
||||
* to be created, or O_TRUNC is specified and write permission
|
||||
* is denied.
|
||||
* EEXIST - O_CREAT and O_EXCL are set and the named file exists.
|
||||
* EINTR - The open( operation was interrupted by a signal.
|
||||
* EINVAL - This implementation does not support synchronized IO for this
|
||||
* file.
|
||||
* EISDIR - The named file is a directory and the flags argument
|
||||
* specified write or read/write access.
|
||||
* EMFILE - Too many file descriptors are in used by this process.
|
||||
* ENAMETOOLONG -
|
||||
* The length of the path exceeds PATH_MAX or a pathname
|
||||
* component is longer than NAME_MAX while POSIX_NO_TRUNC
|
||||
* is in effect.
|
||||
* ENFILE - Too many files are open in the system.
|
||||
* ENOENT - O_CREAT is not set and and the anmed file does not exist,
|
||||
* or O_CREAT is set and either the path prefix does not exist
|
||||
* or the path argument points to an empty string.
|
||||
* ENOSPC - The directory or file system that would contain the new file
|
||||
* cannot be extended.
|
||||
* ENOTDIR - A component of the path prefix is not a directory.
|
||||
* ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
|
||||
* set, and no process has the file open for reading.
|
||||
* EROFS - The named file resides on a read-only file system and either
|
||||
* O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
|
||||
* O_TRUNC is set in the flags argument.
|
||||
*/
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
int open(
|
||||
const char *pathname,
|
||||
int flags,
|
||||
...
|
||||
static void create_regular_file(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
mode_t mode
|
||||
)
|
||||
{
|
||||
va_list ap;
|
||||
mode_t mode;
|
||||
int rc;
|
||||
rtems_libio_t *iop = 0;
|
||||
int status;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
rtems_filesystem_location_info_t *loc_to_free = NULL;
|
||||
int eval_flags;
|
||||
int rv = 0;
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_get_currentloc( ctx );
|
||||
const char *token = rtems_filesystem_eval_path_get_token( ctx );
|
||||
size_t tokenlen = rtems_filesystem_eval_path_get_tokenlen( ctx );
|
||||
|
||||
/*
|
||||
* Set the Evaluation flags
|
||||
*/
|
||||
eval_flags = 0;
|
||||
status = flags + 1;
|
||||
if ( ( status & _FREAD ) == _FREAD )
|
||||
eval_flags |= RTEMS_LIBIO_PERMS_READ;
|
||||
if ( ( status & _FWRITE ) == _FWRITE )
|
||||
eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
|
||||
rv = rtems_filesystem_mknod(
|
||||
currentloc,
|
||||
token,
|
||||
tokenlen,
|
||||
S_IFREG | mode,
|
||||
0
|
||||
);
|
||||
|
||||
va_start(ap, flags);
|
||||
if ( rv == 0 ) {
|
||||
/* The mode only applies to future accesses of the newly created file */
|
||||
rtems_filesystem_eval_path_set_flags( ctx, 0 );
|
||||
|
||||
rtems_filesystem_eval_path_set_path( ctx, token, tokenlen );
|
||||
rtems_filesystem_eval_path_continue( ctx );
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error( ctx, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
static int do_open(
|
||||
rtems_libio_t *iop,
|
||||
const char *path,
|
||||
int oflag,
|
||||
mode_t mode
|
||||
)
|
||||
{
|
||||
int rv = 0;
|
||||
int fd = iop - rtems_libio_iops;
|
||||
int rwflag = oflag + 1;
|
||||
bool read_access = (rwflag & _FREAD) == _FREAD;
|
||||
bool write_access = (rwflag & _FWRITE) == _FWRITE;
|
||||
bool make = (oflag & O_CREAT) == O_CREAT;
|
||||
bool exclusive = (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
|
||||
bool truncate = (oflag & O_TRUNC) == O_TRUNC;
|
||||
int eval_flags = RTEMS_LIBIO_FOLLOW_LINK
|
||||
| (read_access ? RTEMS_LIBIO_PERMS_READ : 0)
|
||||
| (write_access ? RTEMS_LIBIO_PERMS_WRITE : 0)
|
||||
| (make ? RTEMS_LIBIO_MAKE : 0)
|
||||
| (exclusive ? RTEMS_LIBIO_EXCLUSIVE : 0);
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
|
||||
rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
|
||||
|
||||
if ( rtems_filesystem_eval_path_has_token( &ctx ) ) {
|
||||
create_regular_file( &ctx, mode );
|
||||
}
|
||||
|
||||
if ( write_access ) {
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_get_currentloc( &ctx );
|
||||
rtems_filesystem_node_types_t type =
|
||||
(*currentloc->ops->node_type_h)( currentloc );
|
||||
|
||||
if ( type == RTEMS_FILESYSTEM_DIRECTORY ) {
|
||||
rtems_filesystem_eval_path_error( &ctx, EISDIR );
|
||||
}
|
||||
}
|
||||
|
||||
iop->flags |= rtems_libio_fcntl_flags( oflag );
|
||||
rtems_filesystem_eval_path_extract_currentloc( &ctx, &iop->pathinfo );
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
rv = (*iop->pathinfo.handlers->open_h)( iop, path, oflag, mode );
|
||||
|
||||
if ( rv == 0 ) {
|
||||
if ( truncate ) {
|
||||
rv = ftruncate( fd, 0 );
|
||||
if ( rv != 0 ) {
|
||||
(*iop->pathinfo.handlers->close_h)( iop );
|
||||
}
|
||||
}
|
||||
|
||||
if ( rv == 0 ) {
|
||||
rv = fd;
|
||||
} else {
|
||||
rv = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( rv < 0 ) {
|
||||
rtems_libio_free( iop );
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int open( const char *path, int oflag, ... )
|
||||
{
|
||||
int rv = 0;
|
||||
va_list ap;
|
||||
mode_t mode = 0;
|
||||
rtems_libio_t *iop = NULL;
|
||||
|
||||
va_start( ap, oflag );
|
||||
|
||||
mode = va_arg( ap, mode_t );
|
||||
|
||||
/*
|
||||
* NOTE: This comment is OBSOLETE. The proper way to do this now
|
||||
* would be to support a magic mounted file system.
|
||||
*
|
||||
* Additional external I/O handlers would be supported by adding
|
||||
* code to pick apart the pathname appropriately. The networking
|
||||
* code does not require changes here since network file
|
||||
* descriptors are obtained using socket(), not open().
|
||||
*/
|
||||
|
||||
/* allocate a file control block */
|
||||
iop = rtems_libio_allocate();
|
||||
if ( iop == 0 ) {
|
||||
rc = ENFILE;
|
||||
goto done;
|
||||
if ( iop != NULL ) {
|
||||
rv = do_open( iop, path, oflag, mode );
|
||||
} else {
|
||||
errno = ENFILE;
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the file exists.
|
||||
*/
|
||||
status = rtems_filesystem_evaluate_path(
|
||||
pathname, strlen( pathname ), eval_flags, &loc, true );
|
||||
va_end( ap );
|
||||
|
||||
if ( status == -1 ) {
|
||||
if ( errno != ENOENT ) {
|
||||
rc = errno;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* If the file does not exist and we are not trying to create it--> error */
|
||||
if ( !(flags & O_CREAT) ) {
|
||||
rc = ENOENT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create the node for the new regular file */
|
||||
rc = mknod( pathname, S_IFREG | mode, 0LL );
|
||||
if ( rc ) {
|
||||
rc = errno;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* After we do the mknod(), we have to evaluate the path to get the
|
||||
* "loc" structure needed to actually have the file itself open.
|
||||
* So we created it, and then we need to have "look it up."
|
||||
*/
|
||||
status = rtems_filesystem_evaluate_path(
|
||||
pathname, strlen( pathname ), 0x0, &loc, true );
|
||||
if ( status != 0 ) { /* The file did not exist */
|
||||
rc = EACCES;
|
||||
goto done;
|
||||
}
|
||||
|
||||
} else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
|
||||
/* We were trying to create a file that already exists */
|
||||
rc = EEXIST;
|
||||
loc_to_free = &loc;
|
||||
goto done;
|
||||
}
|
||||
|
||||
loc_to_free = &loc;
|
||||
|
||||
/*
|
||||
* Fill in the file control block based on the loc structure
|
||||
* returned by successful path evaluation.
|
||||
*/
|
||||
iop->flags |= rtems_libio_fcntl_flags( flags );
|
||||
iop->pathinfo = loc;
|
||||
|
||||
rc = (*iop->pathinfo.handlers->open_h)( iop, pathname, flags, mode );
|
||||
if ( rc ) {
|
||||
rc = errno;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionally truncate the file.
|
||||
*/
|
||||
if ( (flags & O_TRUNC) == O_TRUNC ) {
|
||||
rc = ftruncate( iop - rtems_libio_iops, 0 );
|
||||
if ( rc ) {
|
||||
if(errno) rc = errno;
|
||||
close( iop - rtems_libio_iops );
|
||||
/* those are released by close(): */
|
||||
iop = 0;
|
||||
loc_to_free = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Single exit and clean up path.
|
||||
*/
|
||||
done:
|
||||
va_end(ap);
|
||||
|
||||
if ( rc ) {
|
||||
if ( iop )
|
||||
rtems_libio_free( iop );
|
||||
if ( loc_to_free )
|
||||
rtems_filesystem_freenode( loc_to_free );
|
||||
rtems_set_errno_and_return_minus_one( rc );
|
||||
}
|
||||
|
||||
return iop - rtems_libio_iops;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -206,10 +159,10 @@ done:
|
||||
int _open_r(
|
||||
struct _reent *ptr __attribute__((unused)),
|
||||
const char *buf,
|
||||
int flags,
|
||||
int oflag,
|
||||
int mode
|
||||
)
|
||||
{
|
||||
return open( buf, flags, mode );
|
||||
return open( buf, oflag, mode );
|
||||
}
|
||||
#endif
|
||||
|
||||
+120
-157
@@ -1,3 +1,9 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup LibIOEnv
|
||||
*/
|
||||
|
||||
/*
|
||||
* Instantiate a private user environment for the calling thread.
|
||||
*
|
||||
@@ -14,191 +20,148 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* free */
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/chain.h>
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
/* cleanup a user environment
|
||||
* NOTE: this must be called with
|
||||
* thread dispatching disabled!
|
||||
*/
|
||||
static void
|
||||
free_user_env(void *venv)
|
||||
static void free_user_env(void *arg)
|
||||
{
|
||||
rtems_user_env_t *env = (rtems_user_env_t*) venv ;
|
||||
rtems_user_env_t *env = arg;
|
||||
bool uses_global_env = env == &rtems_global_user_env;
|
||||
|
||||
if (env != &rtems_global_user_env
|
||||
#ifdef HAVE_USERENV_REFCNT
|
||||
&& --env->refcnt <= 0
|
||||
#endif
|
||||
) {
|
||||
rtems_filesystem_freenode( &env->current_directory);
|
||||
rtems_filesystem_freenode( &env->root_directory);
|
||||
free(env);
|
||||
if (!uses_global_env) {
|
||||
if (env->reference_count == 1) {
|
||||
rtems_filesystem_global_location_release(env->current_directory);
|
||||
rtems_filesystem_global_location_release(env->root_directory);
|
||||
free(env);
|
||||
} else {
|
||||
--env->reference_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void free_user_env_protected(rtems_user_env_t *env)
|
||||
{
|
||||
_Thread_Disable_dispatch();
|
||||
free_user_env(env);
|
||||
_Thread_Enable_dispatch();
|
||||
}
|
||||
|
||||
rtems_status_code rtems_libio_set_private_env(void)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
rtems_id task_id = rtems_task_self();
|
||||
rtems_filesystem_location_info_t root_loc;
|
||||
rtems_filesystem_location_info_t current_loc;
|
||||
rtems_user_env_t *new_env = NULL;
|
||||
int rv = 0;
|
||||
rtems_id self_task_id = rtems_task_self();
|
||||
rtems_user_env_t *old_env = rtems_current_user_env;
|
||||
bool uses_global_env = old_env == &rtems_global_user_env;
|
||||
bool uses_shared_env = old_env->task_id != self_task_id;
|
||||
|
||||
rv = rtems_filesystem_evaluate_path("/", 1, 0, &root_loc, 0);
|
||||
if (rv != 0)
|
||||
goto error_0;
|
||||
if (uses_global_env || uses_shared_env) {
|
||||
rtems_user_env_t *new_env = calloc(1, sizeof(*new_env));
|
||||
|
||||
rv = rtems_filesystem_evaluate_path("/", 1, 0, ¤t_loc, 0);
|
||||
if (rv != 0)
|
||||
goto error_1;
|
||||
if (new_env != NULL) {
|
||||
*new_env = *old_env;
|
||||
new_env->reference_count = 1;
|
||||
new_env->task_id = self_task_id;
|
||||
new_env->root_directory =
|
||||
rtems_filesystem_global_location_obtain(&old_env->root_directory);
|
||||
new_env->current_directory =
|
||||
rtems_filesystem_global_location_obtain(&old_env->current_directory);
|
||||
|
||||
/*
|
||||
* Malloc is necessary whenever the current task does not
|
||||
* have its own environment in place. This could be:
|
||||
* a) it never had one
|
||||
* OR
|
||||
* b) it shared another task's environment
|
||||
*/
|
||||
if (
|
||||
!rtems_filesystem_global_location_is_null(new_env->root_directory)
|
||||
&& !rtems_filesystem_global_location_is_null(new_env->current_directory)
|
||||
) {
|
||||
sc = rtems_task_variable_add(
|
||||
RTEMS_SELF,
|
||||
(void **) &rtems_current_user_env,
|
||||
free_user_env
|
||||
);
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
free_user_env_protected(old_env);
|
||||
rtems_current_user_env = new_env;
|
||||
} else {
|
||||
sc = RTEMS_TOO_MANY;
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_UNSATISFIED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bharath: I'm not sure if the check can be reduced to
|
||||
* if( rtems_current_user_env->task_id != task_id ) {
|
||||
*/
|
||||
|
||||
if (
|
||||
rtems_current_user_env == &rtems_global_user_env
|
||||
|| rtems_current_user_env->task_id != task_id
|
||||
) {
|
||||
new_env = malloc(sizeof(rtems_user_env_t));
|
||||
if (new_env == NULL)
|
||||
goto error_2;
|
||||
|
||||
#ifdef HAVE_USERENV_REFCNT
|
||||
new_env->refcnt = 1;
|
||||
#endif
|
||||
|
||||
sc = rtems_task_variable_add(
|
||||
RTEMS_SELF,
|
||||
(void*)&rtems_current_user_env,
|
||||
(void(*)(void *))free_user_env
|
||||
);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
goto error_3;
|
||||
|
||||
rtems_current_user_env = new_env;
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
free_user_env(new_env);
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Inherit the global values */
|
||||
*rtems_current_user_env = rtems_global_user_env;
|
||||
|
||||
rtems_current_user_env->task_id = task_id;
|
||||
|
||||
/*
|
||||
* Clone the pathlocs. In contrast to most other code we must _not_ free the
|
||||
* original locs because what we are trying to do here is forking off clones.
|
||||
* The reason is a pathloc can be allocated by the file system and needs to
|
||||
* be freed when deleting the environment.
|
||||
*/
|
||||
rtems_filesystem_root = root_loc;
|
||||
rtems_filesystem_current = current_loc;
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
|
||||
error_3:
|
||||
free(new_env);
|
||||
|
||||
error_2:
|
||||
rtems_filesystem_freenode(¤t_loc);
|
||||
|
||||
error_1:
|
||||
rtems_filesystem_freenode(&root_loc);
|
||||
|
||||
error_0:
|
||||
return RTEMS_NO_MEMORY;
|
||||
return sc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Share the same private environment between two tasks:
|
||||
* Task_id (remote) and RTEMS_SELF(current).
|
||||
*/
|
||||
|
||||
/* NOTE:
|
||||
*
|
||||
* THIS CODE HAS NO PROTECTION IMPLEMENTED
|
||||
*
|
||||
* Tasks who wish to share their environments must
|
||||
*
|
||||
* a) assert that no participants are concurrently
|
||||
* executing
|
||||
* libio_share_private_env() and/or libio_set_private_env()
|
||||
*
|
||||
* b) mutex access to rtems_filesystem_current, rtems_filesytem_root
|
||||
* while changing any of those (chdir(), chroot()).
|
||||
*/
|
||||
|
||||
rtems_status_code rtems_libio_share_private_env(rtems_id task_id)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
rtems_user_env_t * shared_user_env;
|
||||
rtems_id current_task_id;
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
rtems_id self_task_id = rtems_task_self();
|
||||
|
||||
/*
|
||||
* get current task id
|
||||
*/
|
||||
current_task_id = rtems_task_self();
|
||||
|
||||
/*
|
||||
* If this was an attempt to share the task with self,
|
||||
* if somebody wanted to do it... Lets tell them, its shared
|
||||
*/
|
||||
|
||||
if( task_id == current_task_id )
|
||||
return RTEMS_SUCCESSFUL;
|
||||
/*
|
||||
* Try to get the requested user environment
|
||||
*/
|
||||
sc = rtems_task_variable_get(
|
||||
task_id,
|
||||
(void*)&rtems_current_user_env,
|
||||
(void*)&shared_user_env );
|
||||
|
||||
/*
|
||||
* If it was not successful, return the error code
|
||||
*/
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
return sc;
|
||||
|
||||
/*
|
||||
* If we are here, we have the required environment to be
|
||||
* shared with the current task
|
||||
*/
|
||||
if (task_id != RTEMS_SELF && self_task_id != task_id) {
|
||||
rtems_user_env_t *env;
|
||||
|
||||
/*
|
||||
* If we have a current environment in place, we need to
|
||||
* free it, since we will be sharing the variable with the
|
||||
* shared_user_env
|
||||
* We have to disable the thread dispatching to prevent deletion of the
|
||||
* environment in the meantime.
|
||||
*/
|
||||
_Thread_Disable_dispatch();
|
||||
sc = rtems_task_variable_get(
|
||||
task_id,
|
||||
(void *) &rtems_current_user_env,
|
||||
(void *) &env
|
||||
);
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
++env->reference_count;
|
||||
} else {
|
||||
sc = RTEMS_UNSATISFIED;
|
||||
}
|
||||
_Thread_Enable_dispatch();
|
||||
|
||||
if (rtems_current_user_env->task_id==current_task_id) {
|
||||
rtems_user_env_t *tmp = rtems_current_user_env;
|
||||
free_user_env( tmp );
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
sc = rtems_task_variable_add(
|
||||
RTEMS_SELF,
|
||||
(void **) &rtems_current_user_env,
|
||||
free_user_env
|
||||
);
|
||||
if (sc == RTEMS_SUCCESSFUL) {
|
||||
free_user_env_protected(rtems_current_user_env);
|
||||
rtems_current_user_env = env;
|
||||
} else {
|
||||
free_user_env_protected(env);
|
||||
sc = RTEMS_TOO_MANY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* the current_user_env is the same pointer that remote env */
|
||||
rtems_current_user_env = shared_user_env;
|
||||
|
||||
/* increase the reference count */
|
||||
#ifdef HAVE_USERENV_REFCNT
|
||||
rtems_current_user_env->refcnt++;
|
||||
#endif
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
return sc;
|
||||
}
|
||||
|
||||
void rtems_libio_use_global_env(void)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
rtems_user_env_t *env = rtems_current_user_env;
|
||||
bool uses_private_env = env != &rtems_global_user_env;
|
||||
|
||||
if (uses_private_env) {
|
||||
sc = rtems_task_variable_delete(
|
||||
RTEMS_SELF,
|
||||
(void **) &rtems_current_user_env
|
||||
);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
rtems_fatal_error_occurred(0xdeadbeef);
|
||||
}
|
||||
|
||||
rtems_current_user_env = &rtems_global_user_env;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,37 +12,31 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
ssize_t readlink(
|
||||
const char *pathname,
|
||||
char *buf,
|
||||
size_t bufsize
|
||||
)
|
||||
ssize_t readlink( const char *path, char *buf, size_t bufsize )
|
||||
{
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int result;
|
||||
ssize_t rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_FOLLOW_HARD_LINK;
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
|
||||
rtems_filesystem_node_types_t type =
|
||||
(*currentloc->ops->node_type_h)( currentloc );
|
||||
|
||||
if (!buf)
|
||||
rtems_set_errno_and_return_minus_one( EFAULT );
|
||||
|
||||
result = rtems_filesystem_evaluate_path( pathname, strlen( pathname ),
|
||||
0, &loc, false );
|
||||
if ( result != 0 )
|
||||
return -1;
|
||||
|
||||
if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK ){
|
||||
rtems_filesystem_freenode( &loc );
|
||||
rtems_set_errno_and_return_minus_one( EINVAL );
|
||||
if ( type == RTEMS_FILESYSTEM_SYM_LINK ) {
|
||||
rv = (*currentloc->ops->readlink_h)( currentloc, buf, bufsize );
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error( &ctx, EINVAL );
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
result = (*loc.ops->readlink_h)( &loc, buf, bufsize );
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
rtems_filesystem_freenode( &loc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -12,84 +12,44 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int rmdir(
|
||||
const char *pathname
|
||||
)
|
||||
int rmdir( const char *path )
|
||||
{
|
||||
int parentpathlen;
|
||||
const char *name;
|
||||
rtems_filesystem_location_info_t parentloc;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int i;
|
||||
int result;
|
||||
bool free_parentloc = false;
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_REJECT_TERMINAL_DOT;
|
||||
rtems_filesystem_location_info_t parentloc;
|
||||
int parent_eval_flags = RTEMS_LIBIO_PERMS_WRITE
|
||||
| RTEMS_LIBIO_PERMS_SEARCH
|
||||
| RTEMS_LIBIO_FOLLOW_LINK;
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start_with_parent(
|
||||
&ctx,
|
||||
path,
|
||||
eval_flags,
|
||||
&parentloc,
|
||||
parent_eval_flags
|
||||
);
|
||||
rtems_filesystem_node_types_t type =
|
||||
(*currentloc->ops->node_type_h)( currentloc );
|
||||
|
||||
/*
|
||||
* Get the parent node of the node we wish to remove. Find the parent path.
|
||||
*/
|
||||
|
||||
parentpathlen = rtems_filesystem_dirname ( pathname );
|
||||
|
||||
if ( parentpathlen == 0 )
|
||||
rtems_filesystem_get_start_loc( pathname, &i, &parentloc );
|
||||
else {
|
||||
result = rtems_filesystem_evaluate_path(pathname, parentpathlen,
|
||||
RTEMS_LIBIO_PERMS_WRITE,
|
||||
&parentloc,
|
||||
false );
|
||||
if ( result != 0 )
|
||||
return -1;
|
||||
|
||||
free_parentloc = true;
|
||||
if ( type == RTEMS_FILESYSTEM_DIRECTORY ) {
|
||||
rv = (*currentloc->ops->rmnod_h)(
|
||||
&parentloc,
|
||||
currentloc
|
||||
);
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error( &ctx, ENOTDIR );
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start from the parent to find the node that should be under it.
|
||||
*/
|
||||
rtems_filesystem_eval_path_cleanup_with_parent( &ctx, &parentloc );
|
||||
|
||||
loc = parentloc;
|
||||
name = pathname + parentpathlen;
|
||||
name += rtems_filesystem_prefix_separators( name, strlen( name ) );
|
||||
|
||||
result = rtems_filesystem_evaluate_relative_path( name , strlen( name ),
|
||||
0, &loc, false );
|
||||
if ( result != 0 ) {
|
||||
if ( free_parentloc )
|
||||
rtems_filesystem_freenode( &parentloc );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify you can remove this node as a directory.
|
||||
*/
|
||||
if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
|
||||
rtems_filesystem_freenode( &loc );
|
||||
if ( free_parentloc )
|
||||
rtems_filesystem_freenode( &parentloc );
|
||||
rtems_set_errno_and_return_minus_one( ENOTDIR );
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the filesystems rmnod to remove the node.
|
||||
*/
|
||||
|
||||
result = (*loc.handlers->rmnod_h)( &parentloc, &loc );
|
||||
|
||||
rtems_filesystem_freenode( &loc );
|
||||
if ( free_parentloc )
|
||||
rtems_filesystem_freenode( &parentloc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -25,55 +25,29 @@
|
||||
#ifndef _STAT_NAME
|
||||
#define _STAT_NAME stat
|
||||
#define _STAT_R_NAME _stat_r
|
||||
#define _STAT_FOLLOW_LINKS true
|
||||
#define _STAT_FOLLOW_LINKS RTEMS_LIBIO_FOLLOW_LINK
|
||||
#endif
|
||||
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include <rtems/libio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int _STAT_NAME(
|
||||
const char *path,
|
||||
struct stat *buf
|
||||
)
|
||||
int _STAT_NAME( const char *path, struct stat *buf )
|
||||
{
|
||||
int status;
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = _STAT_FOLLOW_LINKS;
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
|
||||
|
||||
/*
|
||||
* Check to see if we were passed a valid pointer.
|
||||
*/
|
||||
memset( buf, 0, sizeof( *buf ) );
|
||||
|
||||
if ( !buf )
|
||||
rtems_set_errno_and_return_minus_one( EFAULT );
|
||||
rv = (*currentloc->handlers->fstat_h)( currentloc, buf );
|
||||
|
||||
status = rtems_filesystem_evaluate_path( path, strlen( path ),
|
||||
0, &loc, _STAT_FOLLOW_LINKS );
|
||||
if ( status != 0 )
|
||||
return -1;
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
/*
|
||||
* Zero out the stat structure so the various support
|
||||
* versions of stat don't have to.
|
||||
*/
|
||||
|
||||
memset( buf, 0, sizeof(struct stat) );
|
||||
|
||||
status = (*loc.handlers->fstat_h)( &loc, buf );
|
||||
|
||||
rtems_filesystem_freenode( &loc );
|
||||
|
||||
return status;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -13,40 +13,27 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
statvfs (const char *path, struct statvfs *sb)
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
int statvfs( const char *path, struct statvfs *buf )
|
||||
{
|
||||
rtems_filesystem_location_info_t loc;
|
||||
rtems_filesystem_location_info_t *fs_mount_root;
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry;
|
||||
int result;
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_FOLLOW_LINK;
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
|
||||
|
||||
/*
|
||||
* Get
|
||||
* The root node of the mounted filesytem.
|
||||
* The node for the directory that the fileystem is mounted on.
|
||||
* The mount entry that is being refered to.
|
||||
*/
|
||||
memset( buf, 0, sizeof( *buf ) );
|
||||
|
||||
if ( rtems_filesystem_evaluate_path( path, strlen( path ), 0x0, &loc, true ) )
|
||||
return -1;
|
||||
rv = (*currentloc->ops->statvfs_h)( currentloc, buf );
|
||||
|
||||
mt_entry = loc.mt_entry;
|
||||
fs_mount_root = &mt_entry->mt_fs_root;
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
memset (sb, 0, sizeof (struct statvfs));
|
||||
|
||||
result = ( fs_mount_root->ops->statvfs_h )( fs_mount_root, sb );
|
||||
|
||||
rtems_filesystem_freenode( &loc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
bool rtems_filesystem_check_access(
|
||||
int eval_flags,
|
||||
mode_t node_mode,
|
||||
uid_t node_uid,
|
||||
gid_t node_gid
|
||||
)
|
||||
{
|
||||
mode_t perm_flags = eval_flags & RTEMS_LIBIO_PERMS_RWX;
|
||||
uid_t task_uid = geteuid();
|
||||
|
||||
if (task_uid == 0 || task_uid == node_uid) {
|
||||
perm_flags <<= 6;
|
||||
} else {
|
||||
gid_t task_gid = getegid();
|
||||
|
||||
if (task_gid == 0 || task_gid == node_gid) {
|
||||
perm_flags <<= 3;
|
||||
} else {
|
||||
perm_flags <<= 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (perm_flags & node_mode) == perm_flags;
|
||||
}
|
||||
|
||||
bool rtems_filesystem_eval_path_check_access(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
int eval_flags,
|
||||
mode_t node_mode,
|
||||
uid_t node_uid,
|
||||
gid_t node_gid
|
||||
)
|
||||
{
|
||||
bool access_ok = rtems_filesystem_check_access(
|
||||
eval_flags,
|
||||
node_mode,
|
||||
node_uid,
|
||||
node_gid
|
||||
);
|
||||
|
||||
if (!access_ok) {
|
||||
rtems_filesystem_eval_path_error(ctx, EACCES);
|
||||
}
|
||||
|
||||
return access_ok;
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
static size_t get_parentpathlen(const char *path, size_t pathlen)
|
||||
{
|
||||
while (pathlen > 0) {
|
||||
size_t i = pathlen - 1;
|
||||
|
||||
if (rtems_filesystem_is_delimiter(path [i])) {
|
||||
return pathlen;
|
||||
}
|
||||
|
||||
pathlen = i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_startloc(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
rtems_filesystem_global_location_t *const *global_root_ptr,
|
||||
rtems_filesystem_global_location_t *const *global_current_ptr
|
||||
)
|
||||
{
|
||||
if (ctx->pathlen > 0) {
|
||||
char c = ctx->path [0];
|
||||
|
||||
ctx->rootloc = rtems_filesystem_global_location_obtain(global_root_ptr);
|
||||
|
||||
if (rtems_filesystem_is_delimiter(c)) {
|
||||
++ctx->path;
|
||||
--ctx->pathlen;
|
||||
ctx->startloc = rtems_filesystem_global_location_obtain(
|
||||
&ctx->rootloc
|
||||
);
|
||||
} else {
|
||||
ctx->startloc = rtems_filesystem_global_location_obtain(
|
||||
global_current_ptr
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ctx->rootloc = rtems_filesystem_global_location_obtain_null();
|
||||
ctx->startloc = rtems_filesystem_global_location_obtain_null();
|
||||
errno = ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
static void check_access(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
int eval_flags
|
||||
)
|
||||
{
|
||||
const rtems_filesystem_location_info_t *currentloc = &ctx->currentloc;
|
||||
struct stat st;
|
||||
int rv;
|
||||
|
||||
st.st_mode = 0;
|
||||
st.st_uid = 0;
|
||||
st.st_gid = 0;
|
||||
rv = (*currentloc->handlers->fstat_h)(currentloc, &st);
|
||||
if (rv == 0) {
|
||||
bool access_ok = rtems_filesystem_check_access(
|
||||
eval_flags,
|
||||
st.st_mode,
|
||||
st.st_uid,
|
||||
st.st_gid
|
||||
);
|
||||
|
||||
if (!access_ok) {
|
||||
rtems_filesystem_eval_path_error(ctx, EACCES);
|
||||
}
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(ctx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void rtems_filesystem_eval_path_continue(
|
||||
rtems_filesystem_eval_path_context_t *ctx
|
||||
)
|
||||
{
|
||||
int eval_flags;
|
||||
|
||||
while (ctx->pathlen > 0) {
|
||||
(*ctx->currentloc.ops->eval_path_h)(ctx);
|
||||
}
|
||||
|
||||
eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
|
||||
if (rtems_filesystem_eval_path_has_token(ctx)) {
|
||||
bool make = (eval_flags & RTEMS_LIBIO_MAKE) != 0;
|
||||
|
||||
if (make) {
|
||||
check_access(ctx, RTEMS_LIBIO_PERMS_WRITE);
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(ctx, ENOENT);
|
||||
}
|
||||
} else {
|
||||
bool exclusive = (eval_flags & RTEMS_LIBIO_EXCLUSIVE) != 0;
|
||||
|
||||
if (!exclusive) {
|
||||
check_access(ctx, ctx->flags);
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(ctx, EEXIST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static rtems_filesystem_location_info_t *
|
||||
eval_path_start(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
const char *path,
|
||||
size_t pathlen,
|
||||
int eval_flags,
|
||||
rtems_filesystem_global_location_t *const *global_root_ptr,
|
||||
rtems_filesystem_global_location_t *const *global_current_ptr
|
||||
)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->path = path;
|
||||
ctx->pathlen = pathlen;
|
||||
ctx->flags = eval_flags;
|
||||
|
||||
set_startloc(ctx, global_root_ptr, global_current_ptr);
|
||||
|
||||
rtems_filesystem_instance_lock(&ctx->startloc->location);
|
||||
|
||||
rtems_filesystem_location_clone(
|
||||
&ctx->currentloc,
|
||||
&ctx->startloc->location
|
||||
);
|
||||
|
||||
rtems_filesystem_eval_path_continue(ctx);
|
||||
|
||||
return &ctx->currentloc;
|
||||
}
|
||||
|
||||
rtems_filesystem_location_info_t *
|
||||
rtems_filesystem_eval_path_start_with_root_and_current(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
const char *path,
|
||||
int eval_flags,
|
||||
rtems_filesystem_global_location_t *const *global_root_ptr,
|
||||
rtems_filesystem_global_location_t *const *global_current_ptr
|
||||
)
|
||||
{
|
||||
return eval_path_start(
|
||||
ctx,
|
||||
path,
|
||||
strlen(path),
|
||||
eval_flags,
|
||||
global_root_ptr,
|
||||
global_current_ptr
|
||||
);
|
||||
}
|
||||
|
||||
rtems_filesystem_location_info_t *
|
||||
rtems_filesystem_eval_path_start(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
const char *path,
|
||||
int eval_flags
|
||||
)
|
||||
{
|
||||
return rtems_filesystem_eval_path_start_with_root_and_current(
|
||||
ctx,
|
||||
path,
|
||||
eval_flags,
|
||||
&rtems_filesystem_root,
|
||||
&rtems_filesystem_current
|
||||
);
|
||||
}
|
||||
|
||||
rtems_filesystem_location_info_t *
|
||||
rtems_filesystem_eval_path_start_with_parent(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
const char *path,
|
||||
int eval_flags,
|
||||
rtems_filesystem_location_info_t *parentloc,
|
||||
int parent_eval_flags
|
||||
)
|
||||
{
|
||||
size_t pathlen = strlen(path);
|
||||
const char *parentpath = path;
|
||||
size_t parentpathlen = get_parentpathlen(path, pathlen);
|
||||
const char *name = NULL;
|
||||
size_t namelen = 0;
|
||||
const rtems_filesystem_location_info_t *currentloc = NULL;
|
||||
|
||||
if (pathlen > 0) {
|
||||
if (parentpathlen == 0) {
|
||||
parentpath = ".";
|
||||
parentpathlen = 1;
|
||||
name = path;
|
||||
namelen = pathlen;
|
||||
} else {
|
||||
name = path + parentpathlen;
|
||||
namelen = pathlen - parentpathlen;
|
||||
}
|
||||
}
|
||||
|
||||
currentloc = eval_path_start(
|
||||
ctx,
|
||||
parentpath,
|
||||
parentpathlen,
|
||||
parent_eval_flags,
|
||||
&rtems_filesystem_root,
|
||||
&rtems_filesystem_current
|
||||
);
|
||||
|
||||
rtems_filesystem_location_clone(parentloc, currentloc);
|
||||
|
||||
ctx->path = name;
|
||||
ctx->pathlen = namelen;
|
||||
ctx->flags = eval_flags;
|
||||
|
||||
rtems_filesystem_eval_path_continue(ctx);
|
||||
|
||||
return &ctx->currentloc;
|
||||
}
|
||||
|
||||
void rtems_filesystem_eval_path_recursive(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
const char *path,
|
||||
size_t pathlen
|
||||
)
|
||||
{
|
||||
if (pathlen > 0) {
|
||||
if (ctx->recursionlevel < RTEMS_FILESYSTEM_SYMLOOP_MAX) {
|
||||
const char *saved_path = ctx->path;
|
||||
size_t saved_pathlen = ctx->pathlen;
|
||||
|
||||
if (rtems_filesystem_is_delimiter(path [0])) {
|
||||
rtems_filesystem_eval_path_restart(ctx, &ctx->rootloc);
|
||||
}
|
||||
|
||||
ctx->path = path;
|
||||
ctx->pathlen = pathlen;
|
||||
|
||||
++ctx->recursionlevel;
|
||||
while (ctx->pathlen > 0) {
|
||||
(*ctx->currentloc.ops->eval_path_h)(ctx);
|
||||
}
|
||||
--ctx->recursionlevel;
|
||||
|
||||
ctx->path = saved_path;
|
||||
ctx->pathlen = saved_pathlen;
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(ctx, ELOOP);
|
||||
}
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(ctx, ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
void rtems_filesystem_eval_path_error(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
int eno
|
||||
)
|
||||
{
|
||||
ctx->path = NULL;
|
||||
ctx->pathlen = 0;
|
||||
ctx->token = NULL;
|
||||
ctx->tokenlen = 0;
|
||||
|
||||
if (!rtems_filesystem_location_is_null(&ctx->currentloc)) {
|
||||
if (eno != 0) {
|
||||
errno = eno;
|
||||
}
|
||||
|
||||
rtems_filesystem_location_detach(&ctx->currentloc);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_location(rtems_filesystem_location_info_t *loc)
|
||||
{
|
||||
rtems_filesystem_mt_entry_declare_lock_context(lock_context);
|
||||
|
||||
(*loc->ops->freenod_h)(loc);
|
||||
|
||||
rtems_filesystem_mt_entry_lock(lock_context);
|
||||
rtems_chain_extract_unprotected(&loc->mt_entry_node);
|
||||
rtems_filesystem_mt_entry_unlock(lock_context);
|
||||
}
|
||||
|
||||
void rtems_filesystem_eval_path_cleanup(
|
||||
rtems_filesystem_eval_path_context_t *ctx
|
||||
)
|
||||
{
|
||||
free_location(&ctx->currentloc);
|
||||
rtems_filesystem_instance_unlock(&ctx->startloc->location);
|
||||
rtems_filesystem_global_location_release(ctx->startloc);
|
||||
rtems_filesystem_global_location_release(ctx->rootloc);
|
||||
}
|
||||
|
||||
void rtems_filesystem_eval_path_cleanup_with_parent(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
rtems_filesystem_location_info_t *parentloc
|
||||
)
|
||||
{
|
||||
free_location(parentloc);
|
||||
rtems_filesystem_eval_path_cleanup(ctx);
|
||||
}
|
||||
|
||||
void rtems_filesystem_eval_path_restart(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
rtems_filesystem_global_location_t **newstartloc_ptr
|
||||
)
|
||||
{
|
||||
free_location(&ctx->currentloc);
|
||||
rtems_filesystem_instance_unlock(&ctx->startloc->location);
|
||||
rtems_filesystem_global_location_assign(
|
||||
&ctx->startloc,
|
||||
rtems_filesystem_global_location_obtain(newstartloc_ptr)
|
||||
);
|
||||
rtems_filesystem_instance_lock(&ctx->startloc->location);
|
||||
rtems_filesystem_location_clone(&ctx->currentloc, &ctx->startloc->location);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
static bool is_fs_root( const rtems_filesystem_location_info_t *loc )
|
||||
{
|
||||
const rtems_filesystem_location_info_t *mt_fs_root =
|
||||
&loc->mt_entry->mt_fs_root->location;
|
||||
|
||||
return (*loc->ops->are_nodes_equal_h)( loc, mt_fs_root );
|
||||
}
|
||||
|
||||
static bool is_eval_path_root(
|
||||
const rtems_filesystem_eval_path_context_t *ctx,
|
||||
const rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
const rtems_filesystem_location_info_t *rootloc = &ctx->rootloc->location;
|
||||
|
||||
return loc->mt_entry == rootloc->mt_entry
|
||||
&& (*loc->ops->are_nodes_equal_h)( loc, rootloc );
|
||||
}
|
||||
|
||||
void rtems_filesystem_eval_path_generic(
|
||||
rtems_filesystem_eval_path_context_t *ctx,
|
||||
void *arg,
|
||||
const rtems_filesystem_eval_path_generic_config *config
|
||||
)
|
||||
{
|
||||
rtems_filesystem_eval_path_generic_status status =
|
||||
RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
|
||||
|
||||
while (status == RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE) {
|
||||
const char *token;
|
||||
size_t tokenlen;
|
||||
|
||||
rtems_filesystem_eval_path_get_next_token(ctx, &token, &tokenlen);
|
||||
|
||||
if (tokenlen > 0) {
|
||||
if ((*config->is_directory)(ctx, arg)) {
|
||||
if (rtems_filesystem_is_current_directory(token, tokenlen)) {
|
||||
if (rtems_filesystem_eval_path_has_path(ctx)) {
|
||||
status = (*config->eval_token)(ctx, arg, ".", 1);
|
||||
} else {
|
||||
int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
|
||||
|
||||
if ((eval_flags & RTEMS_LIBIO_REJECT_TERMINAL_DOT) == 0) {
|
||||
status = (*config->eval_token)(ctx, arg, ".", 1);
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(ctx, EINVAL);
|
||||
status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
|
||||
}
|
||||
}
|
||||
} else if (rtems_filesystem_is_parent_directory(token, tokenlen)) {
|
||||
rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_get_currentloc( ctx );
|
||||
|
||||
if (is_eval_path_root(ctx, currentloc)) {
|
||||
/* This prevents the escape from a chroot() environment */
|
||||
status = (*config->eval_token)(ctx, arg, ".", 1);
|
||||
} else if (is_fs_root(currentloc)) {
|
||||
if (currentloc->mt_entry->mt_point_node != NULL) {
|
||||
rtems_filesystem_eval_path_put_back_token(ctx);
|
||||
rtems_filesystem_eval_path_restart(
|
||||
ctx,
|
||||
¤tloc->mt_entry->mt_point_node
|
||||
);
|
||||
status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
|
||||
} else {
|
||||
/* This is the root file system */
|
||||
status = (*config->eval_token)(ctx, arg, ".", 1);
|
||||
}
|
||||
} else {
|
||||
status = (*config->eval_token)(ctx, arg, "..", 2);
|
||||
}
|
||||
} else {
|
||||
status = (*config->eval_token)(ctx, arg, token, tokenlen);
|
||||
}
|
||||
|
||||
if (status == RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY) {
|
||||
if (rtems_filesystem_eval_path_has_path(ctx)) {
|
||||
int eval_flags;
|
||||
|
||||
rtems_filesystem_eval_path_eat_delimiter(ctx);
|
||||
eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
|
||||
if (
|
||||
(eval_flags & RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS) == 0
|
||||
|| rtems_filesystem_eval_path_has_path(ctx)
|
||||
) {
|
||||
rtems_filesystem_eval_path_error(ctx, ENOENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rtems_filesystem_eval_path_error(ctx, ENOTDIR);
|
||||
status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
|
||||
}
|
||||
} else {
|
||||
status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
int rtems_filesystem_location_exists_in_same_fs_instance_as(
|
||||
const rtems_filesystem_location_info_t *a,
|
||||
const rtems_filesystem_location_info_t *b
|
||||
)
|
||||
{
|
||||
int rv = -1;
|
||||
|
||||
if (
|
||||
!rtems_filesystem_location_is_null( a )
|
||||
&& !rtems_filesystem_location_is_null( b )
|
||||
) {
|
||||
if ( a->mt_entry == b->mt_entry ) {
|
||||
rv = 0;
|
||||
} else {
|
||||
errno = EXDEV;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* @file src/sup_fs_get_start_loc.c
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1999.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* rtems_filesystem_get_start_loc
|
||||
*
|
||||
* Function to determine if path is absolute or relative
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* path : IN - path to be checked
|
||||
* index: OUT - 0, if relative, 1 if absolute
|
||||
* loc : OUT - location info of root fs if absolute
|
||||
* location info of current fs if relative
|
||||
*
|
||||
* Returns: void
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
|
||||
#include "rtems/libio_.h"
|
||||
|
||||
void rtems_filesystem_get_start_loc(const char *path,
|
||||
int *index,
|
||||
rtems_filesystem_location_info_t *loc)
|
||||
{
|
||||
if (rtems_filesystem_is_separator(path[0])) {
|
||||
*loc = rtems_filesystem_root;
|
||||
*index = 1;
|
||||
}
|
||||
else {
|
||||
*loc = rtems_filesystem_current;
|
||||
*index = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* @file src/sup_fs_get_sym_start_loc.c
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1999.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* rtems_filesystem_get_sym_start_loc
|
||||
*
|
||||
* Function to determine if path is absolute or relative
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* path : IN - path to be checked
|
||||
* index: OUT - 0, if relative, 1 if absolute
|
||||
* loc : OUT - location info of root fs if absolute
|
||||
* location info of current fs if relative
|
||||
*
|
||||
* Returns: void
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
|
||||
#include "rtems/libio_.h"
|
||||
|
||||
void rtems_filesystem_get_sym_start_loc(const char *path,
|
||||
int *index,
|
||||
rtems_filesystem_location_info_t *loc)
|
||||
{
|
||||
if (rtems_filesystem_is_separator(path[0])) {
|
||||
*loc = rtems_filesystem_root;
|
||||
*index = 1;
|
||||
}
|
||||
else {
|
||||
*index = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* @file src/sup_fs_is_separator.c
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1999.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
/*
|
||||
* rtems_filesystem_is_separator
|
||||
*
|
||||
* Function to determine if a character is a path name separator.
|
||||
* This was originally a macro in libio_.h
|
||||
*
|
||||
* NOTE: This function handles MS-DOS and UNIX style names.
|
||||
*/
|
||||
|
||||
int rtems_filesystem_is_separator(char ch)
|
||||
{
|
||||
return ((ch == '/') || (ch == '\\') || (ch == '\0'));
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/score/thread.h>
|
||||
|
||||
static rtems_filesystem_global_location_t *deferred_released_global_locations;
|
||||
|
||||
rtems_filesystem_location_info_t *rtems_filesystem_location_copy(
|
||||
rtems_filesystem_location_info_t *dst,
|
||||
const rtems_filesystem_location_info_t *src
|
||||
)
|
||||
{
|
||||
dst->node_access = src->node_access;
|
||||
dst->node_access_2 = src->node_access_2;
|
||||
dst->handlers = src->handlers;
|
||||
dst->ops = src->ops;
|
||||
dst->mt_entry = src->mt_entry;
|
||||
rtems_filesystem_location_add_to_mt_entry(dst);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void rtems_filesystem_location_detach(
|
||||
rtems_filesystem_location_info_t *detach
|
||||
)
|
||||
{
|
||||
rtems_filesystem_location_free(detach);
|
||||
rtems_filesystem_location_initialize_to_null(detach);
|
||||
}
|
||||
|
||||
void rtems_filesystem_location_copy_and_detach(
|
||||
rtems_filesystem_location_info_t *copy,
|
||||
rtems_filesystem_location_info_t *detach
|
||||
)
|
||||
{
|
||||
rtems_filesystem_location_copy(copy, detach);
|
||||
rtems_filesystem_location_remove_from_mt_entry(detach);
|
||||
rtems_filesystem_location_initialize_to_null(detach);
|
||||
}
|
||||
|
||||
rtems_filesystem_global_location_t *rtems_filesystem_location_transform_to_global(
|
||||
rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
rtems_filesystem_global_location_t *global_loc = malloc(sizeof(*global_loc));
|
||||
|
||||
if (global_loc != NULL) {
|
||||
global_loc->reference_count = 1;
|
||||
global_loc->deferred_released_next = NULL;
|
||||
global_loc->deferred_released_count = 0;
|
||||
rtems_filesystem_location_copy(&global_loc->location, loc);
|
||||
rtems_filesystem_location_remove_from_mt_entry(loc);
|
||||
} else {
|
||||
rtems_filesystem_location_free(loc);
|
||||
global_loc = rtems_filesystem_global_location_obtain_null();
|
||||
errno = ENOMEM;
|
||||
}
|
||||
|
||||
return global_loc;
|
||||
}
|
||||
|
||||
void rtems_filesystem_global_location_assign(
|
||||
rtems_filesystem_global_location_t **lhs_global_loc_ptr,
|
||||
rtems_filesystem_global_location_t *rhs_global_loc
|
||||
)
|
||||
{
|
||||
rtems_filesystem_mt_entry_declare_lock_context(lock_context);
|
||||
rtems_filesystem_global_location_t *lhs_global_loc;
|
||||
|
||||
rtems_filesystem_mt_entry_lock(lock_context);
|
||||
lhs_global_loc = *lhs_global_loc_ptr;
|
||||
*lhs_global_loc_ptr = rhs_global_loc;
|
||||
rtems_filesystem_mt_entry_unlock(lock_context);
|
||||
|
||||
rtems_filesystem_global_location_release(lhs_global_loc);
|
||||
}
|
||||
|
||||
static void release_with_count(
|
||||
rtems_filesystem_global_location_t *global_loc,
|
||||
int count
|
||||
)
|
||||
{
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry =
|
||||
global_loc->location.mt_entry;
|
||||
rtems_filesystem_mt_entry_declare_lock_context(lock_context);
|
||||
bool do_free;
|
||||
bool do_unmount;
|
||||
|
||||
rtems_filesystem_mt_entry_lock(lock_context);
|
||||
global_loc->reference_count -= count;
|
||||
do_free = global_loc->reference_count == 0;
|
||||
do_unmount = rtems_filesystem_is_ready_for_unmount(mt_entry);
|
||||
rtems_filesystem_mt_entry_unlock(lock_context);
|
||||
|
||||
if (do_free) {
|
||||
rtems_filesystem_location_free(&global_loc->location);
|
||||
free(global_loc);
|
||||
}
|
||||
|
||||
if (do_unmount) {
|
||||
rtems_filesystem_do_unmount(mt_entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void deferred_release(void)
|
||||
{
|
||||
rtems_filesystem_global_location_t *current = NULL;
|
||||
|
||||
do {
|
||||
int count = 0;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
current = deferred_released_global_locations;
|
||||
if (current != NULL) {
|
||||
deferred_released_global_locations = current->deferred_released_next;
|
||||
count = current->deferred_released_count;
|
||||
current->deferred_released_next = NULL;
|
||||
current->deferred_released_count = 0;
|
||||
}
|
||||
_Thread_Enable_dispatch();
|
||||
|
||||
if (current != NULL) {
|
||||
release_with_count(current, count);
|
||||
}
|
||||
} while (current != NULL);
|
||||
}
|
||||
|
||||
rtems_filesystem_global_location_t *rtems_filesystem_global_location_obtain(
|
||||
rtems_filesystem_global_location_t *const *global_loc_ptr
|
||||
)
|
||||
{
|
||||
rtems_filesystem_mt_entry_declare_lock_context(lock_context);
|
||||
rtems_filesystem_global_location_t *global_loc;
|
||||
|
||||
if (deferred_released_global_locations != NULL) {
|
||||
deferred_release();
|
||||
}
|
||||
|
||||
rtems_filesystem_mt_entry_lock(lock_context);
|
||||
global_loc = *global_loc_ptr;
|
||||
if (global_loc == NULL || !global_loc->location.mt_entry->mounted) {
|
||||
global_loc = &rtems_filesystem_global_location_null;
|
||||
errno = ENXIO;
|
||||
}
|
||||
++global_loc->reference_count;
|
||||
rtems_filesystem_mt_entry_unlock(lock_context);
|
||||
|
||||
return global_loc;
|
||||
}
|
||||
|
||||
void rtems_filesystem_global_location_release(
|
||||
rtems_filesystem_global_location_t *global_loc
|
||||
)
|
||||
{
|
||||
if (!_Thread_Dispatch_in_critical_section()) {
|
||||
release_with_count(global_loc, 1);
|
||||
} else {
|
||||
if (global_loc->deferred_released_count == 0) {
|
||||
rtems_filesystem_global_location_t *head =
|
||||
deferred_released_global_locations;
|
||||
|
||||
global_loc->deferred_released_count = 1;
|
||||
global_loc->deferred_released_next = head;
|
||||
deferred_released_global_locations = global_loc;
|
||||
} else {
|
||||
++global_loc->deferred_released_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rtems_filesystem_location_remove_from_mt_entry(
|
||||
rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
rtems_filesystem_mt_entry_declare_lock_context(lock_context);
|
||||
bool do_unmount;
|
||||
|
||||
rtems_filesystem_mt_entry_lock(lock_context);
|
||||
rtems_chain_extract_unprotected(&loc->mt_entry_node);
|
||||
do_unmount = rtems_filesystem_is_ready_for_unmount(loc->mt_entry);
|
||||
rtems_filesystem_mt_entry_unlock(lock_context);
|
||||
|
||||
if (do_unmount) {
|
||||
rtems_filesystem_do_unmount(loc->mt_entry);
|
||||
}
|
||||
}
|
||||
|
||||
void rtems_filesystem_do_unmount(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry
|
||||
)
|
||||
{
|
||||
rtems_filesystem_mt_lock();
|
||||
rtems_chain_extract_unprotected(&mt_entry->mt_node);
|
||||
rtems_filesystem_mt_unlock();
|
||||
rtems_filesystem_global_location_release(mt_entry->mt_point_node);
|
||||
(*mt_entry->mt_fs_root->location.ops->fsunmount_me_h)(mt_entry);
|
||||
free(mt_entry);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
bool rtems_filesystem_mount_iterate(
|
||||
rtems_filesystem_mt_entry_visitor visitor,
|
||||
void *visitor_arg
|
||||
)
|
||||
{
|
||||
rtems_chain_control *chain = &rtems_filesystem_mount_table;
|
||||
rtems_chain_node *node = NULL;
|
||||
bool stop = false;
|
||||
|
||||
rtems_filesystem_mt_lock();
|
||||
for (
|
||||
node = rtems_chain_first( chain );
|
||||
!rtems_chain_is_tail( chain, node ) && !stop;
|
||||
node = rtems_chain_next( node )
|
||||
) {
|
||||
const rtems_filesystem_mount_table_entry_t *mt_entry =
|
||||
(rtems_filesystem_mount_table_entry_t *) node;
|
||||
|
||||
stop = (*visitor)( mt_entry, visitor_arg );
|
||||
}
|
||||
rtems_filesystem_mt_unlock();
|
||||
|
||||
return stop;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
void rtems_filesystem_eval_path_eat_delimiter(
|
||||
rtems_filesystem_eval_path_context_t *ctx
|
||||
)
|
||||
{
|
||||
const char *current = ctx->path;
|
||||
const char *end = current + ctx->pathlen;
|
||||
|
||||
while (current != end && rtems_filesystem_is_delimiter(*current)) {
|
||||
++current;
|
||||
}
|
||||
|
||||
ctx->path = current;
|
||||
ctx->pathlen = (size_t) (end - current);
|
||||
}
|
||||
|
||||
static void next_token(rtems_filesystem_eval_path_context_t *ctx)
|
||||
{
|
||||
const char *begin = ctx->path;
|
||||
const char *end = begin + ctx->pathlen;
|
||||
const char *current = begin;
|
||||
|
||||
while (current != end && !rtems_filesystem_is_delimiter(*current)) {
|
||||
++current;
|
||||
}
|
||||
|
||||
ctx->path = current;
|
||||
ctx->pathlen = (size_t) (end - current);
|
||||
ctx->token = begin;
|
||||
ctx->tokenlen = (size_t) (current - begin);
|
||||
}
|
||||
|
||||
void rtems_filesystem_eval_path_next_token(
|
||||
rtems_filesystem_eval_path_context_t *ctx
|
||||
)
|
||||
{
|
||||
rtems_filesystem_eval_path_eat_delimiter(ctx);
|
||||
next_token(ctx);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
rtems_filesystem_node_types_t rtems_filesystem_node_type(
|
||||
const rtems_filesystem_location_info_t *loc
|
||||
)
|
||||
{
|
||||
rtems_filesystem_node_types_t type;
|
||||
|
||||
rtems_filesystem_instance_lock(loc);
|
||||
type = (*loc->ops->node_type_h)(loc);
|
||||
rtems_filesystem_instance_unlock(loc);
|
||||
|
||||
return type;
|
||||
}
|
||||
@@ -12,31 +12,31 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
#include <rtems/seterr.h>
|
||||
|
||||
int symlink(
|
||||
const char *actualpath,
|
||||
const char *sympath
|
||||
)
|
||||
int symlink( const char *path1, const char *path2 )
|
||||
{
|
||||
rtems_filesystem_location_info_t loc;
|
||||
int i;
|
||||
const char *name_start;
|
||||
int result;
|
||||
int rv = 0;
|
||||
rtems_filesystem_eval_path_context_t ctx;
|
||||
int eval_flags = RTEMS_LIBIO_FOLLOW_HARD_LINK
|
||||
| RTEMS_LIBIO_MAKE
|
||||
| RTEMS_LIBIO_EXCLUSIVE;
|
||||
const rtems_filesystem_location_info_t *currentloc =
|
||||
rtems_filesystem_eval_path_start( &ctx, path2, eval_flags );
|
||||
|
||||
rtems_filesystem_get_start_loc( sympath, &i, &loc );
|
||||
rv = (*currentloc->ops->symlink_h)(
|
||||
currentloc,
|
||||
rtems_filesystem_eval_path_get_token( &ctx ),
|
||||
rtems_filesystem_eval_path_get_tokenlen( &ctx ),
|
||||
path1
|
||||
);
|
||||
|
||||
result = (*loc.ops->evalformake_h)( &sympath[i], &loc, &name_start );
|
||||
if ( result != 0 )
|
||||
return -1;
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
result = (*loc.ops->symlink_h)( &loc, actualpath, name_start);
|
||||
|
||||
rtems_filesystem_freenode( &loc );
|
||||
|
||||
return result;
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -12,22 +12,27 @@
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
mode_t umask(
|
||||
mode_t cmask
|
||||
)
|
||||
mode_t umask( mode_t cmask )
|
||||
{
|
||||
mode_t old_mask;
|
||||
|
||||
old_mask = rtems_filesystem_umask;
|
||||
rtems_filesystem_umask = cmask;
|
||||
/*
|
||||
* We must use the same protection mechanism as in
|
||||
* rtems_libio_set_private_env().
|
||||
*/
|
||||
_Thread_Disable_dispatch();
|
||||
old_mask = rtems_filesystem_umask;
|
||||
rtems_filesystem_umask = cmask & (S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
_Thread_Enable_dispatch();
|
||||
|
||||
return old_mask;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user